RG-T133 User Session, Password Reset Changes, More Audits #187
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: Sync PR to Changerawr | |
| permissions: | |
| contents: read | |
| issues: write | |
| pull-requests: read | |
| on: | |
| pull_request: | |
| types: | |
| - closed | |
| branches: | |
| - master | |
| jobs: | |
| post-to-changerawr: | |
| # Only run if the PR was merged (not just closed) | |
| if: github.event.pull_request.merged == true | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 10 | |
| - name: Extract and prepare release notes | |
| id: prepare_notes | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| PR_TITLE: ${{ github.event.pull_request.title }} | |
| run: | | |
| set -euo pipefail | |
| echo "Fetching PR #${PR_NUMBER} details..." | |
| # Fetch the PR body using GitHub CLI | |
| PR_BODY="$(gh pr view "$PR_NUMBER" --json body --jq '.body' 2>/dev/null || echo "")" | |
| export PR_BODY | |
| # Strip CodeRabbit content and pull out the Release Notes section | |
| NOTES="$(python3 <<'PY' | |
| import os, re | |
| body = os.environ.get("PR_BODY", "") | |
| # 1. Drop the whole CodeRabbit auto-generated block (start marker .. end marker) | |
| body = re.sub( | |
| r"<!--\s*This is an auto-generated comment: release notes by coderabbit\.ai\s*-->" | |
| r".*?" | |
| r"<!--\s*end of auto-generated comment: release notes by coderabbit\.ai\s*-->", | |
| "", | |
| body, | |
| flags=re.IGNORECASE | re.DOTALL, | |
| ) | |
| # 2. Drop any remaining HTML comments (covers unpaired/renamed markers) | |
| body = re.sub(r"<!--.*?-->", "", body, flags=re.DOTALL) | |
| # 3. Drop a leftover "Summary by CodeRabbit" section: heading -> next h1/h2 or EOF | |
| body = re.sub( | |
| r"^#{1,6}\s*Summary by CodeRabbit\b.*?(?=^#{1,2}\s|\Z)", | |
| "", | |
| body, | |
| flags=re.IGNORECASE | re.MULTILINE | re.DOTALL, | |
| ) | |
| # 4. Prefer an explicit "Release Notes" section when the author wrote one | |
| m = re.search( | |
| r"^#{1,6}\s*Release Notes\s*$\n(?P<notes>.*?)(?=^#{1,2}\s|\Z)", | |
| body, | |
| flags=re.IGNORECASE | re.MULTILINE | re.DOTALL, | |
| ) | |
| notes = m.group("notes") if m and m.group("notes").strip() else body | |
| # Collapse runs of blank lines and trim | |
| notes = re.sub(r"\n{3,}", "\n\n", notes).strip() | |
| print(notes) | |
| PY | |
| )" | |
| # Fallback to PR title and recent commits if nothing usable remains | |
| if [ -z "${NOTES//[[:space:]]/}" ]; then | |
| echo "No usable PR body found, using PR title and commits..." | |
| NOTES="## ${PR_TITLE}" | |
| NOTES="$NOTES"$'\n\n'"$(git log -n 5 --pretty=format:'- %s')" | |
| fi | |
| # Save to file and step output | |
| printf '%s\n' "$NOTES" > release_notes.txt | |
| # For multiline output, use a delimiter that cannot appear in the content | |
| DELIM="RELEASE_NOTES_EOF_$(head -c 16 /dev/urandom | od -An -tx1 | tr -d ' \n')" | |
| { | |
| echo "RELEASE_NOTES<<${DELIM}" | |
| printf '%s\n' "$NOTES" | |
| echo "${DELIM}" | |
| } >> "$GITHUB_OUTPUT" | |
| echo "Release notes prepared:" | |
| cat release_notes.txt | |
| - name: Post to Changerawr API | |
| uses: actions/github-script@v7 | |
| env: | |
| CHANGERAWR_API_KEY: ${{ secrets.CHANGERAWR_API_KEY }} | |
| CHANGERAWR_PROJECT_ID: ${{ secrets.CHANGERAWR_PROJECT_ID }} | |
| RELEASE_NOTES: ${{ steps.prepare_notes.outputs.RELEASE_NOTES }} | |
| with: | |
| script: | | |
| const prNumber = context.payload.pull_request.number; | |
| const prTitle = context.payload.pull_request.title; | |
| const prUrl = context.payload.pull_request.html_url; | |
| const releaseNotes = process.env.RELEASE_NOTES || ''; | |
| // Check if required secrets are set | |
| if (!process.env.CHANGERAWR_API_KEY || !process.env.CHANGERAWR_PROJECT_ID) { | |
| console.log('⚠️ Changerawr API credentials not configured, skipping release notes submission'); | |
| return; | |
| } | |
| // Prepare the payload for Changerawr API | |
| const payload = { | |
| title: prTitle, | |
| content: releaseNotes, | |
| metadata: { | |
| pr_number: prNumber, | |
| pr_title: prTitle, | |
| pr_url: prUrl, | |
| merged_at: context.payload.pull_request.merged_at, | |
| merged_by: context.payload.pull_request.merged_by?.login || 'unknown', | |
| commit_sha: context.payload.pull_request.merge_commit_sha | |
| } | |
| }; | |
| console.log('Sending release notes to Changerawr...'); | |
| console.log('Payload:', JSON.stringify(payload, null, 2)); | |
| try { | |
| const response = await fetch( | |
| `https://clog.resgrid.com/api/projects/${process.env.CHANGERAWR_PROJECT_ID}/changelog`, | |
| { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'Authorization': `Bearer ${process.env.CHANGERAWR_API_KEY}` | |
| }, | |
| body: JSON.stringify(payload) | |
| } | |
| ); | |
| const responseText = await response.text(); | |
| if (!response.ok) { | |
| console.warn(`⚠️ Changerawr API request failed: ${response.status} - ${responseText}`); | |
| // Don't fail the workflow, just log the error | |
| return; | |
| } | |
| let result; | |
| try { | |
| result = JSON.parse(responseText); | |
| } catch (e) { | |
| result = responseText; | |
| } | |
| console.log('✅ Successfully posted to Changerawr:', result); | |
| // Optionally, comment on the PR with confirmation | |
| try { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: '✅ Change notes have been posted to Changerawr.' | |
| }); | |
| } catch (commentError) { | |
| console.log('Could not post comment to PR:', commentError.message); | |
| } | |
| } catch (error) { | |
| console.error('⚠️ Error posting to Changerawr:', error); | |
| // Don't fail the workflow | |
| } |