Skip to content

Use PAT in contributors workflow#971

Open
niksirbi wants to merge 2 commits into
mainfrom
use-pat-in-contributors-workflow
Open

Use PAT in contributors workflow#971
niksirbi wants to merge 2 commits into
mainfrom
use-pat-in-contributors-workflow

Conversation

@niksirbi
Copy link
Copy Markdown
Member

@niksirbi niksirbi commented May 1, 2026

Description

What is this PR

  • Bug fix
  • Addition of a new feature
  • Other

Why is this PR needed?

PRs opened by the contributors-readme-action were leaving required CI checks permanently pending (see #694). The root cause is a deliberate GitHub Actions security restriction: when GITHUB_TOKEN creates a PR, GitHub suppresses the resulting pull_request event to prevent infinite workflow loops. This means test_and_deploy.yml never gets triggered, and required status checks hang indefinitely.

Manually triggering the workflow via workflow_dispatch suffered from the same issue.

The only workaround used to be pushing to the branch manually, because that event is not subject to the same restriction.

What does this PR do?

Replaces secrets.GITHUB_TOKEN with secrets.CONTRIBUTORS_PAT (a fine-grained PAT I created and saved in repo secrets, scoped to this repository with contents: write and pull-requests: write permissions) in the contributors workflow. PRs opened via a PAT are treated as user-authored, so the pull_request event fires normally and CI runs without any manual intervention.

References

Fixes #694. Supersedes #806.

How has this PR been tested?

We can only test the fix by manually triggering the workflow from main.

The fix will be fully verified when the next scheduled contributors PR is opened and CI runs automatically without requiring a manual push.

Is this a breaking change?

No.

Does this PR require an update to the documentation?

No.

Checklist:

  • The code has been tested locally
  • Tests have been added to cover all new functionality
  • The documentation has been updated to reflect any changes
  • The code has been formatted with pre-commit

@codecov
Copy link
Copy Markdown

codecov Bot commented May 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (79f324e) to head (cb3109c).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #971   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           41        41           
  Lines         2846      2846           
=========================================
  Hits          2846      2846           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@niksirbi niksirbi force-pushed the use-pat-in-contributors-workflow branch from 49ab979 to d9a0353 Compare May 1, 2026 13:45
@niksirbi niksirbi force-pushed the use-pat-in-contributors-workflow branch from d9a0353 to c51a1e4 Compare May 1, 2026 14:00
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 1, 2026

@niksirbi niksirbi marked this pull request as ready for review May 1, 2026 14:28
@niksirbi niksirbi requested a review from lochhh May 1, 2026 14:28
Copy link
Copy Markdown
Member

@lochhh lochhh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into this issue @niksirbi ! Also tagging @adamltyson here because this concerns potentially creating an org-level app.

I was wondering why PRs from Dependabot and pre-commit.ci bots trigger CI, whereas the contributors one doesn't. And I'm leaving some notes in case we revisit this in the future.

Essentially, both are treated as "external" to the local workflow runner:

  • pre-commit.ci is an external GitHub App,
  • Dependabot is a native GitHub service (and has some kind of exemption)

Because they don't use the restricted GITHUB_TOKEN, they avoid the "no-recursive-triggers" restriction that is the issue this PR is trying to fix.

To fix this, we have 2 options for replacing our "local" GITHUB_TOKEN:

  • a PAT (as seen in this PR), but tied to a specific user
  • a GitHub App Token (like pre-commit.ci), the more robust, long-term solution

While implementation for the GitHub App token is slightly more complex, the approach is the cleaner choice because:

  • it isn't tied to any individual maintainer (survives maintainer turnover),
  • it uses short-lived tokens that expires after 1hr

GitHub docs also explains here when to choose between PAT and a GitHub App.

If we decide to go for the GitHub App option, we would ned to create an NIU GitHub App (e.g. neuroinformatics-unit-bot) and use that to authenticate CI for PRs.

In any repo that uses this app, in the repo settings, we would store:

  • the NIU App ID as a repository variable (e.g. APP_CLIENT_ID)
  • the NIU App's private key as a repository secret (e.g. APP_PRIVATE_KEY)

And finally in the update-contributors workflow, we can use actions/create-github-app-token:

    steps:
      - name: Generate GitHub App Token
        uses: actions/create-github-app-token@v3
        id: app-token
        with:
          client-id: ${{ vars.APP_CLIENT_ID }}
          private-key: ${{ secrets.APP_PRIVATE_KEY }}
      - name: Contribute List
        uses: akhilmhdh/contributors-readme-action@v2.3.11
        with:
          readme_path: docs/source/community/people.md
          commit_message: 'Update contributors list'
          pr_title_on_protected: 'Contributors-Readme-Action: Update contributors list'
        env:
          GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}

@niksirbi
Copy link
Copy Markdown
Member Author

niksirbi commented May 7, 2026

Thanks for the info @lochhh.

I agree the GitHub app (NIU bot) is the cleaner solution. I was anyway feeling slightly uncomfortable being personally 'in charge' of the PAT and having to update it when it expires.

If @adamltyson agrees, I think we should create an "NIU bot". Maybe it will come in handy in other scenarios too?

@adamltyson
Copy link
Copy Markdown
Member

My initial POV is that this seems like a disproportionate amount of infrastructure to maintain to solve a very minor problem (adding a new contributor once every couple of weeks).

@niksirbi
Copy link
Copy Markdown
Member Author

niksirbi commented May 8, 2026

After looking into this a bit more, I do think the GitHub App is the better choice here.

It has a bit higher initial setup cost (compared to PAT), but has several advantages:

  • Org-owned, so not tied to a specific team member
  • No expiry, so maintenance should be actually easier than PAT
  • More secure (short-lived token minted per run)

To @adamltyson's point re proportionality: we could just as well stay with the status quo, i.e. us pushing to a bot-opened PR once per month, which is really not much work.

But this could be a nice opportunity to add the app as a general org-level capability. Any future automation that creates PRs from GitHub Actions (e.g. auto-merge, release automation, changelog generation) may hit the same GITHUB_TOKEN trigger-suppression issue. Having an NIU bot already in place makes these automations more attractive and easier to reach for. Automation will become all the more important as our orgs and repos multiply.

@lochhh
Copy link
Copy Markdown
Member

lochhh commented May 8, 2026

I agree with @niksirbi.
The key here is that it sets the NIU GH org up for future automations, e.g. we can create a central "Management" repo to run mass updates like migrating pyproject.toml dependencies across a list of specified org repos at once. Instead of one member running a local script or asking every maintainer to manually update their own repo, this Management repo acts as the org's command centre. We commit the migration script there, review it, and then the GH App executes it (via GH actions) across the org in a consistent manner.

@adamltyson
Copy link
Copy Markdown
Member

The key here is that it sets the NIU GH org up for future automations, e.g. we can create a central "Management" repo to run mass updates like migrating pyproject.toml dependencies across a list of specified org repos at once. Instead of one member running a local script or asking every maintainer to manually update their own repo, this Management repo acts as the org's command centre. We commit the migration script there, review it, and then the GH App executes it (via GH actions) across the org in a consistent manner.

This seems far more worth it! I'm still not convinced that the contributors action is worth it vs just adding people manually, but this vision of the future of NIU is very appealing!

Either way, happy for you both to do as you see fit.

@IgorTatarnikov
Copy link
Copy Markdown
Member

The key here is that it sets the NIU GH org up for future automations, e.g. we can create a central "Management" repo to run mass updates like migrating pyproject.toml dependencies across a list of specified org repos at once. Instead of one member running a local script or asking every maintainer to manually update their own repo, this Management repo acts as the org's command centre. We commit the migration script there, review it, and then the GH App executes it (via GH actions) across the org in a consistent manner.

This sounds very useful for the BrainGlobe maintenance GSoC project! Being able to easily raise PRs across the org to update all pyproject.toml, .pre-commit-config.yaml, and CI workflows will speed up the entire process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Continuous integration hangs for scheduled PR opened by the contributors-readme-action

4 participants