Commit Graph
6 Commits
Author SHA1 Message Date
Omar SobhandClaude Opus 5 25a3d6902a ci: only publish a release for an actual tag
deploy / test (push) Successful in 3m55s
deploy / build (push) Successful in 57s
On workflow_dispatch GITHUB_REF_NAME is the BRANCH, so the upload step created a
Gitea release AND a git tag both named "main" — a tag sharing the branch name,
from a run that was only meant to be a smoke test. Both have been deleted.

Gated on github.ref_type == 'tag'. A dispatch now exercises build, SBOM, sign
and offline verify, and stops there.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-13 21:06:44 -07:00
Omar SobhandClaude Opus 5 837a3d3ff0 ci: don't run the install rehearsal on the production gateway
deploy / test (push) Successful in 3m56s
deploy / build (push) Successful in 56s
Every other step in the release job is inert with respect to prod — build,
SBOM, sign, offline verify. The rehearsal is the only one whose purpose is to
stand a full stack up and tear it down with `down -v`, and it was doing that on
the machine serving production. On 2026-08-13 it adopted the live compose
project and destroyed clawmates_pgdata.

The script itself is now safe (unique -p, a guard against the production project
name, and a health probe pointing at the port the bundle actually publishes) and
is kept for use on a build box or throwaway VM. What changes here is only WHERE
it runs, which was the real problem: a destructive verification step does not
belong on the host it can destroy.

Releases still build, sign, verify offline in a --network none container, and
upload to Gitea.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-13 20:56:30 -07:00
Omar SobhandClaude Opus 5 41854c70e1 ci: the install rehearsal needs compose v2, and says so
deploy / test (push) Successful in 4m23s
deploy / build (push) Successful in 57s
The v1 fallback I added a commit ago cannot work: deploy/compose/docker-compose.yml
uses v2-only syntax — a top-level `name:` and long-form
`env_file: {path, required}` — so docker-compose 1.29 rejects the file outright
("'name' does not match any of the regexes"). A fallback that always fails is
worse than no fallback, so the script now requires v2 and fails immediately with
what to do about it.

$COMPOSE overrides the detection. gw-04 is deliberately left WITHOUT a
`docker compose` plugin: installing one system-wide would flip the production
rolling deploy (clawmates-deploy.sh prefers v2 when present) off docker-compose
v1 as an invisible side effect of a release change. The runner gets a standalone
v2 binary at /opt/act-runner/bin/docker-compose and the workflow passes it in,
so prod keeps rolling exactly as it did.

Verified on gw-04: standalone v2.32.4 runs, and `docker compose` still resolves
to nothing, so clawmates-deploy.sh takes its v1 branch unchanged.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-13 15:22:29 -07:00
Omar SobhandClaude Opus 5 bd1c970577 ci: let the install rehearsal use a pre-built bundler
deploy / test (push) Failing after 2m56s
deploy / build (push) Skipped
The rehearsal hardcoded `cargo build -p clawmates-bundler`, so it died with
"cargo: command not found" on the release runner — gw-04 builds Rust inside a
container and has no toolchain of its own. The release job had already built the
bundler two steps earlier, so it was also redundant work.

CLAWMATES_BUNDLER now short-circuits that build when it points at an executable,
falling back to cargo otherwise, so running the script by hand is unchanged.

Everything before this step already passed on the runner: images built, SBOMs
generated, bundle assembled and signed, and "bundle OK: 94 artifacts verified
offline" inside a --network none container.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-13 15:02:05 -07:00
Omar SobhandClaude Opus 5 c1642a7004 ci: copy the bundler out of the target volume
deploy / test (push) Successful in 4m24s
deploy / build (push) Successful in 58s
First dispatch failed at exit 127, "target/release/clawmates-bundler: No such
file or directory". The bundler builds inside a container where /w/target is a
NAMED VOLUME, so the binary was written somewhere no later host step can see —
the workspace's target/ stays empty. Copy it to .tools/ (bind-mounted) and
assert it landed, so the next occurrence fails at the build step with a clear
message instead of two steps later as a missing file.

deploy.yml does not hit this because it copies clawmates-node into
frontend/public/dl/ from inside the same container.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-13 14:51:50 -07:00
Omar SobhandClaude Opus 5 de8736c16b ci: move release.yml to Gitea and make it actually runnable
deploy / test (push) Successful in 4m37s
deploy / build (push) Successful in 56s
It could never have run as written: `runs-on: ubuntu-latest` matches no runner
on this forge, and `softprops/action-gh-release` talks to GitHub's API. There
are zero tags and zero releases, which is consistent with it never having fired.

Rewritten for this runner:
- runs-on: gw04 (the only reachable x86_64 host; prod artifacts must be amd64)
- the bundler builds in a rust container with the shared cargo cache volumes —
  gw-04 has no cargo, and installing a toolchain onto the production gateway to
  build a release is the wrong trade
- release creation + asset upload go to Gitea's own API, create-or-reuse so a
  re-run of a tag updates rather than 409s
- syft installs into the workspace, not /usr/local/bin: the host executor runs
  as root on the gateway and a release should leave nothing behind
- a disk-reclaim step, because the artifacts are GBs of image tarballs on a box
  that is also serving production. It removes only the versioned images it
  created — never a blanket prune, since clawmates/agent-*:dev exist in no
  registry and are the source of the microVM rootfs files
- workflow_dispatch added so the pipeline can be exercised without minting a tag

BUNDLE_SIGNING_KEY now exists as a repo secret (fresh ed25519 keypair; nothing
depended on a previous one). The signing and offline-verify steps are unchanged:
verification still runs inside a --network none container, which is the whole
air-gapped contract.

.github/ is now empty and removed.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-13 14:43:33 -07:00