From ab515310b18eec1eab9e5e12242f5ca2861a8c88 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Aug 2026 06:39:21 +0000 Subject: [PATCH] Add tag release workflow Co-authored-by: ar4ft <70501707+ar4ft@users.noreply.github.com> --- .github/workflows/tag-release.yml | 151 ++++++++++++++++++++++++++++++ structure/06_docs-and-release.md | 14 +++ 2 files changed, 165 insertions(+) create mode 100644 .github/workflows/tag-release.yml diff --git a/.github/workflows/tag-release.yml b/.github/workflows/tag-release.yml new file mode 100644 index 0000000000..c4aae0e284 --- /dev/null +++ b/.github/workflows/tag-release.yml @@ -0,0 +1,151 @@ +name: Tag release + +on: + push: + tags: + - "v*" + +permissions: {} + +concurrency: + group: tag-release-${{ github.ref }} + cancel-in-progress: false + +env: + BUN_VERSION: "1.3.14" + +jobs: + prepare-release: + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Create draft GitHub release + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + tag="$GITHUB_REF_NAME" + if gh release view "$tag" >/dev/null 2>&1; then + echo "GitHub release ${tag} already exists; keeping it" + else + gh release create "$tag" \ + --target "$GITHUB_SHA" \ + --title "$tag" \ + --generate-notes \ + --draft \ + --verify-tag + fi + + build-release: + name: build ${{ matrix.target }} + needs: prepare-release + runs-on: ${{ matrix.runner }} + timeout-minutes: 30 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + include: + - target: darwin-arm64 + runner: macos-15 + bun-target: bun-darwin-arm64 + output: opencodex-darwin-arm64 + - target: darwin-x64 + runner: macos-15-intel + bun-target: bun-darwin-x64 + output: opencodex-darwin-x64 + - target: linux-x64 + runner: ubuntu-latest + bun-target: bun-linux-x64 + output: opencodex-linux-x64 + - target: linux-arm64 + runner: ubuntu-24.04-arm + bun-target: bun-linux-arm64 + output: opencodex-linux-arm64 + - target: windows-x64 + runner: windows-latest + bun-target: bun-windows-x64 + output: opencodex-windows-x64.exe + - target: windows-arm64 + runner: windows-11-arm + bun-target: bun-windows-arm64 + output: opencodex-windows-arm64.exe + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + with: + fetch-depth: 1 + persist-credentials: false + + - name: Setup Bun + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 + with: + bun-version: ${{ env.BUN_VERSION }} + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Build release binary + shell: bash + env: + TARGET: ${{ matrix.bun-target }} + OUTPUT: ${{ matrix.output }} + run: | + set -euo pipefail + release_dir="$GITHUB_WORKSPACE/dist/release" + mkdir -p "$release_dir" + out="$release_dir/$OUTPUT" + bun build --compile src/cli/index.ts --target "$TARGET" --outfile "$out" + if [[ "$RUNNER_OS" != "Windows" ]]; then + chmod +x "$out" + fi + if command -v file >/dev/null 2>&1; then + file "$out" + fi + + - name: Upload build artifact + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + with: + name: ${{ matrix.target }} + path: dist/release/${{ matrix.output }} + if-no-files-found: error + + publish-release: + name: publish release assets + needs: build-release + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: write + steps: + - name: Download build artifacts + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + path: dist + merge-multiple: true + + - name: Upload assets and checksums + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + cd dist + shopt -s nullglob + assets=(opencodex-*) + if [[ ${#assets[@]} -ne 6 ]]; then + printf 'expected six release binaries, found %s\n' "${#assets[@]}" >&2 + printf '%s\n' "${assets[@]}" >&2 + exit 1 + fi + sha256sum "${assets[@]}" | sort -k2 > checksums.txt + gh release upload "$GITHUB_REF_NAME" "${assets[@]}" checksums.txt --clobber + gh release edit "$GITHUB_REF_NAME" --draft=false diff --git a/structure/06_docs-and-release.md b/structure/06_docs-and-release.md index 71c86df6f9..e0a7c20617 100644 --- a/structure/06_docs-and-release.md +++ b/structure/06_docs-and-release.md @@ -51,6 +51,7 @@ bun run build | --- | --- | --- | | `.github/workflows/ci.yml` | `pull_request` to `main`/`dev`, `push` to `main`/`preview`/`dev`, or manual dispatch when runtime/package paths change | Cross-platform runtime/package quality gate. Linux runs the suite as four parallel shards (`test 1/4`–`4/4`) plus a consolidated `gates` job; macOS runs the full suite. Windows runs the full suite only on a `push` to `main`/`preview` or a manual dispatch — it is the shipping boundary, not the pull-request lane, because it was last to finish in every sampled run at roughly three times the Linux median. The aggregate `ci` job asserts `platform-windows` actually succeeded on those boundary events rather than accepting a skip. `npm-global-smoke` always remains GitHub-hosted because it mutates the global package prefix. | | `.github/workflows/release.yml` | Manual dispatch only | npm publish/dry-run workflow. It requires the exact `GITHUB_SHA` to have a successful Cross-platform CI run before publish or dry-run. | +| `.github/workflows/tag-release.yml` | `push` of a `v*` tag | Creates a draft GitHub Release, compiles standalone Bun binaries for macOS, Linux, and Windows on x64 and arm64 runners, uploads the six assets, publishes SHA-256 checksums, and then makes the release public. | | `.github/workflows/deploy-docs.yml` | `push` to `main` touching `docs-site/**` or the workflow, or manual dispatch | Build and publish the Astro/Starlight docs site to GitHub Pages. | | `.github/workflows/service-lifecycle.yml` | `pull_request` to `main`/`dev` and `push`, both filtered on the service path set (`src/service.ts`, `src/cli.ts`, `src/cli/index.ts`, `src/lib/bun-runtime.ts`, `package.json`, `bun.lock`, the workflow), or manual dispatch | Service-lifecycle smoke on three platforms: Linux systemd, macOS launchd, and Windows Scheduled Tasks. Each installs, verifies, stops via `ocx stop`, and uninstalls. The path list is kept in sync with the `release.yml` service-gate regex. | | `.github/workflows/enforce-pr-target.yml` | `pull_request_target` (opened, reopened, edited, labeled, unlabeled, ready_for_review, synchronize) plus default-branch `status` events filtered to successful `CodeRabbit` statuses | The `enforce-target` gate: rejects pull requests whose head ancestry sits on the `main` tip while far behind `dev`, rejects empty or malformed descriptions, requires a GUI screenshot when the title/body mentions `gui` (immediately waivable with the maintainer-controlled `gui-screenshot-waived` label; legacy maintainer comments remain compatibility evidence on later PR events), keeps contributor PRs in draft until a four-box readiness checklist is complete, verifies the CI / latest-dev / Codex+CodeRabbit-findings claims (review threads plus current-head CodeRabbit review-body findings outside the diff range), and adds a `review-ready` status label at the ready moment. CodeRabbit status SHAs must resolve to exactly one open current-head PR before writes. Stacked child PRs targeting another open PR's head skip the wrong-base gate. | @@ -253,3 +254,16 @@ The Release workflow remains manual and publish-focused. Before any dry-run or p checks that the exact release commit (`GITHUB_SHA`) already has a successful Cross-platform CI run. This keeps release runs short and makes release a deployment of a verified commit rather than a second CI pipeline. + +### Standalone binary releases + +Push a version tag after the release commit is ready: + +```bash +git tag v +git push origin v +``` + +The tag workflow publishes `opencodex-{darwin,linux,windows}-{x64,arm64}` binaries and a +`checksums.txt` asset to the matching GitHub Release. npm publishing remains controlled by the +manual `release.yml` workflow.