ci: use dedicated token for classref sync PR creation#15
ci: use dedicated token for classref sync PR creation#15MichaelFisher1997 wants to merge 3 commits intoRedot-Engine:masterfrom
Conversation
📝 WalkthroughWalkthroughAdded PR metadata publishing to the PR build, introduced PR preview branch handling and conditional PR commenting in deploy workflow, and switched the sync workflow's create-pull-request step to use a PAT/App token ( Changes
Sequence Diagram(s)sequenceDiagram
participant PR_Build as "PR Build Workflow"
participant Artifact as "Artifact Store (Actions)"
participant Deploy_WF as "Deploy Workflow"
participant DeploySvc as "Deployment Command"
participant GitHub as "GitHub PR"
PR_Build->>Artifact: upload `docusaurus-build` + `pr-metadata/pr_number.txt`
Note over Artifact,Deploy_WF: Trigger: workflow_run -> Deploy_WF runs
Deploy_WF->>Artifact: download `pr-metadata` artifact
Artifact-->>Deploy_WF: return `pr_number`
Deploy_WF->>DeploySvc: run deploy using `preview_branch` (pr-<number>)
DeploySvc-->>Deploy_WF: deployment result
Deploy_WF->>GitHub: post comment (if PR number present)
GitHub-->>Deploy_WF: comment created
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
.github/workflows/sync_class_ref.yml (2)
28-30:pull-requests: writeandcontents: writeGITHUB_TOKEN permissions are now redundant.Both permissions were needed when
peter-evans/create-pull-requestran underGITHUB_TOKEN. Since all PR/branch creation is now delegated toCLASSREF_PR_TOKEN, these scopes on the job's GITHUB_TOKEN are no longer exercised.actions/checkout@v4only requirescontents: read.♻️ Proposed minimal-privilege GITHUB_TOKEN permissions
permissions: - contents: write - pull-requests: write + contents: read🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/sync_class_ref.yml around lines 28 - 30, The workflow's GITHUB_TOKEN permissions block grants unnecessary scopes: remove the redundant pull-requests: write and change contents: write to contents: read because PR/branch creation is handled by CLASSREF_PR_TOKEN and actions/checkout@v4 only requires read access; update the permissions section to only include the minimal GITHUB_TOKEN scope (contents: read) and leave CLASSREF_PR_TOKEN usage for any write/PR operations referenced elsewhere.
65-66: PAT owner cannot self-approve; consider a dedicated machine account or GitHub App.It's advisable to use a dedicated machine account that has collaborator access to the repository, rather than creating a PAT on a personal user account. Because the account that owns the PAT will be the creator of pull requests, that user account will be unable to perform actions such as request changes or approve the pull request.
The inline comment already mentions a GitHub App token as acceptable. A fine-grained PAT with
contents: writeandpull-requests: writescopes, or a GitHub App token with the same scopes, are both supported. A GitHub App token is the more secure option as it is scoped to the specific repository, whereas the PAT cannot be scoped to a specific repository, so the token becomes a very sensitive secret.Documenting these constraints in a runbook or README would help future maintainers understand why the PAT owner (or the GitHub App installation account) cannot approve classref sync PRs.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/sync_class_ref.yml around lines 65 - 66, The workflow comment should warn that a PAT's owner cannot self-approve PRs and recommend a dedicated machine account or a GitHub App; update the comment around CLASSREF_PR_TOKEN to state that the PAT owner will be the PR creator and thus cannot approve/merge its own PRs, and document acceptable alternatives (a dedicated collaborator machine account PAT or, preferably, a GitHub App installation token) plus required scopes (contents:write and pull-requests:write); also add a note to the repository runbook/README describing this constraint and recommended secret provisioning practices for CLASSREF_PR_TOKEN so future maintainers understand the limitation and preferred secure option.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/sync_class_ref.yml:
- Line 80: The workflow currently applies triage labels "bug" and "enhancement"
to every generated class reference PR via the labels field string "labels:
'area:class reference,bug,enhancement'"; remove the inappropriate triage labels
and update that labels value to only include a purpose-specific label such as
"area:class reference" (or any dedicated automation label), ensuring the labels
line in the workflow no longer includes "bug" or "enhancement".
- Around line 62-67: Update the "Submit a pull-request" step to use
peter-evans/create-pull-request@v8 (e.g., `@v8.1.0`) and add a pre-flight step
named "Verify CLASSREF_PR_TOKEN is set" that checks if the CLASSREF_PR_TOKEN
secret is non-empty, emits a clear ::error:: message and exits 1 if not set;
ensure the "Submit a pull-request" step's token input uses '${{
secrets.CLASSREF_PR_TOKEN }}' unchanged. Also consider replacing the labels
value 'bug,enhancement' with a dedicated label like 'type:automation' for the
automated sync PR.
---
Nitpick comments:
In @.github/workflows/sync_class_ref.yml:
- Around line 28-30: The workflow's GITHUB_TOKEN permissions block grants
unnecessary scopes: remove the redundant pull-requests: write and change
contents: write to contents: read because PR/branch creation is handled by
CLASSREF_PR_TOKEN and actions/checkout@v4 only requires read access; update the
permissions section to only include the minimal GITHUB_TOKEN scope (contents:
read) and leave CLASSREF_PR_TOKEN usage for any write/PR operations referenced
elsewhere.
- Around line 65-66: The workflow comment should warn that a PAT's owner cannot
self-approve PRs and recommend a dedicated machine account or a GitHub App;
update the comment around CLASSREF_PR_TOKEN to state that the PAT owner will be
the PR creator and thus cannot approve/merge its own PRs, and document
acceptable alternatives (a dedicated collaborator machine account PAT or,
preferably, a GitHub App installation token) plus required scopes
(contents:write and pull-requests:write); also add a note to the repository
runbook/README describing this constraint and recommended secret provisioning
practices for CLASSREF_PR_TOKEN so future maintainers understand the limitation
and preferred secure option.
| - name: Submit a pull-request | ||
| uses: peter-evans/create-pull-request@v7 | ||
| with: | ||
| # Use a PAT/App token instead of GITHUB_TOKEN so PR events can trigger other workflows. | ||
| # Maintainers must add CLASSREF_PR_TOKEN secret with contents:write + pull_requests:write. | ||
| token: '${{ secrets.CLASSREF_PR_TOKEN }}' |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n .github/workflows/sync_class_ref.ymlRepository: Redot-Engine/redot-docs-site
Length of output: 3881
🌐 Web query:
peter-evans/create-pull-request latest version v8 documentation
💡 Result:
-
Latest
v8release:v8.1.0(released 2026-01-21). (github.com) -
How to use
v8:- uses: peter-evans/create-pull-request@v8 # or pin: - uses: peter-evans/create-pull-request@v8.1.0
-
v7→v8update notes (key changes): runtime updated to Node.js 24; on self-hosted runners you need actions/runner >= v2.327.1. (raw.githubusercontent.com) -
v8documentation entry points (official repo):- README (inputs/outputs/usage + doc links) (github.com)
- Concepts / guidelines / advanced usage (raw.githubusercontent.com)
- Examples (raw.githubusercontent.com)
- Common issues (raw.githubusercontent.com)
Citations:
- 1: https://github.com/peter-evans/create-pull-request/releases
- 2: https://github.com/peter-evans/create-pull-request
- 3: https://raw.githubusercontent.com/peter-evans/create-pull-request/main/docs/updating.md
- 4: https://github.com/peter-evans/create-pull-request
- 5: https://raw.githubusercontent.com/peter-evans/create-pull-request/main/docs/concepts-guidelines.md
- 6: https://raw.githubusercontent.com/peter-evans/create-pull-request/main/docs/examples.md
- 7: https://raw.githubusercontent.com/peter-evans/create-pull-request/main/docs/common-issues.md
🌐 Web query:
GitHub Actions secrets empty string fallback GITHUB_TOKEN behavior
💡 Result:
- If a secret is unavailable, GitHub Actions resolves it to an empty string (
'') at runtime (commonly onpull_requestruns from forks / Dependabot-as-fork). This is a security behavior: you effectively seesecrets.MY_SECRET == ''rather than getting an error. [1], [2] - Because
''is “falsy” in the Actions expression language, you can use an||fallback:This works becauseenv: TOKEN: ${{ secrets.MY_SECRET || 'fallback' }}
""/''/nullare coerced tofalsein conditionals. [3] - You generally cannot distinguish “unset/unavailable secret” vs “secret intentionally set to empty string”—both evaluate to
''in practice, which is a known pain point. [4] GITHUB_TOKENis special: it’s auto-generated per job and (even on fork PRs) is still provided but typically read-only; you can also explicitly reduce/shape its permissions via thepermissions:key. [2], [5]
Sources:
[1] 2i2c blog (fork PR secrets become empty strings) (2i2c.org)
[2] GitHub Blog: fork/PR workflows get read-only token and no secrets (github.blog)
[3] GitHub Docs: falsy values include empty strings (docs.github.com)
[4] actions/toolkit issue describing empty-string behavior and inability to distinguish (github.com)
[5] GitHub Changelog: GITHUB_TOKEN permissions + fork PR read-only (github.blog)
Citations:
- 1: https://2i2c.org/blog/github-action-secrets-forked-repositories/?utm_source=openai
- 2: https://github.blog/news-insights/product-news/github-actions-improvements-for-fork-and-pull-request-workflows/?utm_source=openai
- 3: https://docs.github.com/actions/reference/workflows-and-actions/expressions?utm_source=openai
- 4: Impossible to detect unset inputs from inputs set as the empty string actions/toolkit#940
- 5: https://github.blog/changelog/2021-04-20-github-actions-control-permissions-for-github_token/?utm_source=openai
🌐 Web query:
peter-evans/create-pull-request token input empty string behavior authentication
💡 Result:
In peter-evans/create-pull-request, the token input has a default of ${{ github.token }} (i.e., the workflow’s GITHUB_TOKEN) only when the input is not specified. If you set with: token: '' (or your secret resolves to an empty string), that empty string is used instead of the default. [1][3]
At runtime the action reads the token with core.getInput('token') (which returns '' when the input env var is empty/missing) and then explicitly fails if the token is falsy: if (!inputs.token) { throw new Error("Input 'token' not supplied.") }. So an empty string behaves like “no token” and authentication cannot proceed. [2]
This is a common GitHub Actions pitfall: you generally can’t distinguish “unset” vs “set to empty string”, and missing/unavailable secrets often become empty strings. [4]
Practical takeaway: to use the default GITHUB_TOKEN, omit token entirely; otherwise ensure the expression you pass to token can’t evaluate to '' (or gate the step with an if:). [1][2]
Sources
[1] https://raw.githubusercontent.com/peter-evans/create-pull-request/main/action.yml
[2] https://raw.githubusercontent.com/peter-evans/create-pull-request/main/dist/index.js
[3] https://docs.github.com/actions/reference/workflows-and-actions/metadata-syntax
[4] actions/toolkit#940
🌐 Web query:
peter-evans/create-pull-request README token input defaults
💡 Result:
In peter-evans/create-pull-request, the README states:
- The
tokeninput defaults toGITHUB_TOKEN. [1] - The
branch-tokeninput defaults to the value oftoken(so, by default, it also usesGITHUB_TOKEN). [1]
If you use the default GITHUB_TOKEN, you may need to explicitly grant workflow permissions such as:
permissions:
contents: write
pull-requests: writebecause newer repos often default GITHUB_TOKEN to read-only. [1]
Source: peter-evans/create-pull-request README. [1]
@v7 is outdated; upgrade to @v8 and add a pre-flight guard for the CLASSREF_PR_TOKEN secret.
Two issues:
1. Outdated action version. The current latest release is peter-evans/create-pull-request@v8.1.0 (released January 2026). The workflow pins @v7, missing all v8 bug fixes and improvements.
2. Unset secret will cause workflow failure. When CLASSREF_PR_TOKEN is not provisioned, ${{ secrets.CLASSREF_PR_TOKEN }} resolves to an empty string. The action's code explicitly throws "Input 'token' not supplied." on empty token input, causing every scheduled Saturday run to fail until the secret is added. While the error is visible in logs, a pre-flight if: guard will make the failure explicit and provide actionable context:
- name: Verify CLASSREF_PR_TOKEN is set
run: |
if [ -z "${{ secrets.CLASSREF_PR_TOKEN }}" ]; then
echo "::error::CLASSREF_PR_TOKEN secret is not set. Maintainers must configure it with contents:write + pull_requests:write scopes."
exit 1
fi
- name: Submit a pull-request
uses: peter-evans/create-pull-request@v8
with:
token: '${{ secrets.CLASSREF_PR_TOKEN }}'
# ... rest of configMinor: The labels bug,enhancement (line 80) are GitHub's default triage labels and semantically incorrect for an automated sync PR; consider using a dedicated label like type:automation instead.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/sync_class_ref.yml around lines 62 - 67, Update the
"Submit a pull-request" step to use peter-evans/create-pull-request@v8 (e.g.,
`@v8.1.0`) and add a pre-flight step named "Verify CLASSREF_PR_TOKEN is set" that
checks if the CLASSREF_PR_TOKEN secret is non-empty, emits a clear ::error::
message and exits 1 if not set; ensure the "Submit a pull-request" step's token
input uses '${{ secrets.CLASSREF_PR_TOKEN }}' unchanged. Also consider replacing
the labels value 'bug,enhancement' with a dedicated label like 'type:automation'
for the automated sync PR.
| title: 'classref: Sync with current ${{ env.engine_rev }} branch (${{ steps.engine.outputs.rev_hash_short }})' | ||
| body: 'Update Redot API online class reference to match the engine at https://github.com/Redot-Engine/redot-engine/commit/${{ steps.engine.outputs.rev_hash }} (`${{ env.engine_rev }}`).' | ||
| labels: 'area:class reference,bug,enhancement' No newline at end of file | ||
| labels: 'area:class reference,bug,enhancement' |
There was a problem hiding this comment.
bug and enhancement are issue-triage labels, not appropriate for auto-generated sync PRs.
Applying GitHub's default triage labels (bug, enhancement) to every classref sync PR will pollute label-based issue/PR filters and may confuse contributors triaging bugs or feature requests. Consider restricting to purpose-specific labels only (e.g., area:class reference).
🔖 Proposed fix
- labels: 'area:class reference,bug,enhancement'
+ labels: 'area:class reference'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| labels: 'area:class reference,bug,enhancement' | |
| labels: 'area:class reference' |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/sync_class_ref.yml at line 80, The workflow currently
applies triage labels "bug" and "enhancement" to every generated class reference
PR via the labels field string "labels: 'area:class reference,bug,enhancement'";
remove the inappropriate triage labels and update that labels value to only
include a purpose-specific label such as "area:class reference" (or any
dedicated automation label), ensuring the labels line in the workflow no longer
includes "bug" or "enhancement".
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/deploy.yml:
- Around line 64-70: The PR metadata step (id: prmeta) currently writes
preview_branch using pr_number without validating it; add a guard that trims
whitespace from pr_number and checks if it's non-empty, and if it's empty either
fail fast (exit 1 with a clear error message) or explicitly avoid emitting
preview_branch to GITHUB_OUTPUT so downstream expressions that expect a
non-empty preview_branch won't deploy to a bogus "pr-" branch; implement this
validation around the pr_number variable before writing preview_branch in the
prmeta step.
| - name: Read PR metadata | ||
| if: github.event_name == 'workflow_run' | ||
| id: prmeta | ||
| run: | | ||
| pr_number="$(tr -d '[:space:]' < pr-metadata/pr_number.txt)" | ||
| echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT" | ||
| echo "preview_branch=pr-$pr_number" >> "$GITHUB_OUTPUT" |
There was a problem hiding this comment.
Edge case: empty pr_number would produce a pr- branch name rather than failing fast.
If pr_number.txt were empty or all-whitespace, preview_branch would become "pr-" — a non-empty string that passes the expression on Line 78 and deploys to a meaningless Cloudflare branch instead of falling back safely. Consider adding a guard:
Proposed guard in the metadata step
run: |
pr_number="$(tr -d '[:space:]' < pr-metadata/pr_number.txt)"
+ if [ -z "$pr_number" ]; then
+ echo "::error::PR number is empty"
+ exit 1
+ fi
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
echo "preview_branch=pr-$pr_number" >> "$GITHUB_OUTPUT"Also applies to: 78-78
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/deploy.yml around lines 64 - 70, The PR metadata step (id:
prmeta) currently writes preview_branch using pr_number without validating it;
add a guard that trims whitespace from pr_number and checks if it's non-empty,
and if it's empty either fail fast (exit 1 with a clear error message) or
explicitly avoid emitting preview_branch to GITHUB_OUTPUT so downstream
expressions that expect a non-empty preview_branch won't deploy to a bogus "pr-"
branch; implement this validation around the pr_number variable before writing
preview_branch in the prmeta step.
Summary
sync_class_ref.ymlto use a dedicated secret token forpeter-evans/create-pull-requestpull_requestworkflows (including PR preview build/deploy workflows)Why
PRs created with
GITHUB_TOKENdo not trigger downstream workflows in many cases. This caused classref sync PRs (like #14) to skip GitHub-side PR preview workflows.Required maintainer setup
Before this workflow can run successfully, add this repository/org secret:
CLASSREF_PR_TOKENRecommended permissions for the token:
contents: writepull_requests: write(Using a GitHub App token is also fine if it has equivalent repo permissions.)
Summary by CodeRabbit
New Features
Chores