Ce que vous accomplirez
Vous construirez un pipeline de release qui transforme un tag Git en artefact déployé — signé, testé, versionné, et publié.
Le contrat
- Push d'un tag matchant
v*.*.*. - CI build, test, signe et publie.
- Une release GitHub est créée avec notes auto-générées.
- Le déploiement est journalisé.
Étape 1 : conventions de tag
git tag -a v1.4.0 -m "Release 1.4.0"
git tag -s v1.4.0 -m "Release 1.4.0"
Étape 2 : configurer le workflow
# .github/workflows/release.yml
name: release
on:
push:
tags: ['v*.*.*']
permissions:
contents: write
packages: write
id-token: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run build
- run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Étape 3 : auto-générer les notes de release
- name: Generate notes
id: notes
uses: orhun/git-cliff-action@v2
with:
config: cliff.toml
args: --latest --strip header
- name: Create release
uses: softprops/action-gh-release@v2
with:
body: ${{ steps.notes.outputs.content }}
generate_release_notes: true
Étape 4 : matrice de build pour releases multi-plateformes
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- run: cargo build --release
- uses: actions/upload-artifact@v4
with:
name: bin-${{ matrix.os }}
path: target/release/myapp*
Étape 5 : artefacts signés
- uses: sigstore/cosign-installer@v3
- run: |
cosign sign-blob --yes \
--output-certificate cert.pem \
--output-signature sig.bin \
dist/myapp-1.4.0.tgz
Étape 6 : release d'image Docker
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
push: true
tags: |
ghcr.io/${{ github.repository }}:${{ github.ref_name }}
ghcr.io/${{ github.repository }}:latest
Étape 7 : déployer après publish
- name: Deploy to production
run: ./scripts/deploy.sh
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
Étape 8 : notification
- name: Slack notify
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Released ${{ github.ref_name }} :rocket:"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
Étape 9 : canaux de pre-release
jobs:
release:
steps:
- id: classify
run: |
if [[ "${{ github.ref_name }}" =~ -(alpha|beta|rc) ]]; then
echo "tag=next" >> $GITHUB_OUTPUT
else
echo "tag=latest" >> $GITHUB_OUTPUT
fi
- run: npm publish --tag ${{ steps.classify.outputs.tag }}
Étape 10 : intégrer avec release-please
Étape 11 : tagger le SHA dans les artefacts
- name: Get short SHA
id: vars
run: echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- run: docker build -t myapp:${{ github.ref_name }} -t myapp:${{ steps.vars.outputs.sha }} .
Étape 12 : protection de tags
gh api -X POST repos/owner/repo/tags/protection \
-F pattern='v*.*.*'
Pièges courants
- Le pipeline tourne à chaque push.
- Force-push de tags après release.
- Secrets dans les logs CI.
- Build depuis main au push de tag.