This repository was archived by the owner on Mar 17, 2025. It is now read-only.
chore: robot emoji #49
Workflow file for this run
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: Generate Changeset | |
# This workflow can be triggered in two ways: | |
# 1. When a pull request is merged to any branch (typically develop or main) | |
# 2. Manually via the GitHub Actions UI using the workflow_dispatch event | |
# - Go to Actions > Generate Changeset > Run workflow | |
# - Enter the PR number and click "Run workflow" | |
on: | |
# Using pull_request_target instead of pull_request for security reasons: | |
# - Runs in the context of the BASE repository, not the fork | |
# - Has access to repository secrets | |
# - Can commit changes to protected branches | |
# - SECURITY NOTE: Be careful when checking out PR code with this event type | |
pull_request_target: | |
types: [closed] | |
branches: | |
- develop | |
workflow_dispatch: | |
inputs: | |
pr_number: | |
description: 'PR number to generate changeset for' | |
required: true | |
type: string | |
jobs: | |
debug-event: | |
runs-on: ubuntu-latest | |
if: github.event_name == 'pull_request_target' | |
steps: | |
- name: Debug Event | |
run: | | |
echo "Event name: ${{ github.event_name }}" | |
echo "Action: ${{ github.event.action }}" | |
echo "PR merged: ${{ github.event.pull_request.merged }}" | |
echo "Base ref: ${{ github.event.pull_request.base.ref }}" | |
echo "Head ref: ${{ github.event.pull_request.head.ref }}" | |
echo "PR number: ${{ github.event.pull_request.number }}" | |
echo "PR title: ${{ github.event.pull_request.title }}" | |
generate-changeset: | |
permissions: | |
contents: write | |
pull-requests: write | |
runs-on: ubuntu-latest | |
needs: [debug-event] | |
if: (github.event_name == 'pull_request_target' && github.event.pull_request.merged == true) || github.event_name == 'workflow_dispatch' | |
env: | |
REPO_URL: "https://github.com/${{ github.repository }}" | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v3 | |
with: | |
fetch-depth: 0 | |
ref: ${{ github.event.pull_request.base.ref || 'develop' }} | |
# Use a personal access token with repo scope for better permissions | |
token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Setup Node.js | |
uses: actions/setup-node@v3 | |
with: | |
node-version: '16' | |
- name: Install dependencies | |
run: npm ci | |
- name: Extract PR information | |
id: pr_info | |
run: | | |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
PR_NUMBER="${{ github.event.inputs.pr_number }}" | |
else | |
PR_NUMBER="${{ github.event.pull_request.number }}" | |
fi | |
PR_DATA=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ | |
"https://api.github.com/repos/${{ github.repository }}/pulls/${PR_NUMBER}") | |
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title') | |
PR_BODY=$(echo "$PR_DATA" | jq -r '.body') | |
PR_AUTHOR=$(echo "$PR_DATA" | jq -r '.user.login') | |
echo "pr_number=${PR_NUMBER}" >> $GITHUB_OUTPUT | |
echo "pr_title=${PR_TITLE}" >> $GITHUB_OUTPUT | |
echo "pr_author=${PR_AUTHOR}" >> $GITHUB_OUTPUT | |
echo "pr_body=${PR_BODY}" >> $GITHUB_OUTPUT | |
- name: Generate changeset for current PR | |
run: | | |
# Generate a changeset for the current PR | |
node scripts/generate-changeset.js \ | |
--pr="${{ steps.pr_info.outputs.pr_number }}" \ | |
--title="${{ steps.pr_info.outputs.pr_title }}" \ | |
--author="${{ steps.pr_info.outputs.pr_author }}" \ | |
--body="${{ steps.pr_info.outputs.pr_body }}" | |
# Commit and push the changeset | |
git config --global user.name "GitHub Actions" | |
git config --global user.email "actions@github.com" | |
# Check if there are changes to commit | |
if [[ -n "$(git status --porcelain)" ]]; then | |
git add .changesets/ | |
git commit -m "chore: add changeset for PR #${{ steps.pr_info.outputs.pr_number }}" | |
git push | |
echo "Changeset created and pushed for PR #${{ steps.pr_info.outputs.pr_number }}" | |
else | |
echo "No changes to commit" | |
fi | |
- name: Generate release notes from changesets | |
id: generate_notes | |
run: | | |
# Create a temporary directory for release notes | |
mkdir -p /tmp/release-notes | |
# Generate release notes from all changesets to a temporary file | |
npm run release:notes 2>/dev/null | grep -v "^>" > /tmp/release-notes/temp_notes_raw.md | |
# Remove the "Found X changesets" line | |
sed -n '/^Found/!p' /tmp/release-notes/temp_notes_raw.md > /tmp/release-notes/temp_notes.md | |
# For debugging | |
echo "Generated release notes:" | |
cat /tmp/release-notes/temp_notes.md | |
- name: Check for existing release PR | |
id: check_pr | |
run: | | |
# Check if there's already a PR from develop to main | |
PR_LIST=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ | |
-H "Accept: application/vnd.github.v3+json" \ | |
"https://api.github.com/repos/${{ github.repository }}/pulls?state=open&head=${{ github.repository_owner }}:develop&base=main") | |
PR_COUNT=$(echo "$PR_LIST" | jq length) | |
if [[ "$PR_COUNT" -gt 0 ]]; then | |
PR_NUMBER=$(echo "$PR_LIST" | jq -r '.[0].number') | |
echo "exists=true" >> $GITHUB_OUTPUT | |
echo "number=${PR_NUMBER}" >> $GITHUB_OUTPUT | |
else | |
echo "exists=false" >> $GITHUB_OUTPUT | |
fi | |
- name: Update existing release PR | |
if: steps.check_pr.outputs.exists == 'true' | |
run: | | |
# Update the PR body with the latest changelog | |
PR_NUMBER="${{ steps.check_pr.outputs.number }}" | |
# Get current PR data | |
PR_DATA=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ | |
"https://api.github.com/repos/${{ github.repository }}/pulls/${PR_NUMBER}") | |
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title') | |
# Create the PR body with proper formatting | |
PR_BODY="## Upcoming Changes" | |
PR_BODY="${PR_BODY}"$'\n\n' | |
PR_BODY="${PR_BODY}$(cat /tmp/release-notes/temp_notes.md)" | |
PR_BODY="${PR_BODY}"$'\n\n' | |
PR_BODY="${PR_BODY}This PR contains all changes that will be included in the next release. It is automatically updated when new changesets are added to the develop branch." | |
# Use jq to properly escape the content | |
PAYLOAD=$(jq -n --arg body "$PR_BODY" --arg title "$PR_TITLE" '{body: $body, title: $title}') | |
# For debugging | |
echo "API Payload:" | |
echo "$PAYLOAD" | jq '.' | |
# Update the PR | |
RESPONSE=$(curl -X PATCH \ | |
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ | |
-H "Accept: application/vnd.github.v3+json" \ | |
-H "Content-Type: application/json" \ | |
"https://api.github.com/repos/${{ github.repository }}/pulls/${PR_NUMBER}" \ | |
-d "$PAYLOAD") | |
# Print full response for debugging | |
echo "Full API Response:" | |
echo "$RESPONSE" | jq '.' | |
echo "Updated existing release PR #${PR_NUMBER} with latest changelog" | |
- name: Create new release PR | |
if: steps.check_pr.outputs.exists == 'false' | |
run: | | |
# Create the PR body with proper formatting | |
PR_BODY="## Upcoming Changes" | |
PR_BODY="${PR_BODY}"$'\n\n' | |
PR_BODY="${PR_BODY}$(cat /tmp/release-notes/temp_notes.md)" | |
PR_BODY="${PR_BODY}"$'\n\n' | |
PR_BODY="${PR_BODY}This PR contains all changes that will be included in the next release. It is automatically updated when new changesets are added to the develop branch." | |
# Use jq to properly escape the content | |
PAYLOAD=$(jq -n \ | |
--arg title "release: next version 📦" \ | |
--arg head "develop" \ | |
--arg base "main" \ | |
--arg body "$PR_BODY" \ | |
'{title: $title, head: $head, base: $base, body: $body}') | |
# For debugging | |
echo "API Payload:" | |
echo "$PAYLOAD" | jq '.' | |
# Create a new PR from develop to main | |
RESPONSE=$(curl -X POST \ | |
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ | |
-H "Accept: application/vnd.github.v3+json" \ | |
-H "Content-Type: application/json" \ | |
"https://api.github.com/repos/${{ github.repository }}/pulls" \ | |
-d "$PAYLOAD") | |
# Print full response for debugging | |
echo "Full API Response:" | |
echo "$RESPONSE" | jq '.' | |
# Check for error messages | |
ERROR_MESSAGE=$(echo "$RESPONSE" | jq -r '.message // "No error message"') | |
if [[ "$ERROR_MESSAGE" != "No error message" ]]; then | |
echo "Error creating PR: $ERROR_MESSAGE" | |
# Check for more detailed errors | |
ERRORS=$(echo "$RESPONSE" | jq -r '.errors // []') | |
if [[ "$ERRORS" != "[]" ]]; then | |
echo "Detailed errors: $ERRORS" | |
fi | |
exit 1 | |
fi | |
PR_NUMBER=$(echo "$RESPONSE" | jq -r '.number') | |
if [[ -z "$PR_NUMBER" || "$PR_NUMBER" == "null" ]]; then | |
echo "Failed to create PR. No PR number returned." | |
exit 1 | |
else | |
echo "Created new release PR #${PR_NUMBER} with initial changelog" | |
fi |