diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a6b9949c3..ea85965e8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,8 +9,15 @@ permissions: contents: write jobs: - release: - name: Build and Release XCFrameworks + release-notes: + uses: ./.github/workflows/release_notes.yml + with: + tag-name: ${{ github.ref_name }} + secrets: inherit + + build-xcframeworks: + name: Build and Upload XCFrameworks + needs: release-notes runs-on: macos-15 outputs: checksum_OpenSwiftUI: ${{ steps.build.outputs.checksum_OpenSwiftUI }} @@ -33,41 +40,35 @@ jobs: tag-name: ${{ github.ref_name }} signing-certificate-base64: ${{ secrets.SIGNING_CERTIFICATE_BASE_64 }} signing-certificate-password: ${{ secrets.SIGNING_CERTIFICATE_PASSWORD }} - - name: Create Release - uses: ncipollo/release-action@v1 - with: - body: | - ```swift - ${{ steps.build.outputs.body }} - ``` - allowUpdates: true - artifacts: "build/*.xcframework.zip" - token: ${{ secrets.GITHUB_TOKEN }} + - name: Upload assets to release + run: gh release upload "${{ github.ref_name }}" build/*.xcframework.zip --clobber update-binary-repo: name: Update OpenSwiftUI-spm - needs: release + needs: build-xcframeworks runs-on: ubuntu-latest - if: ${{ secrets.BINARY_REPO_PAT != '' }} + env: + BINARY_REPO_PAT: ${{ secrets.BINARY_REPO_PAT }} steps: - - name: Clone binary repo - run: | - git clone https://x-access-token:${{ secrets.BINARY_REPO_PAT }}@github.com/OpenSwiftUIProject/OpenSwiftUI-spm.git - cd OpenSwiftUI-spm - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - - name: Generate Package.swift from template + - name: Update binary repo env: VERSION: ${{ github.ref_name }} - CHECKSUM_OpenSwiftUI: ${{ needs.release.outputs.checksum_OpenSwiftUI }} - CHECKSUM_OpenSwiftUICore: ${{ needs.release.outputs.checksum_OpenSwiftUICore }} - CHECKSUM_OpenAttributeGraphShims: ${{ needs.release.outputs.checksum_OpenAttributeGraphShims }} - CHECKSUM_OpenCoreGraphicsShims: ${{ needs.release.outputs.checksum_OpenCoreGraphicsShims }} - CHECKSUM_OpenObservation: ${{ needs.release.outputs.checksum_OpenObservation }} - CHECKSUM_OpenQuartzCoreShims: ${{ needs.release.outputs.checksum_OpenQuartzCoreShims }} - CHECKSUM_OpenRenderBoxShims: ${{ needs.release.outputs.checksum_OpenRenderBoxShims }} + CHECKSUM_OpenSwiftUI: ${{ needs.build-xcframeworks.outputs.checksum_OpenSwiftUI }} + CHECKSUM_OpenSwiftUICore: ${{ needs.build-xcframeworks.outputs.checksum_OpenSwiftUICore }} + CHECKSUM_OpenAttributeGraphShims: ${{ needs.build-xcframeworks.outputs.checksum_OpenAttributeGraphShims }} + CHECKSUM_OpenCoreGraphicsShims: ${{ needs.build-xcframeworks.outputs.checksum_OpenCoreGraphicsShims }} + CHECKSUM_OpenObservation: ${{ needs.build-xcframeworks.outputs.checksum_OpenObservation }} + CHECKSUM_OpenQuartzCoreShims: ${{ needs.build-xcframeworks.outputs.checksum_OpenQuartzCoreShims }} + CHECKSUM_OpenRenderBoxShims: ${{ needs.build-xcframeworks.outputs.checksum_OpenRenderBoxShims }} run: | + if [ -z "$BINARY_REPO_PAT" ]; then + echo "::notice::BINARY_REPO_PAT not set, skipping binary repo update" + exit 0 + fi + git clone https://x-access-token:${BINARY_REPO_PAT}@github.com/OpenSwiftUIProject/OpenSwiftUI-spm.git cd OpenSwiftUI-spm + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" sed \ -e "s|{{VERSION}}|${VERSION}|g" \ -e "s|{{CHECKSUM_OpenSwiftUI}}|${CHECKSUM_OpenSwiftUI}|g" \ @@ -80,11 +81,6 @@ jobs: Package.swift.template > Package.swift echo "Generated Package.swift:" head -50 Package.swift - - name: Commit, push, and tag - env: - VERSION: ${{ github.ref_name }} - run: | - cd OpenSwiftUI-spm git add Package.swift git diff --cached --quiet && echo "No changes" && exit 0 git commit -m "Update to ${VERSION} with code-signed XCFrameworks" diff --git a/.github/workflows/release_notes.yml b/.github/workflows/release_notes.yml new file mode 100644 index 000000000..3acfd9862 --- /dev/null +++ b/.github/workflows/release_notes.yml @@ -0,0 +1,126 @@ +name: Release Notes + +on: + workflow_dispatch: + inputs: + tag-name: + description: 'Tag name (e.g. 0.17.1)' + required: true + workflow_call: + inputs: + tag-name: + description: 'Tag name for the release' + required: true + type: string + secrets: + CLAUDE_CODE_OAUTH_TOKEN: + required: false + +permissions: + contents: write + +jobs: + release-notes: + name: Generate Release Notes + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ github.token }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Generate changelog from GitHub + env: + TAG_NAME: ${{ inputs.tag-name }} + run: | + gh api repos/${{ github.repository }}/releases/generate-notes \ + -f tag_name="${TAG_NAME}" \ + --jq '.body' > /tmp/changelog.md + echo "Generated changelog:" + cat /tmp/changelog.md + + - name: Generate highlights with Claude Code + env: + CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + TAG_NAME: ${{ inputs.tag-name }} + run: | + if [ -z "$CLAUDE_CODE_OAUTH_TOKEN" ]; then + echo "::warning::CLAUDE_CODE_OAUTH_TOKEN not set, using placeholder highlights" + printf '## Highlights\n\n_To be written._\n' > /tmp/highlights.md + exit 0 + fi + + { + cat <<'STATIC_EOF' + You are generating the Highlights section for an OpenSwiftUI release. + OpenSwiftUI is an open source reimplementation of Apple's SwiftUI framework. + + Below is the auto-generated changelog: + + STATIC_EOF + cat /tmp/changelog.md + cat <<'STATIC_EOF' + + Write ONLY a ## Highlights section with concise bullet points of key user-facing changes. + Rules: + - Skip [NFC], [CI], refactoring, docs, and internal-only changes + - Each bullet starts with a verb: Add, Fix, Improve, Update + - Keep 1-5 bullets, be concise + - Output ONLY the ## Highlights header followed by bullet points, nothing else + + Examples from past releases: + + ## Highlights + + - Add Xcode Preview support + - Add initial Text support + - Add OpenSwiftUI xcframework release support + + ## Highlights + + - Add NS/UIApplicationDelegateAdapter support + - Add Compute backend support as an alternative to AttributeGraph + - Add NamedImage support for bundle image and system image + STATIC_EOF + } > /tmp/prompt.txt + + npx -y @anthropic-ai/claude-code@latest \ + --model claude-opus-4-6 \ + -p "$(cat /tmp/prompt.txt)" \ + --output-format text > /tmp/highlights.md + + echo "Generated highlights:" + cat /tmp/highlights.md + + - name: Create release + env: + TAG_NAME: ${{ inputs.tag-name }} + run: | + { + cat /tmp/highlights.md + echo "" + cat /tmp/changelog.md + cat < /tmp/release_notes.md + + echo "=== Full release notes ===" + cat /tmp/release_notes.md + echo "==========================" + + if gh release view "${TAG_NAME}" > /dev/null 2>&1; then + gh release edit "${TAG_NAME}" --notes-file /tmp/release_notes.md + else + gh release create "${TAG_NAME}" \ + --title "${TAG_NAME}" \ + --notes-file /tmp/release_notes.md + fi