Create Release #17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Create Release | |
| on: | |
| push: | |
| tags: | |
| - "*" | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: "Tag to release (e.g. v1.2.3)" | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| discussions: write | |
| id-token: write | |
| actions: write | |
| jobs: | |
| release: | |
| if: ${{ github.repository == 'BrkRaw/brkraw' }} | |
| runs-on: ubuntu-latest | |
| outputs: | |
| prerelease: ${{ steps.prerelease.outputs.value }} | |
| tag: ${{ steps.tag.outputs.value }} | |
| zenodo_success: ${{ steps.zenodo.outcome == 'success' }} | |
| steps: | |
| - name: Resolve tag | |
| id: tag | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "value=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "value=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" | |
| fi | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.tag.outputs.value }} | |
| - name: Detect prerelease tag | |
| id: prerelease | |
| run: | | |
| tag="${{ steps.tag.outputs.value }}" | |
| if echo "$tag" | grep -Eq '(a|b|rc)[0-9]*$'; then | |
| echo "value=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "value=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.tag.outputs.value }} | |
| name: ${{ steps.tag.outputs.value }} | |
| body_path: RELEASE_NOTES.md | |
| prerelease: ${{ steps.prerelease.outputs.value }} | |
| - name: Post release announcement | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| TAG_NAME: ${{ steps.tag.outputs.value }} | |
| RELEASE_URL: https://github.com/${{ github.repository }}/releases/tag/${{ steps.tag.outputs.value }} | |
| run: | | |
| python3 - <<'PY' | |
| import json | |
| import os | |
| from pathlib import Path | |
| from urllib import request | |
| token = os.environ.get("GITHUB_TOKEN") | |
| repo = os.environ["GITHUB_REPOSITORY"] | |
| tag = os.environ["TAG_NAME"] | |
| release_url = os.environ["RELEASE_URL"] | |
| owner, name = repo.split("/") | |
| notes = Path("RELEASE_NOTES.md").read_text(encoding="utf-8").strip() | |
| title = f"Release {tag}" | |
| body = f"[Release {tag}]({release_url})\n\n{notes}" | |
| query = { | |
| "query": """ | |
| query($owner: String!, $name: String!) { | |
| repository(owner: $owner, name: $name) { | |
| id | |
| discussionCategories(first: 50) { | |
| nodes { id name } | |
| } | |
| } | |
| } | |
| """, | |
| "variables": {"owner": owner, "name": name}, | |
| } | |
| req = request.Request("https://api.github.com/graphql", method="POST") | |
| req.add_header("Authorization", f"Bearer {token}") | |
| req.add_header("Content-Type", "application/json") | |
| data = json.dumps(query).encode("utf-8") | |
| with request.urlopen(req, data=data) as resp: | |
| payload = json.loads(resp.read().decode("utf-8")) | |
| repo_data = payload.get("data", {}).get("repository", {}) | |
| category_id = None | |
| for node in repo_data.get("discussionCategories", {}).get("nodes", []): | |
| if node.get("name") == "Announcements": | |
| category_id = node.get("id") | |
| break | |
| if not category_id: | |
| print("Announcements category not found; skipping discussion.") | |
| raise SystemExit(0) | |
| mutation = { | |
| "query": """ | |
| mutation($repoId: ID!, $categoryId: ID!, $title: String!, $body: String!) { | |
| createDiscussion(input: {repositoryId: $repoId, categoryId: $categoryId, title: $title, body: $body}) { | |
| discussion { id url } | |
| } | |
| } | |
| """, | |
| "variables": { | |
| "repoId": repo_data.get("id"), | |
| "categoryId": category_id, | |
| "title": title, | |
| "body": body, | |
| }, | |
| } | |
| req = request.Request("https://api.github.com/graphql", method="POST") | |
| req.add_header("Authorization", f"Bearer {token}") | |
| req.add_header("Content-Type", "application/json") | |
| data = json.dumps(mutation).encode("utf-8") | |
| with request.urlopen(req, data=data) as resp: | |
| result = json.loads(resp.read().decode("utf-8")) | |
| url = result.get("data", {}).get("createDiscussion", {}).get("discussion", {}).get("url") | |
| if url: | |
| print(f"Created discussion: {url}") | |
| PY | |
| - name: Checkout main for Zenodo badge update | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: main | |
| - name: Set up git identity | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Update Zenodo badge | |
| id: zenodo | |
| if: ${{ steps.prerelease.outputs.value != 'true' }} | |
| continue-on-error: true | |
| run: | | |
| for i in $(seq 1 10); do | |
| echo "Zenodo badge update attempt $i/10" | |
| python3 scripts/update_zenodo_badge.py --up-to-date-exit-code 2 | |
| exit_code=$? | |
| set -e | |
| if [ "$exit_code" -eq 0 ]; then | |
| echo "Zenodo badge updated." | |
| exit 0 | |
| fi | |
| if [ "$exit_code" -ne 2 ]; then | |
| exit "$exit_code" | |
| fi | |
| sleep 60 | |
| done | |
| echo "Zenodo badge still up to date after 10 attempts; giving up." | |
| - name: Trigger publish workflow | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| target="${{ steps.prerelease.outputs.value == 'true' && 'testpypi' || 'pypi' }}" | |
| tag="${{ steps.tag.outputs.value }}" | |
| gh workflow run publish.yml -f target="$target" -f tag="$tag" |