Kör skaltester i CI-pipelines
Koppla in ShellCheck och Bats i GitHub Actions så att varje skaländring kräver godkända kontroller.
Kör skaltester i CI-pipelines är en gratis lektion i Bemästra Linux-kommandoraden och Bash-skriptning på CoddyKit. Detta är lektion 4 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Bemästra Linux-kommandoraden och Bash-skriptning, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Bemästra Linux-kommandoraden och Bash-skriptning innehåller totalt 4 lektioner.
Varför CI är viktigt för shellskript
Shellskript är kod — och precis som all annan kod förtjänar de automatiserade kvalitetskontroller. Utan CI kan ett skrivfel i ett driftsättningsskript obemärkt nå produktionen och orsaka ett avbrott klockan tre på morgonen.
En stabil CI-pipeline för Bash-projekt ser till att två saker kontrolleras vid varje pull request:
- Statisk analys med
ShellCheck— upptäcker syntaxfel, osäkra mönster och POSIX-portabilitetsproblem innan skriptet ens körs. - Enhets- och integrationstester med
Bats(Bash Automated Testing System) — kör era funktioner och verifierar att de beter sig korrekt.
Tillsammans bildar de ett skyddsnät som gör refaktorering tryggare och introduktionen av nya medarbetare snabbare. I den här lektionen kopplas båda verktygen in i GitHub Actions, den vanligaste kostnadsfria CI-plattformen för projekt med öppen källkod och projekt i små team.
Introduktion till GitHub Actions för shellprojekt
GitHub Actions är händelsestyrd CI/CD som är inbyggd i GitHub. Ett workflow är en YAML-fil som lagras under .github/workflows/. Det utlöses av händelser (push, pull_request med mera) och kör jobb på hostade runners.
Viktiga begrepp ni behöver känna till:
on:— utlösaren (till exempelpush,pull_request)jobs:— parallella arbetsenheter, där varje enhet körs på en ny virtuell maskinsteps:— sekventiella shellkommandon eller återanvändbara actions inom ett jobbruns-on:— runner-avbildningen (vi använderubuntu-latest)
Workflow-filer måste checkas in i arkivet. GitHub upptäcker dem automatiskt — ingen extern konfiguration krävs.
# Minimal skeleton — .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
shell-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "Steps go here"Installera ShellCheck i ett workflow
ShellCheck är förinstallerat på runners med ubuntu-latest, så i de flesta fall behöver ni inte lägga till några installationssteg. Den förinstallerade versionen kan dock ligga efter den senaste utgåvan. För reproducerbara byggen bör ni låsa en specifik version.
Två installationsstrategier:
- Använd den förinstallerade binärfilen — enklast och tillräckligt bra för de flesta projekt.
- Installera en låst version via det officiella GitHub-utgåvearkivet i tarball-format — det garanterar samma linterversion lokalt och i CI.
Steget nedan visar den låsta metoden med en fast versionssträng som lagras som en miljövariabel, vilket gör uppgraderingar till en ändring på en enda rad.
# .github/workflows/ci.yml — ShellCheck install step
- name: Install ShellCheck
env:
SC_VERSION: v0.10.0
run: |
curl -sSfL \
"https://github.com/koalaman/shellcheck/releases/download/${SC_VERSION}/shellcheck-${SC_VERSION}.linux.x86_64.tar.xz" \
| tar -xJf - --strip-components=1 -C /usr/local/bin shellcheck-${SC_VERSION}/shellcheck
shellcheck --versionKör ShellCheck på alla skript
Efter installationen behöver ni ett steg som hittar och analyserar alla shellskript i arkivet. Använd find för att hitta filerna och skicka dem sedan vidare till shellcheck.
Viktiga flaggor att känna till:
-e SC2034— uteslut en specifik regel (använd sparsamt och tillsammans med en kommentar).--severity=warning— misslyckas endast vid varningar och allvarligare problem (ignorerar förslag om stil).-x— följsource-direktiv för att även analysera filer som hämtas in.
Om shellcheck hittar något problem avslutas det med en icke-nollstatus, vilket automatiskt får CI-steget att misslyckas — ingen ytterligare logik behövs.
# .github/workflows/ci.yml — ShellCheck lint step
- name: Lint shell scripts
run: |
# Find all .sh files and files with a bash/sh shebang
mapfile -t scripts < <(
find . -type f -name '*.sh' -not -path './.git/*'
)
if [[ ${#scripts[@]} -eq 0 ]]; then
echo 'No shell scripts found — skipping.'
exit 0
fi
echo "Linting ${#scripts[@]} file(s)..."
shellcheck --severity=warning -x "${scripts[@]}"Vad är Bats och hur fungerar det?
Bats (Bash Automated Testing System) är ett TAP-kompatibelt testningsramverk för Bash. Varje testfil är en .bats-fil som innehåller block med @test.
Ett test godkänns när dess kropp avslutas med 0 och underkänns när den avslutas med en icke-nollstatus. Bats tillhandahåller hjälparvariabler och funktioner:
$status— avslutningskoden för det senaste kommandot som kördes medrun.$output— kombinerad stdout och stderr från det senaste kommandot som kördes medrun.$lines— array med utdatarader.run <cmd>— kör ett kommando utan att få testet att misslyckas vid en icke-nollstatus.
Hjälparen run är nödvändig — utan den skulle ett misslyckat kommando avbryta testet innan ni kan granska $status.
#!/usr/bin/env bats
# tests/greet.bats
setup() {
# Runs before every @test block
source "${BATS_TEST_DIRNAME}/../lib/greet.sh"
}
@test "greet outputs hello with the given name" {
run greet "Alice"
[ "$status" -eq 0 ]
[ "$output" = "Hello, Alice!" ]
}
@test "greet fails when no argument is provided" {
run greet
[ "$status" -eq 1 ]
[[ "$output" == *"Usage"* ]]
}Installera Bats-Core via en Git-submodul
Det vedertagna sättet att lägga till Bats i ett projekt är som en Git-submodul. Då låses en specifik commit, runner-versionen blir identisk med den lokala utvecklingsmiljön och ni slipper vara beroende av pakethanterare.
Kör dessa kommandon en gång lokalt och checka sedan in resultatet:
git submodule add https://github.com/bats-core/bats-core test/batsgit submodule add https://github.com/bats-core/bats-support test/test_helper/bats-supportgit submodule add https://github.com/bats-core/bats-assert test/test_helper/bats-assert
I CI återställer ni submodulerna med actions/checkout@v4 och alternativet submodules: recursive. Steget nedan visar den fullständiga checkout-konfigurationen.
# .github/workflows/ci.yml — checkout with submodules
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive # restores bats-core + helpersKör Bats-tester i CI
När Bats finns tillgängligt (via en submodul eller en paketinstallation) körs testerna med ett enda kommando. Ange en katalog som mål, så hittar Bats rekursivt alla .bats-filer med flaggan --recursive.
Flaggan --formatter tap skriver ut formatet TAP (Test Anything Protocol), som många CI-system kan tolka för testrapportering. Standardformatteraren pretty passar bättre för mänsklig läsning i råa loggar.
Använd --timing för att upptäcka långsamma tester tidigt — ett test som tar mer än 5 sekunder tyder oftast på ett oönskat nätverksanrop eller en mockning som saknas.
# .github/workflows/ci.yml — Bats test step
- name: Run Bats tests
run: |
# If installed as a submodule:
./test/bats/bin/bats \
--recursive \
--timing \
tests/
# If installed via apt or brew (alternative):
# bats --recursive --timing tests/Ett komplett workflow: ShellCheck + Bats
Nu kombinerar vi allt i en produktionsklar workflow-fil. Här tillämpas följande bästa praxis:
- Två separata jobb (
lintochtest) körs parallellt, vilket ger snabbare återkoppling. - Jobbet
testdeklarerarneeds: lint, så testerna körs först när lintningen har godkänts — därmed slösas inga runner-minuter på uppenbart trasig kod. - Låsta action-versioner (
@v4) förhindrar oväntade fel på grund av uppdateringar uppströms. - Ett block med
permissions:begränsar workflow-token till minsta nödvändiga behörighet.
# .github/workflows/ci.yml
name: Shell CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
jobs:
lint:
name: ShellCheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run ShellCheck
run: |
mapfile -t scripts < <(find . -name '*.sh' -not -path './.git/*')
[[ ${#scripts[@]} -gt 0 ]] && shellcheck --severity=warning -x "${scripts[@]}"
test:
name: Bats Tests
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Run tests
run: ./test/bats/bin/bats --recursive --timing tests/Cacha beroenden för snabbare körningar
När Bats-hjälpare eller andra verktyg installeras via en pakethanterare i workflowet kan cachning dramatiskt snabba upp efterföljande körningar. GitHub Actions tillhandahåller actionen actions/cache för detta.
Viktiga punkter för effektiv cachning:
- Använd en cache-nyckel som innehåller operativsystem, verktygsnamn och en hash av låsfilen — då ogiltigförklaras cachen automatiskt när beroenden ändras.
- En reservnyckel med
restore-keysgör att workflowet kan använda en inaktuell cache i stället för att börja om från början när ingen exakt cacheträff hittas. - För Git-submoduler behövs cachning sällan eftersom checkout av submoduler går snabbt. Cache är mest värdefullt för installationer av
npm,pipeller kompilerade verktyg.
# .github/workflows/ci.yml — cache step example
- name: Cache Bats npm helpers
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-bats-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-bats-
- name: Install helpers
run: npm ci # uses cache when availableGren- och mergeskydd: tvinga fram godkända kontroller
Ett CI-workflow som inte blockerar mergningar är i bästa fall rådgivande. GitHubs regler för grenskydd gör era kontroller till obligatoriska spärrar.
Konfigurera dem genom att välja: Settings → Branches → Add rule för main och sedan aktivera:
- Require status checks to pass before merging — välj ShellCheck och Bats Tests efter namn.
- Require branches to be up to date before merging — förhindrar att en pull request som godkänts mot en inaktuell basgren för in trasig kod.
- Do not allow bypassing the above settings — tillämpar reglerna även på arkivets administratörer.
När dessa regler är på plats är den enda vägen till merge en pull request där alla CI-jobb är godkända — precis det skyddsnät ni vill ha.
Felsök misslyckade CI-steg lokalt
När en CI-körning misslyckas är den snabbaste vägen till en lösning att återskapa felet lokalt innan ni skickar upp ytterligare en commit. Här är två tekniker:
- Kör exakt samma kommandon från det misslyckade steget i terminalen — CI kör vanligt shell, så kommandona kan kopieras och köras direkt.
- Använd
act— ett verktyg som kör GitHub Actions-workflows lokalt i Docker och ger den närmaste möjliga motsvarigheten till runner-miljön hos värden.
En vanlig orsak till fel som bara uppstår i CI är att verktygsversionerna skiljer sig mellan er Mac (till exempel BSD find på macOS jämfört med GNU find på Ubuntu). Testa alltid med --posix-flaggor eller använd act för att köra Ubuntu-avbildningen lokalt.
#!/usr/bin/env bash
# run_ci_locally.sh — mimic the CI lint step on your machine
set -euo pipefail
echo '=== ShellCheck ==='
mapfile -t scripts < <(find . -name '*.sh' -not -path './.git/*')
if [[ ${#scripts[@]} -eq 0 ]]; then
echo 'No .sh files found.'
else
shellcheck --severity=warning -x "${scripts[@]}"
echo "Linted ${#scripts[@]} file(s) — OK"
fi
echo '=== Bats ==='
./test/bats/bin/bats --recursive --timing tests/Kunskapskontroll: CI-pipelinebegrepp
Testa er förståelse av hur ShellCheck och Bats kopplas in i GitHub Actions.
Sammanfattning: Shell-CI med ShellCheck och Bats
I den här lektionen byggde ni en komplett CI-pipeline för Bash-projekt med GitHub Actions. Här är vad ni gick igenom:
- Grunderna i GitHub Actions — workflow-YAML lagras i
.github/workflows/, utlöses av push och pull_request och kör jobb på runners medubuntu-latest. - ShellCheck — förinstallerat på Ubuntu-runners; använd
findför att hitta skript och--severity=warning -xsom en praktisk lint-spärr. - Bats via submodul — lås bats-core och hjälparna som Git-submoduler och återställ dem i CI med
submodules: recursivei checkout-actionen. - Jobbordning — använd
needs:så att testerna körs först när lintningen har godkänts, vilket ger snabb återkoppling och undviker slösad beräkningskapacitet. - Grenskydd — tvinga fram statuskontroller i GitHub-inställningarna så att ingen pull request kan mergas utan godkänd CI.
- Lokal återskapning — kopiera CI-kommandona direkt till terminalen eller använd
actför att felsöka problem utan extra commits.
Med den här pipelinen på plats valideras varje ändring i shell automatiskt innan den når er huvudgren.
Lär dig Bash med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 22
- Lektioner
- 88
Vanliga frågor
Är lektionen ”Kör skaltester i CI-pipelines” gratis?
Ja – hela texten till ”Kör skaltester i CI-pipelines” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Bemästra Linux-kommandoraden och Bash-skriptning, kan Ni uppgradera till CoddyKit PRO. Kursen i Bemästra Linux-kommandoraden och Bash-skriptning innehåller totalt 4 lektioner.
Vad lär jag mig i ”Kör skaltester i CI-pipelines”?
Koppla in ShellCheck och Bats i GitHub Actions så att varje skaländring kräver godkända kontroller. Ni övar på Bemästra Linux-kommandoraden och Bash-skriptning med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Bemästra Linux-kommandoraden och Bash-skriptning?
Du behöver inga förkunskaper. Utbildningen i Bemästra Linux-kommandoraden och Bash-skriptning på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.
Hur lång tid tar lektionen ”Kör skaltester i CI-pipelines”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Bemästra Linux-kommandoraden och Bash-skriptning-lektionen?
Ja. Varje Bemästra Linux-kommandoraden och Bash-skriptning-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Enhetstesta funktioner med Bats-core
- Mocka kommandon och stubba externa verktyg
- Testfixturer, temporära miljöer och täckningsgrad
- Kör skaltester i CI-pipelines