Skip to content

Release v0.2.2

Release v0.2.2 #3

Workflow file for this run

name: Release
on:
push:
tags:
- "v*.*.*"
permissions:
contents: write
packages: write
jobs:
validate-release-version:
name: Validate release version
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check crate versions match tag
shell: bash
run: |
set -euo pipefail
tag="${GITHUB_REF_NAME}"
version="${tag#v}"
if [[ "$tag" != v* || "$version" == "$tag" ]]; then
echo "Release tags must be prefixed with v, got: $tag" >&2
exit 1
fi
cli_version="$(awk -F'"' '/^version = / { print $2; exit }' codex-blackbox-cli/Cargo.toml)"
core_version="$(awk -F'"' '/^version = / { print $2; exit }' codex-blackbox-core/Cargo.toml)"
if [[ "$cli_version" != "$version" ]]; then
echo "codex-blackbox-cli version $cli_version does not match tag $tag" >&2
exit 1
fi
if [[ "$core_version" != "$version" ]]; then
echo "codex-blackbox-core version $core_version does not match tag $tag" >&2
exit 1
fi
build-cli:
name: Build CLI (${{ matrix.target }})
runs-on: ${{ matrix.os }}
needs:
- validate-release-version
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
cross: false
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
cross: true
- os: macos-15-intel
target: x86_64-apple-darwin
cross: false
- os: macos-14
target: aarch64-apple-darwin
cross: false
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install cross
if: matrix.cross
run: cargo install cross --locked
- name: Build
shell: bash
run: |
set -euo pipefail
if [[ "${{ matrix.cross }}" == "true" ]]; then
cross build --release -p codex-blackbox-cli --target "${{ matrix.target }}"
else
cargo build --release -p codex-blackbox-cli --target "${{ matrix.target }}"
fi
- name: Package
shell: bash
run: |
set -euo pipefail
target="${{ matrix.target }}"
archive="codex-blackbox-${target}.tar.gz"
staging="dist/${target}"
mkdir -p "$staging"
cp "target/${target}/release/codex-blackbox" "$staging/codex-blackbox"
cp README.md LICENSE "$staging/"
tar -czf "dist/${archive}" -C "$staging" codex-blackbox README.md LICENSE
if command -v sha256sum >/dev/null 2>&1; then
(cd dist && sha256sum "${archive}" > "${archive}.sha256")
else
(cd dist && shasum -a 256 "${archive}" > "${archive}.sha256")
fi
- name: Verify packaged archive
shell: bash
run: |
set -euo pipefail
target="${{ matrix.target }}"
archive="codex-blackbox-${target}.tar.gz"
expected="$(awk '{print $1}' "dist/${archive}.sha256")"
if command -v sha256sum >/dev/null 2>&1; then
actual="$(sha256sum "dist/${archive}" | awk '{print $1}')"
else
actual="$(shasum -a 256 "dist/${archive}" | awk '{print $1}')"
fi
test "$expected" = "$actual"
mkdir -p "dist/verify-${target}"
tar -xzf "dist/${archive}" -C "dist/verify-${target}"
test -x "dist/verify-${target}/codex-blackbox"
if [[ "${{ matrix.cross }}" != "true" ]]; then
"dist/verify-${target}/codex-blackbox" --version
"dist/verify-${target}/codex-blackbox" run --dry-run -- codex exec --sandbox read-only "release archive smoke" > "dist/verify-${target}.txt"
grep -q "Config files: not modified" "dist/verify-${target}.txt"
grep -q "features.enable_request_compression=false" "dist/verify-${target}.txt"
fi
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: codex-blackbox-${{ matrix.target }}
path: |
dist/codex-blackbox-${{ matrix.target }}.tar.gz
dist/codex-blackbox-${{ matrix.target }}.tar.gz.sha256
docker-image:
name: Build and push codex-blackbox-core image (${{ matrix.arch }})
runs-on: ${{ matrix.runner }}
needs:
- validate-release-version
strategy:
fail-fast: false
max-parallel: 1
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-latest
- arch: arm64
platform: linux/arm64
runner: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set image tags
id: tags
shell: bash
run: |
set -euo pipefail
tag="${GITHUB_REF_NAME}"
version="${tag#v}"
image="ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/codex-blackbox-core"
{
echo "image=${image}"
echo "tag=${tag}"
echo "version=${version}"
} >> "$GITHUB_OUTPUT"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v7
with:
context: .
file: ./codex-blackbox-core/Dockerfile
platforms: ${{ matrix.platform }}
push: true
cache-from: type=gha,scope=codex-blackbox-core-${{ matrix.arch }}
cache-to: type=gha,mode=max,scope=codex-blackbox-core-${{ matrix.arch }}
tags: |
${{ steps.tags.outputs.image }}:${{ steps.tags.outputs.tag }}-${{ matrix.arch }}
${{ steps.tags.outputs.image }}:${{ steps.tags.outputs.version }}-${{ matrix.arch }}
docker-manifest:
name: Publish codex-blackbox-core image manifest
runs-on: ubuntu-latest
needs:
- docker-image
steps:
- name: Set image tags
id: tags
shell: bash
run: |
set -euo pipefail
tag="${GITHUB_REF_NAME}"
version="${tag#v}"
image="ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/codex-blackbox-core"
{
echo "image=${image}"
echo "tag=${tag}"
echo "version=${version}"
} >> "$GITHUB_OUTPUT"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Publish manifest
shell: bash
run: |
set -euo pipefail
image="${{ steps.tags.outputs.image }}"
tag="${{ steps.tags.outputs.tag }}"
version="${{ steps.tags.outputs.version }}"
docker buildx imagetools create \
-t "${image}:${tag}" \
-t "${image}:${version}" \
-t "${image}:latest" \
"${image}:${tag}-amd64" \
"${image}:${tag}-arm64"
release:
name: Publish GitHub release
runs-on: ubuntu-latest
needs:
- build-cli
- docker-manifest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download CLI artifacts
uses: actions/download-artifact@v4
with:
path: dist
pattern: codex-blackbox-*
merge-multiple: true
- name: Verify downloaded release assets
shell: bash
run: |
set -euo pipefail
shopt -s nullglob
archives=(dist/codex-blackbox-*.tar.gz)
checksums=(dist/codex-blackbox-*.tar.gz.sha256)
if [[ "${#archives[@]}" -lt 4 || "${#checksums[@]}" -lt 4 ]]; then
echo "expected four CLI archives and checksums" >&2
ls -la dist >&2
exit 1
fi
for checksum in "${checksums[@]}"; do
archive="${checksum%.sha256}"
if [[ ! -f "$archive" ]]; then
echo "missing archive for checksum: $checksum" >&2
exit 1
fi
expected="$(awk '{print $1}' "$checksum")"
actual="$(sha256sum "$archive" | awk '{print $1}')"
test "$expected" = "$actual"
done
- name: Create release
shell: bash
run: |
set -euo pipefail
assets=(
dist/codex-blackbox-*.tar.gz
dist/codex-blackbox-*.tar.gz.sha256
install.sh
)
notes="$(printf '%s\n' \
'Install with:' \
'' \
'```bash' \
'curl -fsSL https://raw.githubusercontent.com/softcane/codex-blackbox/main/install.sh | sh' \
'```' \
'' \
'CLI archives are uploaded with `.sha256` files. The installer verifies the checksum before installing.')"
if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then
gh release upload "$GITHUB_REF_NAME" "${assets[@]}" --clobber
gh release edit "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --notes "$notes"
else
gh release create "$GITHUB_REF_NAME" "${assets[@]}" --title "$GITHUB_REF_NAME" --notes "$notes"
fi