Skip to content

fix(acp): await child background work (#31) #6

fix(acp): await child background work (#31)

fix(acp): await child background work (#31) #6

Workflow file for this run

name: release
on:
push:
tags:
- "v*"
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
verify:
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- uses: useblacksmith/checkout@v1
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.94.0
components: rustfmt, clippy
- name: Verify release tag matches Cargo version
shell: bash
run: |
version=$(sed -n 's/^version = "\([^"]*\)"/\1/p' Cargo.toml | head -1)
escaped_version=${version//./\.}
if [[ $GITHUB_REF_NAME != "v$version" \
&& ! $GITHUB_REF_NAME =~ ^v${escaped_version}-pre(\.[0-9]+)?$ ]]; then
echo "expected v${version}, v${version}-pre, or v${version}-pre.N" >&2
exit 1
fi
- run: cargo fmt --check
- run: cargo clippy --locked --all-targets --all-features -- -D warnings
- run: cargo test --locked
linux-x64:
needs: verify
runs-on: blacksmith-8vcpu-ubuntu-2404
steps:
- uses: useblacksmith/checkout@v1
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.94.0
targets: x86_64-unknown-linux-gnu
- name: Build and package
shell: bash
run: |
version=${GITHUB_REF_NAME#v}
cargo build --locked --release --target x86_64-unknown-linux-gnu
mkdir -p stage dist
cp target/x86_64-unknown-linux-gnu/release/kit stage/kit
stage/kit --version
tar -C stage -czf "dist/kit-v${version}-x86_64-unknown-linux-gnu.tar.gz" kit
- uses: actions/upload-artifact@v4
with:
name: kit-linux-x64
path: dist/*
if-no-files-found: error
macos-arm64:
needs: verify
runs-on: blacksmith-6vcpu-macos-15
outputs:
signed: ${{ steps.signing.outputs.enabled }}
env:
MACOS_CERTIFICATE_P12_BASE64: ${{ secrets.MACOS_CERTIFICATE_P12_BASE64 }}
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
MACOS_SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
APPLE_API_KEY_P8_BASE64: ${{ secrets.APPLE_API_KEY_P8_BASE64 }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER_ID: ${{ secrets.APPLE_API_ISSUER_ID }}
steps:
- uses: useblacksmith/checkout@v1
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.94.0
targets: aarch64-apple-darwin
- name: Check optional signing credentials
id: signing
shell: bash
run: |
credentials=(
MACOS_CERTIFICATE_P12_BASE64
MACOS_CERTIFICATE_PASSWORD
MACOS_SIGNING_IDENTITY
APPLE_API_KEY_P8_BASE64
APPLE_API_KEY_ID
APPLE_API_ISSUER_ID
)
configured=0
for name in "${credentials[@]}"; do
if [[ -n ${!name:-} ]]; then
configured=$((configured + 1))
fi
done
if [[ $configured -eq 0 ]]; then
echo "Apple credentials are not configured; building an unsigned macOS release."
echo "enabled=false" >> "$GITHUB_OUTPUT"
elif [[ $configured -eq ${#credentials[@]} ]]; then
echo "enabled=true" >> "$GITHUB_OUTPUT"
else
echo "Apple signing credentials are only partially configured." >&2
exit 1
fi
- name: Import Developer ID certificate
if: steps.signing.outputs.enabled == 'true'
shell: bash
run: |
keychain=$RUNNER_TEMP/kit-signing.keychain-db
certificate=$RUNNER_TEMP/kit-signing.p12
printf '%s' "$MACOS_CERTIFICATE_P12_BASE64" | base64 --decode > "$certificate"
security create-keychain -p "$MACOS_CERTIFICATE_PASSWORD" "$keychain"
security set-keychain-settings -lut 21600 "$keychain"
security unlock-keychain -p "$MACOS_CERTIFICATE_PASSWORD" "$keychain"
security import "$certificate" -P "$MACOS_CERTIFICATE_PASSWORD" \
-f pkcs12 -k "$keychain" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple: -s \
-k "$MACOS_CERTIFICATE_PASSWORD" "$keychain"
security list-keychains -d user -s "$keychain" login.keychain-db
- name: Build and package
shell: bash
env:
SIGN_RELEASE: ${{ steps.signing.outputs.enabled }}
run: |
version=${GITHUB_REF_NAME#v}
cargo build --locked --release --target aarch64-apple-darwin
mkdir -p stage dist
cp target/aarch64-apple-darwin/release/kit stage/kit
if [[ $SIGN_RELEASE == true ]]; then
codesign --force --options runtime --timestamp \
--identifier com.danielkov.kit \
--sign "$MACOS_SIGNING_IDENTITY" stage/kit
codesign --verify --strict --verbose=2 stage/kit
ditto -c -k --keepParent stage/kit "$RUNNER_TEMP/kit-notarization.zip"
api_key=$RUNNER_TEMP/AuthKey_${APPLE_API_KEY_ID}.p8
trap 'rm -f "$api_key"' EXIT
printf '%s' "$APPLE_API_KEY_P8_BASE64" | base64 --decode > "$api_key"
chmod 600 "$api_key"
notary_log=$RUNNER_TEMP/kit-notarization.log
xcrun notarytool submit "$RUNNER_TEMP/kit-notarization.zip" \
--key "$api_key" \
--key-id "$APPLE_API_KEY_ID" \
--issuer "$APPLE_API_ISSUER_ID" \
--wait 2>&1 | tee "$notary_log"
if ! grep -Eq '(^|[[:space:]])status: Accepted([[:space:]]|$)' "$notary_log"; then
echo "Apple did not accept the notarization submission." >&2
exit 1
fi
fi
stage/kit --version
tar -C stage -czf "dist/kit-v${version}-aarch64-apple-darwin.tar.gz" kit
- uses: actions/upload-artifact@v4
with:
name: kit-macos-arm64
path: dist/*
if-no-files-found: error
publish:
needs: [linux-x64, macos-arm64]
runs-on: blacksmith-2vcpu-ubuntu-2404
permissions:
contents: write
env:
GH_TOKEN: ${{ github.token }}
MACOS_SIGNED: ${{ needs.macos-arm64.outputs.signed }}
steps:
- uses: actions/download-artifact@v4
with:
pattern: kit-*
path: dist
merge-multiple: true
- name: Publish release
shell: bash
run: |
cd dist
sha256sum kit-*.tar.gz > SHA256SUMS
prerelease=false
if [[ $GITHUB_REF_NAME == *-pre* ]]; then
prerelease=true
fi
if [[ $MACOS_SIGNED == true ]]; then
signing_note="The macOS binary is Developer ID signed and notarized."
else
signing_note="The macOS binary is unsigned and not notarized."
fi
title="Kit ${GITHUB_REF_NAME#v}"
notes="Prebuilt Kit binaries. $signing_note"
if gh release view "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
gh release upload "$GITHUB_REF_NAME" kit-*.tar.gz SHA256SUMS \
--clobber --repo "$GITHUB_REPOSITORY"
else
create_args=(
"$GITHUB_REF_NAME" kit-*.tar.gz SHA256SUMS
--repo "$GITHUB_REPOSITORY"
--title "$title"
--notes "$notes"
)
if [[ $prerelease == true ]]; then
create_args+=(--prerelease)
fi
gh release create "${create_args[@]}"
fi
edit_args=(
"$GITHUB_REF_NAME"
--repo "$GITHUB_REPOSITORY"
--title "$title"
--notes "$notes"
--draft=false
--prerelease="$prerelease"
)
if [[ $prerelease == false ]]; then
newest_stable=$(
gh release list --repo "$GITHUB_REPOSITORY" --limit 100 \
--json tagName,isDraft,isPrerelease \
--jq '.[] | select((.isDraft | not) and (.isPrerelease | not)) | .tagName' \
| sort -V | tail -1
)
if [[ $GITHUB_REF_NAME == "$newest_stable" ]]; then
edit_args+=(--latest)
fi
fi
gh release edit "${edit_args[@]}"
container-build:
name: Build container images (${{ matrix.arch }})
needs: publish
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-24.04
- arch: arm64
platform: linux/arm64
runner: ubuntu-24.04-arm
env:
IMAGE: ghcr.io/${{ github.repository }}
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Read container version
id: version
shell: bash
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Log in to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push slim image by digest
id: slim
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
target: slim
platforms: ${{ matrix.platform }}
build-args: |
VERSION=${{ steps.version.outputs.version }}
REVISION=${{ github.sha }}
outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true
- name: Build and push Bookworm image by digest
id: bookworm
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
target: bookworm
platforms: ${{ matrix.platform }}
build-args: |
VERSION=${{ steps.version.outputs.version }}
REVISION=${{ github.sha }}
outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true
- name: Build and push Alpine image by digest
id: alpine
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
target: alpine
platforms: ${{ matrix.platform }}
build-args: |
VERSION=${{ steps.version.outputs.version }}
REVISION=${{ github.sha }}
outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true
- name: Export image digests
env:
SLIM_DIGEST: ${{ steps.slim.outputs.digest }}
BOOKWORM_DIGEST: ${{ steps.bookworm.outputs.digest }}
ALPINE_DIGEST: ${{ steps.alpine.outputs.digest }}
shell: bash
run: |
mkdir -p /tmp/digests/{slim,bookworm,alpine}
touch "/tmp/digests/slim/${SLIM_DIGEST#sha256:}"
touch "/tmp/digests/bookworm/${BOOKWORM_DIGEST#sha256:}"
touch "/tmp/digests/alpine/${ALPINE_DIGEST#sha256:}"
- name: Upload image digests
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: container-digests-${{ matrix.arch }}
path: /tmp/digests
if-no-files-found: error
retention-days: 1
containers:
name: Publish container image manifests
needs: [publish, container-build]
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
env:
IMAGE: ghcr.io/${{ github.repository }}
steps:
- name: Download image digests
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
pattern: container-digests-*
path: /tmp/digests
merge-multiple: true
- name: Read release metadata
id: release
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
if [[ $GITHUB_REF_NAME == *-pre* ]]; then
echo "floating=false" >> "$GITHUB_OUTPUT"
exit 0
fi
newest_stable=$(
gh release list --repo "$GITHUB_REPOSITORY" --limit 100 \
--json tagName,isDraft,isPrerelease \
--jq '.[] | select((.isDraft | not) and (.isPrerelease | not)) | .tagName' \
| sort -V | tail -1
)
if [[ $GITHUB_REF_NAME == "$newest_stable" ]]; then
echo "floating=true" >> "$GITHUB_OUTPUT"
else
echo "floating=false" >> "$GITHUB_OUTPUT"
fi
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Log in to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Generate slim image metadata
id: slim-meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: ${{ env.IMAGE }}
flavor: latest=false
tags: |
type=raw,value=${{ github.ref_name }}
type=raw,value=${{ github.ref_name }}-slim
type=raw,value=latest,enable=${{ steps.release.outputs.floating == 'true' }}
type=raw,value=slim,enable=${{ steps.release.outputs.floating == 'true' }}
- name: Publish slim manifest
env:
METADATA: ${{ steps.slim-meta.outputs.json }}
shell: bash
run: |
mapfile -t tags < <(jq -r '.tags[]' <<< "$METADATA")
mapfile -t digests < <(find /tmp/digests/slim -type f -printf "${IMAGE}@sha256:%f\n")
args=()
for tag in "${tags[@]}"; do args+=(--tag "$tag"); done
docker buildx imagetools create "${args[@]}" "${digests[@]}"
- name: Generate Bookworm image metadata
id: bookworm-meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: ${{ env.IMAGE }}
flavor: latest=false
tags: |
type=raw,value=${{ github.ref_name }}-bookworm
type=raw,value=bookworm,enable=${{ steps.release.outputs.floating == 'true' }}
- name: Publish Bookworm manifest
env:
METADATA: ${{ steps.bookworm-meta.outputs.json }}
shell: bash
run: |
mapfile -t tags < <(jq -r '.tags[]' <<< "$METADATA")
mapfile -t digests < <(find /tmp/digests/bookworm -type f -printf "${IMAGE}@sha256:%f\n")
args=()
for tag in "${tags[@]}"; do args+=(--tag "$tag"); done
docker buildx imagetools create "${args[@]}" "${digests[@]}"
- name: Generate Alpine image metadata
id: alpine-meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: ${{ env.IMAGE }}
flavor: latest=false
tags: |
type=raw,value=${{ github.ref_name }}-alpine
type=raw,value=alpine,enable=${{ steps.release.outputs.floating == 'true' }}
- name: Publish Alpine manifest
env:
METADATA: ${{ steps.alpine-meta.outputs.json }}
shell: bash
run: |
mapfile -t tags < <(jq -r '.tags[]' <<< "$METADATA")
mapfile -t digests < <(find /tmp/digests/alpine -type f -printf "${IMAGE}@sha256:%f\n")
args=()
for tag in "${tags[@]}"; do args+=(--tag "$tag"); done
docker buildx imagetools create "${args[@]}" "${digests[@]}"
- name: Verify container package is public
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
package=${GITHUB_REPOSITORY#*/}
visibility=$(
gh api "/orgs/${GITHUB_REPOSITORY_OWNER}/packages/container/${package}" \
--jq .visibility
)
if [[ $visibility != public ]]; then
echo "::error::Set the ${package} container package visibility to public, then rerun this workflow."
echo "https://github.com/orgs/${GITHUB_REPOSITORY_OWNER}/packages/container/${package}/settings"
exit 1
fi