Skip to content

ci: replace RELEASE_PAT with GitHub App token#2388

Merged
SkrubbySkrubInAShrub merged 1 commit into
devfrom
fix/checkout-token-release-semantic
May 20, 2026
Merged

ci: replace RELEASE_PAT with GitHub App token#2388
SkrubbySkrubInAShrub merged 1 commit into
devfrom
fix/checkout-token-release-semantic

Conversation

@SkrubbySkrubInAShrub
Copy link
Copy Markdown
Collaborator

@SkrubbySkrubInAShrub SkrubbySkrubInAShrub commented May 20, 2026

Switches release-semantic, release-hotfix, and auto-rebase-prs
workflows from a personal PAT (RELEASE_PAT) to a GitHub App token
generated via actions/create-github-app-token@v1. Secrets APP_ID
and APP_PRIVATE_KEY must be set at the org level.

Summary by CodeRabbit

  • Chores
    • Enhanced security in CI/CD workflows by updating authentication mechanisms to use improved token management practices.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

📝 Walkthrough

Walkthrough

Three GitHub Actions workflows migrate from RELEASE_PAT to GitHub App installation token authentication. The auto-rebase-prs, release-hotfix, and release-semantic workflows now generate app tokens via actions/create-github-app-token@v1 and use those tokens for all authenticated Git operations and GitHub CLI calls.

Changes

Workflow Token Authentication Migration

Layer / File(s) Summary
PR Rebase Workflow Token Migration
.github/workflows/auto-rebase-prs.yaml
Generates GitHub App token and updates checkout, rebase action, and GH_TOKEN reference to use the app token output. Token permissions comment documents required Contents, Pull Requests, and Workflows permissions.
Hotfix Release Workflow Token Migration
.github/workflows/release-hotfix.yaml
Generates GitHub App token and updates checkout to use the app token output. GH_TOKEN and GITHUB_TOKEN environment variables for close-PR and push steps are updated to use the generated token instead of RELEASE_PAT.
Semantic Release Workflow Token Migration
.github/workflows/release-semantic.yaml
Generates GitHub App token and updates checkout to use the app token output. TOKEN and GITHUB_TOKEN environment variables across fast-forward, semantic-release, and dev reconciliation steps are updated to use the generated app token instead of RELEASE_PAT.

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • jiayev
  • davo0411

🐰 Three workflows now trust the App,
No secrets needed, just a quick tap,
GitHub tokens flow, rebasing with grace,
Releases promoted at a faster pace! 🚀
Authentication simplified—no more delay!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main change: replacing RELEASE_PAT with a GitHub App token across release-related CI workflows.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/checkout-token-release-semantic

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 actionlint (1.7.12)
.github/workflows/auto-rebase-prs.yaml

could not read ".github/workflows/auto-rebase-prs.yaml": open .github/workflows/auto-rebase-prs.yaml: no such file or directory

.github/workflows/release-hotfix.yaml

could not read ".github/workflows/release-hotfix.yaml": open .github/workflows/release-hotfix.yaml: no such file or directory

.github/workflows/release-semantic.yaml

could not read ".github/workflows/release-semantic.yaml": open .github/workflows/release-semantic.yaml: no such file or directory

🔧 zizmor (1.25.2)
.github/workflows/auto-rebase-prs.yaml

INFO zizmor: 🌈 zizmor v1.25.2
fatal: no audit was performed
invalid input: .github/workflows/auto-rebase-prs.yaml

.github/workflows/release-hotfix.yaml

INFO zizmor: 🌈 zizmor v1.25.2
fatal: no audit was performed
invalid input: .github/workflows/release-hotfix.yaml

.github/workflows/release-semantic.yaml

INFO zizmor: 🌈 zizmor v1.25.2
fatal: no audit was performed
invalid input: .github/workflows/release-semantic.yaml

🔧 YAMLlint (1.38.0)
.github/workflows/release-hotfix.yaml

[Errno 2] No such file or directory: '.github/workflows/release-hotfix.yaml'

.github/workflows/auto-rebase-prs.yaml

[Errno 2] No such file or directory: '.github/workflows/auto-rebase-prs.yaml'

.github/workflows/release-semantic.yaml

[Errno 2] No such file or directory: '.github/workflows/release-semantic.yaml'

🔧 Checkov (3.2.529)
.github/workflows/auto-rebase-prs.yaml

2026-05-20 17:09:13,682 [MainThread ] [ERROR] Template file not found: .github/workflows/auto-rebase-prs.yaml
2026-05-20 17:09:13,724 [MainThread ] [ERROR] Template file not found: .github/workflows/auto-rebase-prs.yaml
2026-05-20 17:09:13,754 [MainThread ] [ERROR] Template file not found: .github/workflows/auto-rebase-prs.yaml
2026-05-20 17:09:13,834 [MainThread ] [ERROR] Failed to invoke function /usr/local/lib/python3.11/dist-packages/checkov/common/runners/object_runner. with .github/workflows/auto-rebase-prs.yaml
Traceback (most recent call last):
File "/usr/local/lib/python3.11/dist-packages/checkov/common/parallelizer/parallel_runner.py", line 88, in func_wrapper
result = original_func(item)
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/object_runner.py", line 74, in
results = parallel_runner.run_function(lambda f: (f, self._parse_file(f)), files_to_load)

... [truncated 9233 characters] ...

ocess file .github/workflows/auto-rebase-prs.yaml
2026-05-20 17:09:13,945 [MainThread ] [ERROR] Exception traceback:
Traceback (most recent call last):
File "/usr/local/lib/python3.11/dist-packages/checkov/main.py", line 647, in run
self.scan_reports = runner_registry.run(
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/runner_registry.py", line 177, in run
for result in parallel_runner_results:
File "/usr/local/lib/python3.11/dist-packages/checkov/common/parallelizer/parallel_runner.py", line 118, in _run_function_multiprocess_fork
raise v.internal_exception.with_traceback(v.internal_exception.traceback)
FileNotFoundError: [Errno 2] No such file or directory: '.github/workflows/auto-rebase-prs.yaml'

.github/workflows/release-semantic.yaml

2026-05-20 17:09:13,682 [MainThread ] [ERROR] Template file not found: .github/workflows/release-semantic.yaml
2026-05-20 17:09:13,690 [MainThread ] [ERROR] Template file not found: .github/workflows/release-semantic.yaml
2026-05-20 17:09:13,825 [MainThread ] [ERROR] Template file not found: .github/workflows/release-semantic.yaml
2026-05-20 17:09:13,865 [MainThread ] [WARNI] Secret scanning: could not process file .github/workflows/release-semantic.yaml
2026-05-20 17:09:13,850 [MainThread ] [ERROR] Failed to invoke function /usr/local/lib/python3.11/dist-packages/checkov/common/runners/object_runner. with .github/workflows/release-semantic.yaml
Traceback (most recent call last):
File "/usr/local/lib/python3.11/dist-packages/checkov/common/parallelizer/parallel_runner.py", line 88, in func_wrapper
result = original_func(item)
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/object_runner.py", line 74, in <la

... [truncated 9250 characters] ...

^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/runner_registry.py", line 839, in _parallel_run
report = runner.run(
^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/object_runner.py", line 131, in run
self._load_files(files)
File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/object_runner.py", line 75, in _load_files
for file_result_pair in results:
File "/usr/local/lib/python3.11/dist-packages/checkov/common/parallelizer/parallel_runner.py", line 118, in _run_function_multiprocess_fork
raise v.internal_exception.with_traceback(v.internal_exception.traceback)
FileNotFoundError: [Errno 2] No such file or directory: '.github/workflows/release-semantic.yaml'

.github/workflows/release-hotfix.yaml

2026-05-20 17:09:13,725 [MainThread ] [ERROR] Template file not found: .github/workflows/release-hotfix.yaml
2026-05-20 17:09:13,751 [MainThread ] [ERROR] Template file not found: .github/workflows/release-hotfix.yaml
2026-05-20 17:09:13,900 [MainThread ] [ERROR] Template file not found: .github/workflows/release-hotfix.yaml
2026-05-20 17:09:13,907 [MainThread ] [ERROR] Failed to invoke function /usr/local/lib/python3.11/dist-packages/checkov/common/runners/object_runner. with .github/workflows/release-hotfix.yaml
Traceback (most recent call last):
File "/usr/local/lib/python3.11/dist-packages/checkov/common/parallelizer/parallel_runner.py", line 88, in func_wrapper
result = original_func(item)
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/object_runner.py", line 74, in
results = parallel_runner.run_function(lambda f: (f, self._parse_file(f)), files_to_load)

... [truncated 9216 characters] ...

^^^^^^^^^^^^^^^^^^^^

File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/runner_registry.py", line 839, in _parallel_run
report = runner.run(
^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/object_runner.py", line 131, in run
self._load_files(files)
File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/object_runner.py", line 75, in _load_files
for file_result_pair in results:
File "/usr/local/lib/python3.11/dist-packages/checkov/common/parallelizer/parallel_runner.py", line 118, in _run_function_multiprocess_fork
raise v.internal_exception.with_traceback(v.internal_exception.traceback)
FileNotFoundError: [Errno 2] No such file or directory: '.github/workflows/release-hotfix.yaml'


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/auto-rebase-prs.yaml:
- Around line 39-44: The workflow step "Generate app token" using
actions/create-github-app-token@v1 (id: app-token) will not be able to push to
user-owned fork branches because a GitHub App installation token is scoped only
to repos where the app is installed; either install the GitHub App on
contributor forks or add a fallback authentication path: detect when a PR head
is from a fork and use a maintainer PAT (or GITHUB_TOKEN when repo is
same-owner) to perform the push, falling back to the app token for in-repo PRs;
also update the workflow header/docs to state that fork PRs require app
installation or a PAT and include instructions for providing the PAT secret.

In @.github/workflows/release-semantic.yaml:
- Around line 146-151: Update the inline comment near the GITHUB_TOKEN
environment assignment (GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}) to
explicitly state that, in addition to using the app token, the GitHub App must
be added to the branch protection/ruleset bypass list for protected branches
(e.g., main, dev, and hotfix/*); without adding the App as an allowed actor in
the repository branch protection or ruleset settings, pushes performed using
steps.app-token.outputs.token will still be blocked by protection rules.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 089292fb-bb65-46ca-9c37-492fa3cf49e8

📥 Commits

Reviewing files that changed from the base of the PR and between 57b827f and 7147352.

📒 Files selected for processing (3)
  • .github/workflows/auto-rebase-prs.yaml
  • .github/workflows/release-hotfix.yaml
  • .github/workflows/release-semantic.yaml

Comment on lines +39 to +44
- name: Generate app token
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 20, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🌐 Web query:

Does a GitHub App installation token generated for a base repository have permission to push to pull request head branches on user-owned forks where the app is not installed?

💡 Result:

No, a GitHub App installation access token does not have permission to push to a branch on a user-owned fork where the GitHub App is not installed [1][2]. GitHub App permissions are strictly scoped to the repositories where the app has been explicitly installed [1][3]. An installation access token is only authorized to access resources within the specific installation context—typically the organization or repository where the app is authorized [1][4]. If the app is not installed on the forked repository, the token generated from the base repository lacks the necessary credentials to interact with or push to that fork [1][2]. To perform actions on a fork, such as pushing to a pull request head branch, the GitHub App must be installed on that specific forked repository [2]. If you are automating workflows that involve pushing to forks, you generally need to ensure the GitHub App is installed on both the base repository and the target forks, or use a different authentication method that the fork owner has explicitly authorized [2]. [2] explicitly notes that when pushing to a remote fork in a CI/CD context, the token must be generated from an installation that has access to that specific fork [2].

Citations:


GitHub App installation token cannot push to user-owned fork PR branches.

This change drops auto-rebase support for user-owned fork pull requests. A GitHub App installation token only has permissions in the repositories where the app is explicitly installed. It cannot push to pull request head branches on forks where the app is not installed. If forked PR auto-rebase is still a requirement, either install the app on those forks or add a fallback authentication method (e.g., a maintainer PAT). Update the workflow header documentation if fork support is being intentionally removed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/auto-rebase-prs.yaml around lines 39 - 44, The workflow
step "Generate app token" using actions/create-github-app-token@v1 (id:
app-token) will not be able to push to user-owned fork branches because a GitHub
App installation token is scoped only to repos where the app is installed;
either install the GitHub App on contributor forks or add a fallback
authentication path: detect when a PR head is from a fork and use a maintainer
PAT (or GITHUB_TOKEN when repo is same-owner) to perform the push, falling back
to the app token for in-repo PRs; also update the workflow header/docs to state
that fork PRs require app installation or a PAT and include instructions for
providing the PAT secret.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

acceptable regression

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@SkrubbySkrubInAShrub Understood — acknowledging the fork auto-rebase limitation as an intentional trade-off. The existing header comment already documents the GitHub App token requirements, so the behavior is clear to future contributors.

Comment on lines +146 to +151
# App token required for two reasons:
# 1. Allows pushing the version commit and tag to the protected
# target branch (GITHUB_TOKEN cannot bypass branch protection).
# 2. A PAT-sourced tag push triggers downstream workflows
# 2. An app-token tag push triggers downstream workflows
# (release-build.yaml); GITHUB_TOKEN pushes do not.
GITHUB_TOKEN: ${{ secrets.RELEASE_PAT }}
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

For GitHub branch protection and rulesets, does a GitHub App installation token bypass protections automatically, or must the app be explicitly added to the bypass / allowed actors list?

💡 Result:

A GitHub App installation token does not automatically bypass GitHub branch protections or rulesets just because it is a GitHub App token. To bypass (or exempt) rules, the GitHub App must be explicitly added as an bypass/allowed actor in the relevant branch protection or ruleset configuration. For GitHub repository rulesets, GitHub docs state that when creating a ruleset you can allow certain users/teams/GitHub Apps to bypass the rules in the ruleset; the “Bypass list” is where you add the apps explicitly [1][2]. GitHub also describes that rulesets can grant bypass permissions specifically to GitHub Apps, and the UI/API flow is to add the app to the bypass list [1]. For branch protection, GitHub’s changelog notes that admins can choose from a list of GitHub Apps installed and authorized for the repository as exceptions to branch protection rules (indicating the exception/bypass is explicitly configured rather than implicit) [3]. So the correct operational answer is: use the GitHub App token for the API/checkout as needed, but you still must configure the ruleset/branch protection to allow that specific app identity (by adding the app to the ruleset bypass/allowed actors list) to get bypass behavior.

Citations:


The GitHub App must be explicitly added to the branch protection/ruleset bypass list for the protected branches.

Using the app token is necessary (better than GITHUB_TOKEN), but the app token alone does not bypass branch protections or rulesets. The GitHub App itself must be explicitly configured as an allowed actor in the bypass list for main, dev, and any protected hotfix/* rulesets in your repository settings. Without this configuration step, the fast-forward and reconcile pushes will fail even with the app token in place.

The inline comment at lines 146-150 should clarify that the app-token bypass also requires explicit repository ruleset/branch protection configuration.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release-semantic.yaml around lines 146 - 151, Update the
inline comment near the GITHUB_TOKEN environment assignment (GITHUB_TOKEN: ${{
steps.app-token.outputs.token }}) to explicitly state that, in addition to using
the app token, the GitHub App must be added to the branch protection/ruleset
bypass list for protected branches (e.g., main, dev, and hotfix/*); without
adding the App as an allowed actor in the repository branch protection or
ruleset settings, pushes performed using steps.app-token.outputs.token will
still be blocked by protection rules.

@SkrubbySkrubInAShrub SkrubbySkrubInAShrub merged commit 7147352 into dev May 20, 2026
6 checks passed
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.

2 participants