Back to "Moderna utsläppsstrategier med GitHub actions"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

CI/CD DevOps GitHub Actions

Moderna utsläppsstrategier med GitHub actions

Thursday, 04 December 2025

Kernprincipen: : gör släppen snabba och smärtfria, , och du kommer att släppa mer ofta. Detta är viktigt för agil utveckling. - snabb , tillförlitliga inplantningar skapar den snabba återkopplingsloop du behöver. ♫ . ♫ När inplanting är skrämmande eller långsamt ♫

Den här handboken omfattar de utsläppsstrategier som jag använder i produktionen, från enkel tag, -, till multi, -, paket-monorepopublicering och .. Alla exempel kommer från verkliga GitHub-aktioner arbetsflöden i detta arkiv.

Release strategier på en titt

Innan man dyker in i detaljer

Strategin bäst för komplexitet 3 vanliga i
Tag-baserad Applikationer , explicita utsläpp låga uppstartar , solo-devs МSK5 mogna lag
Filiala-baserad Kontinuett utplacering lågt Start-up МSK3 snabbt - rörande lag
GitFlow Regulerade versioner , flera versioner Hög
Trunk-based + Feature flags Höga -hastighetsteams Medel stora tekniker МSK4 mogna nystartare
Monorepo multi-package Bibliotekar , gemensama kodexbaser mellan МSK3 Plattenteams

Vad fungerar var

Startups & Små lag: Börja med tag-baserat eller ramverkt -baserad utnyttjandeM SK3 Säg det enkelt ♫ - du kan alltid lägga till komplexitet senare ♫. ♫ Trunk ♫

Företagande: Åtminstone kräver GitFlow eller liknande för noggrannhet , revīzijasspår M SK2 och utsläppshantering . Flera miljöer

Enkel utvecklare: etikett - baserat är idealt. trycka på etiketten

Platform/Library Teams: Bra monorepo-strategier med oberoende versionering per paket

Tag-Based Deployment

Den enklaste och mest tillförlitliga strategin

Miljötargetering

on:
  push:
    tags:
      - 'release-*'  # Production
      - 'local-*'    # Dev environment
- name: Build Docker image
  run: |
    TAG_NAME=${GITHUB_REF#refs/tags/}
    if [[ "$TAG_NAME" == local-* ]]; then
      docker build -t myapp:local .
    else
      docker build -t myapp:latest -t myapp:$(date +%s) .
    fi

Varför det fungerar: Enkel mental modell

# Deploy to production
git tag release-v2024.12.01 && git push origin release-v2024.12.01

# Deploy to dev
git tag local-feature-test && git push origin local-feature-test

Multi-Versionering av paket

För monorepos med flera publicierbara paket, använda tagpräfixer för att identifiera vilket paket man ska släppa

# Different workflows, different tag patterns
# umami-net.yml
on:
  push:
    tags: ['umamiv*.*.*']  # e.g., umamiv1.0.5

# fetchextension.yml
on:
  push:
    tags: ['fetchextension-v*.*.*']  # e.g., fetchextension-v1.2.0

Extrahera versionen och använda den hela tiden:

- name: Extract version
  run: echo "VERSION=${GITHUB_REF#refs/tags/umamiv}" >> $GITHUB_OUTPUT

- name: Build & Pack
  run: |
    dotnet build -c Release -p:Version=${{ steps.version.outputs.VERSION }}
    dotnet pack -c Release -p:PackageVersion=${{ steps.version.outputs.VERSION }}

För automatiska versioneringar, Minver beräknar versioner från Git tags:

<PackageReference Include="MinVer" Version="6.0.0" PrivateAssets="all" />
<PropertyGroup>
  <MinVerTagPrefix>umamiv</MinVerTagPrefix>
</PropertyGroup>

Filiala-baserad utpostning

Deploy automatiskt när koden landar på specifika grannar

on:
  push:
    branches: [main]      # → Production
    # branches: [develop] # → Staging

Förmågor: Inga manuella steg Olyckor: Oavsiktliga utpostningar möjliga , mindre explicit historia

Jag använder ett hybridt tillvägagångssätt - bygga på branch-puss | ( | CI-bekräftelse |), | men publicera bara på tag |

on:
  push:
    tags: ['scheduler-*']
    branches: [main, local]

jobs:
  build:
    # Always build
  publish:
    if: startsWith(github.ref, 'refs/tags/')  # Only publish on tags

Auto-Aktualiseringar med observatori

För självständiga utpostningar Observationstorn drar automatiskt upp nya bilder:

services:
  app:
    image: myapp:latest
    labels:
      - "com.centurylinklabs.watchtower.enable=true"

  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    command: --interval 300  # Check every 5 minutes

Deploymentflödet: Att trycka på tag → GitHub Actions bygger | | → | Springa till registret |

Kwaliteitssteg

Vinniga utspegningar är värdelösa om du utspegs bugs. Varje arbetsflöde bör inkludera grindar:

- name: Run tests
  run: dotnet test --configuration Release

- name: Build
  run: dotnet build --configuration Release

# Tests or build fail → workflow stops → no publish

För multi- -- -frameworkpaket - , -bygg alla mål - :

- run: dotnet build -c Release --framework net8.0
- run: dotnet build -c Release --framework net9.0

Passwordless Publishing med OIDC

Modernt tillvägagångssätt - inga hemligheter för att rotera , inga nycklar för att läcka

permissions:
  id-token: write
  contents: read

- uses: NuGet/login@v1
  with:
    user: 'myusername'

- run: dotnet nuget push *.nupkg --api-key ${{ steps.login.outputs.NUGET_API_KEY }}

GitHub utbyter sin OIDC-token för en kort NuGet API-kliv

Tillförselkedjorskedjan

Artifaktbescheinigunger bevisa att dina artefakter är byggda i CI, inte manipulerade med

permissions:
  id-token: write
  attestations: write

- uses: docker/build-push-action@v6
  id: push
  with:
    push: true
    tags: myapp:latest

- uses: actions/attest-build-provenance@v2
  with:
    subject-name: index.docker.io/myuser/myapp
    subject-digest: ${{ steps.push.outputs.digest }}
    push-to-registry: true

Konsumenter ser med: gh attestation verify oci://index.docker.io/myuser/myapp:latest --owner myuser

Detta uppnår SLSA-nivå 2. För nivån 3, använda återanvändbara arbetsflöden.

Föreställ omgivningar

Teams behöver intressenter för att förutse förändringar innan de går samman

Enterprise-metoden - Filialen -grundade förfogningsmiljöer

on:
  pull_request:
    types: [opened, synchronize]

- run: |
    BRANCH=$(echo ${{ github.head_ref }} | sed 's/[^a-zA-Z0-9]/-/g')
    docker build -t myapp:preview-$BRANCH .
    # Deploy to k8s namespace, cloud platform, etc.

Startup/solo-metod - Tunnelera din lokala maskin

# Cloudflare Tunnel (free)
cloudflared tunnel run --url http://localhost:5000 my-preview
# → https://my-preview.cfargotunnel.com

Eller använda Kabelvakt VPN för inre team-utgång till din dev-maskin.

Praktiska tips

Tag städ: Git-tag står kvar för alltid

git tag -d old-test-tag                      # Delete local
git push origin :refs/tags/old-test-tag      # Delete remote

Nameringskonventioner: Var konsekvent

  • release-YYYY.MM.DD för produktion
  • local-feature-name för dev
  • packagev1.2.3 för bibliotek

Hemligheter: Lagera i GitHub Secrets, aldrig i koden . Erforderliga hemligheter vanligtvis

  • DOCKER_HUB_ACCESS_TOKEN
  • NUGET_API_KEY ( eller använda OIDC
  • NPM_TOKEN

Monorepo-utveckling: Använda projektreferenser under utvecklingen , byta till paketreferens för användningskontroll

<ProjectReference Include="..\MyLib\MyLib.csproj" />
<!-- <PackageReference Include="MyLib" Version="1.0.0" /> -->

Gå till Kubernetes

Samma principer , olika verktyg

Docker Compose Kubernetes
Tydtorn ArgoCD / Flux
docker
Kontineruppstartning Rollingsoperation
Handlig rollback GitOps rollback

sammanfattning

  1. Börja enkelt: Tag-based deployment covers most needs
  2. Lägg till komplexitet när det behövs: Filialen -baserade, flertalig
  3. Automatiserade kvalitet-grindar: Test måste klaras innan de publiceras
  4. Aktivera rollback: Timestamped-tag eller GitOps historia
  5. Bevara din pipeline: OIDC för hemligheter
  6. Matcha din kontext: Solo dev ≠ startup ≠ enterprise

De arbetsflödena som visas här körs i detta arkiv - check .github/workflows/ för kompletta implementeringar.

Kom ihåg: Vinniga implementeringar är grunden till agil utveckling . Investera i din utsläppskedjor tidigt

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.