From 09f0fbf9b07fd262aa41e0013d8beeda2d63f2a7 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Wed, 22 Apr 2026 12:49:02 -0700 Subject: [PATCH] perf(publish-template-image): move to ubuntu-latest for public-repo callers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All 8 template repos are public → GHA-hosted minutes are free, so there's no cost incentive to stay on the self-hosted Mac mini. The only reason we started there was to avoid GHA rate limits (memory feedback_selfhosted_runner); that concern doesn't apply here because: - Linux/amd64 builds go native on ubuntu-latest (no QEMU emulation from arm64 → amd64), so builds run ~2-3x faster. - docker/login-action@v3 + GITHUB_TOKEN handles GHCR auth cleanly, no Keychain gymnastics needed. - No queue wait when the Mac mini is busy publishing canvas/platform or running e2e. Concretely this change: - runs-on: [self-hosted, macos, arm64] → ubuntu-latest - Drops the hand-rolled `auths` config step (macOS Keychain workaround) in favour of `docker/login-action@v3`. - Drops `docker/setup-qemu-action` (unnecessary for a linux/amd64 target on an amd64 runner). - Uses setup-buildx@v3 to match the login-action major version. Self-hosted Mac mini remains the runner for private-repo workflows (follow-up PRs will migrate other public-repo workflows in molecule-core). Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-template-image.yml | 62 +++++++------------- 1 file changed, 20 insertions(+), 42 deletions(-) diff --git a/.github/workflows/publish-template-image.yml b/.github/workflows/publish-template-image.yml index e8a7f6a..9f3c5d7 100644 --- a/.github/workflows/publish-template-image.yml +++ b/.github/workflows/publish-template-image.yml @@ -20,13 +20,14 @@ name: Publish Workspace Template Image # uses: Molecule-AI/molecule-ci/.github/workflows/publish-template-image.yml@main # secrets: inherit # -# Why one workflow instead of 8 copies: -# - Stamp-out consistency: self-hosted macOS runner, Keychain-avoiding -# docker config, QEMU cross-build all live in one place. -# - One PR to change the pattern (e.g. add semver tagging later) instead -# of 8 identical PRs across every plugin repo. -# - Mirrors the existing validate-workspace-template.yml pattern already -# in this repo. +# Runner choice (2026-04-22): ubuntu-latest +# - All caller repos are PUBLIC → GHA-hosted minutes are free. +# - Targets are linux/amd64 natively; Ubuntu runners skip QEMU that +# our arm64 Mac mini had to emulate through, so builds go ~2-3x +# faster on top of having no queue wait when the Mac mini is busy. +# - No macOS Keychain gymnastics — standard docker/login-action works. +# The self-hosted Mac mini remains in service for private repo +# workflows (see memory: feedback_selfhosted_runner). on: workflow_call: @@ -50,10 +51,7 @@ on: jobs: publish: name: Build & push template image - # Self-hosted mac mini runner — memory[feedback_selfhosted_runner]: - # publish workflows must stay on self-hosted to avoid GHA rate limits. - # Do NOT change to ubuntu-latest. - runs-on: [self-hosted, macos, arm64] + runs-on: ubuntu-latest outputs: image: ${{ steps.tags.outputs.image }} sha: ${{ steps.tags.outputs.sha }} @@ -92,33 +90,15 @@ jobs: echo "sha=${SHA}" >> "$GITHUB_OUTPUT" echo "::notice::Publishing runtime='${RUNTIME}' → ${IMAGE}:latest + :sha-${SHA}" - - name: Configure GHCR auth (write auths map; do NOT call docker login) - # Mirrors publish-canvas-image.yml. `docker login` on the Mac mini - # writes to osxkeychain unconditionally, which fails under the - # locked launchd keychain. Writing the auths map directly works - # for docker/build-push-action without needing login. - shell: bash - env: - GHCR_USER: ${{ github.actor }} - GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - set -eu - mkdir -p "${RUNNER_TEMP}/docker-config" - AUTH=$(printf '%s:%s' "${GHCR_USER}" "${GHCR_TOKEN}" | base64) - umask 077 - cat > "${RUNNER_TEMP}/docker-config/config.json" <> "${GITHUB_ENV}" - - - name: Set up QEMU - # Apple-silicon runner producing linux/amd64 for x86 tenant hosts. - uses: docker/setup-qemu-action@v4 + - name: Log in to GHCR + uses: docker/login-action@v3 with: - platforms: linux/amd64 + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@v3 - name: Build & push template image to GHCR uses: docker/build-push-action@v6 @@ -138,19 +118,17 @@ jobs: org.opencontainers.image.description=Molecule AI workspace template — ${{ steps.tags.outputs.runtime }} runtime - name: Smoke test the pushed image - # Pull the tag we just pushed and verify the entrypoint at least - # starts. Catches "image pushed but binary missing" regressions - # without needing a full end-to-end provision test. + # Pull the tag we just pushed and verify the entrypoint is set. + # Catches "image pushed but binary missing" regressions without a + # full end-to-end provision test. We don't `docker run` — most + # templates need platform env (WORKSPACE_ID, PLATFORM_URL, etc.) + # to actually boot, so inspection is the right layer here. shell: bash env: IMAGE: ${{ steps.tags.outputs.image }}:sha-${{ steps.tags.outputs.sha }} run: | set -eu docker pull "${IMAGE}" - # Just inspect — most templates need platform env (WORKSPACE_ID, - # PLATFORM_URL, etc.) to actually boot, so we don't `docker run` - # here. Verifying the image is pullable + has an entrypoint is - # enough for a post-push smoke check. docker inspect "${IMAGE}" --format '{{.Config.Entrypoint}} {{.Config.Cmd}}' \ | tee /dev/stderr \ | grep -qE '.' || { echo "::error::Image has empty entrypoint+cmd"; exit 1; }