Mettre en place la publication CI/CD¶
Ce que vous allez construire : Un pipeline automatisé qui publie un paquet .deb sur Repod à chaque fois que vous poussez un tag de version.
Durée : ~20 minutes Prérequis : Repod démarré et accessible depuis votre runner CI, un dépôt sur GitHub ou GitLab
Étape 1 — Créer un token API¶
Les systèmes CI/CD ne doivent jamais utiliser vos identifiants admin personnels. Créez un token dédié avec le rôle minimum requis (uploader).
- Aller dans Paramètres → Tokens API
- Cliquer sur Créer un token
- Remplir :
- Nom :
gitlab-ci-prod(ougithub-actions-prod) - Rôle :
uploader - Expiration : laisser vide (ou définir une date de rotation annuelle)
- Nom :
- Cliquer Générer
- Copier le token immédiatement — il commence par
repod_et ne sera plus jamais affiché
# Se connecter d'abord en tant qu'admin
TOKEN=$(curl -s -X POST http://REPO_HOST:8000/auth/token \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"YourPassword1!"}' \
| jq -r .access_token)
# Créer le token API
curl -s -X POST http://REPO_HOST:8000/auth/api-tokens \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"gitlab-ci-prod","roles":["uploader"]}' \
| jq .
Sauvegardez la valeur token de la réponse — vous en aurez besoin à l'étape suivante.
Un token par pipeline
Créez un token séparé pour chaque système CI (GitHub, GitLab, Jenkins…). Ainsi vous pouvez en révoquer un sans affecter les autres, et voir quel système a effectué quel upload dans les journaux d'audit.
Étape 2 — Stocker le token comme secret CI¶
- Aller dans votre dépôt → Settings → Secrets and variables → Actions
- Cliquer sur New repository secret
- Nom :
REPOD_TOKEN - Valeur :
repod_xxxxxxxxxx(votre token) - Ajouter également
REPOD_URL=https://repo.example.com(ouhttp://YOUR_HOST:8000)
- Aller dans votre projet → Settings → CI/CD → Variables
- Ajouter une variable :
- Clé :
REPOD_TOKEN - Valeur :
repod_xxxxxxxxxx - Type : Variable
- Protégée : ✅ (disponible uniquement sur les branches/tags protégés)
- Masquée : ✅ (masquée dans les logs)
- Clé :
- Ajouter
REPOD_URLde la même manière
Stockez le token dans le coffre de secrets de votre système CI et exposez-le via la variable d'environnement REPOD_TOKEN.
Étape 3 — Workflow GitHub Actions¶
Créer .github/workflows/publish.yml :
name: Build and publish package
on:
push:
tags:
- 'v*' # triggers on v1.0.0, v2.3.1, etc.
jobs:
publish:
runs-on: ubuntu-latest
strategy:
matrix:
distribution: [jammy, focal, noble] # publish to multiple distros
steps:
- uses: actions/checkout@v4
- name: Build .deb package
run: |
# Replace with your actual build command
make deb VERSION=${GITHUB_REF_NAME#v}
ls -lh *.deb
- name: Upload to Repod
env:
REPOD_TOKEN: ${{ secrets.REPOD_TOKEN }}
REPOD_URL: ${{ secrets.REPOD_URL }}
run: |
DEB_FILE=$(ls *.deb | head -1)
echo "Uploading $DEB_FILE to distribution ${{ matrix.distribution }}..."
RESPONSE=$(curl -s -w "\n%{http_code}" \
-X POST "$REPOD_URL/upload/" \
-H "Authorization: Bearer $REPOD_TOKEN" \
-F "file=@$DEB_FILE" \
-F "distribution=${{ matrix.distribution }}")
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | head -1)
echo "Response: $BODY"
if [ "$HTTP_CODE" != "200" ] && [ "$HTTP_CODE" != "201" ]; then
echo "Upload failed with HTTP $HTTP_CODE"
exit 1
fi
STATUS=$(echo "$BODY" | jq -r .status)
echo "Package status: $STATUS"
if [ "$STATUS" = "pending_review" ]; then
echo "⚠️ Package is pending CVE review by the security team."
# Don't fail — the upload succeeded, review is expected
fi
Stratégie de matrice
La stratégie matrix.distribution exécute le job d'upload une fois par distribution, en parallèle. Retirez les distributions que vous n'utilisez pas.
Étape 4 — Pipeline GitLab CI¶
Créer ou étendre .gitlab-ci.yml :
stages:
- build
- publish
variables:
REPOD_URL: "https://repo.example.com"
DISTRIBUTIONS: "jammy focal noble"
build-deb:
stage: build
image: debian:bookworm
script:
- apt-get update -qq && apt-get install -y build-essential devscripts
- make deb VERSION=${CI_COMMIT_TAG#v}
- ls -lh *.deb
artifacts:
paths:
- "*.deb"
expire_in: 1 day
only:
- tags
publish-to-repod:
stage: publish
image: curlimages/curl:latest
needs: [build-deb]
script:
- DEB_FILE=$(ls *.deb | head -1)
- |
for DIST in $DISTRIBUTIONS; do
echo "Publishing $DEB_FILE to $DIST..."
curl -sf -X POST "$REPOD_URL/upload/" \
-H "Authorization: Bearer $REPOD_TOKEN" \
-F "file=@$DEB_FILE" \
-F "distribution=$DIST" \
|| { echo "Failed to upload to $DIST"; exit 1; }
echo "✅ Published to $DIST"
done
only:
- tags
environment:
name: production
Stockez REPOD_TOKEN dans Settings → CI/CD → Variables (masquée + protégée).
Étape 5 — Script shell générique¶
Pour Jenkins, Drone, Woodpecker, ou tout autre système :
#!/usr/bin/env bash
# Usage: ./scripts/publish-deb.sh mypackage_1.0.0_amd64.deb jammy
set -euo pipefail
DEB_FILE="${1:?Usage: $0 <file.deb> <distribution>}"
DISTRIBUTION="${2:?Usage: $0 <file.deb> <distribution>}"
REPOD_URL="${REPOD_URL:?REPOD_URL env var not set}"
REPOD_TOKEN="${REPOD_TOKEN:?REPOD_TOKEN env var not set}"
echo "📦 Publishing $DEB_FILE → $DISTRIBUTION"
RESPONSE=$(curl -sf -X POST "$REPOD_URL/upload/" \
-H "Authorization: Bearer $REPOD_TOKEN" \
-F "file=@$DEB_FILE" \
-F "distribution=$DISTRIBUTION")
STATUS=$(echo "$RESPONSE" | jq -r .status)
echo "✅ Upload complete — status: $STATUS"
if [ "$STATUS" = "pending_review" ]; then
echo "⚠️ Security team review required before this package is published."
fi
Vérifier un upload réussi¶
Après l'exécution de votre pipeline, vérifiez que le paquet est disponible :
# Vérifier via l'API
curl -s -H "Authorization: Bearer $REPOD_TOKEN" \
"$REPOD_URL/packages/?q=your-package-name" | jq .
# Vérifier le journal d'audit (dernière entrée d'upload)
curl -s -H "Authorization: Bearer $REPOD_TOKEN" \
"$REPOD_URL/artifacts/audit/logs" | jq '.[-1]'
Dans l'interface web, allez dans Packages et recherchez le nom de votre paquet.
Bonnes pratiques¶
| Pratique | Pourquoi |
|---|---|
| Un token API par système CI | Isole le rayon d'impact si un token fuite ; piste d'audit séparée par système |
Utiliser uniquement le rôle uploader |
La CI n'a pas besoin d'approuver des CVE ou de gérer des utilisateurs |
| Définir une date d'expiration | Faire tourner les tokens chaque année ; poser un rappel calendrier |
Vérifier status dans la réponse |
pending_review signifie que des CVE ont été trouvées — alertez votre équipe sécurité |
| Ne jamais logger le token | Masquez-le dans votre système CI ; utilisez des secrets, jamais de valeur en dur |
| Tester les uploads sur une distribution de staging d'abord | Utilisez jammy-staging avant de promouvoir vers jammy |
Étapes suivantes¶
- Référence API → — documentation complète de l'API d'upload
- Faire tourner les tokens API → — procédure de rotation annuelle des tokens
- Workflow de revue CVE → — ce qui se passe quand le pipeline signale un paquet