Commit Graph

9 Commits (d7156ddc96aa4df07de71bba698088d4cae8a623)

Author SHA1 Message Date
boban 4af1633ca9 fix(install): harden release-image resolver — safe build fallback, ghcr digest allowlist, lint + CI coverage
Review found the build fallback could inherit a stale digest pin (compose build aborts), a slash-shaped/non-ghcr lock ref caused a doomed pull, env mode never persisted the pin (host restart used a nonexistent default tag), and the resolver test was unlinted/unrun in CI. Resolver now always leaves a coherent pin, validates ghcr.io/<owner>/<name>@sha256 refs only, exports the mode flag (drops the file-level shellcheck disable), and CI lints + runs the script unit tests.
2026-07-03 21:27:30 +02:00
boban 10486672a5 ci: build+push prod images, gated auto-promote to public
Backbone sub-project #1, CI half (verified with actionlint; the runtime proof is
the first rc/stable tag push — these jobs cannot run locally).

- ci-staging.yml:
  - new `images` job (needs: test): buildx builds clusev-app (Dockerfile) +
    clusev-terminal (docker/terminal/Dockerfile) → private GHCR, tagged by
    version; then a framework smoke-boot (`php artisan route:list`) so a class
    stripped by export-ignore that is still reachable on boot fails before promote.
  - `deploy-staging` widened to any tag; pulls the CI-built private image
    (CLUSEV_IMAGE/CLUSEV_TERMINAL_IMAGE + CLUSEV_PULL=1) instead of building.
  - new gated `promote` job (needs: [test, images], if success + stable vX.Y.Z,
    no -rc): copy the exact image digests to the public GHCR, run promote.sh
    (leak-guard + export-ignore tree), write release-images.lock, push code+tag.
- promote-public.yml: repurposed as a guarded manual fallback mirroring the auto
  promote (image copy + lock + guard). Dropped the "beta channel" naming.
- promote-stable.yml: removed (no beta→stable step in a single-channel model).

Deploy inputs are GitHub vars/secrets (GHCR_OWNER, PUBLIC_GHCR_OWNER,
PUBLIC_REPO_SLUG, STAGING_*, GHCR_TOKEN, PUBLIC_REPO_TOKEN, PROMOTE_FORBIDDEN) —
never hardcoded.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 20:34:00 +02:00
boban 707b031bd2 ci: bump actions/checkout + actions/setup-node to v5 (drop Node 20 runtime)
GitHub deprecated the Node 20 action runtime, so checkout@v4 and setup-node@v4 were
force-run on Node 24 with a warning. v5 of both targets Node 24 natively; their inputs
are unchanged (ref/repository/token/fetch-depth/path; the build's node-version stays
'20', that's the project runtime not the action runtime). setup-php@v2 is the current
major and unaffected. ci-staging runs only on tag pushes, so the warning clears on the
next tagged release.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 18:55:52 +02:00
boban 1eb4c4fef7 fix(release): cache public-tags reads + tighten yank tag validation (review)
- PromotionService::publicTags() is called on every Release render incl. the 5s
  page poll; the anonymous GitHub tag API is rate-limited (60/h per IP). Cache it
  120s so the panel never gets rate-limited to empty. (Test flushes cache in setUp.)
- yank.yml: replace the loose shell-glob tag guard with an anchored grep regex so
  a garbage/space/metachar tag dispatched straight from the GitHub UI is rejected
  before reaching git push --delete (the panel already validates tag ∈ publicTags).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 06:01:36 +02:00
boban 84f84cbb03 ci: yank.yml — workflow_dispatch to delete a tag on the public repo
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 03:13:02 +02:00
boban 25271717c2 fix(ci): build the Vite manifest before php artisan test
Full-page tests render @vite layouts; without public/build/manifest.json (gitignored,
absent on a fresh CI checkout) they 500. Move npm ci + npm run build ahead of the
test step so the manifest exists. Fixes the red CI on every v* tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 02:26:20 +02:00
boban 8e9499780e fix(release): review polish — promote idempotency, CI hardening, docs
- promote.sh: fail fast before mutating the public tree if the tag was already
  promoted (avoids a half-commit left on the runner on re-dispatch).
- ci-staging.yml: pass STAGING_PROJECT_DIR via env + :? guard instead of a
  ${{ }} expression in run: (clears the template-injection lint, fails loudly
  on misconfig).
- README: PUBLIC_REPO_URL was never read by any workflow — keep only the slug.
- set-repository-url.test.sh: chmod +x for mode parity with promote.test.sh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 21:18:44 +02:00
boban 4aa55b7124 ci: workflow_dispatch promotion to public (beta) + beta-to-stable
Promotion workflows for the release pipeline. promote-public publishes a tag to
the public repo's beta channel; promote-stable re-tags a finalised beta as a
stable vX.Y.Z. Both bound to the 'production' environment (required reviewer),
reading PUBLIC_REPO_SLUG/PUBLIC_REPO_TOKEN. Tree copy via scripts/promote.sh
excludes .git/.github so private CI never reaches the public repo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 21:18:32 +02:00
boban c4f90b0830 ci: test on v* tags, optional self-hosted staging deploy on betas
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 21:03:14 +02:00