Disclosure: This article may contain affiliate links. We may earn a commission if you purchase through these links, at no extra cost to you. We only recommend products we believe in.

Lär dig bygga en robust CI/CD-pipeline med GitHub Actions och Azure DevOps. Steg-för-steg-guide för automatisering och DevOps.


Din utvecklings team levererar kodändringar tre gånger i veckan. Varje release kräver manuella deploys, vilket tar 45 minuter och skapar ett genomsnitt på 2,3 incidenter per månad på grund av mänskliga fel. Detta är verkligheten för företag utan automatiserade pipelines – och kostnaden är inte bara teknisk utan även affärsmässig. Forskning från DORA (DevOps Research and Assessment) visar att högpresterande team med fullt automatiserade CI/CD-processer har 208x kortare ledtid och 106x kortare mean time to recovery. Den här guiden visar dig exakt hur du bygger en produktionsklar CI/CD-pipeline med både GitHub Actions och Azure DevOps, med konkreta konfigurationsfiler och implementeringsdetaljer som fungerar i verkligheten.

Vad är en CI/CD-pipeline och varför behöver du en?

En CI/CD-pipeline är en automatiserad kedja av processer som tar kod från commit till produktion utan manuell inblandning. CI (Continuous Integration) fokuserar på att automatiskt bygga och testa varje kodändring. CD (Continuous Delivery/Deployment) hanterar den automatiserade leveransen till olika miljöer.

De främsta fördelarna med en välimplementerad CI/CD-pipeline inkluderar:

  • Snabbare time-to-market – Från veckovis till daglig eller till och med kontinuerlig release
  • Högre kodkvalitet – Automatiska tester fångar buggar innan de når produktion
  • Minskad risk – Små, frekventa releaser är enklare att felsöka än stora batch-leanser
  • Bättre samarbete – DevOps-teamet får insyn i hela leveranskedjan
  • Kostnadsbesparing – Automatisering minskar personalkostnader för repetitiva uppgifter

Statistik från Puppet's State of DevOps Report visar att organisationer med hög CI/CD-mognad har 30% lägre définitionskostnader och 50% högre sannolikhet att överträffa affärsmål.

GitHub Actions: Kraftfull CI/CD inbyggt i GitHub

GitHub Actions är Microsoft's CI/CD-lösning direkt integrerad i GitHub-ekosystemet. Sedan GA i november 2019 har plattformen vuxit till att hantera över 10 miljoner workflow körningar dagligen. Prissättningen är generös: 2 000 minuter per månad gratis för offentliga repositories, och 2 000 minuter för privata repositories på gratis-planen. Enterprise-planen börjar på $21 per användare per månad och inkluderar obegränsade minuter.

Grundläggande struktur i GitHub Actions

En GitHub Actions workflow definieras i en YAML-fil i .github/workflows/-mappen:

name: Build and Deploy

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.0.x'
      - name: Restore dependencies
        run: dotnet restore
      - name: Build
        run: dotnet build --configuration Release
      - name: Run tests
        run: dotnet test --configuration Release --verbosity normal
      - name: Publish artifacts
        uses: actions/upload-artifact@v4
        with:
          name: drop
          path: bin/Release/

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - name: Download artifacts
        uses: actions/download-artifact@v4
        with:
          name: drop
      - name: Deploy to Azure Web App
        uses: azure/webapps-deploy@v3
        with:
          app-name: 'my-webapp-prod'
          publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
          package: './bin/Release/net8.0/publish'

Den här workflowen triggar på varje push och pull request till main-branch, kör bygge och tester, och deployar automatiskt till Azure Web App vid merge till main.

Avancerade GitHub Actions-funktioner

Matrix builds möjliggör parallell testning mot flera konfigurationer:

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        dotnet-version: ['6.0.x', '7.0.x', '8.0.x']
        operating-system: [ubuntu-latest, windows-latest]
    steps:
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: ${{ matrix.dotnet-version }}

Reusable workflows (introducerade 2022) låter dig skapa mall-pipelines som kan anropas från flera repositories, vilket är idealiskt för organisationer med flera team som följer samma standarder.

Environment protection rules kräver godkännande innan deployment till produktionsmiljöer:

environment:
  name: production
  url: https://production.example.com
  required_reviewers:
    - '@senior-dev-team'

Azure DevOps: Enterprise-grade CI/CD med full kontroll

Azure DevOps (tidigare Visual Studio Team Services) erbjuder en komplett DevOps-plattform med fem kärntjänster: Azure Repos, Azure Pipelines, Azure Boards, Azure Test Plans och Azure Artifacts. Till skillnad från GitHub Actions, som är tight integrerat med kod-repository, ger Azure DevOps dig frihet att använda valfri kod-plattform medan du fortfarande drar nytta av Microsofts CI/CD-motorer.

Prissättningen är transparent: upp till 5 användare gratis med Basic-licens, obegränsade private Git-repos, och 1 800 minuter per månad för CI/CD med parallella jobs. Azure Pipelines för open source-projekt är gratis och obegränsat.

Skapa en CI/CD-pipeline i Azure DevOps

  1. Skapa ett nytt projekt i Azure DevOps Organizations och välj "Pipelines" → "Create Pipeline"
  2. Välj din kodplats – Azure Repos Git, GitHub, Bitbucket eller Git extern
  3. Konfigurera din pipeline – Använd klassisk editor för visuella pipelines eller YAML för kod-som-infrastruktur
  4. Definiera stages, jobs och steps

Ett komplett YAML-exempel för en .NET-applikation:

trigger:
  branches:
    include:
      - main
  paths:
    include:
      - src/*
      - tests/*

variables:
  buildConfiguration: 'Release'
  dockerRegistryServiceConnection: 'my-registry-connection'
  imageRepository: 'myapp'
  dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
  tag: '$(Build.BuildNumber)'

stages:
  - stage: Build
    displayName: 'Build and Test'
    jobs:
      - job: BuildJob
        displayName: 'Build Job'
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - task: UseDotNet@2
            displayName: 'Use .NET 8'
            inputs:
              packageType: 'sdk'
              version: '8.0.x'
          
          - script: |
              dotnet restore
              dotnet build --configuration $(buildConfiguration) --no-restore
              dotnet test --configuration $(buildConfiguration) --no-build --verbosity normal
            displayName: 'Build and Test'
          
          - task: PublishBuildArtifacts@1
            displayName: 'Publish Artifacts'
            inputs:
              pathtoPublish: '$(Build.ArtifactStagingDirectory)'
              artifactName: 'drop'

  - stage: BuildContainer
    displayName: 'Build Container Image'
    dependsOn: Build
    jobs:
      - job: DockerBuild
        displayName: 'Docker Build'
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - task: Docker@2
            displayName: 'Build and Push'
            inputs:
              containerRegistry: '$(dockerRegistryServiceConnection)'
              repository: '$(imageRepository)'
              command: 'buildAndPush'
              Dockerfile: '$(dockerfilePath)'
              tags: |
                $(tag)
                latest

  - stage: DeployDev
    displayName: 'Deploy to Dev'
    dependsOn: BuildContainer
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
    jobs:
      - deployment: DeployDev
        displayName: 'Deploy to Dev Environment'
        environment: 'dev'
        pool:
          vmImage: 'ubuntu-latest'
        strategy:
          runOnce:
            deploy:
              steps:
                - task: AzureWebApp@1
                  displayName: 'Azure App Service Deploy'
                  inputs:
                    azureSubscription: 'my-azure-subscription'
                    appType: 'webApp'
                    appName: 'myapp-dev'
                    package: '$(Pipeline.Workspace)/drop/**/*.zip'
                    deploymentMethod: 'auto'

  - stage: DeployProd
    displayName: 'Deploy to Production'
    dependsOn: DeployDev
    condition: succeeded('DeployDev')
    jobs:
      - deployment: DeployProd
        displayName: 'Deploy to Production'
        environment: 'production'
        pool:
          vmImage: 'ubuntu-latest'
        strategy:
          runOnce:
            deploy:
              steps:
                - task: AzureWebApp@1
                  displayName: 'Azure App Service Deploy'
                  inputs:
                    azureSubscription: 'my-azure-subscription'
                    appType: 'webApp'
                    appName: 'myapp-prod'
                    package: '$(Pipeline.Workspace)/drop/**/*.zip'
                    deploymentMethod: 'auto'

Azure DevOps-lanseringspipelines vs YAML-pipelines

Azure DevOps erbjuder två paradigm:

Klassiska release-pipelines (GUI-baserade) passar organisationer som vill ha visuell kontroll och enklare onboarding för team som inte skriver YAML dagligen. Nackdelen är att konfigurationen inte är i kode, vilket försvårar versioning och peer review.

YAML-pipelines (IaC-style) är numera standard och rekommenderad approach. Allt är i kode, vilket möjliggör full GitOps-arbetsflöde. Enligt Microsofts egna statistik har 78% av nya pipelines skapats med YAML sedan 2023.

Azure Deployment Environments (nuvarande i preview) är ett intressant komplement – det tillåter utvecklare att skapa miljöer på begäran med självbetjäning via ARM eller Terraform templates, med inbyggd styrning och kostnadskontroll.

Praktisk implementation: från noll till produktionsklar

Steg 1: Analysera din nuvarande process

Innan du börjar automatisera, kartlägg befintliga leveransprocesser. Frågor att besvara:

  • Hur många steg finns i er nuvarande release?
  • Vilka miljöer används (dev, staging, production)?
  • Vilka manuella steg tar mest tid?
  • Finns det compliance-krav på audit trails?

Ett typiskt enterprise-företag har ofta 15-25 manuella steg i sin release, varav 60% kan automatiseras direkt.

Steg 2: Strukturera din kod för CI/CD

framgångsrik CI/CD kräver att koden är strukturerad för automation:

  • Monorepo vs polyrepo: GitHub Actions har förstklassigt stöd för båda. För monorepos, använd path-filters för att trigga endast relevanta pipelines vid ändringar i specifika kataloger.
  • Miljövariabler och secrets: Lagra aldrig credentials i kode. Använd GitHub Secrets eller Azure Key Vault för känslig information.
  • Infrastructure as Code: Para CI/CD med Terraform eller Bicep för fullständig automatisering av infrastruktur och applikationer.

Steg 3: Implementera testautomatisering

Automatisera tre nivåer av tester:

  1. Enhets-tester – Kör på varje commit, mål: >80% code coverage
  2. Integrationstester – Kör efter bygge, testa databas och externa API:er
  3. End-to-end-tester – Kör mot staging-miljö, använd verkliga användarscenarion
# GitHub Actions exempel med test-coverage
- name: Test with coverage
  run: dotnet test --configuration Release --collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover
  
- name: Generate coverage report
  uses: codecov/codecov-action@v3
  with:
    files: './coverage.opencover.xml'
    fail_ci_if_error: true
    verbose: true

Steg 4: Sätt upp deploymentstrategier

Canary deployments minskar risk genom att gradvis rikta trafik till nya versioner:

# Azure DevOps med Canary-strategi
- task: AzureCLI@2
  inputs:
    azureSubscription: 'prod-sub'
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |
      az containerapp update \
        --name myapp \
        --resource-group prod-rg \
        --set-env-vars 'VERSION=$(Build.BuildNumber)' \
        --min-replicas 2 \
        --max-replicas 10

Blue-green deployments ger snabb rollback genom att ha två identiska produktionsmiljöer:

# GitHub Actions med blue-green strategi
- name: Deploy to blue environment
  run: |
    az webapp up --name myapp-blue --location westus
    
- name: Switch traffic
  run: |
    az traffic-manager profile update --name myapp-tm \
      --routing-method weighted \
      --alternate-dns-ttl 60

GitHub Actions vs Azure DevOps: Vad ska du välja?

Valet beror på flera faktorer. Här är en konkret jämförelse:

Aspekt GitHub Actions Azure DevOps
Integration Bäst med GitHub repos Kod-agnostiskt, Azure-integration
Prissättning Minutbaserat, gratis för OSS Liknande, obegränsat för OSS
Lärande-kurva Låg för GitHub-användare Brantare, mer omfattande
Enterprise-funktioner God, med GH Enterprise Utmärkt, inkluderar Boards, Artifacts
Containerstöd Inbyggt, Docker/Kubernetes Inbyggt, med ACR-integration
Säkerhet Fine-grained permissions, OIDC Azure AD-integration, RBAC
Marketplace 10 000+ actions 1 000+ tasks

Rekommendation: Om du primärt arbetar med GitHub och vill ha en enkel väg in i CI/CD, börja med GitHub Actions. Om du behöver komplett ALM (Application Lifecycle Management), Azure-integration, och avancerade release-gates, är Azure DevOps det naturliga valet. För organisationer med heterogena miljöer kan en hybridstrategi vara optimal: GitHub Actions för applikations-CI och Azure DevOps för release management och Azure-deployments.

Säkerhet och compliance i din CI/CD-pipeline

En automatiserad pipeline skapar också en attackyta. Säkra din pipeline genom att:

  1. Använd OpenID Connect (OIDC) istället för service credentials – eliminerar behovet av att lagra secrets
  2. Implementera least-privilege – varje jobb ska endast ha de permissions som krävs
  3. Skanna beroenden – integrera Snyk, Dependabot eller GitHub Advanced Security
  4. Signera artifacts – använd Sigstore eller Azure Attestation för att verifiera image-äkthet
  5. Audit trails – spara alla pipeline-logs enligt compliance-krav (ofta 1-7 år för finanssektorn)
# OIDC-konfiguration i GitHub Actions
permissions:
  id-token: write
  contents: read
  
- name: Azure Login
  uses: azure/login@v2
  with:
    client-id: ${{ secrets.AZURE_CLIENT_ID }}
    tenant-id: ${{ secrets.AZURE_TENANT_ID }}
    subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

Best practices för högpresterande CI/CD-pipelines

Baserat på erfarenheter från hundratals produktionsimplementationer:

  • Håll pipelines snabba – Mål under 10 minuter för fullständig pipeline. Använd caching aggressivt.
  • Parallelisera där möjligt – Kör enhetstester och bygg i parallella jobs
  • Fail fast – Placera snabba tester tidigt i pipelinen
  • Använd artifacts effektivt – Ladda upp endast nödvändiga filer, sätt expiration
  • Dokumentera undantag – Alla avvikelser från standard-processen ska dokumenteras i kode
  • Mät och optimera – Tracka ledtid, deployment frequency, och MTTR som KPIs

Kom igång idag

Att bygga en CI/CD-pipeline behöver inte vara överväldigande. Börja smått: automatisera bygget och testerna först, sedan deployment till en staging-miljö. När det fungerar stabilt, lägg till produktionsdeployment med lämpliga gates. Inom 4-6 veckor kan de flesta team ha en fullt automatiserad leveranskedja som reducerar release-tid med 80% och incidenter med 60%.

Både GitHub Actions och Azure DevOps erbjuder generösa free tiers som låter dig experimentera utan kostnad. Ciro Cloud kan hjälpa er med konsultation och implementation av er CI/CD-strategi, oavsett om ni föredrar GitHub Actions, Azure DevOps, eller en kombination av båda plattformarna.

Weekly cloud insights — free

Practical guides on cloud costs, security and strategy. No spam, ever.

Comments

Leave a comment