Release v0.2.2 #3
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |