CI : Deployment
This commit is contained in:
204
.gitea/workflows/release.yml
Normal file
204
.gitea/workflows/release.yml
Normal file
@@ -0,0 +1,204 @@
|
||||
name: release
|
||||
|
||||
# Construit l'image du plan de contrôle et publie le bundle d'agent.
|
||||
#
|
||||
# Prérequis côté Gitea :
|
||||
# - un secret REGISTERYKEY (jeton d'accès avec les portées repository + package)
|
||||
# - les paquets activés sur l'instance
|
||||
# - un runner ubuntu-latest ayant accès au socket Docker
|
||||
# - un runner windows-latest (test de fumée de l'agent)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
tags: ['v*']
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
IMAGE_NAME: stream-control-server
|
||||
PACKAGE_NAME: stream-control-agent
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.meta.outputs.version }}
|
||||
registry: ${{ steps.meta.outputs.registry }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '24'
|
||||
|
||||
# --- Identité de la version -----------------------------------------
|
||||
- name: Calculer version et registre
|
||||
id: meta
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Une étiquette v1.2.3 donne 1.2.3 ; sinon 0.1.0-<sha court>.
|
||||
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
||||
VERSION="${GITHUB_REF#refs/tags/}"
|
||||
VERSION="${VERSION#v}"
|
||||
else
|
||||
VERSION="0.1.0-${GITHUB_SHA:0:7}"
|
||||
fi
|
||||
|
||||
# L'hôte du registre est celui de l'instance Gitea. La variable
|
||||
# REGISTRY_HOST permet de le forcer (instance derrière un autre nom).
|
||||
REGISTRY="${{ vars.REGISTRY_HOST }}"
|
||||
if [ -z "$REGISTRY" ]; then
|
||||
REGISTRY="${GITHUB_SERVER_URL#http://}"
|
||||
REGISTRY="${REGISTRY#https://}"
|
||||
fi
|
||||
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "registry=$REGISTRY" >> "$GITHUB_OUTPUT"
|
||||
echo "Version $VERSION → registre $REGISTRY"
|
||||
|
||||
# --- Qualité ---------------------------------------------------------
|
||||
- name: Installer les dépendances
|
||||
run: npm ci
|
||||
|
||||
- name: Contrôle de types
|
||||
run: npm run typecheck
|
||||
|
||||
- name: Compiler
|
||||
run: npm run build
|
||||
|
||||
- name: Produire le bundle d'agent
|
||||
run: npm run bundle -w @stream-control/agent
|
||||
|
||||
# Un bundle qui ne démarre pas ne doit jamais être publié. Le serveur est
|
||||
# volontairement injoignable ici : on vérifie que le diagnostic s'exécute.
|
||||
- name: Vérifier le bundle (Linux)
|
||||
env:
|
||||
AGENT_TOKEN: ci-smoke-test
|
||||
SERVER_URL: ws://127.0.0.1:1/ws/agent
|
||||
run: |
|
||||
set -euo pipefail
|
||||
OUT="$(node packages/agent/dist-bundle/agent.cjs --check 2>&1 || true)"
|
||||
echo "$OUT"
|
||||
echo "$OUT" | grep -q 'obs-websocket' || { echo 'Diagnostic incomplet'; exit 1; }
|
||||
|
||||
# --- Image du plan de contrôle ---------------------------------------
|
||||
- name: Authentification au registre
|
||||
run: |
|
||||
echo "${{ secrets.REGISTERYKEY }}" \
|
||||
| docker login "${{ steps.meta.outputs.registry }}" \
|
||||
--username "${{ github.repository_owner }}" --password-stdin
|
||||
|
||||
- name: Construire et pousser l'image
|
||||
run: |
|
||||
set -euo pipefail
|
||||
BASE="${{ steps.meta.outputs.registry }}/${{ github.repository_owner }}/${IMAGE_NAME}"
|
||||
VERSION="${{ steps.meta.outputs.version }}"
|
||||
|
||||
docker build \
|
||||
--tag "$BASE:$VERSION" \
|
||||
--tag "$BASE:sha-${GITHUB_SHA:0:7}" \
|
||||
--label "org.opencontainers.image.revision=$GITHUB_SHA" \
|
||||
--label "org.opencontainers.image.version=$VERSION" \
|
||||
--label "org.opencontainers.image.source=$GITHUB_SERVER_URL/${{ github.repository }}" \
|
||||
.
|
||||
|
||||
docker push "$BASE:$VERSION"
|
||||
docker push "$BASE:sha-${GITHUB_SHA:0:7}"
|
||||
|
||||
# :latest ne suit que main et les étiquettes, jamais une branche de travail.
|
||||
if [[ "$GITHUB_REF" == refs/heads/main || "$GITHUB_REF" == refs/tags/* ]]; then
|
||||
docker tag "$BASE:$VERSION" "$BASE:latest"
|
||||
docker push "$BASE:latest"
|
||||
fi
|
||||
|
||||
# --- Bundle d'agent et scripts d'installation ------------------------
|
||||
- name: Publier les artefacts d'agent
|
||||
run: |
|
||||
set -euo pipefail
|
||||
API="${GITHUB_SERVER_URL}/api/packages/${{ github.repository_owner }}/generic/${PACKAGE_NAME}"
|
||||
AUTH="${{ github.repository_owner }}:${{ secrets.REGISTERYKEY }}"
|
||||
VERSION="${{ steps.meta.outputs.version }}"
|
||||
|
||||
publish() {
|
||||
local version="$1" file="$2" path="$3"
|
||||
curl -sS -f -X PUT --user "$AUTH" --upload-file "$path" \
|
||||
"$API/$version/$file"
|
||||
echo " publié : $version/$file"
|
||||
}
|
||||
|
||||
# Version immuable, tracée.
|
||||
publish "$VERSION" agent.cjs packages/agent/dist-bundle/agent.cjs
|
||||
publish "$VERSION" install-agent.sh deploy/install-agent.sh
|
||||
publish "$VERSION" install-agent.ps1 deploy/install-agent.ps1
|
||||
|
||||
# Alias « latest », que visent les commandes d'installation. Le registre
|
||||
# générique refuse d'écraser un fichier : on supprime la version d'abord.
|
||||
if [[ "$GITHUB_REF" == refs/heads/main || "$GITHUB_REF" == refs/tags/* ]]; then
|
||||
curl -sS -X DELETE --user "$AUTH" "$API/latest" >/dev/null || true
|
||||
publish latest agent.cjs packages/agent/dist-bundle/agent.cjs
|
||||
publish latest install-agent.sh deploy/install-agent.sh
|
||||
publish latest install-agent.ps1 deploy/install-agent.ps1
|
||||
fi
|
||||
|
||||
- name: Récapitulatif
|
||||
run: |
|
||||
BASE="${{ steps.meta.outputs.registry }}/${{ github.repository_owner }}/${IMAGE_NAME}"
|
||||
{
|
||||
echo "### Publié"
|
||||
echo ""
|
||||
echo "| Artefact | Référence |"
|
||||
echo "| --- | --- |"
|
||||
echo "| Image | \`$BASE:${{ steps.meta.outputs.version }}\` |"
|
||||
echo "| Agent | \`${PACKAGE_NAME}/${{ steps.meta.outputs.version }}/agent.cjs\` |"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
# Le bundle doit démarrer sur Windows : chemins, PowerShell, résolution de
|
||||
# modules. Un test sur Linux seul ne couvre pas ces différences.
|
||||
verify-windows:
|
||||
runs-on: windows-latest
|
||||
needs: build
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Le script d'installation Windows n'est exécutable que sur Windows :
|
||||
# ce contrôle de syntaxe est la seule barrière avant qu'il n'atterrisse
|
||||
# sur une VM de production.
|
||||
- name: Valider la syntaxe du script d'installation
|
||||
shell: pwsh
|
||||
run: |
|
||||
$errors = $null
|
||||
[System.Management.Automation.Language.Parser]::ParseFile(
|
||||
(Resolve-Path 'deploy/install-agent.ps1'), [ref]$null, [ref]$errors) | Out-Null
|
||||
if ($errors) {
|
||||
$errors | ForEach-Object { Write-Host "$($_.Extent.StartLineNumber): $($_.Message)" }
|
||||
throw "$($errors.Count) erreur(s) de syntaxe dans install-agent.ps1"
|
||||
}
|
||||
Write-Host 'install-agent.ps1 : syntaxe valide.'
|
||||
|
||||
- name: Récupérer le bundle publié
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$url = "$env:GITHUB_SERVER_URL/api/packages/${{ github.repository_owner }}/generic/$env:PACKAGE_NAME/${{ needs.build.outputs.version }}/agent.cjs"
|
||||
$pair = "${{ github.repository_owner }}:${{ secrets.REGISTERYKEY }}"
|
||||
$auth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($pair))
|
||||
Invoke-WebRequest -Uri $url -Headers @{ Authorization = "Basic $auth" } -OutFile agent.cjs
|
||||
Write-Host "Bundle récupéré : $((Get-Item agent.cjs).Length) octets"
|
||||
|
||||
- name: Exécuter le diagnostic
|
||||
shell: pwsh
|
||||
env:
|
||||
AGENT_TOKEN: ci-smoke-test
|
||||
SERVER_URL: ws://127.0.0.1:1/ws/agent
|
||||
run: |
|
||||
$out = (& node agent.cjs --check 2>&1 | Out-String)
|
||||
Write-Host $out
|
||||
# Le serveur est injoignable par construction : on valide que le
|
||||
# diagnostic s'est déroulé, pas son verdict.
|
||||
foreach ($marker in @('obs-websocket', 'powershell')) {
|
||||
if ($out -notmatch [regex]::Escape($marker)) {
|
||||
throw "Diagnostic incomplet : « $marker » absent de la sortie"
|
||||
}
|
||||
}
|
||||
Write-Host 'Bundle fonctionnel sous Windows.'
|
||||
Reference in New Issue
Block a user