feat(infra): Terraform provisionne la VM, GitHub Actions continue de déployer

Le seul Terraform du dépôt installait un cluster k3s que rien ne consomme, et
sa racine ne passait même pas `terraform init` : depuis Terraform 1.x, un
provisioner `destroy` impose que tout le bloc `connection` ne lise que `self`,
et celui du module k3s lisait `var.*`. Il est corrigé en batissant la connexion
sur `triggers`, où ne figurent que l'adresse, le port, l'utilisateur et le
chemin de la clé : jamais la clé ni un mot de passe.

`environments/vm-eni` provisionne la machine qui porte la recette et la
production : Docker et le plugin Compose, `scripts/provision-host.sh`, puis
l'enregistrement du runner. Rien n'y construit d'image ni ne lance de
conteneur, et un `apply` n'interrompt pas la stack qui tourne. Le déploiement
continu ne bouge pas : `deploy.yml` reste le seul chemin de livraison.

`environments/dev` devient `k3s-cible`, parce qu'il provisionnait un cluster et
pas un environnement applicatif, et que `rec` et `prod` vivent sur la même
machine. `environments/prod`, dossier vide, disparaît.

`infra.yml` formate et valide chaque racine à chaque push : c'est l'absence
d'un tel job qui a laissé ce Terraform cassé sans que rien ne le dise. La
boucle parcourt `environments/*`, une racine ajoutée est couverte sans y
toucher.

ADR 0010 pour la frontière entre provisionnement et livraison, et la doc
d'architecture alignée dessus.
This commit is contained in:
Johan LEROY
2026-09-22 11:27:21 +02:00
parent be6be42947
commit 0db69fd023
22 changed files with 543 additions and 30 deletions
@@ -0,0 +1,84 @@
variable "ssh_host" {
type = string
description = "Adresse de la VM ENI qui porte les deux environnements (ADR 0009)."
}
variable "ssh_port" {
type = number
description = "Port SSH de la VM."
default = 22
}
variable "ssh_user" {
type = string
description = "Utilisateur SSH du provisionnement. Different de root, les commandes privilegiees sont prefixees par sudo."
default = "root"
}
variable "ssh_private_key_path" {
type = string
description = "Chemin local vers la cle privee SSH. L'authentification par mot de passe n'est volontairement pas prise en charge : une variable de mot de passe finit en clair dans le state ou dans les triggers."
sensitive = true
}
variable "proprietaire" {
type = string
description = "Utilisateur qui possede la racine et fait tourner le runner. Il doit exister sur la machine : git refuse les depots appartenant a un autre utilisateur, et un .env en 600 lui echapperait."
validation {
condition = can(regex("^[a-z_][a-z0-9_-]*$", var.proprietaire))
error_message = "proprietaire doit etre un nom d'utilisateur Unix valide."
}
}
variable "racine" {
type = string
description = "Dossier qui porte un clone du depot par environnement."
default = "/srv/enervision"
}
variable "depot_url" {
type = string
description = "URL de clonage du depot, passee a provision-host.sh."
default = "https://github.com/ineszang/ProjetPiscine_EnerVision.git"
}
variable "adresse_publique" {
type = string
description = "Adresse annoncee dans les certificats auto-signes. Vide : la premiere adresse de la VM."
default = ""
}
variable "runner_url" {
type = string
description = "Depot GitHub auquel le runner s'enregistre."
default = "https://github.com/ineszang/ProjetPiscine_EnerVision"
}
variable "runner_version" {
type = string
description = "Version d'actions-runner a installer, sans le v initial (ex: 2.330.0). Voir https://github.com/actions/runner/releases."
validation {
condition = can(regex("^[0-9]+\\.[0-9]+\\.[0-9]+$", var.runner_version))
error_message = "runner_version doit etre epinglee explicitement (ex: 2.330.0), sinon l'installation cesse d'etre reproductible."
}
}
variable "runner_token" {
type = string
description = "Jeton d'enregistrement du runner. Expire au bout d'une heure et ne vaut que pour une inscription : Parametres du depot > Actions > Runners > New self-hosted runner. Seul un administrateur du depot peut le creer."
sensitive = true
}
variable "runner_labels" {
type = string
description = "Libelles supplementaires du runner. deploy.yml cible [self-hosted, linux, eni-g3], les deux premiers etant poses par GitHub."
default = "eni-g3"
}
variable "runner_dossier" {
type = string
description = "Dossier d'installation du runner sur la machine."
default = "/opt/actions-runner"
}