Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
a9786a2
docs(devcontainer): un poste de développement qui n'installe rien — c…
lostmind84 Aug 11, 2026
b6711f9
docs(devcontainer): le plan d'implementation, banc avant fichiers
lostmind84 Aug 11, 2026
ea32250
test(devcontainer): un lecteur de JSONC qui sait ou sont les chaines
lostmind84 Aug 11, 2026
a1c7705
test(devcontainer): le banc qui refuse un quatrieme endroit ou vivent…
lostmind84 Aug 11, 2026
2fc9ee7
feat(devcontainer): une image ou six des sept verifications de la CI …
lostmind84 Aug 11, 2026
7187972
fix(devcontainer): deux fuites root et quatre commentaires qui affirm…
lostmind84 Aug 11, 2026
42e7606
fix(deploy): le banc systemd verifie une copie, pas le bind mount
lostmind84 Aug 11, 2026
2dbf828
build(devcontainer): epingler les quatre features par empreinte
lostmind84 Aug 11, 2026
6bcb536
fix(devcontainer): declarer le depot monte comme safe.directory pour git
lostmind84 Aug 11, 2026
dd46d72
docs(devcontainer): clarifier deux commentaires qui pretaient a confu…
lostmind84 Aug 11, 2026
05ae6df
docs(devcontainer): deux chemins, et ce que le conteneur ne juge pas
lostmind84 Aug 11, 2026
a8c7eef
docs(devcontainer): l'intro annonce le cout des deux chemins, pas d'u…
lostmind84 Aug 11, 2026
7647faa
test(devcontainer): fermer trois portes ouvertes par la revue finale
lostmind84 Aug 11, 2026
f134856
fix(devcontainer): un volume par conteneur, un piege sous set -e, un …
lostmind84 Aug 11, 2026
eac9707
docs(devcontainer): deux politiques d'epinglage, et ce qu'est le fich…
lostmind84 Aug 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# L'image du poste de développement — voir devcontainer.json à côté.
#
# Trois paquets, et chacun tient un banc précis. Alléger cette liste est un changement qui
# a l'air raisonnable ; deploy/devcontainer_test.go le refuse et dit ce qu'il coûterait.
FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04

# build-essential : gcc ET make. La passe `-race` de `make test` EXIGE ThreadSanitizer,
# donc cgo — sans lui elle se saute, et on perd la seule vérification
# automatique des trois invariants de concurrence du Hub (important-3).
# Et post-create.sh appelle `make -s golangci-version` pour lire cette
# version : réduire ce paquet à gcc seul casserait le script, qui a besoin
# de make autant que de gcc.
# zip : la cible `release` du Makefile empaquette avec.
# systemd : pour `systemd-analyze` seul — il ne tourne pas ici. Sans lui,
# TestTheUnitIsValidAccordingToSystemdItself se saute, et plus rien ne
# demande à systemd lui-même s'il accepte les unités livrées.
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get install -y --no-install-recommends \
build-essential \
zip \
systemd \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
24 changes: 24 additions & 0 deletions .devcontainer/devcontainer-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"features": {
"ghcr.io/devcontainers/features/go:1": {
"version": "1.3.4",
"resolved": "ghcr.io/devcontainers/features/go@sha256:d85e921f91b41340055bb12b325d9d551170ed04b3b832e33530bf42f167c032",
"integrity": "sha256:d85e921f91b41340055bb12b325d9d551170ed04b3b832e33530bf42f167c032"
},
"ghcr.io/devcontainers/features/node:1": {
"version": "1.7.1",
"resolved": "ghcr.io/devcontainers/features/node@sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6",
"integrity": "sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6"
},
"ghcr.io/devcontainers/features/powershell:1": {
"version": "1.5.1",
"resolved": "ghcr.io/devcontainers/features/powershell@sha256:df7baa89598c93bfd15808641d9ec9eb03e0ccdf52e5de4cbbce9ab2d9755d18",
"integrity": "sha256:df7baa89598c93bfd15808641d9ec9eb03e0ccdf52e5de4cbbce9ab2d9755d18"
},
"ghcr.io/devcontainers/features/python:1": {
"version": "1.8.0",
"resolved": "ghcr.io/devcontainers/features/python@sha256:fbcad6955caeecc5ad3f7886baf652e25cba5225a6c4c2287c536de2e5607511",
"integrity": "sha256:fbcad6955caeecc5ad3f7886baf652e25cba5225a6c4c2287c536de2e5607511"
}
}
}
73 changes: 73 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// OpenScale — le poste de développement en conteneur.
//
// CE FICHIER EST UNE SECONDE PORTE. Le chemin sans conteneur — `make`, `make.ps1` — reste
// la référence, et c'est lui que la CI exécute. Rien ici ne doit devenir un passage obligé.
//
// AUCUN NUMÉRO DE VERSION N'EST DÉCIDÉ ICI. Go vient de `go.mod` et de `ci.yml`, Node de
// `ci.yml`, Python de `docs.yml` — et `deploy/devcontainer_test.go` compare les trois
// premières dans les deux sens. golangci-lint n'est pas comparée : elle est INTERDITE
// D'ÉCRITURE ici et lue dans le `Makefile`, une garantie plus forte qu'une comparaison.
// Une version modifiée ici sans l'être là-bas rougit.
//
// Ce que ce conteneur NE JUGE PAS : les scripts d'installation sous Windows PowerShell 5.1.
// Un conteneur Linux n'a que pwsh 7, qui n'est pas le shell d'un poste de balance. Le job
// « scripts » de ci.yml est le seul endroit où ils sont exécutés pour de bon.
{
"name": "OpenScale",
"build": { "dockerfile": "Dockerfile" },

"features": {
"ghcr.io/devcontainers/features/go:1": { "version": "1.26.5" },
"ghcr.io/devcontainers/features/node:1": { "version": "22" },
"ghcr.io/devcontainers/features/python:1": { "version": "3.13" },
// pwsh 7 ANALYSE les .ps1 — `powershellPaths` les lit sous tout shell présent, et une
// faute de syntaxe grossière rougit donc ici plutôt qu'en CI. Il ne les EXÉCUTE pas :
// `requireWindowsToRunCommonPs1` s'y oppose, et il a raison.
"ghcr.io/devcontainers/features/powershell:1": {}
},

// "vscode" est ici le nom d'un COMPTE UNIX — uid 1000, sans mot de passe — livré par
// l'image de base mcr.microsoft.com/devcontainers/base. Rien à voir avec l'éditeur : ce
// conteneur tourne identiquement sous VS Code, un fork, ou la CLI seule.
//
// Non root, et ce n'est pas de l'hygiène : TestADirectoryTheServiceCanReadButNotWriteIsRefused
// se saute sous root — et se saute aussi sous Windows. Un conteneur root laisserait cette
// branche couverte par rien, en restant vert.
"remoteUser": "vscode",

// Les caches sont dans des volumes et non dans le dossier monté : sous Windows, le bind
// coûte ×29 sur les métadonnées (143 ms contre 5 ms pour parcourir 577 fichiers). Sortis
// du bind, ils ne paient plus cette taxe, et la lenteur ne porte que sur les sources.
"containerEnv": {
"GOPATH": "/home/vscode/go",
"GOMODCACHE": "/home/vscode/go/pkg/mod",
"GOCACHE": "/home/vscode/.cache/go-build"
},
"remoteEnv": { "PATH": "${containerEnv:PATH}:/home/vscode/go/bin" },
// GOMODCACHE et GOCACHE restent partagés entre deux conteneurs OpenScale ouverts en même
// temps : leur contenu est adressé par version, l'outil Go verrouille ce qu'il lit, et le
// partage n'est qu'un gain. web/node_modules ne peut pas suivre la même règle — un dépôt
// principal et un arbre de revue ouverts ensemble peuvent avoir des package-lock.json
// différents, et le `npm ci` de l'un viderait et reconstruirait le dossier de l'autre, en
// silence. ${devcontainerId} isole ce volume par conteneur.
"mounts": [
"source=openscale-gomodcache,target=/home/vscode/go/pkg/mod,type=volume",
"source=openscale-gocache,target=/home/vscode/.cache/go-build,type=volume",
"source=openscale-node-modules-${devcontainerId},target=${containerWorkspaceFolder}/web/node_modules,type=volume"
],

"postCreateCommand": "bash .devcontainer/post-create.sh",

// La clé customizations.vscode est IGNORÉE par tout ce qui n'est pas VS Code ou l'un de
// ses forks (Cursor, Windsurf...) : sa présence n'oblige à rien qui ouvre ce conteneur
// autrement, CLI comprise.
"customizations": {
"vscode": {
"extensions": [
"golang.go",
"svelte.svelte-vscode",
"ms-vscode.powershell"
]
}
}
}
61 changes: 61 additions & 0 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/sh
# Ce qui s'installe une fois l'image construite.
#
# Ce fichier est commité en LF, et .gitattributes l'impose (`*.sh text eol=lf`) — la règle
# reste vraie ici, mais pas par le mécanisme qui l'a fait poser sur install.sh : ce shebang
# n'est jamais consulté, devcontainer.json lance ce fichier par `bash .devcontainer/post-
# create.sh`, pas par exécution directe. Un CRLF ici sortirait donc en `$'\r': command not
# found` de bash, pas en « Syntax error: word unexpected » de dash.
set -eu

# Le poste Windows monte le dépôt tel quel, et tout y appartient à root alors que ce
# script tourne sous vscode : git refuse alors le dépôt pour « dubious ownership », et
# la panne ne se présente jamais sous ce nom. Le premier symptôme vu est « boundary: 1
# violation(s) — voir docs/02-architecture.md §5.2 », parce que `go list` perd son
# horodatage VCS sur ce même refus de git — rien n'y mentionne git ni les droits. Le
# --replace-all évite d'empiler des doublons si ce script est rejoué.
git config --global --replace-all safe.directory "$PWD"

# Docker crée sous root les PARENTS manquants d'une cible de montage, pas seulement la
# cible elle-même. $HOME/.cache est un tel parent — go-build en est la seule cible montée
# — et golangci-lint écrit dans $HOME/.cache/golangci-lint : sans ce chown récursif sur
# .cache entier, `go build` échoue sur « permission denied » au fond d'un cache, ce qui
# ne ressemble pas à un problème de montage.
sudo chown -R vscode:vscode "$HOME/go" "$HOME/.cache" web/node_modules

# golangci-lint s'installe HORS MODULE, et ADR-039 l'impose : `make deps` compare go.mod
# aux deux tables de §17.1 dans les deux sens, et une dépendance de développement inscrite
# là ouvrirait un écart permanent.
#
# La VERSION N'EST PAS ÉCRITE ICI : elle est lue dans le Makefile, qui en est la source
# unique — exactement ce que fait l'étape `make lint` de ci.yml.
golangci_version=$(make -s golangci-version)
install_dir=$(mktemp -d)
# Sous `set -e`, un `go install` qui échoue fait sortir le script AVANT le `rm -rf` de la
# dernière ligne du bloc : ce trap couvre ce chemin-là en plus du chemin heureux.
trap 'rm -rf "$install_dir"' EXIT
(
cd "$install_dir"
go mod init lintinstall >/dev/null 2>&1
go install "github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$golangci_version"
)
rm -rf "$install_dir"

# mkdocs, pour rejouer `mkdocs build --strict` avant de pousser. Le feature python installe
# son propre interpréteur : pip y fonctionne, là où le python système d'Ubuntu refuserait
# (PEP 668, « externally-managed-environment »).
pip install --no-cache-dir -r handbook/requirements.txt

# `npm ci` et non `npm install` : les versions sont gelées dans package-lock.json (§14.1),
# et `ci` est DÉTERMINISTE — il ÉCHOUE sur un lock désynchronisé au lieu de le réparer
# en silence, là où `install` l'aurait accepté et modifié sans le dire.
npm --prefix web ci

echo ''
echo 'Poste prêt. Ce que vous pouvez rejouer ici :'
echo ' make test les deux passes, -race comprise'
echo ' make front-check types, tests et budget de l ecran client'
echo ' mkdocs build --strict'
echo ''
echo 'Ce que ce conteneur NE juge PAS : les scripts d installation sous Windows'
echo 'PowerShell 5.1. Le job « scripts » de la CI le fait a chaque pull request.'
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,10 @@ qu'un détail compte.

## Développer

Go 1.26.5, Node 22 seulement pour le front. Pas de chaîne C, pas de Docker.
Go 1.26.5, Node 22 seulement pour le front. Pas de chaîne C. Un devcontainer est fourni
pour qui préfère ne rien installer : `.devcontainer/`, et
[le parcours de démarrage](https://lostmind84.github.io/OpenScale/getting-started/) le
détaille.

```bash
make test # ou : pwsh -File ./make.ps1 test
Expand Down
Loading