fix: Scope image build credentials #67

Manually merged
day01 merged 1 commits from fix/0.6-scoped-image-credentials into develop 2026-08-30 16:53:33 +00:00
2 changed files with 12 additions and 2 deletions
Showing only changes of commit c21e87ea3d - Show all commits
+6 -2
View File
@@ -1,39 +1,43 @@
ARG SOURCE_DATE_EPOCH=0

FROM rust:1.95.0-bookworm@sha256:6258907abe69656e41cd992e0b705cdcfabcbbe3db374f92ed2d47121282d4a1 AS source

WORKDIR /src
COPY . .

FROM source AS validation
ARG TARGETARCH
RUN --mount=type=cache,id=syncode-cargo-registry-${TARGETARCH},target=/usr/local/cargo/registry,sharing=locked \
--mount=type=cache,id=syncode-validation-${TARGETARCH},target=/src/target,sharing=locked \
cargo fmt --check \
&& cargo clippy --workspace --all-targets --all-features -- -D warnings \
&& cargo test --workspace --all-targets --all-features \
&& ./scripts/check-architecture.sh \
&& ./scripts/check-rust-loc.sh

FROM source AS builder
ARG TARGETARCH
RUN --mount=type=cache,id=syncode-cargo-registry-${TARGETARCH},target=/usr/local/cargo/registry,sharing=locked \
--mount=type=cache,id=syncode-release-${TARGETARCH},target=/src/target,sharing=locked \
cargo build --locked --release \
&& install -D -m 0755 target/release/syncode-runner /out/syncode-runner

FROM debian:bookworm-slim@sha256:7b140f374b289a7c2befc338f42ebe6441b7ea838a042bbd5acbfca6ec875818

ARG VERSION=dev

LABEL org.opencontainers.image.source="https://syncode.sh/syncode/runner"
LABEL org.opencontainers.image.version="${VERSION}"

COPY --from=source /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /out/syncode-runner /usr/local/bin/syncode-runner
COPY --chmod=0755 scripts/container-entrypoint.sh /usr/local/bin/syncode-runner-entrypoint

VOLUME ["/var/lib/syncode-runner"]

ENTRYPOINT ["/usr/local/bin/syncode-runner-entrypoint"]
CMD ["daemon"]
ARG SOURCE_DATE_EPOCH=0

FROM rust:1.95.0-bookworm@sha256:6258907abe69656e41cd992e0b705cdcfabcbbe3db374f92ed2d47121282d4a1 AS source

WORKDIR /src
COPY . .

FROM source AS validation
ARG TARGETARCH
RUN --mount=type=cache,id=syncode-cargo-registry-${TARGETARCH},target=/usr/local/cargo/registry,sharing=locked \
--mount=type=cache,id=syncode-validation-${TARGETARCH},target=/src/target,sharing=locked \
--mount=type=secret,id=syncode_git_config,target=/root/.gitconfig,required=true \
export CARGO_NET_GIT_FETCH_WITH_CLI=true \
&& cargo fmt --check \
&& cargo clippy --workspace --all-targets --all-features -- -D warnings \
&& cargo test --workspace --all-targets --all-features \
&& ./scripts/check-architecture.sh \
&& ./scripts/check-rust-loc.sh

FROM source AS builder
ARG TARGETARCH
RUN --mount=type=cache,id=syncode-cargo-registry-${TARGETARCH},target=/usr/local/cargo/registry,sharing=locked \
--mount=type=cache,id=syncode-release-${TARGETARCH},target=/src/target,sharing=locked \
--mount=type=secret,id=syncode_git_config,target=/root/.gitconfig,required=true \
export CARGO_NET_GIT_FETCH_WITH_CLI=true \
&& cargo build --locked --release \
&& install -D -m 0755 target/release/syncode-runner /out/syncode-runner

FROM debian:bookworm-slim@sha256:7b140f374b289a7c2befc338f42ebe6441b7ea838a042bbd5acbfca6ec875818

ARG VERSION=dev

LABEL org.opencontainers.image.source="https://syncode.sh/syncode/runner"
LABEL org.opencontainers.image.version="${VERSION}"

COPY --from=source /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /out/syncode-runner /usr/local/bin/syncode-runner
COPY --chmod=0755 scripts/container-entrypoint.sh /usr/local/bin/syncode-runner-entrypoint

VOLUME ["/var/lib/syncode-runner"]

ENTRYPOINT ["/usr/local/bin/syncode-runner-entrypoint"]
CMD ["daemon"]
+6
View File
@@ -1,328 +1,334 @@
name: build-images

on:
push:
branches: [develop, main]
tags: ["v*"]
workflow_dispatch:

concurrency:
group: runner-build-images-${{ github.ref_name }}
cancel-in-progress: ${{ github.ref_type != 'tag' }}

env:
RUNNER_IMAGE: syncode.sh/syncode/runner
JOB_IMAGE: syncode.sh/syncode/runner-job

jobs:
resolve:
runs-on: ubuntu-latest
outputs:
operation: ${{ steps.release.outputs.operation }}
product_version: ${{ steps.release.outputs.product_version }}
runner_source: ${{ steps.release.outputs.runner_source }}
runner_tags: ${{ steps.release.outputs.runner_tags }}
job_source: ${{ steps.release.outputs.job_source }}
job_tags: ${{ steps.release.outputs.job_tags }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- id: release
name: Resolve release
run: |
set -euo pipefail
SHA="$(git rev-parse --short HEAD)"
BASE_VERSION="$(tr -d '[:space:]' < VERSION)"
OPERATION=build
NAMES=
JOB_NAMES=
case "${GITHUB_REF}" in
refs/tags/*)
VERSION="${BASE_VERSION}"
test "${GITHUB_REF_NAME#v}" = "${BASE_VERSION}"
OPERATION=promote
;;
refs/heads/develop)
VERSION="${BASE_VERSION}-dev"
NAMES="${SHA} develop ${VERSION}"
JOB_NAMES="ubuntu-24.04-${SHA} ubuntu-24.04-develop ubuntu-24.04-${VERSION}"
;;
refs/heads/main)
VERSION="${BASE_VERSION}"
NAMES="${SHA} main latest"
JOB_NAMES="ubuntu-24.04-${SHA} ubuntu-24.04-${VERSION} ubuntu-24.04"
;;
*)
echo "unsupported ref: ${GITHUB_REF}"
exit 1
;;
esac
RUNNER_HASH="$( { git ls-files -s -- . \
':(exclude).gitea/**' ':(exclude)images/**' ':(exclude)tools/**' \
':(exclude)scripts/release/**' ':(exclude)*.md' ':(exclude)docs/**' \
':(exclude)LICENSE'
printf 'version=%s\n' "${VERSION}"; } | git hash-object --stdin | cut -c1-12)"
JOB_HASH="$(git ls-files -s images crates/runner-workflow-github-actions/assets \
| git hash-object --stdin | cut -c1-12)"
refs() {
local image="$1" separator=""
shift
for name in "$@"; do
printf '%s%s:%s' "${separator}" "${image}" "${name}"
separator=,
done
}
{
echo "operation=${OPERATION}"
echo "product_version=${VERSION}"
echo "runner_source=${RUNNER_IMAGE}:src-${RUNNER_HASH}"
echo "runner_tags=$(refs "${RUNNER_IMAGE}" ${NAMES})"
echo "job_source=${JOB_IMAGE}:ubuntu-24.04-src-${JOB_HASH}"
echo "job_tags=$(refs "${JOB_IMAGE}" ${JOB_NAMES})"
} >> "${GITHUB_OUTPUT}"

validate:
needs: resolve
if: ${{ needs.resolve.outputs.operation == 'build' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
target: validation
outputs: type=cacheonly

runner_published:
needs: resolve
if: ${{ needs.resolve.outputs.operation == 'build' }}
runs-on: ubuntu-latest
outputs:
exists: ${{ steps.check.outputs.exists }}
steps:
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- id: check
name: Look for the image in the registry
env:
SOURCE: ${{ needs.resolve.outputs.runner_source }}
run: |
set -euo pipefail
if docker buildx imagetools inspect "${SOURCE}" >/dev/null 2>&1; then
echo "exists=true" >> "${GITHUB_OUTPUT}"
else
echo "exists=false" >> "${GITHUB_OUTPUT}"
fi

# Each architecture builds natively on a runner labeled for it, rather than
# one job cross-building both under QEMU — arm64 under emulation was slow
# enough to stall the whole CI queue behind it (meta issue #42).
runner-image-amd64:
needs: [resolve, validate, runner_published]
if: ${{ needs.resolve.outputs.operation == 'build' && needs.runner_published.outputs.exists == 'false' }}
runs-on: syncode-linux-amd64
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
platforms: linux/amd64
provenance: false
build-args: |
SOURCE_DATE_EPOCH=0
VERSION=${{ needs.resolve.outputs.product_version }}
tags: ${{ needs.resolve.outputs.runner_source }}-amd64
cache-from: type=registry,ref=syncode.sh/syncode/runner:buildcache-amd64
cache-to: type=registry,ref=syncode.sh/syncode/runner:buildcache-amd64,mode=max
outputs: type=registry,rewrite-timestamp=true

runner-image-arm64:
needs: [resolve, validate, runner_published]
if: ${{ needs.resolve.outputs.operation == 'build' && needs.runner_published.outputs.exists == 'false' }}
runs-on: syncode-linux-arm64
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
platforms: linux/arm64
provenance: false
build-args: |
SOURCE_DATE_EPOCH=0
VERSION=${{ needs.resolve.outputs.product_version }}
tags: ${{ needs.resolve.outputs.runner_source }}-arm64
cache-from: type=registry,ref=syncode.sh/syncode/runner:buildcache-arm64
cache-to: type=registry,ref=syncode.sh/syncode/runner:buildcache-arm64,mode=max
outputs: type=registry,rewrite-timestamp=true

runner-image:
needs: [resolve, runner_published, runner-image-amd64, runner-image-arm64]
if: ${{ needs.resolve.outputs.operation == 'build' }}
runs-on: ubuntu-latest
steps:
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- name: Combine per-arch images and point the release tags at them
env:
SOURCE: ${{ needs.resolve.outputs.runner_source }}
TAGS: ${{ needs.resolve.outputs.runner_tags }}
EXISTS: ${{ needs.runner_published.outputs.exists }}
run: |
set -euo pipefail
if [ "${EXISTS}" = "false" ]; then
docker buildx imagetools create --tag "${SOURCE}" "${SOURCE}-amd64" "${SOURCE}-arm64"
fi
for REF in ${TAGS//,/ }; do
docker buildx imagetools create --tag "${REF}" "${SOURCE}"
done

job_published:
needs: resolve
if: ${{ needs.resolve.outputs.operation == 'build' }}
runs-on: ubuntu-latest
outputs:
exists: ${{ steps.check.outputs.exists }}
steps:
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- id: check
name: Look for the image in the registry
env:
SOURCE: ${{ needs.resolve.outputs.job_source }}
run: |
set -euo pipefail
if docker buildx imagetools inspect "${SOURCE}" >/dev/null 2>&1; then
echo "exists=true" >> "${GITHUB_OUTPUT}"
else
echo "exists=false" >> "${GITHUB_OUTPUT}"
fi

job-image-amd64:
needs: [resolve, validate, job_published]
if: ${{ needs.resolve.outputs.operation == 'build' && needs.job_published.outputs.exists == 'false' }}
runs-on: syncode-linux-amd64
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
file: images/ubuntu-24.04/Dockerfile
platforms: linux/amd64
provenance: false
build-args: SOURCE_DATE_EPOCH=0
tags: ${{ needs.resolve.outputs.job_source }}-amd64
cache-from: type=registry,ref=syncode.sh/syncode/runner-job:buildcache-amd64
cache-to: type=registry,ref=syncode.sh/syncode/runner-job:buildcache-amd64,mode=max
outputs: type=registry,rewrite-timestamp=true

job-image-arm64:
needs: [resolve, validate, job_published]
if: ${{ needs.resolve.outputs.operation == 'build' && needs.job_published.outputs.exists == 'false' }}
runs-on: syncode-linux-arm64
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
file: images/ubuntu-24.04/Dockerfile
platforms: linux/arm64
provenance: false
build-args: SOURCE_DATE_EPOCH=0
tags: ${{ needs.resolve.outputs.job_source }}-arm64
cache-from: type=registry,ref=syncode.sh/syncode/runner-job:buildcache-arm64
cache-to: type=registry,ref=syncode.sh/syncode/runner-job:buildcache-arm64,mode=max
outputs: type=registry,rewrite-timestamp=true

job-image:
needs: [resolve, job_published, job-image-amd64, job-image-arm64]
if: ${{ needs.resolve.outputs.operation == 'build' }}
runs-on: ubuntu-latest
steps:
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- name: Combine per-arch images and point the release tags at them
env:
SOURCE: ${{ needs.resolve.outputs.job_source }}
TAGS: ${{ needs.resolve.outputs.job_tags }}
EXISTS: ${{ needs.job_published.outputs.exists }}
run: |
set -euo pipefail
if [ "${EXISTS}" = "false" ]; then
docker buildx imagetools create --tag "${SOURCE}" "${SOURCE}-amd64" "${SOURCE}-arm64"
fi
for REF in ${TAGS//,/ }; do
docker buildx imagetools create --tag "${REF}" "${SOURCE}"
done

promote:
needs: resolve
if: ${{ needs.resolve.outputs.operation == 'promote' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- name: Promote release manifests
env:
PRODUCT_VERSION: ${{ needs.resolve.outputs.product_version }}
run: |
set -euo pipefail
MAIN_SHA="$(git ls-remote origin refs/heads/main | awk 'NR == 1 {print $1}')"
test -n "${MAIN_SHA}"
test "$(git rev-parse HEAD)" = "${MAIN_SHA}"
docker buildx imagetools create \
--tag "${RUNNER_IMAGE}:${PRODUCT_VERSION}" \
"${RUNNER_IMAGE}:main"
docker buildx imagetools create \
--tag "${JOB_IMAGE}:ubuntu-24.04-${PRODUCT_VERSION}" \
"${JOB_IMAGE}:ubuntu-24.04"
name: build-images

on:
push:
branches: [develop, main]
tags: ["v*"]
workflow_dispatch:

concurrency:
group: runner-build-images-${{ github.ref_name }}
cancel-in-progress: ${{ github.ref_type != 'tag' }}

env:
RUNNER_IMAGE: syncode.sh/syncode/runner
JOB_IMAGE: syncode.sh/syncode/runner-job

jobs:
resolve:
runs-on: ubuntu-latest
outputs:
operation: ${{ steps.release.outputs.operation }}
product_version: ${{ steps.release.outputs.product_version }}
runner_source: ${{ steps.release.outputs.runner_source }}
runner_tags: ${{ steps.release.outputs.runner_tags }}
job_source: ${{ steps.release.outputs.job_source }}
job_tags: ${{ steps.release.outputs.job_tags }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- id: release
name: Resolve release
run: |
set -euo pipefail
SHA="$(git rev-parse --short HEAD)"
BASE_VERSION="$(tr -d '[:space:]' < VERSION)"
OPERATION=build
NAMES=
JOB_NAMES=
case "${GITHUB_REF}" in
refs/tags/*)
VERSION="${BASE_VERSION}"
test "${GITHUB_REF_NAME#v}" = "${BASE_VERSION}"
OPERATION=promote
;;
refs/heads/develop)
VERSION="${BASE_VERSION}-dev"
NAMES="${SHA} develop ${VERSION}"
JOB_NAMES="ubuntu-24.04-${SHA} ubuntu-24.04-develop ubuntu-24.04-${VERSION}"
;;
refs/heads/main)
VERSION="${BASE_VERSION}"
NAMES="${SHA} main latest"
JOB_NAMES="ubuntu-24.04-${SHA} ubuntu-24.04-${VERSION} ubuntu-24.04"
;;
*)
echo "unsupported ref: ${GITHUB_REF}"
exit 1
;;
esac
RUNNER_HASH="$( { git ls-files -s -- . \
':(exclude).gitea/**' ':(exclude)images/**' ':(exclude)tools/**' \
':(exclude)scripts/release/**' ':(exclude)*.md' ':(exclude)docs/**' \
':(exclude)LICENSE'
printf 'version=%s\n' "${VERSION}"; } | git hash-object --stdin | cut -c1-12)"
JOB_HASH="$(git ls-files -s images crates/runner-workflow-github-actions/assets \
| git hash-object --stdin | cut -c1-12)"
refs() {
local image="$1" separator=""
shift
for name in "$@"; do
printf '%s%s:%s' "${separator}" "${image}" "${name}"
separator=,
done
}
{
echo "operation=${OPERATION}"
echo "product_version=${VERSION}"
echo "runner_source=${RUNNER_IMAGE}:src-${RUNNER_HASH}"
echo "runner_tags=$(refs "${RUNNER_IMAGE}" ${NAMES})"
echo "job_source=${JOB_IMAGE}:ubuntu-24.04-src-${JOB_HASH}"
echo "job_tags=$(refs "${JOB_IMAGE}" ${JOB_NAMES})"
} >> "${GITHUB_OUTPUT}"

validate:
needs: resolve
if: ${{ needs.resolve.outputs.operation == 'build' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
target: validation
outputs: type=cacheonly
secrets: |
"syncode_git_config=${{ secrets.SYNCODE_GIT_CONFIG }}"

runner_published:
needs: resolve
if: ${{ needs.resolve.outputs.operation == 'build' }}
runs-on: ubuntu-latest
outputs:
exists: ${{ steps.check.outputs.exists }}
steps:
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- id: check
name: Look for the image in the registry
env:
SOURCE: ${{ needs.resolve.outputs.runner_source }}
run: |
set -euo pipefail
if docker buildx imagetools inspect "${SOURCE}" >/dev/null 2>&1; then
echo "exists=true" >> "${GITHUB_OUTPUT}"
else
echo "exists=false" >> "${GITHUB_OUTPUT}"
fi

# Each architecture builds natively on a runner labeled for it, rather than
# one job cross-building both under QEMU — arm64 under emulation was slow
# enough to stall the whole CI queue behind it (meta issue #42).
runner-image-amd64:
needs: [resolve, validate, runner_published]
if: ${{ needs.resolve.outputs.operation == 'build' && needs.runner_published.outputs.exists == 'false' }}
runs-on: syncode-linux-amd64
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
platforms: linux/amd64
provenance: false
build-args: |
SOURCE_DATE_EPOCH=0
VERSION=${{ needs.resolve.outputs.product_version }}
tags: ${{ needs.resolve.outputs.runner_source }}-amd64
cache-from: type=registry,ref=syncode.sh/syncode/runner:buildcache-amd64
cache-to: type=registry,ref=syncode.sh/syncode/runner:buildcache-amd64,mode=max
outputs: type=registry,rewrite-timestamp=true
secrets: |
"syncode_git_config=${{ secrets.SYNCODE_GIT_CONFIG }}"

runner-image-arm64:
needs: [resolve, validate, runner_published]
if: ${{ needs.resolve.outputs.operation == 'build' && needs.runner_published.outputs.exists == 'false' }}
runs-on: syncode-linux-arm64
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
platforms: linux/arm64
provenance: false
build-args: |
SOURCE_DATE_EPOCH=0
VERSION=${{ needs.resolve.outputs.product_version }}
tags: ${{ needs.resolve.outputs.runner_source }}-arm64
cache-from: type=registry,ref=syncode.sh/syncode/runner:buildcache-arm64
cache-to: type=registry,ref=syncode.sh/syncode/runner:buildcache-arm64,mode=max
outputs: type=registry,rewrite-timestamp=true
secrets: |
"syncode_git_config=${{ secrets.SYNCODE_GIT_CONFIG }}"

runner-image:
needs: [resolve, runner_published, runner-image-amd64, runner-image-arm64]
if: ${{ needs.resolve.outputs.operation == 'build' }}
runs-on: ubuntu-latest
steps:
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- name: Combine per-arch images and point the release tags at them
env:
SOURCE: ${{ needs.resolve.outputs.runner_source }}
TAGS: ${{ needs.resolve.outputs.runner_tags }}
EXISTS: ${{ needs.runner_published.outputs.exists }}
run: |
set -euo pipefail
if [ "${EXISTS}" = "false" ]; then
docker buildx imagetools create --tag "${SOURCE}" "${SOURCE}-amd64" "${SOURCE}-arm64"
fi
for REF in ${TAGS//,/ }; do
docker buildx imagetools create --tag "${REF}" "${SOURCE}"
done

job_published:
needs: resolve
if: ${{ needs.resolve.outputs.operation == 'build' }}
runs-on: ubuntu-latest
outputs:
exists: ${{ steps.check.outputs.exists }}
steps:
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- id: check
name: Look for the image in the registry
env:
SOURCE: ${{ needs.resolve.outputs.job_source }}
run: |
set -euo pipefail
if docker buildx imagetools inspect "${SOURCE}" >/dev/null 2>&1; then
echo "exists=true" >> "${GITHUB_OUTPUT}"
else
echo "exists=false" >> "${GITHUB_OUTPUT}"
fi

job-image-amd64:
needs: [resolve, validate, job_published]
if: ${{ needs.resolve.outputs.operation == 'build' && needs.job_published.outputs.exists == 'false' }}
runs-on: syncode-linux-amd64
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
file: images/ubuntu-24.04/Dockerfile
platforms: linux/amd64
provenance: false
build-args: SOURCE_DATE_EPOCH=0
tags: ${{ needs.resolve.outputs.job_source }}-amd64
cache-from: type=registry,ref=syncode.sh/syncode/runner-job:buildcache-amd64
cache-to: type=registry,ref=syncode.sh/syncode/runner-job:buildcache-amd64,mode=max
outputs: type=registry,rewrite-timestamp=true

job-image-arm64:
needs: [resolve, validate, job_published]
if: ${{ needs.resolve.outputs.operation == 'build' && needs.job_published.outputs.exists == 'false' }}
runs-on: syncode-linux-arm64
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: .
file: images/ubuntu-24.04/Dockerfile
platforms: linux/arm64
provenance: false
build-args: SOURCE_DATE_EPOCH=0
tags: ${{ needs.resolve.outputs.job_source }}-arm64
cache-from: type=registry,ref=syncode.sh/syncode/runner-job:buildcache-arm64
cache-to: type=registry,ref=syncode.sh/syncode/runner-job:buildcache-arm64,mode=max
outputs: type=registry,rewrite-timestamp=true

job-image:
needs: [resolve, job_published, job-image-amd64, job-image-arm64]
if: ${{ needs.resolve.outputs.operation == 'build' }}
runs-on: ubuntu-latest
steps:
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- name: Combine per-arch images and point the release tags at them
env:
SOURCE: ${{ needs.resolve.outputs.job_source }}
TAGS: ${{ needs.resolve.outputs.job_tags }}
EXISTS: ${{ needs.job_published.outputs.exists }}
run: |
set -euo pipefail
if [ "${EXISTS}" = "false" ]; then
docker buildx imagetools create --tag "${SOURCE}" "${SOURCE}-amd64" "${SOURCE}-arm64"
fi
for REF in ${TAGS//,/ }; do
docker buildx imagetools create --tag "${REF}" "${SOURCE}"
done

promote:
needs: resolve
if: ${{ needs.resolve.outputs.operation == 'promote' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262

- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: syncode.sh
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}

- name: Promote release manifests
env:
PRODUCT_VERSION: ${{ needs.resolve.outputs.product_version }}
run: |
set -euo pipefail
MAIN_SHA="$(git ls-remote origin refs/heads/main | awk 'NR == 1 {print $1}')"
test -n "${MAIN_SHA}"
test "$(git rev-parse HEAD)" = "${MAIN_SHA}"
docker buildx imagetools create \
--tag "${RUNNER_IMAGE}:${PRODUCT_VERSION}" \
"${RUNNER_IMAGE}:main"
docker buildx imagetools create \
--tag "${JOB_IMAGE}:ubuntu-24.04-${PRODUCT_VERSION}" \
"${JOB_IMAGE}:ubuntu-24.04"