ci: isolate buildx builders on shared evo Docker hosts (#178)
* ci: isolate buildx builders for parallel publish-server-image builds Parallel matrix jobs on shared evo runners raced on ~/.docker/buildx current builder; one job's setup-buildx cleanup then stopped another job's BuildKit during cache export. Use per-job DOCKER_CONFIG, stable builder names, and wire build-push to steps.buildx.outputs.name. Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> * test: avoid biome noTemplateCurlyInString in publish workflow asserts Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: cynarAI <cynarAI@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f07d17e927
commit
b1b76a846e
28
.github/workflows/publish-server-image.yml
vendored
28
.github/workflows/publish-server-image.yml
vendored
@ -3,8 +3,9 @@ name: publish-server-image
|
|||||||
# Release tags publish the source-addressed image used by in-app updates plus the human-readable
|
# Release tags publish the source-addressed image used by in-app updates plus the human-readable
|
||||||
# semver tags. Main publishes `edge`. Pull requests build with a read-only token and an isolated
|
# semver tags. Main publishes `edge`. Pull requests build with a read-only token and an isolated
|
||||||
# cache, so untrusted code can validate the images without receiving package-publish authority.
|
# cache, so untrusted code can validate the images without receiving package-publish authority.
|
||||||
# Self-hosted runners on one host often share ~/.docker; build/publish set DOCKER_CONFIG under
|
# Self-hosted evo runners on one host share a Docker daemon and often ~/.docker; parallel matrix
|
||||||
# RUNNER_TEMP so docker/login-action post-logout cannot evict a concurrent job's GHCR session.
|
# jobs must use DOCKER_CONFIG under RUNNER_TEMP plus a per-job buildx builder name wired into
|
||||||
|
# build-push-action, or setup-buildx --use races and one job's post cleanup stops another's BuildKit.
|
||||||
# `ci-<run>-<image>-<arch>` handoff tags are extra aliases on the per-arch digest; GHCR does not
|
# `ci-<run>-<image>-<arch>` handoff tags are extra aliases on the per-arch digest; GHCR does not
|
||||||
# expose a safe tag-only delete API (DELETE /v2/.../manifests/<tag> is unsupported or digest-scoped),
|
# expose a safe tag-only delete API (DELETE /v2/.../manifests/<tag> is unsupported or digest-scoped),
|
||||||
# so they are left in place and do not affect edge/sha-* manifests assembled in publish.
|
# so they are left in place and do not affect edge/sha-* manifests assembled in publish.
|
||||||
@ -129,7 +130,16 @@ jobs:
|
|||||||
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
|
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
- name: Prepare isolated Docker config directory
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cfg="${RUNNER_TEMP}/docker-config"
|
||||||
|
mkdir -p "$cfg"
|
||||||
|
echo "DOCKER_CONFIG=${cfg}" >> "$GITHUB_ENV"
|
||||||
|
- id: buildx
|
||||||
|
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||||
|
with:
|
||||||
|
name: ci-pr-${{ github.event.pull_request.number }}-${{ matrix.name }}
|
||||||
- name: Resolve the lowercase image namespace
|
- name: Resolve the lowercase image namespace
|
||||||
id: ns
|
id: ns
|
||||||
# GHCR rejects repository names with capitals; the GitHub repository slug has them.
|
# GHCR rejects repository names with capitals; the GitHub repository slug has them.
|
||||||
@ -141,6 +151,7 @@ jobs:
|
|||||||
tags: type=sha,prefix=sha-
|
tags: type=sha,prefix=sha-
|
||||||
- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||||
with:
|
with:
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
context: ${{ matrix.context }}
|
context: ${{ matrix.context }}
|
||||||
file: ${{ matrix.dockerfile }}
|
file: ${{ matrix.dockerfile }}
|
||||||
push: false
|
push: false
|
||||||
@ -197,7 +208,10 @@ jobs:
|
|||||||
cfg="${RUNNER_TEMP}/docker-config"
|
cfg="${RUNNER_TEMP}/docker-config"
|
||||||
mkdir -p "$cfg"
|
mkdir -p "$cfg"
|
||||||
echo "DOCKER_CONFIG=${cfg}" >> "$GITHUB_ENV"
|
echo "DOCKER_CONFIG=${cfg}" >> "$GITHUB_ENV"
|
||||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
- id: buildx
|
||||||
|
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||||
|
with:
|
||||||
|
name: ci-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.name }}-${{ matrix.arch }}
|
||||||
- name: Log in to GHCR
|
- name: Log in to GHCR
|
||||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||||
with:
|
with:
|
||||||
@ -217,6 +231,7 @@ jobs:
|
|||||||
- id: build
|
- id: build
|
||||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||||
with:
|
with:
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
context: ${{ matrix.context }}
|
context: ${{ matrix.context }}
|
||||||
file: ${{ matrix.dockerfile }}
|
file: ${{ matrix.dockerfile }}
|
||||||
platforms: linux/${{ matrix.arch }}
|
platforms: linux/${{ matrix.arch }}
|
||||||
@ -267,7 +282,10 @@ jobs:
|
|||||||
cfg="${RUNNER_TEMP}/docker-config"
|
cfg="${RUNNER_TEMP}/docker-config"
|
||||||
mkdir -p "$cfg"
|
mkdir -p "$cfg"
|
||||||
echo "DOCKER_CONFIG=${cfg}" >> "$GITHUB_ENV"
|
echo "DOCKER_CONFIG=${cfg}" >> "$GITHUB_ENV"
|
||||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
- id: buildx
|
||||||
|
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||||
|
with:
|
||||||
|
name: ci-${{ github.run_id }}-${{ github.run_attempt }}-publish-${{ matrix.name }}
|
||||||
- name: Log in to GHCR
|
- name: Log in to GHCR
|
||||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||||
with:
|
with:
|
||||||
|
|||||||
@ -62,6 +62,20 @@ describe("server image publish workflow", () => {
|
|||||||
expect(workflowText).toContain("ci-${GITHUB_RUN_ID}-");
|
expect(workflowText).toContain("ci-${GITHUB_RUN_ID}-");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("isolates buildx per matrix job on shared self-hosted Docker hosts", () => {
|
||||||
|
expect(workflowText).toContain('echo "DOCKER_CONFIG=${cfg}" >> "$GITHUB_ENV"');
|
||||||
|
expect(workflowText).toMatch(/builder:\s+\$\{\{\s*steps\.buildx\.outputs\.name\s*\}\}/);
|
||||||
|
expect(workflowText).toMatch(
|
||||||
|
/name: ci-\$\{\{ github\.run_id \}\}-\$\{\{ github\.run_attempt \}\}-\$\{\{ matrix\.name \}\}-\$\{\{ matrix\.arch \}\}/,
|
||||||
|
);
|
||||||
|
expect(workflowText).toMatch(
|
||||||
|
/name: ci-pr-\$\{\{ github\.event\.pull_request\.number \}\}-\$\{\{ matrix\.name \}\}/,
|
||||||
|
);
|
||||||
|
expect(workflowText).toMatch(
|
||||||
|
/name: ci-\$\{\{ github\.run_id \}\}-\$\{\{ github\.run_attempt \}\}-publish-\$\{\{ matrix\.name \}\}/,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("isolates Docker registry auth per job and does not delete handoff tags via the registry API", () => {
|
it("isolates Docker registry auth per job and does not delete handoff tags via the registry API", () => {
|
||||||
expect(workflowText).toContain('echo "DOCKER_CONFIG=${cfg}" >> "$GITHUB_ENV"');
|
expect(workflowText).toContain('echo "DOCKER_CONFIG=${cfg}" >> "$GITHUB_ENV"');
|
||||||
expect(workflowText).toContain("Prepare isolated Docker config directory");
|
expect(workflowText).toContain("Prepare isolated Docker config directory");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user