native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Trigger release on GitHub release publish instead of tag push

- Remove release_notes job (AI-generated notes via OpenAI)
- Fetch release notes from the GitHub release body instead
- Simplify publish job to just upload artifacts to existing release
- Remove workflow_dispatch trigger and REVIEW_OPENAI_API_KEY dependency

khoi 635c4b66 15daa8c1

+11 -149
+11 -149
.github/workflows/release.yml
··· 1 1 name: Release 2 2 3 3 on: 4 - push: 5 - tags: 6 - - "v*" 7 - workflow_dispatch: 8 - inputs: 9 - tag: 10 - required: true 11 - type: string 4 + release: 5 + types: [published] 12 6 13 7 concurrency: 14 8 group: release 15 9 cancel-in-progress: false 16 10 17 11 jobs: 18 - release_notes: 19 - runs-on: ubuntu-latest 20 - permissions: 21 - contents: read 22 - env: 23 - RELEASE_REPO: supabitapp/supacode 24 - GH_TOKEN: ${{ github.token }} 25 - steps: 26 - - uses: actions/checkout@v6 27 - with: 28 - fetch-depth: 0 29 - fetch-tags: true 30 - - run: | 31 - TAG="$GITHUB_REF_NAME" 32 - if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then 33 - TAG="${{ inputs.tag }}" 34 - fi 35 - echo "TAG=$TAG" >> "$GITHUB_ENV" 36 - - name: Prepare release context 37 - run: | 38 - set -euo pipefail 39 - RELEASE_TAGS=$(gh release list -R "$RELEASE_REPO" --limit 100 | awk '{print $1}') 40 - PREV_TAG=$(printf '%s\n' "$RELEASE_TAGS" | awk -v tag="$TAG" '$1!=tag {print $1; exit}') 41 - if [ -z "$PREV_TAG" ]; then 42 - PREV_TAG=$(git describe --tags --abbrev=0 --match "v*" "$TAG^" 2>/dev/null || true) 43 - fi 44 - if [ -n "$PREV_TAG" ]; then 45 - if git rev-parse "$PREV_TAG" >/dev/null 2>&1; then 46 - RANGE="$PREV_TAG..$TAG" 47 - else 48 - RANGE="$(git rev-list --max-parents=0 "$TAG")..$TAG" 49 - fi 50 - else 51 - RANGE="$(git rev-list --max-parents=0 "$TAG")..$TAG" 52 - fi 53 - COMMITS=$(git log --pretty=format:"%h %s" "$RANGE") 54 - CHANGES=$(git diff --name-status "$RANGE") 55 - mkdir -p build 56 - cat > build/release-prompt.txt <<EOF 57 - You are generating release notes for Supacode. 58 - Release tag: $TAG 59 - Compare range: $RANGE 60 - 61 - Commits: 62 - $COMMITS 63 - 64 - Files changed: 65 - $CHANGES 66 - 67 - Requirements: 68 - - Return JSON that matches the provided schema exactly. 69 - - new_features, bug_fixes, improvements are arrays of user-facing bullet text. 70 - - Keep each item short, concrete, and non-redundant. 71 - - If a section has no items, use an empty array. 72 - - ONLY include user-facing changes that affect the end user experience. 73 - - EXCLUDE internal changes, refactoring, CI/CD configs, build configs, gatekeeping, linting, and developer tooling. 74 - EOF 75 - - name: Generate release notes data 76 - uses: openai/codex-action@v1 77 - with: 78 - openai-api-key: ${{ secrets.REVIEW_OPENAI_API_KEY }} 79 - prompt-file: build/release-prompt.txt 80 - output-schema: | 81 - { 82 - "type": "object", 83 - "properties": { 84 - "new_features": { "type": "array", "items": { "type": "string" } }, 85 - "bug_fixes": { "type": "array", "items": { "type": "string" } }, 86 - "improvements": { "type": "array", "items": { "type": "string" } } 87 - }, 88 - "required": ["new_features", "bug_fixes", "improvements"], 89 - "additionalProperties": false 90 - } 91 - output-file: build/release-notes.json 92 - - name: Build release notes markdown 93 - run: | 94 - python3 - <<'PY' 95 - import json 96 - from datetime import datetime 97 - from pathlib import Path 98 - 99 - data = json.loads(Path("build/release-notes.json").read_text()) 100 - today = datetime.now().strftime("%d %b %Y") 101 - lines = [f"**📅 Release date:** {today}"] 102 - 103 - def add_section(title, items): 104 - if items: 105 - lines.append("") 106 - lines.append(f"**{title}**") 107 - lines.extend([f"- {item}" for item in items]) 108 - 109 - new_features = data.get("new_features", []) 110 - bug_fixes = data.get("bug_fixes", []) 111 - improvements = data.get("improvements", []) 112 - 113 - add_section("✨ New Features", new_features) 114 - add_section("🐛 Bug Fixes", bug_fixes) 115 - add_section("🌱 Improvements", improvements) 116 - 117 - if not (new_features or bug_fixes or improvements): 118 - lines.append("") 119 - lines.append("**ℹ️ Notes**") 120 - lines.append("- No user-facing changes in this release.") 121 - 122 - Path("build/release-notes.md").write_text("\n".join(lines).strip() + "\n") 123 - PY 124 - - uses: actions/upload-artifact@v6 125 - with: 126 - name: release-notes 127 - path: build/release-notes.md 128 - 129 12 build: 130 13 runs-on: macos-26 131 - needs: [release_notes] 132 14 permissions: 133 15 contents: read 134 16 env: ··· 164 46 set -euo pipefail 165 47 GHOSTTY_SHA=$(git -C ThirdParty/ghostty rev-parse HEAD) 166 48 printf '%s\n' "GHOSTTY_SHA=$GHOSTTY_SHA" >> "$GITHUB_ENV" 167 - - run: | 168 - TAG="$GITHUB_REF_NAME" 169 - if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then 170 - TAG="${{ inputs.tag }}" 171 - fi 172 - echo "TAG=$TAG" >> "$GITHUB_ENV" 49 + - run: echo "TAG=${{ github.event.release.tag_name }}" >> "$GITHUB_ENV" 173 50 - run: | 174 51 echo "$DEVELOPER_ID_CERT_P12" | base64 --decode > build-cert.p12 175 52 security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain ··· 320 197 321 198 xcrun stapler staple "$DMG_PATH" 322 199 echo "DMG_PATH=$DMG_PATH" >> "$GITHUB_ENV" 323 - - uses: actions/download-artifact@v7 324 - with: 325 - name: release-notes 326 - path: build 200 + - name: Fetch release notes 201 + env: 202 + GH_TOKEN: ${{ github.token }} 203 + run: | 204 + gh release view "$TAG" --json body --jq '.body' > build/release-notes.md 327 205 - name: Generate appcast with history and deltas 328 206 env: 329 207 GH_TOKEN: ${{ github.token }} ··· 374 252 375 253 publish: 376 254 runs-on: ubuntu-latest 377 - needs: [release_notes, build] 255 + needs: [build] 378 256 permissions: 379 257 contents: write 380 258 env: 381 259 RELEASE_REPO: supabitapp/supacode 382 260 steps: 383 - - run: | 384 - TAG="$GITHUB_REF_NAME" 385 - if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then 386 - TAG="${{ inputs.tag }}" 387 - fi 388 - echo "TAG=$TAG" >> "$GITHUB_ENV" 389 - - uses: actions/download-artifact@v7 390 - with: 391 - name: release-notes 392 - path: build 261 + - run: echo "TAG=${{ github.event.release.tag_name }}" >> "$GITHUB_ENV" 393 262 - uses: actions/download-artifact@v7 394 263 with: 395 264 name: build-artifacts 396 265 path: build 397 266 - run: | 398 - NOTES_FILE=build/release-notes.md 399 267 DELTA_FILES=$(find build -name "*.delta" -type f 2>/dev/null | tr '\n' ' ' || true) 400 - 401 - if gh release view "$TAG" -R "$RELEASE_REPO" >/dev/null 2>&1; then 402 - gh release edit "$TAG" --notes-file "$NOTES_FILE" -R "$RELEASE_REPO" 403 - gh release upload "$TAG" build/supacode.app.zip build/supacode.dmg build/appcast.xml $DELTA_FILES --clobber -R "$RELEASE_REPO" 404 - else 405 - gh release create "$TAG" build/supacode.app.zip build/supacode.dmg build/appcast.xml $DELTA_FILES --title "$TAG" --notes-file "$NOTES_FILE" -R "$RELEASE_REPO" 406 - fi 268 + gh release upload "$TAG" build/supacode.app.zip build/supacode.dmg build/appcast.xml $DELTA_FILES --clobber -R "$RELEASE_REPO" 407 269 - run: | 408 270 set -euo pipefail 409 271 curl -fsSL "https://supacode.sh/download/$TAG/supacode.app.zip" -o /dev/null