Repository navigation
feat: plain compose with shared fragments, a shared backup service, the secret store's host side, and the chart, tags and people retired - #43
Merged
Conversation
… as root and re-applies for the console graphite-up and the agent use /etc/graphite/<project>.env when it exists and secrets.env otherwise, so each project moves to the console's secret store on its next rollout after its secrets are imported. The agent runs as root, reads /etc/graphite/agent.env, and answers POST /reapply with a Bearer CONSOLE_TOKEN by re-running graphite-up on the project's last applied folder.
…p service, and the chart, tags and people retired Every compose project is deploy/<slug>/compose.yaml extending shared/app.yaml, postgres.yaml, redis.yaml or redis-password.yaml, plus deploy/<slug>/values with IMAGE_TAG and only the values that differ from a default. deploy.py flattens the compose, renders it with the secret names stubbed, and sends compose, values and files to the agent. check-memory.py and check-values.py run on every PR. edge/backup.yaml runs a nightly backup at 03:00 UTC of every postgres labelled graphite.backup.postgres and every volume labelled graphite.backup, with consistent copies of SQLite databases, verifies each archive, keeps 14 days, and runs, verifies and restores on request from the console. The core chart, deploy/chart.yaml, tags/, people/, compile.py, people.py, the person schema and the Main workflow are removed. validate.py checks owners against organisation membership. Message Lab and the disabled Traceboard lose their deploy folders, which takes Message Lab down.
AmrMsCLL
added a commit
to Project-Graphite/actions
that referenced
this pull request
Nov 5, 2026
…nc workflow (#10) Phase 1, step 6 of the Graphite Hub plan, with the `actions` part of step 7. Goes with Project-Graphite/platform#43, which replaces `tags/` and the chart with `deploy/<slug>/compose.yaml` and `values`. ## Changes - **Deploy** writes `IMAGE_TAG=<tag>` as the first line of `platform/deploy/<slug>/values`, keeping every other line, and commits it as before. A project without a `deploy/<slug>/` folder (Message Lab after #43) is skipped with a notice instead of failing. - **Changelog** lists the repository's tags before `sync:releases --cut` and publishes a GitHub release, with generated notes, for each tag the cut added. The hub's release records are still written as today until the new hub replaces them. - **Sync registry** (`reusable-sync-registry.yml`) is removed. `platform`'s Sync registry now runs hourly as well as on dispatch, and the new hub will dispatch it from the organisation webhook. Each project's `registry.yml` that called this workflow is removed in its own PR. ## Merge order Merge platform#43 first, then this straight after. Between the two, project CI still writes `tags/`, which platform no longer reads, so a deploy in that window waits for the next push. ## Checks The `values` rewrite was run locally against a sample file. The workflows are linted by this repository's CI. `README.md` is stale on `reusable-sync-registry`, the `tags/<slug>.json` description of Deploy, and the `registry.yml` every project needs.
AmrMsCLL
added a commit
that referenced
this pull request
Nov 5, 2026
…upply (#44) The Deploy run for #43 failed every compose project with `no service joins the edge network as <slug>`. The workflow sets `PROJECT: ${{ inputs.project }}` for the job, empty on a push, and Compose gives the process environment priority over `--env-file`, so `${PROJECT}` rendered empty. PR checks passed because that job has no `PROJECT`. `deploy.py` now runs `docker compose` without any process variable that one of its env files supplies. Nothing reached the agent in the failed run: the four projects kept running as before. Checked locally with `PROJECT=wrong` and `HOST=wrong` in the environment: all four routes render; `deploy.py check`, `check-memory.py` and `check-values.py` pass.
AmrMsCLL
added a commit
that referenced
this pull request
Nov 5, 2026
… hosts (#48) `uptime.py` still read `deploy/<slug>/values.yaml` and `core.yaml`, both retired with the chart in #43. The `enabled` check therefore always passed, so a project set to `ENABLED=false` (#47) would be probed and reported as Down. - Projects come from `deploy/` folders, with `entry`, `values`, `projects` and `DEPLOY_HOST` imported from `deploy.py` instead of a second parser. - A project whose `values` says `ENABLED=false` is not probed. - The `core.yaml` extra-hosts loop is gone; compose projects have one host, from the registry. Checked locally: `targets()` lists the six live hosts plus the agent, and drops a project whose `values` has `ENABLED=false`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1 of the Graphite Hub plan for
platform: the host side of the console's secret store (step 2), the shared backup service (step 3), plain compose with shared fragments (steps 4 and 5), and the retirement of the chart, tag records and people files (step 7). Goes with Project-Graphite/console#19 and Project-Graphite/actions#10.Host and agent
graphite-upand the agent use/etc/graphite/<project>.envwhen it exists andsecrets.envotherwise, so each project moves to the console's store on its first rollout after its secrets are imported there./etc/graphite/agent.env, acceptsvaluesandfiles/<name>in a payload, refuses a missing secret name before it writes anything, and answersPOST /reapplywithAuthorization: Bearer <CONSOLE_TOKEN>for the console's Redeploy.graphite-uppasses--env-file valuesbefore the secrets file.Plain compose
shared/app.yaml(service: hardening, logging, health timing, limits;app: plus the edge alias${PROJECT},APP_URL,APP_PORT/APP_MEMORY/APP_CPUS/APP_RESERVE),shared/postgres.yaml,shared/redis.yaml,shared/redis-password.yaml.deploy/<slug>/compose.yamlplusdeploy/<slug>/values; the Pages projects keep onlyvalueswithIMAGE_TAG. Volume names, container names and the compose project name are unchanged, so data stays where it is.deploy.pyflattens the compose (docker compose config --no-interpolate), renders it with the secret names stubbed, derives the Traefik route from the service on the edge network, and sends compose, values (withPROJECTandHOSTfrom the registry) andfiles/to the agent. A removeddeploy/<slug>/takes a compose project down.deploy.py check(every compose renders),check-memory.py(reservations againstdeploy/host.yaml),check-values.py(no value equal to its default,ghcr.ioimages only on${IMAGE_TAG:?}orsha-, no${NAME}without:?or:-).Rendered both ways
Each project rendered through the chart (origin/main) and through the new compose, both interpolated with the same stubbed secrets, differs only in:
SECRETS_KEY: ${SECRETS_KEY:-}added;graphite.backuplabel ondatabackupsvolume gone; postgres flags reordered andwork_mem=4MB(the default) dropped; health check reads$POSTGRES_USER/$POSTGRES_DB; backup labels on postgres andfiles-datashared_buffers=128MB,max_connections=100; health check as above; backup label on postgresAPP_URLon the frontend; the unusedMONGO_PASSWORDgone from mongoRequired secret names and routes are identical for all four.
Backups
edge/backup.yamlrunsedge/backup.py(Python standard library, Docker API over the socket):pg_dumpof every container labelledgraphite.backup.postgres, run and checked withpg_restore --listinside the container, pulled out through the archive API and compared by checksum; a tar of every volume labelledgraphite.backup, with every SQLite database in it replaced by a consistent copy through SQLite's online backup API (no endpoint in the app). One/var/lib/graphite/backups/<project>/<stamp>.tarwith a manifest, and a<stamp>.jsonsummary beside it.integrity_check. A failure marks the run failed, which the console alerts on..requests/; a restore verifies first, stops the project, restores the dumps withpg_restore --clean --single-transactionand the volumes, starts it and waits for health.Removed
charts/,deploy/chart.yaml,tags/,people/,scripts/compile.py,scripts/people.py,schema/person.schema.json, the Main workflow, sleep and wake jobs (no project uses them;edge/wake.yamlgoes),release-core, Helm in CI,sync.py's single-manifest check.validate.pychecks owners against organisation membership. Sync registry runs hourly as well as on dispatch.deploy/graphite-message-lab/is removed, which takes Message Lab down on merge (volumes kept).deploy/traceboard/(disabled) is removed.Rollout
Merge this, then feat: IMAGE_TAG in platform's values, GitHub releases, no registry sync workflow actions#10 straight after. If
maingainedtags/commits meanwhile, rebase and copy the newest tags into eachvaluesIMAGE_TAG.Deploy runs on merge: the edge and Message Lab's takedown work with the current agent; the backup service and the compose projects are refused by it before anything is written.
Install the new agent over SSH:
Run Deploy by hand with project
all.Back up one project from the console's Backups page, download it, import it and restore it: the phase 1 exit check.
The
core-v1.0.0,core-v1.0.1andcore-v2.0.0tags are left in place;git push origin --delete core-v1.0.0 core-v1.0.1 core-v2.0.0removes them when wanted.Checks
deploy.py check,check-memory.py,check-values.py(plus a negative run catching each of its rules),validate.pyagainst live membership, the render diff above,py_compileand a local agent answering 401, 409 and a signeddown.backup.pywas run locally for packing a volume with a live WAL database, verification, tamper and wrong-project refusal, retention and the schedule. Not run: anything against Docker on the VPS (dumps, archive pulls, restore),graphite-upandbootstrap.sh.README.mdis stale throughout on the chart,core.yaml/values.yaml,tags/,people/, the Main workflow,/etc/graphite-agent.envand the backup sidecar.