|
| 1 | +# Changeset Generation Workflow |
| 2 | + |
| 3 | +This document outlines the requirements and implementation details for the Changeset Generation workflow. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +This workflow automatically generates changesets for pull requests. Changesets are used to track changes that will be included in the next release, and they help in generating changelogs and determining version bumps. |
| 8 | + |
| 9 | +## Triggers |
| 10 | + |
| 11 | +The workflow is triggered by: |
| 12 | + |
| 13 | +1. When a pull request is labeled with 'ready-for-changeset' |
| 14 | +2. Manually via the GitHub Actions UI using the workflow_dispatch event |
| 15 | + - Go to Actions > Generate Changeset > Run workflow |
| 16 | + - Enter the PR number and click "Run workflow" |
| 17 | + |
| 18 | +## Implementation Options |
| 19 | + |
| 20 | +There are two main approaches to implementing changeset generation: |
| 21 | + |
| 22 | +1. **Using @changesets/cli package**: A popular solution for managing changesets in JavaScript projects. |
| 23 | +2. **Custom implementation**: A tailored solution that fits specific needs, which is the approach used in this repository. |
| 24 | + |
| 25 | +## Changeset Format |
| 26 | + |
| 27 | +Each changeset is a markdown file stored in the `.changesets` directory with the following format: |
| 28 | + |
| 29 | +```md |
| 30 | +--- |
| 31 | +title: "Brief description of the change" |
| 32 | +pr: 123 |
| 33 | +author: "username" |
| 34 | +type: "feat|fix|chore|docs|refactor|test|style|perf" |
| 35 | +breaking: true|false |
| 36 | +--- |
| 37 | + |
| 38 | +Detailed description of the change... |
| 39 | +``` |
| 40 | + |
| 41 | +### Fields |
| 42 | + |
| 43 | +- **title**: A brief description of the change |
| 44 | +- **pr**: The pull request number |
| 45 | +- **author**: The GitHub username of the PR author |
| 46 | +- **type**: The type of change, following conventional commit types |
| 47 | +- **breaking**: Whether this is a breaking change (true/false) |
| 48 | + |
| 49 | +## Breaking Change Detection |
| 50 | + |
| 51 | +Breaking changes are detected by: |
| 52 | + |
| 53 | +1. Explicit flag in the changeset (`breaking: true`) |
| 54 | +2. Conventional commit prefix with `!` (e.g., `feat!:`) |
| 55 | +3. The phrase "BREAKING CHANGE" in the PR title or body |
| 56 | + |
| 57 | +## Workflow Steps |
| 58 | + |
| 59 | +1. **Detect PR Merge**: The workflow runs when a PR is merged or when manually triggered. |
| 60 | +2. **Extract Metadata**: The workflow extracts relevant information from the PR, including title, author, and body. |
| 61 | +3. **Generate Changeset**: A changeset file is created with the extracted metadata. |
| 62 | +4. **Commit Changeset**: The changeset is committed to the branch (typically `develop`). |
| 63 | +5. **Generate Release Notes**: The `release:notes` script processes all changesets to create formatted release notes in a temporary file. |
| 64 | +6. **Update/Create Release PR**: The workflow either updates an existing release PR or creates a new one with the generated release notes. |
| 65 | + |
| 66 | +## Release Notes Generation |
| 67 | + |
| 68 | +The `generate-release-notes.js` script: |
| 69 | + |
| 70 | +1. Reads all changeset files from the `.changesets` directory |
| 71 | +2. Categorizes changes into breaking changes, features, fixes, and other changes |
| 72 | +3. Determines the appropriate version bump type (major, minor, or patch) |
| 73 | +4. Formats the release notes in either Markdown or JSON format |
| 74 | +5. Identifies contributors and first-time contributors |
| 75 | +6. Can be run locally for testing with `npm run release:notes` |
| 76 | + |
| 77 | +### Script Options |
| 78 | + |
| 79 | +The script supports the following command-line options: |
| 80 | + |
| 81 | +- `--format`: Output format (json or markdown, default: markdown) |
| 82 | +- `--repo-url`: Repository URL to use for PR links (overrides package.json) |
| 83 | +- `--token`: GitHub token for API requests (needed to identify first-time contributors) |
| 84 | + |
| 85 | +### Environment Variables |
| 86 | + |
| 87 | +The script also supports the following environment variables: |
| 88 | + |
| 89 | +- `REPO_URL`: Repository URL to use for PR links (can be used instead of `--repo-url`) |
| 90 | +- `GITHUB_TOKEN`: GitHub token for API requests (can be used instead of `--token`) |
| 91 | + |
| 92 | +Using environment variables allows you to set these values once in your environment rather than passing them as command-line arguments each time. |
| 93 | + |
| 94 | +### Contributors Section |
| 95 | + |
| 96 | +The release notes include a special section to acknowledge contributors: |
| 97 | + |
| 98 | +1. **Contributors**: Lists all contributors who made changes in this release |
| 99 | +2. **First-time Contributors**: Gives special recognition to first-time contributors |
| 100 | + |
| 101 | +To identify first-time contributors, the script uses the GitHub API to check if a contributor has made 3 or fewer commits to the repository. This requires a GitHub token to be provided via the `--token` option or the `GITHUB_TOKEN` environment variable. |
| 102 | + |
| 103 | +## GitHub Action Implementation |
| 104 | + |
| 105 | +```yaml |
| 106 | +name: Generate Changeset |
| 107 | + |
| 108 | +on: |
| 109 | + pull_request_target: |
| 110 | + types: [closed] |
| 111 | + workflow_dispatch: |
| 112 | + inputs: |
| 113 | + pr_number: |
| 114 | + description: 'Pull Request Number' |
| 115 | + required: true |
| 116 | + type: string |
| 117 | + |
| 118 | +jobs: |
| 119 | + generate-changeset: |
| 120 | + if: (github.event_name == 'pull_request_target' && github.event.pull_request.merged == true) || github.event_name == 'workflow_dispatch' |
| 121 | + runs-on: ubuntu-latest |
| 122 | + env: |
| 123 | + REPO_URL: "https://github.com/${{ github.repository }}" |
| 124 | + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 125 | + steps: |
| 126 | + # Checkout code |
| 127 | + # Setup Node.js |
| 128 | + # Install dependencies |
| 129 | + # Get PR details |
| 130 | + # Generate changeset |
| 131 | + # Commit changeset |
| 132 | + # Generate release notes to temporary file |
| 133 | + # Check for existing release PR |
| 134 | + # Update/Create release PR |
| 135 | +``` |
| 136 | + |
| 137 | +## Temporary Files |
| 138 | + |
| 139 | +The workflow uses temporary files to store release notes during execution: |
| 140 | + |
| 141 | +1. Release notes are generated to a temporary directory (`/tmp/release-notes`) |
| 142 | +2. These files are not committed to the repository |
| 143 | +3. The temporary files are automatically cleaned up after the workflow completes |
| 144 | + |
| 145 | +This approach keeps the repository clean while still allowing the workflow to process and use the release notes. |
| 146 | + |
| 147 | +## Prerequisites |
| 148 | + |
| 149 | +1. Create a 'ready-for-changeset' label in your repository |
| 150 | +2. Set up a Personal Access Token (PAT) with the "repo" scope as a repository secret named `REPO_PAT` |
| 151 | + |
| 152 | +## Local Testing |
| 153 | + |
| 154 | +You can test the release notes generation locally by running: |
| 155 | + |
| 156 | +```bash |
| 157 | +npm run release:notes |
| 158 | +``` |
| 159 | + |
| 160 | +For JSON output (used in PR descriptions): |
| 161 | + |
| 162 | +```bash |
| 163 | +npm run release:notes -- --format=json |
| 164 | +``` |
| 165 | + |
| 166 | +To specify a custom repository URL for PR links: |
| 167 | + |
| 168 | +```bash |
| 169 | +npm run release:notes -- --repo-url="https://github.com/wp-graphql/automation-tests" |
| 170 | +``` |
| 171 | + |
| 172 | +Or using environment variables: |
| 173 | + |
| 174 | +```bash |
| 175 | +export REPO_URL="https://github.com/wp-graphql/automation-tests" |
| 176 | +npm run release:notes |
| 177 | +``` |
| 178 | + |
| 179 | +To identify first-time contributors (requires a GitHub token): |
| 180 | + |
| 181 | +```bash |
| 182 | +npm run release:notes -- --token="your_github_token" |
| 183 | +``` |
| 184 | + |
| 185 | +Or using environment variables: |
| 186 | + |
| 187 | +```bash |
| 188 | +export GITHUB_TOKEN="your_github_token" |
| 189 | +npm run release:notes |
| 190 | +``` |
| 191 | + |
| 192 | +## Next Steps and Considerations |
| 193 | + |
| 194 | +- Create the 'ready-for-changeset' label in the repository |
| 195 | +- Set up a Personal Access Token (PAT) with repo scope as a repository secret named `REPO_PAT` |
| 196 | +- Test workflow with sample PRs |
| 197 | +- Consider how to handle merge conflicts |
| 198 | +- Plan integration with the release workflow |
| 199 | + |
| 200 | +## Workflow Configuration |
| 201 | + |
| 202 | +The workflow is configured to run in two scenarios: |
| 203 | + |
| 204 | +1. When a pull request is merged to any branch (typically develop or main) |
| 205 | +2. Manually via the GitHub Actions UI using the workflow_dispatch event |
| 206 | + |
| 207 | +### Environment Variables |
| 208 | + |
| 209 | +The workflow uses the following environment variables: |
| 210 | + |
| 211 | +- `REPO_URL`: Set to `https://github.com/${{ github.repository }}` to provide the repository URL for generating PR links |
| 212 | +- `GITHUB_TOKEN`: Set to `${{ secrets.REPO_PAT }}` to provide authentication for GitHub API requests |
| 213 | + |
| 214 | +These environment variables are automatically set at the job level and are used by the `generate-release-notes.js` script without needing to pass them as command-line arguments. |
| 215 | + |
| 216 | +### Prerequisites |
| 217 | + |
| 218 | +For the workflow to function correctly, you need to: |
| 219 | + |
| 220 | +1. Create a Personal Access Token (PAT) with `repo` scope |
| 221 | +2. Add this token as a repository secret named `REPO_PAT` |
0 commit comments