Bemästra Linux-kommandoraden och Bash-skriptning · Lektion

Kör skaltester i CI-pipelines

Koppla in ShellCheck och Bats i GitHub Actions så att varje skaländring kräver godkända kontroller.

Lektion 4 av 413 steg

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 exempel push, pull_request)
  • jobs: — parallella arbetsenheter, där varje enhet körs på en ny virtuell maskin
  • steps: — sekventiella shellkommandon eller återanvändbara actions inom ett jobb
  • runs-on: — runner-avbildningen (vi använder ubuntu-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 --version

Kö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ölj source-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 med run.
  • $output — kombinerad stdout och stderr från det senaste kommandot som kördes med run.
  • $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/bats
  • git submodule add https://github.com/bats-core/bats-support test/test_helper/bats-support
  • git 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 + helpers

Kö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 (lint och test) körs parallellt, vilket ger snabbare återkoppling.
  • Jobbet test deklarerar needs: 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-keys gö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, pip eller 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 available

Gren- 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 med ubuntu-latest.
  • ShellCheck — förinstallerat på Ubuntu-runners; använd find för att hitta skript och --severity=warning -x som 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: recursive i 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 act fö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.

Gratis att börja

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

  1. Enhetstesta funktioner med Bats-core
  2. Mocka kommandon och stubba externa verktyg
  3. Testfixturer, temporära miljöer och täckningsgrad
  4. Kör skaltester i CI-pipelines
← Tillbaka till Bemästra Linux-kommandoraden och Bash-skriptning