Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 137 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,129 @@ jobs:
--type spdxjson \
ghcr.io/${{ github.repository }}/cli-proxy@${{ steps.build_cli_proxy.outputs.digest }}

# Build the AWF Apple Container init image (Apple's vminit with the AWF guest
# capability relay installed at /sbin/vminitd).
#
# Gated on the `APPLE_VMINIT_IMAGE` repository variable, which must hold a
# digest-pinned reference to Apple's own vminit image for the supported
# `container` CLI range. There is deliberately no default: a floating base
# would let Apple's init move underneath a shim that hard-codes where that
# init lives. When the variable is unset the job is skipped and no
# apple-init digest is published — and because the Apple Container backend
# refuses to launch without a digest-pinned init image, the runtime fails
# closed at preflight rather than running with an unknown guest init.
build-apple-init:
name: Build Apple Container Init Image
runs-on: ubuntu-latest
needs: bump-version
if: vars.APPLE_VMINIT_IMAGE != ''
outputs:
digest: ${{ steps.build_apple_init.outputs.digest }}
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
with:
ref: ${{ needs.bump-version.outputs.version }}

- name: Validate the Apple base image is digest-pinned
env:
AWF_VMINIT_IMAGE: ${{ vars.APPLE_VMINIT_IMAGE }}
run: |
set -euo pipefail
case "$AWF_VMINIT_IMAGE" in
*@sha256:*) echo "Apple vminit base: $AWF_VMINIT_IMAGE" ;;
*) echo "::error::APPLE_VMINIT_IMAGE must be digest-pinned"; exit 1 ;;
esac

- name: Read the transport contract constants
id: contract
run: |
set -euo pipefail
src=src/apple-container/transport-capabilities.ts
min=$(sed -n "s/^export const APPLE_CONTAINER_TRANSPORT_MIN_CLI_VERSION = '\\([^']*\\)';$/\\1/p" "$src")
max=$(sed -n "s/^export const APPLE_CONTAINER_TRANSPORT_MAX_CLI_VERSION_EXCLUSIVE = '\\([^']*\\)';$/\\1/p" "$src")
contract=$(sed -n 's/^export const APPLE_CONTAINER_TRANSPORT_CONTRACT_VERSION = \([0-9]*\);$/\1/p' "$src")
test -n "$min" && test -n "$max" && test -n "$contract"
echo "min=$min" >> "$GITHUB_OUTPUT"
echo "max=$max" >> "$GITHUB_OUTPUT"
echo "contract=$contract" >> "$GITHUB_OUTPUT"

- name: Log in to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3

- name: Set up QEMU
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0
with:
platforms: arm64

- name: Install cosign
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0

# arm64 only: Apple Container guests are native arm64 and Rosetta
# translation is never used, so an amd64 variant would be a silently
# unusable artifact rather than a useful one.
- name: Build and push Apple init image
id: build_apple_init
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5
with:
context: .
file: ./containers/apple-init/Dockerfile
push: true
platforms: linux/arm64
build-args: |
AWF_VMINIT_IMAGE=${{ vars.APPLE_VMINIT_IMAGE }}
AWF_CLI_MIN_VERSION=${{ steps.contract.outputs.min }}
AWF_CLI_MAX_VERSION_EXCLUSIVE=${{ steps.contract.outputs.max }}
AWF_TRANSPORT_CONTRACT_VERSION=${{ steps.contract.outputs.contract }}
tags: |
ghcr.io/${{ github.repository }}/apple-init:${{ needs.bump-version.outputs.version_number }}
ghcr.io/${{ github.repository }}/apple-init:latest
cache-from: type=gha,scope=apple-init
cache-to: type=gha,mode=max,scope=apple-init

- name: Verify the published init image layout
run: |
set -euo pipefail
ref="ghcr.io/${{ github.repository }}/apple-init@${{ steps.build_apple_init.outputs.digest }}"
# Extracting the image is the only way to prove the relocation
# happened; the image has no shell, so it cannot be probed by running it.
id=$(docker create --platform linux/arm64 "$ref")
trap 'docker rm -f "$id" >/dev/null 2>&1 || true' EXIT
docker export "$id" > init.tar
tar -tf init.tar | grep -qx 'sbin/vminitd'
tar -tf init.tar | grep -qx 'sbin/vminitd.apple'
mkdir -p extracted
tar -xf init.tar -C extracted sbin/vminitd
file extracted/sbin/vminitd | tee /dev/stderr | \
grep -q 'ELF 64-bit LSB executable, ARM aarch64'
file extracted/sbin/vminitd | grep -q 'statically linked'

- name: Sign Apple init image with cosign
run: |
cosign sign --yes \
ghcr.io/${{ github.repository }}/apple-init@${{ steps.build_apple_init.outputs.digest }}

- name: Generate SBOM for Apple init image
uses: anchore/sbom-action@28d71544de8eaf1b958d335707167c5f783590ad # v0.22.2
with:
image: ghcr.io/${{ github.repository }}/apple-init@${{ steps.build_apple_init.outputs.digest }}
format: spdx-json
output-file: apple-init-sbom.spdx.json

- name: Attest SBOM for Apple init image
run: |
cosign attest --yes \
--predicate apple-init-sbom.spdx.json \
--type spdxjson \
ghcr.io/${{ github.repository }}/apple-init@${{ steps.build_apple_init.outputs.digest }}

# Build the unified enclave images from containers/enclave/Dockerfile.
build-enclaves:
name: Build Enclave Images
Expand Down Expand Up @@ -721,7 +844,7 @@ jobs:
release:
name: Create Release
runs-on: ubuntu-latest
needs: [bump-version, build-squid, build-agent, build-api-proxy, build-cli-proxy, build-agent-act, build-build-tools, build-enclaves, build-gh-aw-node, build-cloud-hypervisor-test-artifacts]
needs: [bump-version, build-squid, build-agent, build-api-proxy, build-cli-proxy, build-agent-act, build-build-tools, build-enclaves, build-gh-aw-node, build-cloud-hypervisor-test-artifacts, build-apple-init]
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
Expand Down Expand Up @@ -830,6 +953,8 @@ jobs:
release/cloud-hypervisor-test-x86_64.sbom.spdx.json

- name: Generate containers list
env:
APPLE_INIT_DIGEST: ${{ needs['build-apple-init'].outputs.digest }}
run: |
mkdir -p release
printf '%s\n' \
Expand All @@ -843,6 +968,17 @@ jobs:
"ghcr.io/${{ github.repository }}/enclave-mcp-server@${{ needs['build-enclaves'].outputs.enclave_mcp_server_digest }}" \
"ghcr.io/${{ github.repository }}/gh-aw-node@${{ needs['build-gh-aw-node'].outputs.digest }}" \
> release/containers.txt
# The Apple Container init image is only built when APPLE_VMINIT_IMAGE
# is configured. Its absence is not silently equivalent to "use latest":
# the Apple Container backend refuses any init image that is not
# digest-pinned, so a release without this line simply cannot select
# that preview runtime.
if [ -n "${APPLE_INIT_DIGEST:-}" ]; then
echo "ghcr.io/${{ github.repository }}/apple-init@${APPLE_INIT_DIGEST}" \
>> release/containers.txt
else
echo "No apple-init digest; the Apple Container preview runtime is not selectable in this release."
fi
echo "Generated containers.txt:"
cat release/containers.txt

Expand Down
Loading
Loading