docs(runbooks): add "new web app" setup runbook under doc/runbooks/

Document, as a tree-docs tree, the end-to-end procedure to stand up a new
web application on the Arcodange platform — a mechanic spread across the
factory, tools and app repos with non-trivial ordering dependencies.

Covers: Gitea repo creation (org-secret inheritance), Postgres DB + owner
role (factory/postgres/iac), platform Vault declaration (gitea_cicd_<app>
+ policies, tools/hashicorp-vault/iac), the app Helm chart (VSO dynamic
secrets via pgbouncer), the app Terraform (app_roles module), the CI
workflows (tofu apply + image build, incl. the copy-pasted role pitfall),
and ArgoCD registration (factory/argocd/values.yaml). Adds a naming-
conventions concept page and an ordered checklist.

Wires the legacy doc/adr "setup hello world web app" item and the factory
README to the runbook. New docs live under doc/ (singular) per the PR #8
convention.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 17:22:30 +02:00
parent 54b3092305
commit 8330d82225
14 changed files with 1048 additions and 3 deletions

View File

@@ -0,0 +1,108 @@
[Factory](../../../README.md) > [Doc](../../README.md) > [Runbooks](../README.md) > [Nouvelle application web](README.md) > **6. Workflows CI**
# 6. Les workflows CI (`.gitea/workflows/`)
> **Status:** ✅ Active
> **Upstream:** [1. Dépôt Gitea](01-gitea-repo.md) (secrets d'org), [3. Vault plateforme](03-vault-platform.md) (`gitea_cicd_<app>`)
> **Related:** [4. Chart Helm](04-helm-chart.md) · [5. Terraform de l'app](05-app-terraform.md) · [7. Enregistrement ArgoCD](07-argocd-register.md) · [Conventions de nommage](conventions.md)
---
## Summary
Deux workflows Gitea Actions vivent dans le dépôt : **`vault.yaml`** applique le Terraform de l'app (`iac/`) en s'authentifiant à Vault via OIDC, et **`dockerimage.yaml`** (optionnel) construit l'image et la pousse au registre Gitea. Le déploiement lui-même n'est pas dans la CI : c'est ArgoCD qui s'en charge ([étape 7](07-argocd-register.md)).
## `vault.yaml` — appliquer le `iac/` de l'app
Déclenché sur tout changement de `iac/*.tf`. Deux jobs : obtenir un JWT depuis Gitea, puis `tofu apply`.
```yaml
on:
workflow_dispatch: {}
push: { paths: ['iac/*.tf'] }
pull_request: { paths: ['iac/*.tf'] }
# job 1 : échange OIDC Gitea → JWT (script base64 fourni en secret d'org)
# run: echo -n "${{ secrets.vault_oauth__sh_b64 }}" | base64 -d | bash
# job 2 : lire les secrets de bootstrap puis appliquer
- name: read vault secret
uses: https://gitea.arcodange.lab/arcodange-org/vault-action.git@main
with:
url: https://vault.arcodange.lab
caCertificate: ${{ secrets.HOMELAB_CA_CERT }}
jwtGiteaOIDC: ${{ needs.gitea_vault_auth.outputs.gitea_vault_jwt }}
role: gitea_cicd_<app> # ← le rôle JWT de l'app (étape 3)
method: jwt
path: gitea_jwt
secrets: |
kvv1/google/credentials credentials | GOOGLE_BACKEND_CREDENTIALS ;
kvv1/gitea/tofu_module_reader ssh_private_key | TERRAFORM_SSH_KEY ;
- uses: actions/checkout@v4
- name: terraform apply
uses: dflook/terraform-apply@v1
with: { path: iac, auto_approve: true }
```
Les deux secrets lus servent au backend (clé GCS `GOOGLE_BACKEND_CREDENTIALS`) et au clone du module partagé en SSH (`TERRAFORM_SSH_KEY`, cf. [étape 5](05-app-terraform.md)).
> [!WARNING]
> **Piège du `role:` copié-collé.** Le `role:` du step `vault-action` **et** le `role` de `iac/providers.tf` doivent tous deux être `gitea_cicd_<app>`. L'exemple `erp` porte encore `role: gitea_cicd_webapp` dans son [`vault.yaml`](https://gitea.arcodange.lab/arcodange-org/erp/src/branch/main/.gitea/workflows/vault.yaml) (reliquat de copier-coller) alors que son `providers.tf` utilise bien `gitea_cicd_erp`. Vérifie et aligne sur le nom de **ton** app, sinon la CI lit/écrit avec la mauvaise identité.
## `dockerimage.yaml` — construire l'image (si image maison)
À n'ajouter **que** si l'app build sa propre image (pas pour une image publique comme `erp`/Dolibarr). Déclenché au push sur `main`, en ignorant `README.md` et `chart/**` (changer le chart ne reconstruit pas l'image).
```yaml
on:
push: { branches: [main], paths-ignore: ['README.md', 'chart/**'] }
jobs:
build-and-push-image:
steps:
- uses: docker/login-action@v3
with:
registry: gitea.arcodange.lab
username: ${{ github.actor }}
password: ${{ secrets.PACKAGES_TOKEN }} # secret d'org (étape 1)
- uses: actions/checkout@v4
- run: |
TAGS="latest ${{ github.ref_name }}"
docker build -t app .
for TAG in $TAGS; do
docker tag app gitea.arcodange.lab/${{ github.repository }}:$TAG
docker push gitea.arcodange.lab/${{ github.repository }}:$TAG
done
```
L'image atterrit donc en `gitea.arcodange.lab/arcodange-org/<app>:latest` — exactement ce que `image.repository` du chart référence ([étape 4](04-helm-chart.md)). Un `Dockerfile` multi-stage à la racine convient (cf. [`webapp/Dockerfile`](https://gitea.arcodange.lab/arcodange-org/webapp/src/branch/main/Dockerfile)).
## Vue d'ensemble
```mermaid
%%{init: {'theme': 'base'}}%%
flowchart TB
classDef ci fill:#059669,stroke:#047857,color:#fff
classDef out fill:#7c3aed,stroke:#6d28d9,color:#fff
PUSH["push sur main"]:::ci
PUSH -->|"iac/*.tf modifié"| TF["vault.yaml<br>OIDC → JWT → tofu apply iac/"]:::ci
PUSH -->|"code modifié"| IMG["dockerimage.yaml<br>build + push image"]:::ci
TF --> VR["creds/app + rôle K8s app + KV"]:::out
IMG --> REG["registre gitea.arcodange.lab/arcodange-org/app"]:::out
```
## Déploiement automatique sur nouvelle image
Pour qu'ArgoCD redéploie quand une nouvelle image est poussée, on n'ajoute **rien** dans la CI : ce sont les annotations `argocd-image-updater` posées à l'[étape 7](07-argocd-register.md) (stratégie `digest`) qui surveillent le tag `latest`.
## Notes / contraintes
- `concurrency: cancel-in-progress` est activé sur les deux workflows : un nouveau push annule le run précédent sur la même ref.
- Le `vault-action` est lui-même un dépôt Gitea (`arcodange-org/vault-action`) épinglé `@main`.
## Related
- [3. Vault plateforme](03-vault-platform.md) — d'où vient `gitea_cicd_<app>`.
- [5. Terraform de l'app](05-app-terraform.md) — ce que `vault.yaml` applique.
- [4. Chart Helm](04-helm-chart.md) — `image.repository` = l'image poussée ici.
- [7. Enregistrement ArgoCD](07-argocd-register.md) — déploie, et porte les annotations d'auto-update.