mirror of
https://github.com/element-hq/matrix-authentication-service.git
synced 2026-06-04 08:11:49 +00:00
Split multi-arch Docker build into parallel jobs
- Modify Dockerfile to build single architecture based on TARGETARCH instead of cross-compiling both targets in one run - Replace single build-image job with matrix job (amd64, arm64) - Add finalize-image job that creates multi-arch manifests using `docker buildx imagetools create` and signs the final images - Each architecture gets its own build cache This enables parallel builds of each architecture, reducing total build time by running both simultaneously rather than sequentially.
This commit is contained in:
committed by
Quentin Gliech
parent
750de33486
commit
c2dc7c11a9
+280
-53
@@ -207,25 +207,17 @@ jobs:
|
||||
name: mas-cli-x86_64-linux
|
||||
path: mas-cli-x86_64-linux.tar.gz
|
||||
|
||||
build-image:
|
||||
name: Build and push Docker image
|
||||
compute-image-meta:
|
||||
name: Compute Docker image metadata
|
||||
if: github.event_name == 'push' || github.event.label.name == 'Z-Build-Workflow'
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
outputs:
|
||||
metadata: ${{ steps.metadata.outputs.result }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
|
||||
needs:
|
||||
- compute-version
|
||||
|
||||
env:
|
||||
VERGEN_GIT_DESCRIBE: ${{ needs.compute-version.outputs.describe }}
|
||||
SOURCE_DATE_EPOCH: ${{ needs.compute-version.outputs.timestamp }}
|
||||
outputs:
|
||||
regular-json: ${{ steps.meta.outputs.json }}
|
||||
debug-json: ${{ steps.meta-debug.outputs.json }}
|
||||
|
||||
steps:
|
||||
- name: Docker meta
|
||||
@@ -247,6 +239,15 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
# GitHub's license detection (via Licensee) can only report a single
|
||||
# SPDX identifier and still emits the legacy `AGPL-3.0` form, which
|
||||
# `metadata-action` would otherwise propagate as-is. Override it with
|
||||
# the project's actual dual-license SPDX expression so the image
|
||||
# advertises both halves of the dual licensing.
|
||||
labels: |
|
||||
org.opencontainers.image.licenses=AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
annotations: |
|
||||
org.opencontainers.image.licenses=AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
|
||||
- name: Docker meta (debug variant)
|
||||
id: meta-debug
|
||||
@@ -266,10 +267,63 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
labels: |
|
||||
org.opencontainers.image.licenses=AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
annotations: |
|
||||
org.opencontainers.image.licenses=AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
|
||||
- name: Setup Cosign
|
||||
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
|
||||
# Stage the labels bake files under predictable names (the metadata-action
|
||||
# writes them under a random temp dir with the same base name) and ship
|
||||
# them to `build-image` as an artifact. We deliberately only pass through
|
||||
# `bake-file-labels` (not `bake-file-annotations`): the per-arch images
|
||||
# then carry the same config labels as today, while annotations are only
|
||||
# applied at the index level in `finalize-image` — matching `:latest`'s
|
||||
# shape and sidestepping `metadata-action`'s empty-value annotations
|
||||
# which would otherwise trip `docker buildx imagetools create`.
|
||||
- name: Stage bake files
|
||||
env:
|
||||
REGULAR_FILE: ${{ steps.meta.outputs.bake-file-labels }}
|
||||
DEBUG_FILE: ${{ steps.meta-debug.outputs.bake-file-labels }}
|
||||
run: |
|
||||
mkdir -p /tmp/bake
|
||||
cp "$REGULAR_FILE" /tmp/bake/regular.json
|
||||
cp "$DEBUG_FILE" /tmp/bake/debug.json
|
||||
|
||||
- name: Upload bake files
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: bake-files
|
||||
path: /tmp/bake/
|
||||
retention-days: 1
|
||||
|
||||
build-image:
|
||||
name: Build Docker image (${{ matrix.arch }})
|
||||
if: github.event_name == 'push' || github.event.label.name == 'Z-Build-Workflow'
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
|
||||
needs:
|
||||
- compute-version
|
||||
- compute-image-meta
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [amd64, arm64]
|
||||
|
||||
env:
|
||||
VERGEN_GIT_DESCRIBE: ${{ needs.compute-version.outputs.describe }}
|
||||
SOURCE_DATE_EPOCH: ${{ needs.compute-version.outputs.timestamp }}
|
||||
# Comma-separated list of registries to push each per-arch image to.
|
||||
# The oci-push registry is only included on `push` events because the
|
||||
# Tailscale + Vault login below requires the right OIDC token.
|
||||
IMAGES: ghcr.io/element-hq/matrix-authentication-service${{ github.event_name == 'push' && ',oci-push.vpn.infra.element.io/matrix-authentication-service' || '' }}
|
||||
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
with:
|
||||
@@ -323,7 +377,13 @@ jobs:
|
||||
username: ${{ steps.import-secrets.outputs.OCI_USERNAME }}
|
||||
password: ${{ steps.import-secrets.outputs.OCI_PASSWORD }}
|
||||
|
||||
- name: Build and push
|
||||
- name: Download bake files
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
name: bake-files
|
||||
path: /tmp/bake
|
||||
|
||||
- name: Build and push by digest
|
||||
id: bake
|
||||
uses: docker/bake-action@a66e1c87e2eca0503c343edf1d208c716d54b8a8 # v7.1.0
|
||||
env:
|
||||
@@ -337,35 +397,185 @@ jobs:
|
||||
with:
|
||||
files: |
|
||||
./docker-bake.hcl
|
||||
cwd://${{ steps.meta.outputs.bake-file }}
|
||||
cwd://${{ steps.meta-debug.outputs.bake-file }}
|
||||
cwd:///tmp/bake/regular.json
|
||||
cwd:///tmp/bake/debug.json
|
||||
set: |
|
||||
base.output=type=image,push=true
|
||||
base.cache-from=type=registry,ref=${{ env.BUILDCACHE }}:buildcache
|
||||
base.cache-to=type=registry,ref=${{ env.BUILDCACHE }}:buildcache,mode=max
|
||||
*.platform=linux/${{ matrix.arch }}
|
||||
*.output=type=image,"name=${{ env.IMAGES }}",push-by-digest=true,name-canonical=true,push=true
|
||||
*.cache-from=type=registry,ref=${{ env.BUILDCACHE }}:buildcache-${{ matrix.arch }}
|
||||
*.cache-to=type=registry,ref=${{ env.BUILDCACHE }}:buildcache-${{ matrix.arch }},mode=max
|
||||
|
||||
- name: Transform bake output
|
||||
# This transforms the output to an object which looks like this:
|
||||
# { regular: { digest: "…", tags: ["…", "…"] }, debug: { digest: "…", tags: ["…"] }, … }
|
||||
# We use github-script rather than shelling out to jq because the bake
|
||||
# metadata can exceed the shell ARG_MAX limit when expanded.
|
||||
id: metadata
|
||||
# We use github-script rather than shelling out to jq because the bake
|
||||
# metadata can exceed the shell ARG_MAX limit when inherited as an env
|
||||
# var by an exec'd jq.
|
||||
- name: Export digests
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
env:
|
||||
STEPS_BAKE_OUTPUTS_METADATA: ${{ steps.bake.outputs.metadata }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
with:
|
||||
script: |
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const bakeOutput = JSON.parse(process.env.STEPS_BAKE_OUTPUTS_METADATA);
|
||||
const metadata = {};
|
||||
for (const [key, value] of Object.entries(bakeOutput)) {
|
||||
if (value && typeof value === 'object' && ('containerimage.digest' in value)) {
|
||||
metadata[key] = {
|
||||
digest: value['containerimage.digest'],
|
||||
tags: value['image.name'].split(','),
|
||||
};
|
||||
const arch = process.env.ARCH;
|
||||
fs.mkdirSync('/tmp/digests', { recursive: true });
|
||||
for (const target of ['regular', 'debug']) {
|
||||
const digest = bakeOutput[target]?.['containerimage.digest'];
|
||||
if (!digest) {
|
||||
throw new Error(`Missing containerimage.digest for target ${target}`);
|
||||
}
|
||||
fs.writeFileSync(path.join('/tmp/digests', `${target}-${arch}`), digest);
|
||||
}
|
||||
return metadata;
|
||||
|
||||
- name: Upload digests
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: digests-${{ matrix.arch }}
|
||||
path: /tmp/digests/*
|
||||
retention-days: 1
|
||||
|
||||
finalize-image:
|
||||
name: Create multi-arch manifests
|
||||
if: github.event_name == 'push' || github.event.label.name == 'Z-Build-Workflow'
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
needs:
|
||||
- build-image
|
||||
- compute-image-meta
|
||||
|
||||
outputs:
|
||||
metadata: ${{ steps.output.outputs.metadata }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
pattern: digests-*
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Setup Cosign
|
||||
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# See `build-image` for why the Element OCI Registry login is gated on
|
||||
# `push` events.
|
||||
- name: Tailscale
|
||||
if: github.event_name == 'push'
|
||||
uses: tailscale/github-action@53acf823325fe9ca47f4cdaa951f90b4b0de5bb9 # v4.1.1
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
audience: ${{ secrets.TS_AUDIENCE }}
|
||||
tags: tag:github-actions
|
||||
|
||||
- name: Compute vault jwt role name
|
||||
id: vault-jwt-role
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
echo "role_name=github_service_management_$( echo "${{ github.repository }}" | sed -r 's|[/-]|_|g')" | tee -a "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Get team registry token
|
||||
id: import-secrets
|
||||
if: github.event_name == 'push'
|
||||
uses: hashicorp/vault-action@4c06c5ccf5c0761b6029f56cfb1dcf5565918a3b # v3.4.0
|
||||
with:
|
||||
url: https://vault.infra.ci.i.element.dev
|
||||
role: ${{ steps.vault-jwt-role.outputs.role_name }}
|
||||
path: service-management/github-actions
|
||||
jwtGithubAudience: https://vault.infra.ci.i.element.dev
|
||||
method: jwt
|
||||
secrets: |
|
||||
services/backend-repositories/secret/data/oci.element.io username | OCI_USERNAME ;
|
||||
services/backend-repositories/secret/data/oci.element.io password | OCI_PASSWORD ;
|
||||
|
||||
- name: Login to Element OCI Registry
|
||||
if: github.event_name == 'push'
|
||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||
with:
|
||||
registry: oci-push.vpn.infra.element.io
|
||||
username: ${{ steps.import-secrets.outputs.OCI_USERNAME }}
|
||||
password: ${{ steps.import-secrets.outputs.OCI_PASSWORD }}
|
||||
|
||||
- name: Create regular manifest
|
||||
env:
|
||||
META_JSON: ${{ needs.compute-image-meta.outputs.regular-json }}
|
||||
run: |
|
||||
REGULAR_AMD64=$(cat /tmp/digests/regular-amd64)
|
||||
REGULAR_ARM64=$(cat /tmp/digests/regular-arm64)
|
||||
# Build `-t TAG` and `--annotation index:NAME=VALUE` args into a bash
|
||||
# array so that values containing spaces survive shell word-splitting.
|
||||
# We keep the `index:` prefix so the annotations land on the index
|
||||
# manifest itself rather than getting applied at the default manifest
|
||||
# level. Empty-valued entries are filtered as a safety net (the bake
|
||||
# step's annotation file is already pre-filtered upstream).
|
||||
declare -a ARGS=()
|
||||
while IFS= read -r tag; do
|
||||
ARGS+=(-t "$tag")
|
||||
done < <(jq -r '.tags[]' <<< "$META_JSON")
|
||||
while IFS= read -r annotation; do
|
||||
ARGS+=(--annotation "$annotation")
|
||||
done < <(jq -r '
|
||||
.annotations
|
||||
| map(select(startswith("index:")))
|
||||
| map(select(endswith("=") | not))
|
||||
| .[]
|
||||
' <<< "$META_JSON")
|
||||
docker buildx imagetools create \
|
||||
"${ARGS[@]}" \
|
||||
"ghcr.io/element-hq/matrix-authentication-service@$REGULAR_AMD64" \
|
||||
"ghcr.io/element-hq/matrix-authentication-service@$REGULAR_ARM64"
|
||||
|
||||
- name: Create debug manifest
|
||||
env:
|
||||
META_DEBUG_JSON: ${{ needs.compute-image-meta.outputs.debug-json }}
|
||||
run: |
|
||||
DEBUG_AMD64=$(cat /tmp/digests/debug-amd64)
|
||||
DEBUG_ARM64=$(cat /tmp/digests/debug-arm64)
|
||||
declare -a ARGS=()
|
||||
while IFS= read -r tag; do
|
||||
ARGS+=(-t "$tag")
|
||||
done < <(jq -r '.tags[]' <<< "$META_DEBUG_JSON")
|
||||
while IFS= read -r annotation; do
|
||||
ARGS+=(--annotation "$annotation")
|
||||
done < <(jq -r '
|
||||
.annotations
|
||||
| map(select(startswith("index:")))
|
||||
| map(select(endswith("=") | not))
|
||||
| .[]
|
||||
' <<< "$META_DEBUG_JSON")
|
||||
docker buildx imagetools create \
|
||||
"${ARGS[@]}" \
|
||||
"ghcr.io/element-hq/matrix-authentication-service@$DEBUG_AMD64" \
|
||||
"ghcr.io/element-hq/matrix-authentication-service@$DEBUG_ARM64"
|
||||
|
||||
- name: Get manifest digests
|
||||
id: manifests
|
||||
env:
|
||||
META_JSON: ${{ needs.compute-image-meta.outputs.regular-json }}
|
||||
META_DEBUG_JSON: ${{ needs.compute-image-meta.outputs.debug-json }}
|
||||
run: |
|
||||
# Inspect the manifest list under the first tag to retrieve its digest
|
||||
REGULAR_TAG=$(jq -r '.tags[0]' <<< "$META_JSON")
|
||||
DEBUG_TAG=$(jq -r '.tags[0]' <<< "$META_DEBUG_JSON")
|
||||
REGULAR_DIGEST=$(docker buildx imagetools inspect "$REGULAR_TAG" --format '{{ json . }}' | jq -r '.manifest.digest')
|
||||
DEBUG_DIGEST=$(docker buildx imagetools inspect "$DEBUG_TAG" --format '{{ json . }}' | jq -r '.manifest.digest')
|
||||
echo "regular=$REGULAR_DIGEST" >> $GITHUB_OUTPUT
|
||||
echo "debug=$DEBUG_DIGEST" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Sign the images with GitHub Actions provided token
|
||||
# Only sign on tags and on commits on main branch
|
||||
@@ -374,8 +584,8 @@ jobs:
|
||||
&& (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
|
||||
|
||||
env:
|
||||
REGULAR_DIGEST: ${{ steps.metadata.outputs.result && fromJSON(steps.metadata.outputs.result).regular.digest }}
|
||||
DEBUG_DIGEST: ${{ steps.metadata.outputs.result && fromJSON(steps.metadata.outputs.result).debug.digest }}
|
||||
REGULAR_DIGEST: ${{ steps.manifests.outputs.regular }}
|
||||
DEBUG_DIGEST: ${{ steps.manifests.outputs.debug }}
|
||||
|
||||
run: |-
|
||||
cosign sign --yes \
|
||||
@@ -385,13 +595,30 @@ jobs:
|
||||
"oci-push.vpn.infra.element.io/matrix-authentication-service@$REGULAR_DIGEST" \
|
||||
"oci-push.vpn.infra.element.io/matrix-authentication-service@$DEBUG_DIGEST"
|
||||
|
||||
- name: Output metadata
|
||||
id: output
|
||||
env:
|
||||
REGULAR_DIGEST: ${{ steps.manifests.outputs.regular }}
|
||||
DEBUG_DIGEST: ${{ steps.manifests.outputs.debug }}
|
||||
META_JSON: ${{ needs.compute-image-meta.outputs.regular-json }}
|
||||
META_DEBUG_JSON: ${{ needs.compute-image-meta.outputs.debug-json }}
|
||||
run: |
|
||||
echo 'metadata<<EOF' >> $GITHUB_OUTPUT
|
||||
jq -nc \
|
||||
--arg regular_digest "$REGULAR_DIGEST" \
|
||||
--arg debug_digest "$DEBUG_DIGEST" \
|
||||
--argjson regular_tags "$(jq '.tags' <<< "$META_JSON")" \
|
||||
--argjson debug_tags "$(jq '.tags' <<< "$META_DEBUG_JSON")" \
|
||||
'{regular: {digest: $regular_digest, tags: $regular_tags}, debug: {digest: $debug_digest, tags: $debug_tags}}' >> $GITHUB_OUTPUT
|
||||
echo 'EOF' >> $GITHUB_OUTPUT
|
||||
|
||||
release:
|
||||
name: Release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- assemble-archives
|
||||
- build-image
|
||||
- finalize-image
|
||||
|
||||
steps:
|
||||
- name: Download the artifacts from the previous job
|
||||
@@ -412,12 +639,12 @@ jobs:
|
||||
|
||||
- Digest:
|
||||
```
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.build-image.outputs.metadata).regular.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.build-image.outputs.metadata).regular.digest }}
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).regular.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).regular.digest }}
|
||||
```
|
||||
- Tags:
|
||||
```
|
||||
${{ join(fromJSON(needs.build-image.outputs.metadata).regular.tags, '
|
||||
${{ join(fromJSON(needs.finalize-image.outputs.metadata).regular.tags, '
|
||||
') }}
|
||||
```
|
||||
|
||||
@@ -425,12 +652,12 @@ jobs:
|
||||
|
||||
- Digest:
|
||||
```
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.build-image.outputs.metadata).debug.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.build-image.outputs.metadata).debug.digest }}
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).debug.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).debug.digest }}
|
||||
```
|
||||
- Tags:
|
||||
```
|
||||
${{ join(fromJSON(needs.build-image.outputs.metadata).debug.tags, '
|
||||
${{ join(fromJSON(needs.finalize-image.outputs.metadata).debug.tags, '
|
||||
') }}
|
||||
```
|
||||
|
||||
@@ -446,7 +673,7 @@ jobs:
|
||||
|
||||
needs:
|
||||
- assemble-archives
|
||||
- build-image
|
||||
- finalize-image
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -492,12 +719,12 @@ jobs:
|
||||
|
||||
- Digest:
|
||||
```
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.build-image.outputs.metadata).regular.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.build-image.outputs.metadata).regular.digest }}
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).regular.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).regular.digest }}
|
||||
```
|
||||
- Tags:
|
||||
```
|
||||
${{ join(fromJSON(needs.build-image.outputs.metadata).regular.tags, '
|
||||
${{ join(fromJSON(needs.finalize-image.outputs.metadata).regular.tags, '
|
||||
') }}
|
||||
```
|
||||
|
||||
@@ -505,12 +732,12 @@ jobs:
|
||||
|
||||
- Digest:
|
||||
```
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.build-image.outputs.metadata).debug.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.build-image.outputs.metadata).debug.digest }}
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).debug.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).debug.digest }}
|
||||
```
|
||||
- Tags:
|
||||
```
|
||||
${{ join(fromJSON(needs.build-image.outputs.metadata).debug.tags, '
|
||||
${{ join(fromJSON(needs.finalize-image.outputs.metadata).debug.tags, '
|
||||
') }}
|
||||
```
|
||||
|
||||
@@ -526,7 +753,7 @@ jobs:
|
||||
if: github.event_name == 'pull_request' && github.event.label.name == 'Z-Build-Workflow'
|
||||
|
||||
needs:
|
||||
- build-image
|
||||
- finalize-image
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -543,7 +770,7 @@ jobs:
|
||||
- name: Remove label and comment
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
env:
|
||||
BUILD_IMAGE_MANIFEST: ${{ needs.build-image.outputs.metadata }}
|
||||
BUILD_IMAGE_MANIFEST: ${{ needs.finalize-image.outputs.metadata }}
|
||||
with:
|
||||
script: |
|
||||
const script = require('./.github/scripts/cleanup-pr.cjs');
|
||||
|
||||
+13
-10
@@ -6,9 +6,9 @@
|
||||
# Please see LICENSE files in the repository root for full details.
|
||||
|
||||
# Builds a minimal image with the binary only. It is multi-arch capable,
|
||||
# cross-building to aarch64 and x86_64. When cross-compiling, Docker sets two
|
||||
# cross-building to aarch64 or x86_64. When cross-compiling, Docker sets two
|
||||
# implicit BUILDARG: BUILDPLATFORM being the host platform and TARGETPLATFORM
|
||||
# being the platform being built.
|
||||
# being the platform being built. Each architecture is built separately.
|
||||
|
||||
# The Debian version and version name must be in sync
|
||||
ARG DEBIAN_VERSION=13
|
||||
@@ -119,20 +119,25 @@ ENV SQLX_OFFLINE=true
|
||||
ARG VERGEN_GIT_DESCRIBE
|
||||
ENV VERGEN_GIT_DESCRIBE=${VERGEN_GIT_DESCRIBE}
|
||||
|
||||
ARG TARGETARCH
|
||||
|
||||
# Network access: cargo auditable needs it
|
||||
RUN --network=default \
|
||||
--mount=type=cache,target=/root/.cargo/registry \
|
||||
--mount=type=cache,target=/app/target \
|
||||
RUST_TARGET=$(case "${TARGETARCH}" in \
|
||||
amd64) echo "x86_64-unknown-linux-gnu" ;; \
|
||||
arm64) echo "aarch64-unknown-linux-gnu" ;; \
|
||||
*) echo "unsupported architecture: ${TARGETARCH}" >&2; exit 1 ;; \
|
||||
esac) && \
|
||||
cargo auditable build \
|
||||
--locked \
|
||||
--release \
|
||||
--bin mas-cli \
|
||||
--no-default-features \
|
||||
--features docker \
|
||||
--target x86_64-unknown-linux-gnu \
|
||||
--target aarch64-unknown-linux-gnu \
|
||||
&& mv "target/x86_64-unknown-linux-gnu/release/mas-cli" /usr/local/bin/mas-cli-amd64 \
|
||||
&& mv "target/aarch64-unknown-linux-gnu/release/mas-cli" /usr/local/bin/mas-cli-arm64
|
||||
--target "${RUST_TARGET}" \
|
||||
&& mv "target/${RUST_TARGET}/release/mas-cli" /usr/local/bin/mas-cli
|
||||
|
||||
#######################################
|
||||
## Prepare /usr/local/share/mas-cli/ ##
|
||||
@@ -149,8 +154,7 @@ COPY ./translations/ /share/translations
|
||||
##################################
|
||||
FROM gcr.io/distroless/cc-debian${DEBIAN_VERSION}:debug-nonroot AS debug
|
||||
|
||||
ARG TARGETARCH
|
||||
COPY --from=builder /usr/local/bin/mas-cli-${TARGETARCH} /usr/local/bin/mas-cli
|
||||
COPY --from=builder /usr/local/bin/mas-cli /usr/local/bin/mas-cli
|
||||
COPY --from=share /share /usr/local/share/mas-cli
|
||||
|
||||
WORKDIR /
|
||||
@@ -161,8 +165,7 @@ ENTRYPOINT ["/usr/local/bin/mas-cli"]
|
||||
###################
|
||||
FROM gcr.io/distroless/cc-debian${DEBIAN_VERSION}:nonroot
|
||||
|
||||
ARG TARGETARCH
|
||||
COPY --from=builder /usr/local/bin/mas-cli-${TARGETARCH} /usr/local/bin/mas-cli
|
||||
COPY --from=builder /usr/local/bin/mas-cli /usr/local/bin/mas-cli
|
||||
COPY --from=share /share /usr/local/share/mas-cli
|
||||
|
||||
WORKDIR /
|
||||
|
||||
+3
-7
@@ -1,3 +1,4 @@
|
||||
# Copyright 2025, 2026 Element Creations Ltd.
|
||||
# Copyright 2025 New Vector Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
@@ -15,8 +16,8 @@ group "default" { targets = ["regular", "debug"] }
|
||||
target "docker-metadata-action" {}
|
||||
target "docker-metadata-action-debug" {}
|
||||
|
||||
// This sets the platforms and is further extended by GitHub Actions to set the
|
||||
// output and the cache locations
|
||||
// This is extended by GitHub Actions to set the output, cache locations,
|
||||
// and platforms (one architecture per job for parallel builds)
|
||||
target "base" {
|
||||
args = {
|
||||
// This is set so that when we use a git context, the .git directory is
|
||||
@@ -26,11 +27,6 @@ target "base" {
|
||||
// Pass down the version from an external git describe source
|
||||
VERGEN_GIT_DESCRIBE = "${VERGEN_GIT_DESCRIBE}"
|
||||
}
|
||||
|
||||
platforms = [
|
||||
"linux/amd64",
|
||||
"linux/arm64",
|
||||
]
|
||||
}
|
||||
|
||||
target "regular" {
|
||||
|
||||
Reference in New Issue
Block a user