Skip to content

Commit 6b306a9

Browse files
[ci:fix] Resolved issues with changelog bot for fork PRs
Co-authored-by: Federico Capoano <f.capoano@openwisp.io>
1 parent 1c893d6 commit 6b306a9

5 files changed

Lines changed: 208 additions & 49 deletions

File tree

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Changelog Bot Runner
2+
3+
on:
4+
workflow_run:
5+
workflows: ["Changelog Bot Trigger"]
6+
types:
7+
- completed
8+
9+
permissions:
10+
actions: read
11+
contents: read
12+
pull-requests: write
13+
issues: write
14+
15+
jobs:
16+
fetch-metadata:
17+
runs-on: ubuntu-latest
18+
if: github.event.workflow_run.conclusion == 'success'
19+
outputs:
20+
pr_number: ${{ steps.metadata.outputs.pr_number }}
21+
steps:
22+
- name: Download PR metadata
23+
id: download
24+
uses: actions/download-artifact@v4
25+
with:
26+
name: changelog-metadata
27+
github-token: ${{ secrets.GITHUB_TOKEN }}
28+
run-id: ${{ github.event.workflow_run.id }}
29+
continue-on-error: true
30+
31+
- name: Read PR metadata
32+
if: steps.download.outcome == 'success'
33+
id: metadata
34+
run: |
35+
PR_NUMBER=$(cat pr_number)
36+
if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
37+
echo "::error::Invalid PR number: $PR_NUMBER"
38+
exit 1
39+
fi
40+
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
41+
42+
changelog:
43+
needs: fetch-metadata
44+
if: needs.fetch-metadata.outputs.pr_number != ''
45+
uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-changelog.yml@master
46+
with:
47+
pr_number: ${{ needs.fetch-metadata.outputs.pr_number }}
48+
secrets:
49+
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
50+
OPENWISP_BOT_APP_ID: ${{ secrets.OPENWISP_BOT_APP_ID }}
51+
OPENWISP_BOT_PRIVATE_KEY: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Changelog Bot Trigger
2+
3+
on:
4+
pull_request_review:
5+
types: [submitted]
6+
7+
jobs:
8+
check:
9+
if: |
10+
github.event.review.state == 'approved' &&
11+
(github.event.review.author_association == 'OWNER' ||
12+
github.event.review.author_association == 'MEMBER' ||
13+
github.event.review.author_association == 'COLLABORATOR')
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Check for noteworthy PR
17+
id: check
18+
env:
19+
PR_TITLE: ${{ github.event.pull_request.title }}
20+
run: |
21+
if echo "$PR_TITLE" | grep -qiE '^\[(feature|fix|change)\]'; then
22+
echo "has_noteworthy=true" >> $GITHUB_OUTPUT
23+
fi
24+
25+
- name: Save PR metadata
26+
if: steps.check.outputs.has_noteworthy == 'true'
27+
env:
28+
PR_NUMBER: ${{ github.event.pull_request.number }}
29+
run: echo "$PR_NUMBER" > pr_number
30+
31+
- name: Upload PR metadata
32+
if: steps.check.outputs.has_noteworthy == 'true'
33+
uses: actions/upload-artifact@v4
34+
with:
35+
name: changelog-metadata
36+
path: pr_number

.github/workflows/bot-changelog.yml

Lines changed: 0 additions & 20 deletions
This file was deleted.

.github/workflows/reusable-bot-changelog.yml

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ name: Reusable Changelog Bot
22

33
on:
44
workflow_call:
5+
inputs:
6+
pr_number:
7+
description: "Pull request number"
8+
required: true
9+
type: string
510
secrets:
611
GEMINI_API_KEY:
712
description: "Google Gemini API key"
@@ -15,13 +20,6 @@ on:
1520

1621
jobs:
1722
generate-changelog:
18-
# Trigger only when PR is approved
19-
if: |
20-
github.event_name == 'pull_request_review' &&
21-
github.event.review.state == 'approved' &&
22-
(github.event.review.author_association == 'OWNER' ||
23-
github.event.review.author_association == 'MEMBER' ||
24-
github.event.review.author_association == 'COLLABORATOR')
2523
runs-on: ubuntu-latest
2624
permissions:
2725
contents: read
@@ -32,31 +30,17 @@ jobs:
3230
- name: Checkout PR repository
3331
uses: actions/checkout@v6
3432
with:
35-
ref: ${{ github.event.pull_request.head.sha }}
33+
ref: refs/pull/${{ inputs.pr_number }}/head
3634
fetch-depth: 0
3735

38-
- name: Check for noteworthy commits
39-
id: check-commits
40-
env:
41-
PR_TITLE: ${{ github.event.pull_request.title }}
42-
run: |
43-
echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
44-
if echo "$PR_TITLE" | grep -qiE '^\[(feature|fix|change)\]'; then
45-
echo "has_noteworthy=true" >> $GITHUB_OUTPUT
46-
else
47-
echo "has_noteworthy=false" >> $GITHUB_OUTPUT
48-
fi
49-
5036
- name: Generate App Token
51-
if: steps.check-commits.outputs.has_noteworthy == 'true'
52-
uses: actions/create-github-app-token@v1
37+
uses: actions/create-github-app-token@v2
5338
id: app-token
5439
with:
5540
app-id: ${{ secrets.OPENWISP_BOT_APP_ID }}
5641
private-key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }}
5742

5843
- name: Checkout openwisp-utils for action
59-
if: steps.check-commits.outputs.has_noteworthy == 'true'
6044
uses: actions/checkout@v6
6145
with:
6246
repository: openwisp/openwisp-utils
@@ -66,10 +50,9 @@ jobs:
6650
path: openwisp-utils-action
6751

6852
- name: Generate changelog
69-
if: steps.check-commits.outputs.has_noteworthy == 'true'
7053
uses: ./openwisp-utils-action/.github/actions/bot-changelog-generator
7154
with:
7255
github-token: ${{ steps.app-token.outputs.token }}
7356
gemini-api-key: ${{ secrets.GEMINI_API_KEY }}
74-
pr-number: ${{ steps.check-commits.outputs.pr_number }}
57+
pr-number: ${{ inputs.pr_number }}
7558
repo-name: ${{ github.repository }}

docs/developer/reusable-github-utils.rst

Lines changed: 113 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -472,28 +472,137 @@ maintainer. It analyzes the PR's title, description, code changes, and
472472
linked issues, then posts a properly formatted changelog entry as a
473473
comment on the PR.
474474

475+
The bot uses a two-workflow pattern to support PRs from forks. The first
476+
workflow is triggered by ``pull_request_review``: it checks whether the PR
477+
qualifies and uploads the PR number as an artifact, but requires no
478+
secrets. The second workflow executes via ``workflow_run`` once the first
479+
completes: it runs in the context of the base repository, has full access
480+
to secrets, and is the one that generates and posts the changelog comment.
481+
475482
**Secrets**
476483

477484
- ``GEMINI_API_KEY`` (required): Google Gemini API key.
478485
- ``OPENWISP_BOT_APP_ID`` (required): OpenWISP Bot GitHub App ID.
479486
- ``OPENWISP_BOT_PRIVATE_KEY`` (required): OpenWISP Bot GitHub App private
480487
key.
481488

482-
**Usage Example**
489+
**Setup for Other Repositories**
483490

484-
To enable the changelog bot in any OpenWISP repository, create a workflow
485-
file at ``.github/workflows/changelog-bot.yml``:
491+
To enable the changelog bot in any OpenWISP repository, create the
492+
following two workflow files.
493+
494+
**1. Trigger** (``.github/workflows/bot-changelog-trigger.yml``)
495+
496+
This workflow fires on PR approval, checks if the PR is noteworthy, and
497+
uploads the PR number as an artifact for the runner to pick up.
486498

487499
.. code-block:: yaml
488500
489-
name: Changelog Bot
501+
name: Changelog Bot Trigger
502+
490503
on:
491504
pull_request_review:
492505
types: [submitted]
506+
507+
jobs:
508+
check:
509+
if: |
510+
github.event.review.state == 'approved' &&
511+
(github.event.review.author_association == 'OWNER' ||
512+
github.event.review.author_association == 'MEMBER' ||
513+
github.event.review.author_association == 'COLLABORATOR')
514+
runs-on: ubuntu-latest
515+
steps:
516+
- name: Check for noteworthy PR
517+
id: check
518+
env:
519+
PR_TITLE: ${{ github.event.pull_request.title }}
520+
run: |
521+
if echo "$PR_TITLE" | grep -qiE '^\[(feature|fix|change)\]'; then
522+
echo "has_noteworthy=true" >> $GITHUB_OUTPUT
523+
fi
524+
525+
- name: Save PR metadata
526+
if: steps.check.outputs.has_noteworthy == 'true'
527+
env:
528+
PR_NUMBER: ${{ github.event.pull_request.number }}
529+
run: echo "$PR_NUMBER" > pr_number
530+
531+
- name: Upload PR metadata
532+
if: steps.check.outputs.has_noteworthy == 'true'
533+
uses: actions/upload-artifact@v4
534+
with:
535+
name: changelog-metadata
536+
path: pr_number
537+
538+
**2. Runner** (``.github/workflows/bot-changelog-runner.yml``)
539+
540+
This workflow triggers after the trigger completes, downloads the
541+
artifact, and calls the reusable workflow with full secret access.
542+
543+
.. code-block:: yaml
544+
545+
name: Changelog Bot Runner
546+
547+
on:
548+
workflow_run:
549+
workflows: ["Changelog Bot Trigger"]
550+
types:
551+
- completed
552+
553+
permissions:
554+
actions: read
555+
contents: read
556+
pull-requests: write
557+
issues: write
558+
493559
jobs:
560+
fetch-metadata:
561+
runs-on: ubuntu-latest
562+
if: github.event.workflow_run.conclusion == 'success'
563+
outputs:
564+
pr_number: ${{ steps.metadata.outputs.pr_number }}
565+
steps:
566+
- name: Download PR metadata
567+
id: download
568+
uses: actions/download-artifact@v4
569+
with:
570+
name: changelog-metadata
571+
github-token: ${{ secrets.GITHUB_TOKEN }}
572+
run-id: ${{ github.event.workflow_run.id }}
573+
continue-on-error: true
574+
575+
- name: Read PR metadata
576+
if: steps.download.outcome == 'success'
577+
id: metadata
578+
run: |
579+
PR_NUMBER=$(cat pr_number)
580+
if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
581+
echo "::error::Invalid PR number: $PR_NUMBER"
582+
exit 1
583+
fi
584+
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
585+
494586
changelog:
587+
needs: fetch-metadata
588+
if: needs.fetch-metadata.outputs.pr_number != ''
495589
uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-changelog.yml@master
590+
with:
591+
pr_number: ${{ needs.fetch-metadata.outputs.pr_number }}
496592
secrets:
497593
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
498594
OPENWISP_BOT_APP_ID: ${{ secrets.OPENWISP_BOT_APP_ID }}
499595
OPENWISP_BOT_PRIVATE_KEY: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }}
596+
597+
.. note::
598+
599+
The ``name`` field in the trigger workflow must be exactly ``Changelog
600+
Bot Trigger``. The runner watches for this name via ``workflow_run``.
601+
Changing it will silently break the connection between the two
602+
workflows.
603+
604+
Both ``bot-changelog-trigger.yml`` and ``bot-changelog-runner.yml``
605+
must be committed to the **default branch** of the repository. GitHub
606+
only activates ``workflow_run`` listeners that exist on the default
607+
branch: adding the runner only to a feature branch will cause it to
608+
silently do nothing.

0 commit comments

Comments
 (0)