Le principe de base : faire relâcher rapidement et sans douleur, et vous relâcherez plus souvent. C'est essentiel pour le développement agile - des déploiements rapides et fiables créent la boucle de rétroaction rapide dont vous avez besoin. Lorsque le déploiement est effrayant ou lent, les équipes raffolent des changements, augmentant le risque.
Ce guide couvre les stratégies de diffusion que j'utilise en production, des déploiements simples basés sur des tags à l'édition monorepo multi-package. Actions GitHub les flux de travail dans ce dépôt.
Avant de plonger dans les détails, voici comment les stratégies communes se comparent:
Stratégie du mieux pour la complexité de l'information commune |----------|----------|------------|-----------| | Étiquette Applications, sorties explicites, startups Low, devs solo, équipes matures | Branche Déploiement continu | GitFlow Releases réglementées, versions multiples | Drapeaux basés sur le réseau + Caractéristiques Grande technologie, startups matures | Monorepo multi-emballages Librairies, bases de code partagées
Les startups et les petites équipes: Commencez par un déploiement basé sur les tags ou des branches. Gardez-le simple - vous pouvez toujours ajouter de la complexité plus tard. Le développement basé sur le réseau avec des drapeaux de fonctionnalités est populaire à l'échelle mais surkill pour les petites équipes.
Entreprise: Il faut souvent GitFlow ou similaire pour la conformité, les pistes d'audit et la gestion des rejets. Environnements multiples (dev, QA, mise en scène, prod) avec portes d'approbation.
Développeurs Solo: Tag-based est idéal. Poussez une étiquette, le déploiement se produit. Pas de cérémonie, pas de frais généraux.
Équipes de plate-forme/bibliothèque: Besoin de stratégies monorepo avec version indépendante par paquet. La version sémantique est critique pour les consommateurs en aval.
La stratégie la plus simple et la plus fiable. Différente balise préfixe la route vers différents environnements ou déclenche différentes actions.
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
Pourquoi ça marche ?: Modèle mental simple, déploiements explicites, retour facile via des balises horodatées.
# 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
Pour les monorepos avec plusieurs paquets publiables, utilisez les préfixes d'étiquettes pour identifier le paquet à publier:
# 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
Extraire la version et l'utiliser tout au long :
- 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 }}
Pour la version automatique, MinVer calcule les versions à partir des tags Git:
<PackageReference Include="MinVer" Version="6.0.0" PrivateAssets="all" />
<PropertyGroup>
<MinVerTagPrefix>umamiv</MinVerTagPrefix>
</PropertyGroup>
Déployer automatiquement lorsque le code atterrit sur des branches spécifiques. Commun dans les startups et les équipes en mouvement rapide.
on:
push:
branches: [main] # → Production
# branches: [develop] # → Staging
Points positifs: Pas d'étape manuelle, se déploie lors de la fusion Inconvénients: Déploiement accidentel possible, historique moins explicite
J'utilise une approche hybride - construire sur la poussée de branche (vérification CI), mais ne publier que sur les tags:
on:
push:
tags: ['scheduler-*']
branches: [main, local]
jobs:
build:
# Always build
publish:
if: startsWith(github.ref, 'refs/tags/') # Only publish on tags
Pour les déploiements auto-organisés, La Tour de Garde tire automatiquement de nouvelles images :
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
Débit de déploiement: Push tag → GitHub Actions builds → Push to registry → La Tour de Garde tire → Redémarrage des conteneurs. Temps total: ~5 minutes.
Les déploiements rapides sont inutiles si vous déployez des bogues. Chaque workflow doit inclure des portes :
- name: Run tests
run: dotnet test --configuration Release
- name: Build
run: dotnet build --configuration Release
# Tests or build fail → workflow stops → no publish
Pour les paquets multi-cadres, construire toutes les cibles:
- run: dotnet build -c Release --framework net8.0
- run: dotnet build -c Release --framework net9.0
Approche moderne - pas de secrets à tourner, pas de clés à fuite:
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 échange son jeton OIDC pour une clé d'API NuGet à courte durée de vie. Configurez la confiance sur NuGet.org pour l'activer.
Attestations d'artéfacts prouver que vos artefacts ont été construits dans CI, non falsifiés. De plus en plus requis par les entreprises.
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
Les consommateurs vérifient avec: gh attestation verify oci://index.docker.io/myuser/myapp:latest --owner myuser
Cela permet d'atteindre les objectifs suivants : SLSA de niveau 2. Pour le niveau 3, utiliser flux de travail réutilisables.
Les équipes ont besoin d'intervenants pour prévoir les changements avant la fusion.
Approche de l'entreprise - Environnements de prévisualisation basés sur les branches :
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.
Approche startup/solo - Tunnel votre machine locale:
# Cloudflare Tunnel (free)
cloudflared tunnel run --url http://localhost:5000 my-preview
# → https://my-preview.cfargotunnel.com
Ou utiliser Garde-fils VPN pour l'accès interne de l'équipe à votre dev machine.
Nettoyage des étiquettes: Des étiquettes git restent dans le coin pour toujours.
git tag -d old-test-tag # Delete local
git push origin :refs/tags/old-test-tag # Delete remote
Conventions relatives à la désignation: Soyez cohérent.
release-YYYY.MM.DD pour la productionlocal-feature-name pour devpackagev1.2.3 pour les bibliothèquesSecrets: A conserver dans Les secrets de GitHub, jamais en code. Secrets requis typiquement:
DOCKER_HUB_ACCESS_TOKENNUGET_API_KEY (ou utiliser OIDC)NPM_TOKENDéveloppement de Monorepo: Utiliser les références de projet pendant le développement, passer aux références de paquet pour la vérification du déploiement :
<ProjectReference Include="..\MyLib\MyLib.csproj" />
<!-- <PackageReference Include="MyLib" Version="1.0.0" /> -->
Mêmes principes, différents outils :
Constitué de Docker |----------------|------------| La Tour de Garde ArgoCD / Flux | Environnements docker-compose.yml Redémarrage du conteneur Rétrospective manuelle Rétrospective GitOps Rétrospective
Les workflows affichés ici s'exécutent dans ce dépôt - vérifier .github/workflows/ pour des implémentations complètes.
Rappelez-vous: Des déploiements rapides et fiables sont à la base d'un développement agile. Investissez tôt dans votre pipeline de libération.
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.