Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

chore: robot emoji

chore: robot emoji #49

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