Ce site est construit avec Lume puis déployé sur Alibaba
Cloud OSS, avec Alibaba Cloud CDN en frontal. La chaîne de
déploiement reste volontairement compacte : un workflow
GitHub, Deno disponible sur le runner, et une action
personnalisée qui restaure un cache local de build, exécute
le build, synchronise OSS et nettoie :
frenchvandal/aliyun-oss-cdn-sync-action.
Je cherche désormais cinq propriétés en même temps : des identifiants à durée de vie courte, des builds réchauffés sur des runners neufs, des uploads prévisibles, des en-têtes de cache cohérents avec les fichiers livrés, et une cohérence de cache automatique. Cette configuration me donne les cinq sans ajouter de scripts de déploiement propres à chaque dépôt.
Pipeline en un coup d’œil
En régime de production nominal, le workflow de ce dépôt fait maintenant trois choses :
- Récupère le dépôt.
-
Installe Deno avec la version verrouillée dans
.tool-versionset active le cache outillage du runner. -
Exécute l’action de synchronisation OSS/CDN, qui restaure
_cache, lancedeno task build, synchronise_site, rafraîchit le CDN et nettoie.
À ce stade, ce build fingerprint aussi la feuille partagée
et les feuilles critiques par route, retire les source maps
et supprime les fichiers optionnels de Pagefind qui ne sont
plus référencés par le HTML final avant la synchro de
_site.
name: Deploy static content to OSS
on:
push:
branches: ["master"]
workflow_dispatch:
permissions:
contents: read
id-token: write
concurrency:
group: "oss-deploy"
cancel-in-progress: true
jobs:
deploy:
environment:
name: development
runs-on: macos-26
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup Deno environment
uses: denoland/setup-deno@v2
with:
deno-version-file: .tool-versions
cache: true
- name: Deploy to Alibaba Cloud OSS
uses: frenchvandal/aliyun-oss-cdn-sync-action@master
with:
role-oidc-arn: ${{ secrets.ALIBABA_CLOUD_ROLE_ARN }}
oidc-provider-arn: ${{ secrets.ALIBABA_CLOUD_OIDC_PROVIDER_ARN }}
role-session-name: ${{ github.run_id }}
role-session-expiration: 3600
cache-enabled: true
cache-key: >-
lume-cache-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('deno.lock') }}-${{ hashFiles('_cache/**/*') || 'empty' }}
cache-restore-keys: |
lume-cache-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('deno.lock') }}-
lume-cache-${{ runner.os }}-${{ runner.arch }}-
input-dir: _site
bucket: ${{ secrets.OSS_BUCKET }}
region: ${{ secrets.OSS_REGION }}
audience: ${{ github.repository_id }}
cdn-enabled: true
cdn-base-url: ${{ secrets.OSS_CDN_BASE_URL }}
cdn-actions: refresh
build-command: deno task build
Dans ce dépôt, j’utilise maintenant cdn-actions:
refresh. L’action supporte toujours refresh,preload, mais le workflow de ce site
n’active plus le preload à chaque déploiement.
Pourquoi OIDC plutôt que des clés d’accès
L’action utilise GitHub OIDC pour endosser un rôle RAM
Alibaba Cloud à l’exécution. Aucune clé d’accès longue durée
n’est stockée dans le dépôt. Le workflow n’a besoin que de
id-token: write, de l’ARN du rôle RAM et de
l’ARN du fournisseur OIDC.
L’authentification est désormais strictement OIDC : l’action ne retombe pas sur des access keys statiques passées en entrée ou via l’environnement si la prise de rôle échoue.
La configuration actuelle transmet aussi
audience: ${{ github.repository_id }}. GitHub
peut émettre un ID token avec une audience personnalisée, et
Alibaba Cloud RAM peut valider cette valeur aud
par rapport aux Client ID configurés sur le fournisseur
d’identité OIDC et dans la trust policy du rôle. La
frontière de confiance est donc plus resserrée qu’avec
l’audience par défaut seule.
Fonctionnement interne de l’action
L’action est découpée en trois phases :
- pre : endosse le rôle RAM via OIDC et stocke des identifiants temporaires dans l’état de l’action.
-
main : restaure éventuellement le
dossier local
_cache, exécutebuild-command, upload les fichiers locaux sur OSS, applique les en-têtes de cache et déclenche les actions CDN si elles sont activées. -
post : compare les objets distants
sous le préfixe cible avec les fichiers locaux produits
par le build, supprime les orphelins côté distant,
rafraîchit au besoin les URL supprimées, écrit des résumés
d’exécution CDN et peut sauvegarder
_cachesicache-keyest configuré.
La phase de nettoyage s’exécute avec post-if:
always(), donc elle se lance même si des étapes
précédentes échouent. Le nettoyage, les appels CDN et la
restauration ou sauvegarde du cache sont volontairement non
bloquants : les avertissements sont journalisés, mais
des incidents CDN ou cache transitoires n’interrompent pas
le déploiement.
Upload, cache, quota et contrôle de dérive
Quelques détails d’implémentation comptent pour la fiabilité :
-
build-commands’exécute dans l’action avant tout upload OSS ou appel CDN. -
Si
cache-enabledvauttrueet quecache-keyest configuré,_cacheest restauré avant le build et un nouvel instantané peut être sauvegardé pendantpost. -
cache-enabledne contrôle que la restauration : je peux donc neutraliser le warm cache temporairement sans perdre la sauvegarde de cache en post-step. -
Les uploads sont parallélisés via
max-concurrency. -
Un throttling global d’API est appliqué avec
api-rps-limit. - Chaque upload de fichier est retenté jusqu’à trois fois avant d’être marqué en échec.
-
Les échecs partiels d’upload remontent via
failed-countet le résumé du job GitHub Actions au lieu d’être noyés dans les logs. -
L’étape d’upload écrit désormais automatiquement des
en-têtes
Cache-Control: les fichiers HTML etsw.jssont revalidés de manière agressive, les assets hashés sont envoyés comme immuables, et les ressources statiques courantes reçoivent des fenêtres de revalidation plus courtes au lieu d’une politique unique pour tout. -
cdn-actionsn’accepte querefreshourefresh,preload; si le CDN est activé et que la valeur est vide ou invalide, l’action retombe surrefresh. - L’action vérifie le quota CDN restant avant de soumettre des lots de refresh ou de preload.
- La suppression d’objets OSS peut déclencher un refresh CDN des URL supprimées, ce qui réduit les fenêtres de cache obsolète et limite la dérive des objets dans le temps.
- L’action écrit aussi un résumé GitHub Actions pour le déploiement, le nettoyage et l’état des tâches CDN.
Ce dernier point est facile à sous-estimer : l’upload seul ne suffit pas pour un site statique qui évolue. Il faut aussi gérer la suppression et l’invalidation de cache des objets qui ne devraient plus exister.
Permissions RAM minimales
Au niveau des politiques, le rôle a besoin de permissions OSS sur le scope du bucket cible pour lister, uploader et supprimer les objets. Côté CDN, ce workflow a besoin des permissions de refresh ainsi que des API de lecture utilisées pour les contrôles de quota et le suivi des tâches. Si le preload est activé, il faut y ajouter la permission correspondante. La trust policy doit autoriser le fournisseur OIDC GitHub à endosser le rôle de déploiement.
Je conserve ce rôle comme rôle de déploiement dédié, sans le mélanger à des permissions opérationnelles plus larges.
Réutiliser l’action dans d’autres dépôts
L’action est publiée et réutilisable : github.com/frenchvandal/aliyun-oss-cdn-sync-action.
Ce dépôt suit actuellement @master parce que je
fais évoluer le site et l’action ensemble. Dans un autre
dépôt, j’épinglerais plutôt @v1, voire un SHA
de commit complet. Je laisse maintenant l’action piloter le
build et le cycle de vie de _cache, ce qui
raccourcit encore le workflow consommateur.
Pour moi, le résultat clé reste le même : des déploiements prévisibles. Restauration du cache, build, sync, refresh, cleanup, terminé.