From bf9ee3d4e888b22867ba2a512908acad3ae09eec Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:04:48 +0600 Subject: [PATCH 01/14] Create changelog-generator. yml --- .github/workflows/changelog-generator. yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/workflows/changelog-generator. yml diff --git a/.github/workflows/changelog-generator. yml b/.github/workflows/changelog-generator. yml new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/.github/workflows/changelog-generator. yml @@ -0,0 +1 @@ + From 8014d7fd64a6bd33873445f988843443c09926b0 Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:05:26 +0600 Subject: [PATCH 02/14] Delete .github/workflows/changelog-generator.yml --- .github/workflows/changelog-generator. yml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .github/workflows/changelog-generator. yml diff --git a/.github/workflows/changelog-generator. yml b/.github/workflows/changelog-generator. yml deleted file mode 100644 index 8b137891..00000000 --- a/.github/workflows/changelog-generator. yml +++ /dev/null @@ -1 +0,0 @@ - From 7d02e76bf58ae4c457758c435b70144a283e68c7 Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:05:45 +0600 Subject: [PATCH 03/14] Create changelog-generator.yml --- .github/workflows/changelog-generator.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/workflows/changelog-generator.yml diff --git a/.github/workflows/changelog-generator.yml b/.github/workflows/changelog-generator.yml new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/.github/workflows/changelog-generator.yml @@ -0,0 +1 @@ + From 7d2aea40bc55fbd164d9fdc826843d58dddab8b3 Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:06:13 +0600 Subject: [PATCH 04/14] Add workflow to generate changelog on milestone closure --- .github/workflows/changelog-generator.yml | 138 ++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/.github/workflows/changelog-generator.yml b/.github/workflows/changelog-generator.yml index 8b137891..3f52f003 100644 --- a/.github/workflows/changelog-generator.yml +++ b/.github/workflows/changelog-generator.yml @@ -1 +1,139 @@ +name: Generate Changelog +on: + milestone: + types: [closed] + workflow_dispatch: + inputs: + milestone: + description: 'Milestone number or title to generate changelog for' + required: true + type: string + dry_run: + description: 'Preview changelog without committing' + required: false + type: boolean + default: false + +permissions: + contents: write + pull-requests: read + +jobs: + generate-changelog: + name: Generate WordPress readme.txt Changelog + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + tools: composer:v2 + + - name: Install dependencies + run: composer install --no-progress --prefer-dist --no-interaction + + - name: Get milestone information + id: milestone + env: + GH_TOKEN: ${{ secrets. GITHUB_TOKEN }} + MILESTONE_INPUT: ${{ github.event.inputs.milestone }} + EVENT_MILESTONE: ${{ github.event.milestone.number }} + run: | + if [ -n "$MILESTONE_INPUT" ]; then + MILESTONE="$MILESTONE_INPUT" + else + MILESTONE="$EVENT_MILESTONE" + fi + + echo "milestone=$MILESTONE" >> $GITHUB_OUTPUT + + # Fetch milestone details + MILESTONE_DATA=$(gh api "repos/${{ github.repository }}/milestones" \ + --jq ". [] | select(.number == $MILESTONE or .title == \"$MILESTONE\")") + + MILESTONE_TITLE=$(echo "$MILESTONE_DATA" | jq -r '.title') + MILESTONE_NUMBER=$(echo "$MILESTONE_DATA" | jq -r '.number') + DUE_DATE=$(echo "$MILESTONE_DATA" | jq -r '.due_on // empty') + + echo "title=$MILESTONE_TITLE" >> $GITHUB_OUTPUT + echo "number=$MILESTONE_NUMBER" >> $GITHUB_OUTPUT + + if [ -n "$DUE_DATE" ]; then + FORMATTED_DATE=$(date -d "$DUE_DATE" "+%d %b %Y") + echo "date=$FORMATTED_DATE" >> $GITHUB_OUTPUT + else + FORMATTED_DATE=$(date "+%d %b %Y") + echo "date=$FORMATTED_DATE" >> $GITHUB_OUTPUT + fi + + - name: Fetch PRs from milestone + id: prs + env: + GH_TOKEN: ${{ secrets. GITHUB_TOKEN }} + MILESTONE_NUMBER: ${{ steps.milestone.outputs.number }} + run: | + # Fetch all merged PRs in this milestone + gh pr list \ + --repo "${{ github.repository }}" \ + --state merged \ + --milestone "$MILESTONE_NUMBER" \ + --limit 1000 \ + --json number,title,labels,author,mergedAt \ + > prs.json + + echo "Found $(jq length prs.json) merged PRs in milestone" + + - name: Generate changelog entry + id: changelog + env: + MILESTONE_TITLE: ${{ steps.milestone.outputs.title }} + RELEASE_DATE: ${{ steps.milestone.outputs.date }} + run: | + php bin/generate-changelog.php \ + --milestone-title "$MILESTONE_TITLE" \ + --release-date "$RELEASE_DATE" \ + --prs-file prs.json \ + --output changelog-entry.txt + + echo "Generated changelog entry:" + cat changelog-entry.txt + + - name: Update readme.txt + if: github.event.inputs.dry_run != 'true' + run: | + php bin/update-readme-changelog. php \ + --readme readme.txt \ + --changelog-entry changelog-entry.txt \ + --output readme.txt + + - name: Commit changes + if: github.event. inputs.dry_run != 'true' + env: + MILESTONE_TITLE: ${{ steps. milestone.outputs.title }} + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + git add readme.txt + + if git diff --staged --quiet; then + echo "No changes to commit" + else + git commit -m "Update changelog for $MILESTONE_TITLE" + git push origin trunk + fi + + - name: Display changelog preview + if: github.event. inputs.dry_run == 'true' + run: | + echo "# Changelog Preview (Dry Run)" + echo "" + cat changelog-entry.txt From f5170a9e4936388742a3a21143dd4fa7ba0f953f Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:06:49 +0600 Subject: [PATCH 05/14] Create generate-changelog.php --- bin/generate-changelog.php | 1 + 1 file changed, 1 insertion(+) create mode 100644 bin/generate-changelog.php diff --git a/bin/generate-changelog.php b/bin/generate-changelog.php new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/bin/generate-changelog.php @@ -0,0 +1 @@ + From d24793fd7695fb7d4de3a1d9a5fed897fa879253 Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:07:28 +0600 Subject: [PATCH 06/14] Add script to generate changelog from PRs This script generates a changelog entry from milestone PRs, categorizing them by labels and formatting the output for a specified release date. --- bin/generate-changelog.php | 92 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/bin/generate-changelog.php b/bin/generate-changelog.php index 8b137891..9ac6f973 100644 --- a/bin/generate-changelog.php +++ b/bin/generate-changelog.php @@ -1 +1,93 @@ + [], + 'Enhancements' => [], + 'Fixes' => [], + 'Documentation' => [], + 'Project Management' => [], + 'Other' => [], +]; + +$label_mapping = [ + '[Type] Feature' => 'Features', + '[Type] Enhancement' => 'Enhancements', + '[Type] Bug' => 'Fixes', + 'documentation' => 'Documentation', + '[Type] Project Management' => 'Project Management', +]; + +foreach ($prs as $pr) { + $category = 'Other'; + + foreach ($pr['labels'] as $label) { + $label_name = $label['name']; + if (isset($label_mapping[$label_name])) { + $category = $label_mapping[$label_name]; + break; + } + } + + $categorized[$category][] = $pr; +} + +// Generate changelog entry +$changelog = "= {$milestone_title} =\n"; +$changelog .= "*Release Date {$release_date}*\n\n"; + +foreach ($categorized as $category => $items) { + if (empty($items)) { + continue; + } + + $changelog .= "*{$category}*\n\n"; + + foreach ($items as $pr) { + $title = $pr['title']; + // Remove common prefixes + $title = preg_replace('/^(Fix|Add|Update|Remove|Improve|Create|Delete|Refactor):\s*/i', '', $title); + $title = ucfirst($title); + + $changelog .= "- {$title}.\n"; + } + + $changelog .= "\n"; +} + +// Write output +if ($output_file === 'php://stdout') { + echo $changelog; +} else { + file_put_contents($output_file, $changelog); + fwrite(STDERR, "Changelog entry written to {$output_file}\n"); +} From 322bd3046c1c972ba5320e5a0b80849a1dedfae1 Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:07:49 +0600 Subject: [PATCH 07/14] Create update-readme-changelog.php --- bin/update-readme-changelog.php | 1 + 1 file changed, 1 insertion(+) create mode 100644 bin/update-readme-changelog.php diff --git a/bin/update-readme-changelog.php b/bin/update-readme-changelog.php new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/bin/update-readme-changelog.php @@ -0,0 +1 @@ + From ae77ff71f03f6d02a02021b7f26d0bda54ec17b4 Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 08:08:08 +0600 Subject: [PATCH 08/14] Add script to update readme with changelog entry This script updates the readme.txt file with a new changelog entry from a specified file. It checks for the existence of the readme and changelog entry files before proceeding with the update. --- bin/update-readme-changelog.php | 49 +++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/bin/update-readme-changelog.php b/bin/update-readme-changelog.php index 8b137891..21dbfaf5 100644 --- a/bin/update-readme-changelog.php +++ b/bin/update-readme-changelog.php @@ -1 +1,50 @@ + Date: Thu, 15 Jan 2026 08:10:08 +0600 Subject: [PATCH 09/14] Add changelog generation script to composer.json --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 198be53f..9507b90b 100644 --- a/composer.json +++ b/composer.json @@ -66,6 +66,7 @@ "docs:lint": "npm run lint:md", "docs:manifest": "php docs/bin/generate-manifest.php", "docs:parse": "php docs/bin/generate-parsed-md.php --output=${DOCS_OUTPUT_DIR:-docs/code-reference}", + "changelog:generate": "php bin/generate-changelog.php" "format": [ "@format:php", "@format:packages" From b8f45082b62f9ca4d70aa0d2b8180dde9f6f0aef Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 18:44:52 +0600 Subject: [PATCH 10/14] Update .github/workflows/changelog-generator.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/changelog-generator.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/changelog-generator.yml b/.github/workflows/changelog-generator.yml index 3f52f003..8306205b 100644 --- a/.github/workflows/changelog-generator.yml +++ b/.github/workflows/changelog-generator.yml @@ -43,7 +43,7 @@ jobs: - name: Get milestone information id: milestone env: - GH_TOKEN: ${{ secrets. GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} MILESTONE_INPUT: ${{ github.event.inputs.milestone }} EVENT_MILESTONE: ${{ github.event.milestone.number }} run: | From cbbc6f62ff9ebf65a6d5b0fee4c8173dbb645903 Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 18:45:39 +0600 Subject: [PATCH 11/14] Update .github/workflows/changelog-generator.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/changelog-generator.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/changelog-generator.yml b/.github/workflows/changelog-generator.yml index 8306205b..8ba63494 100644 --- a/.github/workflows/changelog-generator.yml +++ b/.github/workflows/changelog-generator.yml @@ -109,7 +109,7 @@ jobs: - name: Update readme.txt if: github.event.inputs.dry_run != 'true' run: | - php bin/update-readme-changelog. php \ + php bin/update-readme-changelog.php \ --readme readme.txt \ --changelog-entry changelog-entry.txt \ --output readme.txt From d90a46a05c504bd1b57b90d5661b4384b6a38610 Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 18:46:15 +0600 Subject: [PATCH 12/14] Update .github/workflows/changelog-generator.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/changelog-generator.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/changelog-generator.yml b/.github/workflows/changelog-generator.yml index 8ba63494..5d008e4e 100644 --- a/.github/workflows/changelog-generator.yml +++ b/.github/workflows/changelog-generator.yml @@ -117,7 +117,7 @@ jobs: - name: Commit changes if: github.event. inputs.dry_run != 'true' env: - MILESTONE_TITLE: ${{ steps. milestone.outputs.title }} + MILESTONE_TITLE: ${{ steps.milestone.outputs.title }} run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" From dd4a8c6c958e22c97993ff0be08a5e03e6c741c9 Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 18:47:22 +0600 Subject: [PATCH 13/14] Update .github/workflows/changelog-generator.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/changelog-generator.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/changelog-generator.yml b/.github/workflows/changelog-generator.yml index 5d008e4e..af4d1ecb 100644 --- a/.github/workflows/changelog-generator.yml +++ b/.github/workflows/changelog-generator.yml @@ -133,7 +133,7 @@ jobs: - name: Display changelog preview if: github.event. inputs.dry_run == 'true' - run: | + run: | echo "# Changelog Preview (Dry Run)" echo "" cat changelog-entry.txt From 9a21b1a0938cab77c2b88c393e22045e140508d3 Mon Sep 17 00:00:00 2001 From: Md Aminul Islam <56115259+theaminuli@users.noreply.github.com> Date: Thu, 15 Jan 2026 18:50:13 +0600 Subject: [PATCH 14/14] Fix formatting issues in changelog generator workflow --- .github/workflows/changelog-generator.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/changelog-generator.yml b/.github/workflows/changelog-generator.yml index af4d1ecb..c47f2d53 100644 --- a/.github/workflows/changelog-generator.yml +++ b/.github/workflows/changelog-generator.yml @@ -77,7 +77,7 @@ jobs: - name: Fetch PRs from milestone id: prs env: - GH_TOKEN: ${{ secrets. GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} MILESTONE_NUMBER: ${{ steps.milestone.outputs.number }} run: | # Fetch all merged PRs in this milestone @@ -115,7 +115,7 @@ jobs: --output readme.txt - name: Commit changes - if: github.event. inputs.dry_run != 'true' + if: github.event.inputs.dry_run != 'true' env: MILESTONE_TITLE: ${{ steps.milestone.outputs.title }} run: | @@ -132,7 +132,7 @@ jobs: fi - name: Display changelog preview - if: github.event. inputs.dry_run == 'true' + if: github.event.inputs.dry_run == 'true' run: | echo "# Changelog Preview (Dry Run)" echo ""