Skip to content

Add upstream release watcher (workload-identity auth)#4

Open
aryehlev wants to merge 2 commits into
mainfrom
atuoupdate
Open

Add upstream release watcher (workload-identity auth)#4
aryehlev wants to merge 2 commits into
mainfrom
atuoupdate

Conversation

@aryehlev

@aryehlev aryehlev commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Adds a weekly (and manual) watcher that opens a PR when the upstream library
publishes a newer release than the one pinned in build.rs. Claude reviews the
upstream C API header diff and edits the crate; peter-evans/create-pull-request
opens the PR. The only remote write is the PR itself.

Auth: Anthropic workload identity federation (OIDC) — no stored API key.

Before this can run, add repo secrets: ANTHROPIC_FEDERATION_RULE_ID,
ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID
(+ ANTHROPIC_WORKSPACE_ID if the federation rule spans multiple workspaces).

Note: the federation rule subject should match this repo\x27s default branch once merged.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added automated weekly monitoring for newer upstream LightGBM releases.
    • Automatically prepares a pull request with upstream release notes and relevant header changes when an update is detected.
    • Supports manually triggering the update check.
    • Prevents duplicate pull requests for releases already being processed.

aryehlev and others added 2 commits July 19, 2026 21:46
Swap static ANTHROPIC_API_KEY for OIDC/WIF: add id-token: write and the
anthropic_federation_* inputs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changes

LightGBM upstream release automation

Layer / File(s) Summary
Release detection and deduplication
.github/workflows/upstream-release.yml
Runs weekly or manually, reads the pinned version, fetches the latest release, and skips updates when a matching open PR exists.
Header diff and PR body preparation
.github/workflows/upstream-release.yml
Downloads selected upstream headers for both versions, generates a unified diff, and seeds the PR body.
Automated review and PR creation
.github/workflows/upstream-release.yml
Uses Claude to update permitted files and review wrapper-relevant changes, then applies labels and opens the pull request.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant GitHubReleasesAPI
  participant ClaudeCodeAction
  participant CreatePullRequest
  GitHubActions->>GitHubReleasesAPI: Fetch latest LightGBM release
  GitHubActions->>GitHubActions: Compare versions and prepare header diff
  GitHubActions->>ClaudeCodeAction: Review diff and edit repository files
  ClaudeCodeAction->>GitHubActions: Return updated files and PR body content
  GitHubActions->>CreatePullRequest: Create labeled update PR
Loading
🚥 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 summarizes the new upstream release watcher and its workload-identity authentication approach.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch atuoupdate

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
.github/workflows/upstream-release.yml (1)

32-46: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Brittle version extraction from build.rs.

grep 'unwrap_or_else' build.rs | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 assumes there's exactly one unwrap_or_else call with a semver literal in the whole file. Per build.rs get_lightgbm_version() defaults to "4.6.0" today, but any future unwrap_or_else call elsewhere in build.rs containing a version-like literal would silently produce the wrong "current" version and desync the whole workflow's diffing/PR logic.

Consider anchoring the grep more specifically, e.g. grep -oE 'LIGHTGBM_VERSION.*[0-9]+\.[0-9]+\.[0-9]+' or grep -A1 'fn get_lightgbm_version'.

🤖 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/upstream-release.yml around lines 32 - 46, Update the
versions step’s CURRENT extraction to target the pinned version within
get_lightgbm_version, using the LIGHTGBM_VERSION assignment or function-scoped
context instead of matching any unwrap_or_else in build.rs. Preserve the
existing validation and workflow outputs while ensuring future unrelated version
literals cannot be selected.
🤖 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/upstream-release.yml:
- Around line 56-68: Validate the upstream tag in the workflow before assigning
or using LATEST, requiring the expected semver-shaped value after removing the
optional v prefix and failing otherwise. In the “Skip if an update PR is already
open” step, pass the validated value through env and reference it as a shell
variable when constructing BRANCH; apply the same indirect env-based handling to
the Claude prompt interpolation of LATEST, preserving the existing
release-update flow.
- Around line 18-21: Add issues: write to the workflow-level permissions block
alongside id-token, contents, and pull-requests so the label-ensure step can
create repository labels using GITHUB_TOKEN.

---

Nitpick comments:
In @.github/workflows/upstream-release.yml:
- Around line 32-46: Update the versions step’s CURRENT extraction to target the
pinned version within get_lightgbm_version, using the LIGHTGBM_VERSION
assignment or function-scoped context instead of matching any unwrap_or_else in
build.rs. Preserve the existing validation and workflow outputs while ensuring
future unrelated version literals cannot be selected.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b2500c64-8c76-481c-a6cb-9cd7e5d3ec72

📥 Commits

Reviewing files that changed from the base of the PR and between 01fb89f and eb4cd4c.

📒 Files selected for processing (1)
  • .github/workflows/upstream-release.yml

Comment on lines +18 to +21
permissions:
id-token: write # fetch the GitHub OIDC token for Anthropic WIF
contents: write # minimum GitHub allows for creating a PR branch
pull-requests: write # open/update the PR

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does the GitHub REST "Create a label" endpoint require issues:write permission on GITHUB_TOKEN, or is pull-requests:write sufficient?

💡 Result:

For the GitHub REST API "Create a label" endpoint, possessing issues:write permission is generally recommended and recognized as the effective requirement for success [1][2]. While technical documentation for fine-grained personal access tokens often lists both issues:write and pull-requests:write as potential permission sets for label management [3][2], real-world usage in GitHub Actions with the GITHUB_TOKEN frequently shows that pull-requests:write alone is insufficient for creating new labels [1][2]. Users consistently report encountering authorization errors when attempting to create labels with only pull-requests:write and resolve them by explicitly adding issues:write to their workflow permissions [1][2]. Therefore, if your workflow needs to create labels, you should include issues:write in your permissions configuration: permissions: issues: write pull-requests: write # Optional, depending on your other needs This configuration ensures the GITHUB_TOKEN has the necessary access to manage repository labels effectively [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files .github/workflows/upstream-release.yml
echo '---'
nl -ba .github/workflows/upstream-release.yml | sed -n '130,190p'
echo '--- search ---'
rg -n "gh label create|create-pull-request|permissions:" .github/workflows/upstream-release.yml

Repository: aryehlev/lightgbm-rust

Length of output: 243


🏁 Script executed:

#!/bin/bash
set -euo pipefail
nl -ba .github/workflows/upstream-release.yml | sed -n '145,180p'
echo '---'
rg -n "GH_TOKEN|GITHUB_TOKEN|gh label create|issues: write|pull-requests: write|contents: write|id-token: write" .github/workflows/upstream-release.yml

Repository: aryehlev/lightgbm-rust

Length of output: 200


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- permissions and label steps ---'
sed -n '1,230p' .github/workflows/upstream-release.yml | cat -n | sed -n '1,230p'

echo '--- focused search ---'
rg -n "gh label create|create-pull-request|GH_TOKEN|GITHUB_TOKEN|issues: write|pull-requests: write|contents: write|id-token: write" .github/workflows/upstream-release.yml

Repository: aryehlev/lightgbm-rust

Length of output: 10905


Add issues: write to the workflow permissions.

gh label create runs against GITHUB_TOKEN, and pull-requests: write doesn’t cover label creation. Without issues: write, the label-ensure step can silently no-op under || true, so dependencies and upstream-release may never be created on a fresh repo.

🤖 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/upstream-release.yml around lines 18 - 21, Add issues:
write to the workflow-level permissions block alongside id-token, contents, and
pull-requests so the label-ensure step can create repository labels using
GITHUB_TOKEN.

Comment on lines +56 to +68
- name: Skip if an update PR is already open
id: existing
if: steps.versions.outputs.update == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
BRANCH="chore/lightgbm-${{ steps.versions.outputs.latest }}"
if gh pr list --state open --head "$BRANCH" --json number --jq '.[0].number' | grep -q '[0-9]'; then
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

Template-injection risk: unsanitized upstream tag spliced directly into a shell script.

LATEST (Line 40) is taken verbatim from tag_name of microsoft/LightGBM's latest release with only a v prefix stripped — unlike CURRENT, it is never constrained to a semver shape. It is then substituted directly via ${{ }} into this run: script rather than via an env:-indirected $VAR reference (as is correctly done elsewhere in this same file, e.g. Lines 74-75). This is exactly the classic GitHub Actions template-injection pattern zizmor flags at Line 63: if the upstream tag ever contained shell metacharacters (`, $(), quotes), it would execute arbitrary commands in a job holding contents: write, pull-requests: write, and an OIDC token for Anthropic — not merely break string comparison. The same unvalidated LATEST is also interpolated straight into the Claude prompt text (Lines 114-151), giving it a secondary prompt-injection surface against an agent with Bash access.

Harden at the source and at this use site:

🔒 Proposed fix
           echo "current=$CURRENT" >> "$GITHUB_OUTPUT"
           echo "latest=$LATEST"   >> "$GITHUB_OUTPUT"
+          [[ "$LATEST" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::Unexpected release tag format: $LATEST"; exit 1; }
       - name: Skip if an update PR is already open
         id: existing
         if: steps.versions.outputs.update == 'true'
         env:
           GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          LATEST: ${{ steps.versions.outputs.latest }}
         run: |
           set -euo pipefail
-          BRANCH="chore/lightgbm-${{ steps.versions.outputs.latest }}"
+          BRANCH="chore/lightgbm-${LATEST}"
📝 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.

Suggested change
- name: Skip if an update PR is already open
id: existing
if: steps.versions.outputs.update == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
BRANCH="chore/lightgbm-${{ steps.versions.outputs.latest }}"
if gh pr list --state open --head "$BRANCH" --json number --jq '.[0].number' | grep -q '[0-9]'; then
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Skip if an update PR is already open
id: existing
if: steps.versions.outputs.update == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
LATEST: ${{ steps.versions.outputs.latest }}
run: |
set -euo pipefail
BRANCH="chore/lightgbm-${LATEST}"
if gh pr list --state open --head "$BRANCH" --json number --jq '.[0].number' | grep -q '[0-9]'; then
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
🧰 Tools
🪛 zizmor (1.26.1)

[info] 63-63: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 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/upstream-release.yml around lines 56 - 68, Validate the
upstream tag in the workflow before assigning or using LATEST, requiring the
expected semver-shaped value after removing the optional v prefix and failing
otherwise. In the “Skip if an update PR is already open” step, pass the
validated value through env and reference it as a shell variable when
constructing BRANCH; apply the same indirect env-based handling to the Claude
prompt interpolation of LATEST, preserving the existing release-update flow.

Source: Linters/SAST tools

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.

1 participant