From f0160f7c303f7a3bb1481868d904ed1231589df2 Mon Sep 17 00:00:00 2001 From: Ola Adebayo Date: Wed, 25 Feb 2026 13:08:13 +0000 Subject: [PATCH 1/3] chore(ci): optimize workflows for pull request handling and condition checks --- .github/workflows/docs.yml | 11 +++++++---- .github/workflows/gateway.yml | 7 +++++-- .github/workflows/sdk.yml | 7 +++++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 133339d..925870e 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -21,14 +21,14 @@ permissions: jobs: changes: name: Detect changes + if: github.event_name == 'pull_request' runs-on: ubuntu-latest outputs: - should_run: ${{ github.event_name != 'pull_request' || steps.filter.outputs.docs == 'true' }} + should_run: ${{ steps.filter.outputs.docs }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 id: filter - if: github.event_name == 'pull_request' with: filters: | docs: @@ -42,7 +42,10 @@ jobs: build-and-deploy: name: Build and Deploy Docs needs: changes - if: needs.changes.outputs.should_run == 'true' + if: | + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' || + needs.changes.outputs.should_run == 'true' runs-on: ubuntu-latest steps: @@ -84,7 +87,7 @@ jobs: docs-status: name: Docs Status - if: always() + if: always() && github.event_name == 'pull_request' needs: [build-and-deploy] runs-on: ubuntu-latest steps: diff --git a/.github/workflows/gateway.yml b/.github/workflows/gateway.yml index 8bde776..fc1c5e8 100644 --- a/.github/workflows/gateway.yml +++ b/.github/workflows/gateway.yml @@ -12,6 +12,7 @@ on: jobs: changes: name: Detect changes + if: github.event_name == 'pull_request' runs-on: ubuntu-latest outputs: should_run: ${{ steps.filter.outputs.gateway }} @@ -28,7 +29,9 @@ jobs: ci: name: Vet · Test · Build needs: changes - if: needs.changes.outputs.should_run == 'true' + if: | + github.event_name == 'push' || + needs.changes.outputs.should_run == 'true' runs-on: ubuntu-latest defaults: run: @@ -53,7 +56,7 @@ jobs: gateway-status: name: Gateway Status - if: always() + if: always() && github.event_name == 'pull_request' needs: [ci] runs-on: ubuntu-latest steps: diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml index eeab6d6..d0b360d 100644 --- a/.github/workflows/sdk.yml +++ b/.github/workflows/sdk.yml @@ -16,6 +16,7 @@ on: jobs: changes: name: Detect changes + if: github.event_name == 'pull_request' runs-on: ubuntu-latest outputs: should_run: ${{ steps.filter.outputs.sdk }} @@ -36,7 +37,9 @@ jobs: ci: name: Install · Build · Test needs: changes - if: needs.changes.outputs.should_run == 'true' + if: | + github.event_name == 'push' || + needs.changes.outputs.should_run == 'true' runs-on: ubuntu-latest steps: @@ -60,7 +63,7 @@ jobs: sdk-status: name: SDK Status - if: always() + if: always() && github.event_name == 'pull_request' needs: [ci] runs-on: ubuntu-latest steps: From 1cddfc67621c3e1ec62520d24da3384da5234a35 Mon Sep 17 00:00:00 2001 From: Ola Adebayo Date: Wed, 25 Feb 2026 14:11:25 +0000 Subject: [PATCH 2/3] fix(release): add stale-release recovery and concurrency guard - Add workflow-level concurrency group (cancel-in-progress: false) so simultaneous pushes cannot race and leave a release PR half-tagged. - Add recover-stale-releases job that runs before release-please on every push: creates any git tags where manifest version == package.json version but the tag is absent, then relabels merged release PRs from 'autorelease: pending' to 'autorelease: tagged'. This auto-heals the 'untagged merged release PRs outstanding - aborting' state without any manual intervention on future occurrences. --- .github/workflows/release-sdk.yml | 81 +++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/.github/workflows/release-sdk.yml b/.github/workflows/release-sdk.yml index f6d0792..2b8a3d4 100644 --- a/.github/workflows/release-sdk.yml +++ b/.github/workflows/release-sdk.yml @@ -16,6 +16,12 @@ on: type: boolean default: false +# Prevent concurrent release runs racing each other. +# cancel-in-progress: false ensures an in-flight release always completes. +concurrency: + group: release + cancel-in-progress: false + permissions: contents: write pull-requests: write @@ -23,9 +29,84 @@ permissions: packages: write # push to GHCR jobs: + # --------------------------------------------------------------------------- + # recover-stale-releases + # + # Runs before release-please on every push. Idempotently creates any git tags + # that the manifest says should exist but don't (e.g. when the tagging step + # failed on a previous run), and relabels merged release PRs that are still + # carrying the 'autorelease: pending' label. This permanently prevents the + # "untagged merged release PRs outstanding - aborting" failure that occurs + # whenever the tagging step doesn't complete. + # --------------------------------------------------------------------------- + recover-stale-releases: + name: Recover Stale Releases + runs-on: ubuntu-latest + if: github.event_name == 'push' + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Create missing manifest tags and relabel stale PRs + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + + git fetch --tags --quiet + + # Map: package path → tag prefix (must match include-component-in-tag convention) + declare -A TAG_PREFIX=( + ["sdk"]="sdk-v" + ["cli"]="cli-v" + ["codemod"]="codemod-v" + ["adapters/react"]="react-v" + ["adapters/vue"]="vue-v" + ["adapters/svelte"]="svelte-v" + ) + + TAGGED=0 + + for pkg_path in "sdk" "cli" "codemod" "adapters/react" "adapters/vue" "adapters/svelte"; do + manifest_ver=$(jq -r --arg p "$pkg_path" '.[$p]' .release-please-manifest.json) + pkg_ver=$(jq -r '.version' "${pkg_path}/package.json") + prefix="${TAG_PREFIX[$pkg_path]}" + tag="${prefix}${manifest_ver}" + + # Only create the tag when both sources agree on the version (meaning + # the release PR was merged) and the tag doesn't already exist. + if [[ "$manifest_ver" == "$pkg_ver" ]] && ! git rev-parse "$tag" >/dev/null 2>&1; then + commit=$(git log --format="%H" -1 -- "${pkg_path}/package.json") + echo "::notice::Creating missing tag $tag at $commit" + git tag "$tag" "$commit" + git push origin "$tag" + TAGGED=1 + fi + done + + # If we just created tags, find any merged release PRs that are still + # labeled 'autorelease: pending' and flip them to 'autorelease: tagged' + # so that release-please no longer considers them untagged. + if [[ "$TAGGED" -eq 1 ]]; then + gh pr list \ + --label "autorelease: pending" \ + --state merged \ + --json number \ + --jq '.[].number' \ + | while read -r pr_number; do + echo "::notice::Relabeling PR #${pr_number}: autorelease: pending → autorelease: tagged" + gh pr edit "$pr_number" \ + --remove-label "autorelease: pending" \ + --add-label "autorelease: tagged" + done + fi + release-please: name: Release Please runs-on: ubuntu-latest + needs: recover-stale-releases + if: always() # run even if recover-stale-releases was skipped (workflow_dispatch) outputs: releases_created: ${{ steps.resolve.outputs.releases_created }} paths_released: ${{ steps.resolve.outputs.paths_released }} From 057e3c9db205321a15f532cef35f434b07988076 Mon Sep 17 00:00:00 2001 From: Ola Adebayo Date: Wed, 25 Feb 2026 14:39:00 +0000 Subject: [PATCH 3/3] chore: add pull request template for improved contribution guidelines --- .github/pull_request_template.md | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..78862e8 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,41 @@ +## What + + + +## Why + + + +## Type + + + +- [ ] `fix` — Bug fix (patch) +- [ ] `feat` — New feature (minor) +- [ ] `feat!` — Breaking change (major) +- [ ] `docs` — Documentation only +- [ ] `refactor` — Code restructuring (no behaviour change) +- [ ] `test` — Adding or updating tests +- [ ] `chore` — Maintenance, deps, CI +- [ ] `perf` — Performance improvement + +## Scope + + + +- [ ] `sdk` — Core TypeScript client +- [ ] `cli` — CLI tooling +- [ ] `gateway` — Go gateway +- [ ] `react` / `vue` / `svelte` — Framework adapters +- [ ] `codemod` — Migration tool +- [ ] `spec` — Protocol specification +- [ ] `docs` — Documentation site + +## Checklist + +- [ ] PR title follows [conventional commit](https://www.conventionalcommits.org/) format (we squash-merge) +- [ ] Tests added/updated for the change +- [ ] All tests pass: + - TypeScript: `pnpm run test` + - Go: `cd gateway && go test -race ./...` +- [ ] No manual version bumps (release-please handles versioning)