Commit Graph

6 Commits

Author SHA1 Message Date
Hongming Wang
64796838e0 ci: update GitHub Actions to current stable versions (closes #780)
- golangci/golangci-lint-action@v4 → v9
- docker/setup-qemu-action@v3 → v4
- docker/setup-buildx-action@v3 → v4
- docker/build-push-action@v5 → v6

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 12:04:10 -07:00
Hongming Wang
0c9fda559a fix(ci): bypass docker login + macOS Keychain for image publish
Six prior PRs (#273, #319, #322, #341, #484, #486) all kept calling
`docker login` and tried to coerce credsStore via increasingly elaborate
config tricks. None worked. The latest publish-canvas-image and
publish-platform-image runs on main are still failing with:

    error storing credentials - err: exit status 1,
    out: `User interaction is not allowed. (-25308)`

Verified locally on the runner host (2026-04-16): `docker login` on
macOS unconditionally writes credentials to osxkeychain after a
successful login, regardless of the config presented to it.

    # I wrote this:
    { "auths": {}, "credsStore": "", "credHelpers": {} }
    # After `docker login --config <dir> ghcr.io ...` succeeded:
    {
      "auths": { "ghcr.io": {} },        # empty — auth is in Keychain
      "credsStore": "osxkeychain"        # Docker rewrote it back
    }

So `--config` flag, DOCKER_CONFIG env var, credsStore="" etc. all share
the same fate: Docker re-enables osxkeychain after every successful
login. The Mac mini runner is a launchd user agent with a locked
Keychain, so storage fails with -25308.

This PR replaces the `docker login` invocation entirely. We write
`base64(user:pat)` directly into the disposable DOCKER_CONFIG's `auths`
map. `docker/build-push-action@v5` and the daemon honor the auths map
for push without ever calling `docker login`, so the Keychain is never
involved.

Same shape in both workflows:
- publish-canvas-image.yml — single registry (ghcr.io)
- publish-platform-image.yml — two registries (ghcr.io + registry.fly.io)
  Fly username remains literal "x".

Security:
- Token env vars never echoed. Heredoc writes the auth blob via
  `umask 077` (file mode 600). The temp config dir lives under
  RUNNER_TEMP and is reaped at job end.
- Diagnostics preserved (docker version + binary ls + registry keys
  only, no values) so future runner permission regressions remain
  visible without leaking secrets.

Equivalent to closed PR #464 — re-opening because main is still
broken (verified by inspecting the most recent failure). The closing
comment on #464 stated the issue was already addressed by #341, but
it isn't.
2026-04-16 09:25:20 -07:00
Hongming Wang
6f3c16eb78 fix(ci): use docker login CLI instead of login-action to bypass macOS Keychain
docker/login-action@v3 ignores DOCKER_CONFIG and still tries the
macOS system keychain on the self-hosted runner, producing:
  error storing credentials: User interaction is not allowed. (-25308)

Switch to `docker login ... --password-stdin` which respects
DOCKER_CONFIG and writes credentials to the per-run config.json
we created in the isolate step. Applied to both GHCR and Fly
registry logins in both publish workflows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:45:20 -07:00
Hongming Wang
f93ec926cb fix(ci): replace heredoc JSON with printf in publish workflows
The heredoc block writing Docker config.json had unindented `{` at
column 1, which GitHub Actions' YAML parser interpreted as a flow
mapping start — causing every publish-platform-image and
publish-canvas-image run to fail with 0 jobs (startup_failure).

Replace `cat <<'JSON' ... JSON` with a single `printf` call that
produces identical config.json content without confusing the parser.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:20:43 -07:00
Hongming Wang
77d6f5e7a0 fix(ci): heredoc indentation in publish workflows + add dev-start.sh
Two fixes:
1. publish-canvas-image.yml + publish-platform-image.yml: the JSON
   heredoc for config.json had leading whitespace from YAML indentation,
   producing invalid JSON. Docker fell back to osxkeychain → -25308.
   Fixed by removing indentation inside the heredoc body.

2. Added scripts/dev-start.sh — one-command local dev environment.
   Starts infra (docker-compose), platform (Go), and canvas (Next.js)
   with proper health checks and cleanup on Ctrl-C.
2026-04-16 05:56:25 -07:00
Canvas Agent
c928b4cbe8 feat(ci): auto-publish canvas Docker image to GHCR on canvas/** merges
Closes #399.

## Root cause
`publish-platform-image.yml` existed for the Go platform image but there
was no equivalent for the canvas. After every canvas PR merged, CI ran
`npm run build` and passed — but the live container at :3000 was never
updated. The `canvas-deploy-reminder` job only posted a comment asking
operators to manually rebuild, which was consistently missed.

## What this adds
- `.github/workflows/publish-canvas-image.yml`: triggers on `canvas/**`
  changes to main (and `workflow_dispatch`). Mirrors the platform workflow:
  macOS Keychain isolation, QEMU for linux/amd64, Buildx, GHCR push with
  `:latest` + `:sha-<7>` tags.
  - `NEXT_PUBLIC_PLATFORM_URL` / `NEXT_PUBLIC_WS_URL` resolve from
    `workflow_dispatch` inputs → `CANVAS_PLATFORM_URL` / `CANVAS_WS_URL`
    repo secrets → `localhost:8080` defaults (safe for self-hosted dev).
  - Inputs are passed via env vars (not direct `${{ }}` interpolation) to
    prevent shell injection from string inputs.

- `docker-compose.yml`: adds `image: ghcr.io/molecule-ai/canvas:latest`
  to the canvas service so `docker compose pull canvas && docker compose
  up -d canvas` applies the new image. `build:` is retained for local
  development. Adds a comment clarifying that `NEXT_PUBLIC_*` runtime env
  vars are ignored by the standalone bundle (build-time only).

- `ci.yml`: updates `canvas-deploy-reminder` commit comment to reference
  `docker compose pull` as the fast path, with `docker compose build` as
  the local-source fallback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 09:23:26 +00:00