name: Build and Release permissions: contents: write on: push: tags: - "v*.*.*" concurrency: group: release-${{ github.ref }} cancel-in-progress: true jobs: build: runs-on: macos-latest steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Validate release tag format run: | TAG="${GITHUB_REF_NAME}" if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z]+)?$ ]]; then echo "Tag '$TAG' does not match required format vX.X.X or vX.X.X-word" exit 1 fi - name: Install Rust uses: dtolnay/rust-toolchain@stable - name: Cache Rust uses: Swatinem/rust-cache@v2 - name: Resolve target commit run: | TARGET_SHA="$(git rev-list -n 1 "${GITHUB_REF_NAME}")" echo "TARGET_SHA=$TARGET_SHA" >> "$GITHUB_ENV" - name: Verify CI passed env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | COUNT="$(gh run list --workflow ci.yml --commit "$TARGET_SHA" --json conclusion,createdAt --jq 'length')" if [ "$COUNT" -eq 0 ]; then echo "No CI runs found for commit $TARGET_SHA" exit 1 fi CONCLUSION="$(gh run list --workflow ci.yml --commit "$TARGET_SHA" --json conclusion,createdAt --jq '.[0].conclusion')" if [ "$CONCLUSION" != "success" ]; then echo "Latest CI run for commit $TARGET_SHA is $CONCLUSION" exit 1 fi - name: Build release binary run: cargo build --release --locked - name: Publish crate env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} run: cargo publish --locked - name: Package binary run: | cd target/release zip vibebox-macos-arm64.zip vibebox - name: Create tag release run: | gh release create "${{ github.ref_name }}" \ --title "${{ github.ref_name }}" \ --notes "Built from commit $TARGET_SHA" \ target/release/vibebox-macos-arm64.zip env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Delete existing latest release run: gh release delete latest --cleanup-tag --yes || true env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Create latest release run: | gh release create latest \ --title "Latest" \ --notes "Built from commit $TARGET_SHA" \ --prerelease \ target/release/vibebox-macos-arm64.zip env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}