# Open a "Release (vscode): vX.Y.Z" PR that bumps the extension version and # fills the CHANGELOG. This is step 1 of the two-step release: a human reviews # and merges this PR, then dispatches `vscode-extension-release.yml` to build # the `.vsix` and cut the draft GitHub release. Doing the version bump through a # reviewed PR keeps `package.json` and the tag from ever diverging (the tag is # derived from the merged `package.json`, never typed by hand). # # The new CHANGELOG section is DRAFTED BY AN LLM from the PRs merged into # editors/vscode since the previous release, so the coordinator only # reviews/edits on the PR. If no LLM credentials are configured, or nothing # user-facing is found, it falls back to a placeholder bullet for the # coordinator to fill in by hand. # # This is a tools-less, one-shot "prompt in -> text out" call, so it hits the # Databricks gateway's OpenAI-compatible /chat/completions endpoint directly # with a stdlib urllib POST (same pattern as auto-assign-reviewer.yml) — no # Omnigent runtime, uv sync, or Claude Code CLI needed. The agent only ever # sees already-merged history. name: VS Code Extension Release PR on: workflow_dispatch: inputs: version: description: "Extension release version, e.g. 0.2.0 (no leading v)." required: true type: string dry_run: description: "Bump + draft the CHANGELOG and show the diff, but do NOT push the branch or open the PR." required: false type: boolean default: true # Opening a PR needs contents + pull-requests write. permissions: contents: write pull-requests: write jobs: release-pr: if: github.repository == 'omnigent-ai/omnigent' runs-on: ubuntu-latest timeout-minutes: 30 steps: # Only repo collaborators (write or higher) may cut a release. This is a # sanity gate on top of GitHub's Actions-write dispatch permission; the # real ship gate is PR review on merge and the secure repo's own checks. - name: Check actor env: GH_TOKEN: ${{ github.token }} run: | role=$(gh api "repos/${GITHUB_REPOSITORY}/collaborators/${GITHUB_ACTOR}/permission" --jq '.role_name') if [[ "$role" != "admin" && "$role" != "maintain" && "$role" != "write" ]]; then echo "::error::Actor '${GITHUB_ACTOR}' has '${role}' role, but 'write' or higher is required." exit 1 fi # Full history + tags so we can find the previous vscode-v* tag and # harvest the PRs merged since it. - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 fetch-tags: true - name: Validate version env: VERSION: ${{ inputs.version }} run: | # Strict X.Y.Z only. VS Code Marketplace versions are numeric # major.minor.patch — `vsce package` rejects prerelease suffixes # (pre-releases use the --pre-release flag, not a version suffix), so # accepting a suffix here would produce a version bump that later # fails at package time. if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "::error::Version '$VERSION' is not a valid X.Y.Z." exit 1 fi - name: Bump package.json version working-directory: editors/vscode env: VERSION: ${{ inputs.version }} # `npm pkg set` edits ONLY package.json (unlike `npm version`, which also # rewrites package-lock.json). Keeps the release PR to package.json + # CHANGELOG.md. run: npm pkg set version="$VERSION" - name: Add the CHANGELOG section (placeholder) working-directory: editors/vscode env: VERSION: ${{ inputs.version }} run: | # Insert a fresh "## []" section (with a placeholder bullet) # above the newest existing version heading. The drafter step below # replaces the placeholder with LLM-drafted bullets when it can; if it # can't, the placeholder stays for the coordinator to fill in. python3 - "$VERSION" <<'PY' import sys, re, pathlib version = sys.argv[1] p = pathlib.Path("CHANGELOG.md") text = p.read_text() if f"## [{version}]" in text: print(f"CHANGELOG already has a [{version}] section — leaving as-is.") sys.exit(0) m = re.search(r"^## \[", text, re.MULTILINE) section = f"## [{version}]\n\n- _Describe changes here._\n\n" if m: text = text[:m.start()] + section + text[m.start():] else: text = text.rstrip("\n") + "\n\n" + section p.write_text(text) print(f"Added CHANGELOG section for {version}") PY # --- Harvest the PRs merged into editors/vscode since the last release --- - name: Harvest merged PRs id: harvest env: GH_TOKEN: ${{ github.token }} run: | set -euo pipefail # Previous extension release = newest vscode-v* tag (empty on the # first release → harvest the whole history touching editors/vscode). prev="$(git tag --list 'vscode-v*' --sort=-v:refname | head -n1 || true)" if [ -n "$prev" ]; then range="${prev}..HEAD" echo "Harvesting PRs in ${range} touching editors/vscode" else range="HEAD" echo "No previous vscode-v* tag — harvesting all history touching editors/vscode" fi # PR numbers from squash-merge commit subjects ("… (#123)") on commits # that touched editors/vscode. Sorted, unique. nums="$(git log "$range" --no-merges --pretty=%s -- editors/vscode \ | grep -oE '\(#[0-9]+\)' | tr -dc '0-9\n' | sort -un || true)" : > /tmp/pr_material.txt count=0 for n in $nums; do # title + the author's `## Changelog` line (best-effort). data="$(gh pr view "$n" --repo "$GITHUB_REPOSITORY" --json title,body \ --jq '{title, body}' 2>/dev/null || true)" [ -z "$data" ] && continue title="$(printf '%s' "$data" | jq -r '.title')" cl="$(printf '%s' "$data" | jq -r '.body' \ | awk '/^##[[:space:]]+Changelog/{f=1;next} /^##[[:space:]]/{f=0} f' \ | grep -vE '^\s*(