docs(devops): add executable roadmap with checklist for Codex agent

Adds HOSTINGER_GITEA_RUNNER_ROADMAP.md — a single execution tracker
that Codex on the Hostinger VM works through phase-by-phase, ticking
checkboxes and recording commit hashes as it goes.

Structure:
- 6 phases (P0 Pre-flight → P5 First real release) + P6 review handoff
- Each task: [ ] checkbox + Commit hash field + Status note
- Detail steps live in the two companion docs (act_runner setup +
  publish workflow); the roadmap is the orchestrator
- Final report section Codex fills in when P0-P5 are complete
- Human review checklist (R1-R9) for verification after handoff
- Operating notes: commit message format, when to ask, never-do list
- Change log table Codex auto-appends to

Critical invariant repeated at P3.6 and P5.4: cross-Gitea SHA1
comparison must match. If it doesn't, Codex stops — it's the
load-bearing architectural guarantee that the dual-Gitea, no-sync-
script model rests on.

Also adds roadmap-pointer banners to the two companion docs
(HOSTINGER_GITEA_ACT_RUNNER_SETUP.md, GITEA_PACKAGES_PUBLISH_WORKFLOW.md)
so anyone landing there knows the master tracker exists.
This commit is contained in:
saravanakumardb1 2026-05-24 18:22:16 -07:00
parent d1bdcdd9a7
commit a55f207f80
3 changed files with 287 additions and 1 deletions

View File

@ -1,9 +1,14 @@
# `@bytelyst/*` Package Publish Workflow (Gitea Actions)
> 📋 **Track progress in the master roadmap:** [`HOSTINGER_GITEA_RUNNER_ROADMAP.md`](./HOSTINGER_GITEA_RUNNER_ROADMAP.md) — Phase 4 references this doc. Codex updates the roadmap checkboxes as each step here completes.
> **Delegation prompt for a coding agent.**
> Implements the canonical `publish-packages.yml` workflow that publishes `@bytelyst/*` packages to the Gitea npm registry on every `v*` tag, and propagates it to all 20+ ByteLyst repos.
> Companion: [`HOSTINGER_GITEA_ACT_RUNNER_SETUP.md`](./HOSTINGER_GITEA_ACT_RUNNER_SETUP.md) — the runner that executes this workflow.
> Companions:
>
> - [`HOSTINGER_GITEA_RUNNER_ROADMAP.md`](./HOSTINGER_GITEA_RUNNER_ROADMAP.md) — execution tracker.
> - [`HOSTINGER_GITEA_ACT_RUNNER_SETUP.md`](./HOSTINGER_GITEA_ACT_RUNNER_SETUP.md) — the runner that executes this workflow.
---

View File

@ -1,10 +1,13 @@
# Hostinger VM — Gitea Actions `act_runner` Setup
> 📋 **Track progress in the master roadmap:** [`HOSTINGER_GITEA_RUNNER_ROADMAP.md`](./HOSTINGER_GITEA_RUNNER_ROADMAP.md). The roadmap has the checklist; this doc has the implementation detail. Codex updates checkboxes + commit hashes in the roadmap as each phase completes.
> **Delegation prompt for the Codex agent running on the Hostinger VM.**
> Canonical CI runner setup for the ByteLyst ecosystem. Read top-to-bottom before executing. Stop and ask the human if any pre-flight check fails or any deliverable is unclear.
> Companion docs:
>
> - [`HOSTINGER_GITEA_RUNNER_ROADMAP.md`](./HOSTINGER_GITEA_RUNNER_ROADMAP.md) — **execution tracker (this doc's checklist)**.
> - [`GITEA_PACKAGES_PUBLISH_WORKFLOW.md`](./GITEA_PACKAGES_PUBLISH_WORKFLOW.md) — the publish workflow this runner executes.
> - [`HOSTINGER_GITHUB_RUNNER_SETUP.md`](./HOSTINGER_GITHUB_RUNNER_SETUP.md) — Plan B (GitHub Actions runner). Kept for reference.

View File

@ -0,0 +1,278 @@
# Hostinger Gitea Actions Runner — Execution Roadmap
> **Codex agent — this is your execution tracker.**
>
> 1. Read this file top-to-bottom before starting.
> 2. Work through phases in order. **Do not skip phases.**
> 3. After completing each task, edit this file: change `- [ ]``- [x]`, fill in the commit hash, and add a one-line status note. Then commit the roadmap update with message `chore(roadmap): mark P<phase>.<task> complete`.
> 4. If anything blocks you or surprises you, stop, fill in the `Status` line as `BLOCKED: <reason>`, and report back to the human.
> 5. When all phases are ✅, fill in **§Review handoff** and ping the human.
>
> **Detailed instructions** for each phase live in two companion docs — link from each phase. Don't repeat the details here; just track progress.
>
> - Runner install detail: [`HOSTINGER_GITEA_ACT_RUNNER_SETUP.md`](./HOSTINGER_GITEA_ACT_RUNNER_SETUP.md)
> - Publish workflow detail: [`GITEA_PACKAGES_PUBLISH_WORKFLOW.md`](./GITEA_PACKAGES_PUBLISH_WORKFLOW.md)
> - Plan B (GitHub Actions instead, not used): [`HOSTINGER_GITHUB_RUNNER_SETUP.md`](./HOSTINGER_GITHUB_RUNNER_SETUP.md)
---
## 🎯 Outcome
After this roadmap is fully executed, the following invariant holds:
> Pushing a `v*` tag to both Gitea instances (`git push origin && git push gitea --tags`) causes each Gitea's `act_runner` to independently build `@bytelyst/*` packages from the same git tag and publish byte-identical tarballs to its local Gitea registry — **with no sync script and no manual intervention**.
The cross-Gitea SHA comparison in P3.6 and P5.3 is the proof.
---
## 📋 Master execution tracker
Total phases: **6** (P0 → P5) + **Review handoff (P6)**
### P0 — Pre-flight + environment verification
> Detail: [§2 of runner setup doc](./HOSTINGER_GITEA_ACT_RUNNER_SETUP.md#2-pre-flight-checks-run-first-do-not-skip)
- [ ] **P0.1** All 10 pre-flight checks pass on Hostinger VM
- Commit: _none (read-only)_
- Status: `<fill in: e.g., "All checks green — arch=linux-amd64, Gitea 1.21.5, docker 27.0.1, ~/.gitea_npm_token at /home/sd/...">`
- [ ] **P0.2** Architecture confirmed and `RUNNER_ARCH` exported
- Commit: _none_
- Status: `<x86_64 → linux-amd64 | aarch64 → linux-arm64>`
- [ ] **P0.3** Human confirmed registration scope (instance-level recommended)
- Commit: _none_
- Status: `<scope confirmed: instance | org | repo>`
- [ ] **P0.4** Human confirmed E2E throwaway-package consent
- Commit: _none_
- Status: `<yes/no, and any constraints>`
### P1 — Install `act_runner` on Hostinger VM
> Detail: [§4 of runner setup doc](./HOSTINGER_GITEA_ACT_RUNNER_SETUP.md#4-installation)
- [ ] **P1.1** Create `gitea-runner` user (idempotent; docker group)
- Commit: _system change, not git_
- Status: ``
- [ ] **P1.2** Download `act_runner` binary, SHA256-verify, install to `/usr/local/bin/`
- Commit: _system change_
- Status: `<version installed, e.g., v0.2.10>`
- [ ] **P1.3** Obtain registration token from Gitea (instance level)
- Commit: _none (token in memory only)_
- Status: `<token length confirmed nonzero>`
- [ ] **P1.4** Register runner with config.yaml (Docker mode, `node:20-bookworm` label mapping)
- Commit: _system change_
- Status: `<runner name: hostinger-bytelyst-1, labels: ...>`
- [ ] **P1.5** Mount `~/.gitea_npm_token` to `gitea-runner` (mode 600)
- Commit: _system change_
- Status: `<copied from <user>, owner gitea-runner:gitea-runner, mode 600, bytes=...>`
- [ ] **P1.6** Install systemd service `gitea-act-runner.service` and verify `active (running)` + "Polling" in journal
- Commit: _system change_
- Status: `<journalctl shows: "Runner registered" + "Polling for tasks">`
- [ ] **P1.7** Confirm runner shows "Idle" green in Gitea Admin UI (`<gitea>/-/admin/actions/runners`)
- Commit: _none (UI verification)_
- Status: `<screenshot URL or "confirmed at <timestamp>">`
### P2 — Smoke test (runner picks up jobs)
> Detail: [§5 of runner setup doc](./HOSTINGER_GITEA_ACT_RUNNER_SETUP.md#5-smoke-test-basic--runner-picks-up-jobs)
- [ ] **P2.1** Create branch `runner/gitea-smoke` with `.gitea/workflows/runner-smoke.yml`
- Commit: `<sha7>`
- Status: `<branch pushed to gitea>`
- [ ] **P2.2** Trigger smoke workflow via Gitea Actions UI
- Commit: _trigger only_
- Status: `<run URL on Gitea>`
- [ ] **P2.3** All smoke steps pass (host info, Node, pnpm, Gitea reachability, token presence)
- Commit: _none_
- Status: `<run conclusion: success>`
### P3 — End-to-end validation (throwaway package + cross-Gitea byte-identical check)
> Detail: [§6 of runner setup doc](./HOSTINGER_GITEA_ACT_RUNNER_SETUP.md#6-end-to-end-validation--proves-the-actual-publish-pipeline)
- [ ] **P3.1** Create throwaway `@bytelyst/_runner-e2e-test` package on branch `runner/gitea-e2e`
- Commit: `<sha7>`
- Status: `<branch pushed to both gitea and origin>`
- [ ] **P3.2** Add `.gitea/workflows/runner-e2e-publish.yml` to the same branch
- Commit: `<sha7>`
- Status: ``
- [ ] **P3.3** Trigger E2E workflow with `version=0.0.1-e2e.1`
- Commit: _trigger only_
- Status: `<run URL>`
- [ ] **P3.4** Verify publish succeeds + Gitea registry returns the version
- Commit: _none_
- Status: ``
- [ ] **P3.5** Verify consumer `pnpm install` + `require()` works from clean `/tmp` dir
- Commit: _none_
- Status: ``
- [ ] **P3.6** **Cross-Gitea SHA1 comparison** — corp Mac runner publishes same version to corp Gitea; verify tarball shasum matches Hostinger
- Commit: _none (cross-machine verification)_
- Status: `<HOSTINGER_SHA=... | CORP_SHA=... | MATCH: ✅/❌>`
- **This is the architectural invariant. If it fails, STOP and investigate Node/pnpm/lockfile version drift before proceeding to P4.**
- [ ] **P3.7** Cleanup: delete test version from both Giteas, delete `runner/gitea-e2e` branch, remove `packages/_runner-e2e-test/`
- Commit: `<sha7>` (the cleanup commit on main)
- Status: `<verified package absent from both Gitea UIs>`
### P4 — Implement publish-packages.yml (the real workflow)
> Detail: [Publish workflow doc](./GITEA_PACKAGES_PUBLISH_WORKFLOW.md)
- [ ] **P4.1** Look up current `node:20-bookworm` digest from Docker Hub via `docker inspect` on Hostinger
- Commit: _none_
- Status: `<sha256:digest>`
- [ ] **P4.2** Create `.gitea/workflows/publish-packages.yml` in `learning_ai_common_plat` with the digest pinned (replace `PIN_THIS_DIGEST_FOR_DETERMINISM`)
- Commit: `<sha7>`
- Status: ``
- [ ] **P4.3** Confirm `GITEA_NPM_TOKEN` is set as a Gitea repo-level secret (or instance-level) — Settings → Secrets
- Commit: _none (configuration check)_
- Status: `<confirmed: scope=repo|instance, set at <timestamp>>`
- [ ] **P4.4** Dry-run the workflow: `workflow_dispatch` with `dry_run: true` on a branch
- Commit: `<sha7>` (the workflow file commit on a branch)
- Status: `<run URL, all steps pass except actual publish (which is skipped)>`
- [ ] **P4.5** Merge workflow to `main`
- Commit: `<sha7>`
- Status: `<merged>`
### P5 — First real release through the new pipeline
> Detail: [§4 of publish workflow doc](./GITEA_PACKAGES_PUBLISH_WORKFLOW.md#4-releasing-a-new-package-version-operator-workflow)
- [ ] **P5.1** Coordinate with human: which package to bump for the first real release? (Suggestion: lowest-risk one — `@bytelyst/errors` or similar with no consumers' tests depending on a version bump.)
- Commit: _none (decision)_
- Status: `<package + version selected, e.g., @bytelyst/errors v0.1.5>`
- [ ] **P5.2** Bump version, commit, tag, push to BOTH `origin` and `gitea`
- Commit: `<sha7 of version bump>`
- Status: `<tag pushed to both remotes>`
- [ ] **P5.3** Watch the workflow run on both Giteas; verify both succeed
- Commit: _none_
- Status: `<Hostinger run URL: ... | corp run URL: ...>`
- [ ] **P5.4** **Cross-Gitea SHA1 comparison** for the real release (same check as P3.6)
- Commit: _none_
- Status: `<HOSTINGER_SHA=... | CORP_SHA=... | MATCH: ✅/❌>`
- [ ] **P5.5** From a consumer repo (suggest `learning_ai_clock` since you have it open), `pnpm update @bytelyst/<package>` + `pnpm install` + `pnpm typecheck`
- Commit: _none (verification)_
- Status: `<consumer install + typecheck clean>`
### P6 — Review handoff (human reviews after Codex finishes)
When all phases above are checked, the agent fills in this section and stops:
- [ ] **P6.1** Roadmap fully ticked through P5.5
- [ ] **P6.2** Final report summary (fill below)
- [ ] **P6.3** Human reviewed and approved
---
## 📊 Final report (Codex fills in when P0P5 complete)
**Runner installation:**
- Runner name: `<name>`
- Labels: `<comma-sep labels>`
- Gitea instance URL: `<url>`
- Service status: `<systemctl is-active output>`
- act_runner version: `<vX.Y.Z>`
- Docker image used: `node:20-bookworm@sha256:<digest>`
**E2E validation (P3):**
- Workflow run URL: `<url>`
- Cross-Gitea SHA match: `<✅/❌>`
- Throwaway package fully cleaned up: `<yes/no>`
**First real release (P5):**
- Package + version: `<@bytelyst/foo v1.2.3>`
- Hostinger workflow run: `<url>`
- Corp workflow run: `<url>`
- Cross-Gitea SHA match: `<✅/❌>`
- Consumer verification: `<which repo, result>`
**Architectural invariant verdict:** `<HOLDS / DOES NOT HOLD — explanation>`
**Surprises / deviations from the plan:**
- `<bullet 1>`
- `<bullet 2>`
**Recommendations for the human:**
- `<bullet 1>`
- `<bullet 2>`
---
## 🔍 Review checklist for the human (after Codex hands off)
When Codex marks P6.2 complete, the human verifies:
- [ ] **R1** Final report (above) is filled in with no `<placeholder>` strings
- [ ] **R2** Both cross-Gitea SHA matches (P3.6 + P5.4) are ✅
- [ ] **R3** `systemctl status gitea-act-runner.service` on Hostinger VM is `active (running)`
- [ ] **R4** Gitea admin UI shows runner as Idle and recently seen
- [ ] **R5** `.gitea/workflows/publish-packages.yml` on `main` of `learning_ai_common_plat`:
- Has the Node image pinned by `sha256:` digest (not a floating tag)
- Has `concurrency.cancel-in-progress: false`
- Mounts `~/.gitea_npm_token` as a read-only volume (not in env vars or logs)
- [ ] **R6** The throwaway `@bytelyst/_runner-e2e-test` package is **gone from both Gitea registries** (visit Packages UI to confirm)
- [ ] **R7** No leftover branches: `runner/gitea-smoke`, `runner/gitea-e2e` deleted from both `origin` and `gitea` remotes
- [ ] **R8** A consumer repo can `pnpm install` against either Gitea without lockfile churn (run the corp-network test and the home-network test if possible)
- [ ] **R9** This roadmap doc itself has no surprises in the "Surprises / deviations" section that need follow-up
Sign-off:
- Reviewed by: `<name>`
- Date: `<YYYY-MM-DD>`
- Approved: `<yes/no>`
---
## 🛠 Operating notes for Codex
### How to commit roadmap updates
When you tick a checkbox, write the commit message like:
```
chore(roadmap): mark P1.6 complete — act_runner systemd service active
Service is running and journal shows "Polling for tasks". See
docs/devops/HOSTINGER_GITEA_RUNNER_ROADMAP.md for the full tracker.
```
When you fill in a commit hash field for a code change, use the **short SHA** (7 chars) of the commit that performed the work — **not** the SHA of the roadmap-update commit itself. Example:
```
- [x] **P3.1** Create throwaway @bytelyst/_runner-e2e-test package
- Commit: abc1234
- Status: branch pushed to both gitea and origin
```
### When to ask the human
Stop and ask if:
- A pre-flight check fails or surprises you (P0).
- The cross-Gitea SHA comparison fails (P3.6 or P5.4) — don't paper over this; it's the load-bearing invariant.
- You need to deviate from the plan in a non-trivial way (e.g., the Docker image digest isn't available, a step in the underlying doc doesn't work as written).
- The human's earlier answers in P0 turn out to be wrong (e.g., they said instance-level scope but you only have repo admin).
For minor things (e.g., a typo in the underlying doc, an extra package installation step), proceed and note it in "Surprises / deviations".
### What you should NEVER do
- Skip P3.6 or P5.4 (cross-Gitea SHA checks).
- Publish to either Gitea outside of the workflow you just built — manual publishes break the invariant.
- Leave the throwaway test package in either Gitea registry.
- Force-push the roadmap file (always normal commits with descriptive messages).
- Mark something `[x]` if it didn't actually fully succeed. Use `[ ] FAILED: <reason>` instead, and stop.
---
## 📜 Change log (auto-maintained by Codex via roadmap-update commits)
| Date | Phase | Action | Commit |
| -------------------- | ----- | ------------------------ | -------- |
| `<YYYY-MM-DD HH:MM>` | P0.1 | Pre-flight checks passed | _system_ |
| | | | |