molecule-core is a public repo — GHA-hosted minutes are free. The self-hosted Mac mini was only in play to dodge GHA rate limits (memory feedback_selfhosted_runner), but for these specific workflows it came with real costs: - Docker-push workflows emulated linux/amd64 from arm64 via QEMU — every canvas + platform image build ran ~2-3x slower than native. - Six PRs worth of keychain-avoidance hacks in publish-* because `docker login` on macOS writes to osxkeychain unconditionally, and the Mac mini's launchd user-agent keychain is locked. - Homebrew pin-down environment variables (HOMEBREW_NO_*) sprinkled everywhere to work around the shared /opt/homebrew symlink mess on the runner. - Setup-python@v5 couldn't write to /Users/runner, so ci.yml python-lint resorted to a hand-rolled Homebrew python3.11 dance. - Single runner → fan-out contention; CodeQL's 45-min analysis fought the canvas publish for the one slot. Changes across the 7 workflows: - runs-on: [self-hosted, macos, arm64] → ubuntu-latest (every job) - publish-canvas-image + publish-workspace-server-image: drop the hand-rolled auths-map step + QEMU setup + buildx v4 → docker/login-action@v3 + setup-buildx@v3. Linux + amd64 target = native build. - canary-verify + promote-latest: replace `brew install crane` + HOMEBREW_NO_* incantations with imjasonh/setup-crane@v0.4. - codeql.yml: drop `brew install jq` — jq is preinstalled on ubuntu-latest. - ci.yml shellcheck: drop the self-hosted existence check — shellcheck is preinstalled via apt. - ci.yml python-lint: replace the Homebrew python3.11 path dance with actions/setup-python@v5 (which works fine on GHA-hosted), add requirements.txt caching while we're there. - Remove stale comments referencing "the self-hosted runner", "Mac mini", keychain, osxkeychain etc. The self-hosted Mac mini remains in service for private-repo workflows only. Memory feedback_selfhosted_runner updated to reflect the public-repo scope carve-out. Net -96 lines across the 7 files. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
106 lines
4.0 KiB
YAML
106 lines
4.0 KiB
YAML
name: publish-canvas-image
|
|
|
|
# Builds and pushes the canvas Docker image to GHCR whenever a commit lands
|
|
# on main that touches canvas code. Previously canvas changes were visible in
|
|
# CI (npm run build passed) but the live container was never updated —
|
|
# operators had to manually run `docker compose build canvas` each time.
|
|
#
|
|
# Mirror of publish-platform-image.yml, adapted for the Next.js canvas layer.
|
|
# See that workflow for inline notes on macOS Keychain isolation and QEMU.
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
# Only rebuild when canvas source changes — saves GHA minutes on
|
|
# platform-only / docs-only / MCP-only merges.
|
|
- 'canvas/**'
|
|
- '.github/workflows/publish-canvas-image.yml'
|
|
# Manual trigger: use after a non-canvas merge that still needs a fresh
|
|
# image (e.g. a Dockerfile change lives outside the canvas/ tree).
|
|
workflow_dispatch:
|
|
inputs:
|
|
platform_url:
|
|
description: 'NEXT_PUBLIC_PLATFORM_URL baked into the bundle (default: http://localhost:8080)'
|
|
required: false
|
|
default: ''
|
|
ws_url:
|
|
description: 'NEXT_PUBLIC_WS_URL baked into the bundle (default: ws://localhost:8080/ws)'
|
|
required: false
|
|
default: ''
|
|
|
|
permissions:
|
|
contents: read
|
|
packages: write # required to push to ghcr.io/${{ github.repository_owner }}/*
|
|
|
|
env:
|
|
IMAGE_NAME: ghcr.io/molecule-ai/canvas
|
|
|
|
jobs:
|
|
build-and-push:
|
|
name: Build & push canvas image
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Log in to GHCR
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Compute tags
|
|
id: tags
|
|
shell: bash
|
|
run: |
|
|
echo "sha=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Resolve build args
|
|
id: build_args
|
|
# Priority: workflow_dispatch input > repo secret > hardcoded default.
|
|
# NEXT_PUBLIC_* env vars are baked into the JS bundle at build time by
|
|
# Next.js — they cannot be changed at runtime without a full rebuild.
|
|
# For local docker-compose deployments the defaults (localhost:8080)
|
|
# work as-is; production deployments should set CANVAS_PLATFORM_URL
|
|
# and CANVAS_WS_URL as repository secrets.
|
|
#
|
|
# Inputs are passed via env vars (not direct ${{ }} interpolation) to
|
|
# prevent shell injection from workflow_dispatch string inputs.
|
|
shell: bash
|
|
env:
|
|
INPUT_PLATFORM_URL: ${{ github.event.inputs.platform_url }}
|
|
SECRET_PLATFORM_URL: ${{ secrets.CANVAS_PLATFORM_URL }}
|
|
INPUT_WS_URL: ${{ github.event.inputs.ws_url }}
|
|
SECRET_WS_URL: ${{ secrets.CANVAS_WS_URL }}
|
|
run: |
|
|
PLATFORM_URL="${INPUT_PLATFORM_URL:-${SECRET_PLATFORM_URL:-http://localhost:8080}}"
|
|
WS_URL="${INPUT_WS_URL:-${SECRET_WS_URL:-ws://localhost:8080/ws}}"
|
|
|
|
echo "platform_url=${PLATFORM_URL}" >> "$GITHUB_OUTPUT"
|
|
echo "ws_url=${WS_URL}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Build & push canvas image to GHCR
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: ./canvas
|
|
file: ./canvas/Dockerfile
|
|
platforms: linux/amd64
|
|
push: true
|
|
build-args: |
|
|
NEXT_PUBLIC_PLATFORM_URL=${{ steps.build_args.outputs.platform_url }}
|
|
NEXT_PUBLIC_WS_URL=${{ steps.build_args.outputs.ws_url }}
|
|
tags: |
|
|
${{ env.IMAGE_NAME }}:latest
|
|
${{ env.IMAGE_NAME }}:sha-${{ steps.tags.outputs.sha }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
labels: |
|
|
org.opencontainers.image.source=https://github.com/${{ github.repository }}
|
|
org.opencontainers.image.revision=${{ github.sha }}
|
|
org.opencontainers.image.description=Molecule AI canvas (Next.js 15 + React Flow)
|