Skip to content

ci: add workflow to auto-regenerate licenses for Dependabot PRs#387

Open
svor wants to merge 2 commits into
mainfrom
sv-dependabot-license-check
Open

ci: add workflow to auto-regenerate licenses for Dependabot PRs#387
svor wants to merge 2 commits into
mainfrom
sv-dependabot-license-check

Conversation

@svor
Copy link
Copy Markdown
Collaborator

@svor svor commented May 21, 2026

Summary

  • Adds a GitHub Actions workflow that automatically regenerates license dependency files for Dependabot PRs
  • Parses unresolved dependencies from .deps/problems.md and adds them to .deps/EXCLUDED/*.md
  • Commits and pushes updated .deps/ files back to the PR branch

Summary by CodeRabbit

  • Chores
    • Added an automated workflow that regenerates and validates project license data when dependency updates arrive, classifies unresolved production vs development dependencies, updates exclusion lists for problematic packages, and automatically commits license-related documentation changes back to the update pull request to keep license records in sync.

Review Change Stack

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Valerii Svydenko <vsvydenk@redhat.com>
@svor svor requested review from ibuziuk and tolusha as code owners May 21, 2026 11:11
@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 21, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: svor

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

📝 Walkthrough

Walkthrough

Adds a GitHub Actions workflow that runs on Dependabot PRs to regenerate license metadata with up to 3 retries, parses .deps/problems.md on failure to update .deps/EXCLUDED/{prod,dev}.md, and commits any .deps/ updates back to the PR.

Changes

Dependabot License Update

Layer / File(s) Summary
License generation workflow with retry and fallback
.github/workflows/dependabot-license.yml
Workflow trigger for Dependabot PRs on main, Node.js v24 and yarn setup, yarn license:generate with 3 retry attempts, failure parsing of .deps/problems.md to classify and append unresolved packages to .deps/EXCLUDED/{prod,dev}.md (skipping duplicates), and automated commit/push of .deps/ changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I hopped through CI with a careful stride,
Ran yarn and Node, let retries be tried,
When problems appeared I parsed with delight,
Tucked unresolved packages out of sight,
Pushed .deps/ changes—now the PR's polite.

🚥 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 clearly and concisely summarizes the main change: adding a CI workflow to auto-regenerate licenses for Dependabot PRs, which matches the changeset perfectly.
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 sv-dependabot-license-check

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

@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: 3

🤖 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/dependabot-license.yml:
- Around line 32-35: Replace the floating action tag "uses:
actions/setup-node@v4" with a pinned commit SHA to mitigate supply-chain risks:
locate the workflow step that currently reads uses: actions/setup-node@v4 (the
block that also sets node-version: 24) and update the uses value to the full
actions/setup-node@<commit-sha> for the intended release (verify the correct SHA
for v4.1.0 or the latest secure release first), ensuring the rest of the step
(node-version: 24) remains unchanged.
- Around line 26-30: Update the Checkout step using the actions/checkout usage
by adding persist-credentials: false to prevent the GH token from being written
to local git config and replace the floating tag actions/checkout@v4 with a
pinned reference to the specific commit SHA (the secure SHA matching v4.2.2 or
current vetted SHA) so the workflow points to an immutable release; modify the
Checkout step block (the uses: actions/checkout entry) to include the new
persist-credentials key and change the uses value to the commit-pinned ref.
- Line 24: The workflow currently only checks "if: github.actor ==
'dependabot[bot]'" which can be spoofed; update the conditional to also verify
the sender is a GitHub App bot by adding a check for "github.event.sender.type
== 'Bot'" (e.g. "if: github.actor == 'dependabot[bot]' &&
github.event.sender.type == 'Bot'") and optionally tighten further by verifying
"github.event.sender.login == 'dependabot[bot]'" so both the actor and sender
type/login are validated.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6690f0c2-c7c6-455d-8ae0-746b69f4f52c

📥 Commits

Reviewing files that changed from the base of the PR and between 19723d1 and b08237e.

📒 Files selected for processing (1)
  • .github/workflows/dependabot-license.yml

Comment thread .github/workflows/dependabot-license.yml Outdated
Comment on lines +26 to +30
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Security: Prevent credential persistence and pin action version.

Two security concerns:

  1. Missing persist-credentials: false allows the GitHub token to persist in the local git config, potentially leaking through artifacts or logs.
  2. The action reference should be pinned to a specific commit SHA hash to prevent supply chain attacks.
🔒 Recommended security hardening
       - name: Checkout
-        uses: actions/checkout@v4
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
         with:
           ref: ${{ github.head_ref }}
           fetch-depth: 0
+          persist-credentials: false

Note: The commit SHA corresponds to actions/checkout@v4.2.2. Verify the latest secure version before applying.

📝 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: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.head_ref }}
fetch-depth: 0
persist-credentials: false
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 26-30: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 27-27: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 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/dependabot-license.yml around lines 26 - 30, Update the
Checkout step using the actions/checkout usage by adding persist-credentials:
false to prevent the GH token from being written to local git config and replace
the floating tag actions/checkout@v4 with a pinned reference to the specific
commit SHA (the secure SHA matching v4.2.2 or current vetted SHA) so the
workflow points to an immutable release; modify the Checkout step block (the
uses: actions/checkout entry) to include the new persist-credentials key and
change the uses value to the commit-pinned ref.

Comment on lines +32 to +35
- name: Use Node 24
uses: actions/setup-node@v4
with:
node-version: 24
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Security: Pin action to commit SHA.

The action reference should be pinned to a specific commit SHA hash to prevent supply chain attacks.

🔒 Recommended fix
       - name: Use Node 24
-        uses: actions/setup-node@v4
+        uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
         with:
           node-version: 24

Note: The commit SHA corresponds to actions/setup-node@v4.1.0. Verify the latest secure version before applying.

📝 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: Use Node 24
uses: actions/setup-node@v4
with:
node-version: 24
- name: Use Node 24
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 24
🧰 Tools
🪛 zizmor (1.25.2)

[error] 33-33: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 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/dependabot-license.yml around lines 32 - 35, Replace the
floating action tag "uses: actions/setup-node@v4" with a pinned commit SHA to
mitigate supply-chain risks: locate the workflow step that currently reads uses:
actions/setup-node@v4 (the block that also sets node-version: 24) and update the
uses value to the full actions/setup-node@<commit-sha> for the intended release
(verify the correct SHA for v4.1.0 or the latest secure release first), ensuring
the rest of the step (node-version: 24) remains unchanged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Valerii Svydenko <vsvydenk@redhat.com>
Copy link
Copy Markdown

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
.github/workflows/dependabot-license.yml (3)

43-83: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Final attempt parses problems.md and mutates exclusion files but never retries or commits.

On attempt 3, yarn license:generate fails → the loop parses problems and appends to .deps/EXCLUDED/*.md → then hits the attempt -eq MAX_ATTEMPTS branch and exit 1. Because the step exits non‑zero, the subsequent Commit and push changes step is skipped (default if: success()), so those last‑attempt additions are computed but thrown away. Either skip the parse on the final attempt, or run the parse, retry once more, and only fail after that final retry.

🛠️ Suggested control flow
             if yarn license:generate; then
               echo "License generation succeeded."
               break
             fi

+            if [ "$attempt" -eq "$MAX_ATTEMPTS" ]; then
+              echo "::error::Failed to resolve all dependencies after $MAX_ATTEMPTS attempts."
+              exit 1
+            fi
+
             if [ ! -f .deps/problems.md ]; then
               echo "::error::License generation failed but no problems.md found."
               exit 1
             fi
@@
               echo "| \`${PKG}\` | transitive dependency |" >> "$EXCLUDED_FILE"
               echo "Added $PKG to $EXCLUDED_FILE"
             done < .deps/problems.md
-
-            if [ "$attempt" -eq "$MAX_ATTEMPTS" ]; then
-              echo "::error::Failed to resolve all dependencies after $MAX_ATTEMPTS attempts."
-              exit 1
-            fi
           done
🤖 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/dependabot-license.yml around lines 43 - 83, The
final-attempt logic currently parses .deps/problems.md and mutates
.deps/EXCLUDED/*.md even when attempt == MAX_ATTEMPTS, then immediately exits so
the “Commit and push changes” step never runs; change the control flow in the
retry loop around yarn license:generate so that either (A) you skip
parsing/appending when attempt == MAX_ATTEMPTS (only parse on intermediate
failures), or (B) after parsing on the penultimate attempt you perform one
additional retry (i.e., only treat failure as terminal after parsing+one more
yarn license:generate attempt), ensuring that additions to the .deps/EXCLUDED
files are only made when a subsequent attempt will occur or are committed before
exiting; refer to the loop variables MAX_ATTEMPTS and attempt, the yarn
license:generate invocation, the .deps/problems.md parsing block and the
EXCLUDED file writes when implementing the change.

69-77: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Append may corrupt the table if the excluded file lacks a trailing newline.

echo ... >> "$EXCLUDED_FILE" concatenates onto the last line when the file doesn't already end with \n, producing a row like | existing |\n| \pkg` | … |` glued to the previous one and breaking the markdown table. Ensure a newline boundary before appending (or check for trailing newline first).

🛠️ Proposed change
-              echo "| \`${PKG}\` | transitive dependency |" >> "$EXCLUDED_FILE"
+              # Ensure the file ends with a newline before appending a new row
+              if [ -s "$EXCLUDED_FILE" ] && [ "$(tail -c1 "$EXCLUDED_FILE" | wc -l)" -eq 0 ]; then
+                printf '\n' >> "$EXCLUDED_FILE"
+              fi
+              printf '| `%s` | transitive dependency |\n' "$PKG" >> "$EXCLUDED_FILE"
               echo "Added $PKG to $EXCLUDED_FILE"
🤖 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/dependabot-license.yml around lines 69 - 77, The append to
EXCLUDED_FILE using echo ... >> "$EXCLUDED_FILE" can glue the new table row to
the previous line if the file lacks a trailing newline; update the loop that
writes to EXCLUDED_FILE (using the EXCLUDED_FILE, SECTION, PKG variables and the
input .deps/problems.md) to ensure a newline boundary before appending—either
check for a trailing newline and add one if missing or write a newline first
when creating/appending to EXCLUDED_FILE so the markdown table row is always on
its own line.

85-93: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

git diff --quiet .deps/ misses untracked files; newly created entries won't be committed.

git diff only inspects tracked files. If yarn license:generate produces new files under .deps/ (e.g. a brand new EXCLUDED/*.md or a new per-package file), this check returns 0 and the step exits before staging/committing them, silently dropping the work. Use git status --porcelain (or git add -N before the diff) to also catch untracked entries.

🛠️ Proposed change
-          git diff --quiet .deps/ && exit 0
-
-          git config user.name "github-actions[bot]"
-          git config user.email "41898282+github-actions[bot]`@users.noreply.github.com`"
-          git add .deps/
-          git commit -s -m "chore(deps): regenerate license dependencies"
-          git push
+          git config user.name "github-actions[bot]"
+          git config user.email "41898282+github-actions[bot]`@users.noreply.github.com`"
+          git add .deps/
+          if git diff --cached --quiet -- .deps/; then
+            echo "No .deps/ changes to commit."
+            exit 0
+          fi
+          git commit -s -m "chore(deps): regenerate license dependencies"
+          git push
🤖 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/dependabot-license.yml around lines 85 - 93, The step
currently uses the command git diff --quiet .deps/ which only detects changes to
tracked files and will miss newly created/untracked files; replace that check
with a command that also detects untracked entries (for example run git add -N
.deps/ to stage intention-to-add files then run git diff --quiet -- .deps/ or
use git status --porcelain .deps/ and test for non-empty output) so that newly
generated files under .deps/ are detected and the subsequent git add/.commit
steps run; update the step that runs git diff --quiet .deps/ accordingly and
keep the existing git add .deps/, git commit, and git push commands.
♻️ Duplicate comments (2)
.github/workflows/dependabot-license.yml (2)

26-30: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin actions/checkout to a commit SHA and disable credential persistence.

Still applicable on the current revision: actions/checkout@v4 is unpinned, and without persist-credentials: false the GITHUB_TOKEN is written into the local git config and can leak through subsequent steps or artifacts. Note this will also require an explicit token on the git push step (e.g. via a remote URL with ${{ secrets.GITHUB_TOKEN }} or by re-running checkout with credentials only where needed).

🤖 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/dependabot-license.yml around lines 26 - 30, Update the
actions/checkout usage to pin the action to a specific commit SHA instead of the
version tag (replace uses: actions/checkout@v4 with the full SHA) and add
persist-credentials: false to the with: block to prevent GITHUB_TOKEN from being
written to git config; keep ref: ${{ github.head_ref }} and fetch-depth: 0 as
needed, and ensure any later git push step uses an explicit token (e.g., include
the secrets.GITHUB_TOKEN in the remote URL or re-run a checkout step with
credentials only where required).

32-35: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin actions/setup-node to a commit SHA.

Same supply‑chain concern as previously raised — actions/setup-node@v4 is still floating.

🤖 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/dependabot-license.yml around lines 32 - 35, The workflow
currently uses the floating tag "actions/setup-node@v4" which should be pinned
to a commit SHA; update the "uses" entry replacing actions/setup-node@v4 with a
specific commit SHA (actions/setup-node@<commit-sha>) for the version that
supports node-version: 24, fetch the correct SHA from the actions/setup-node v4
release (or GitHub Actions marketplace), and commit that SHA so the runner pulls
an immutable reference instead of the floating tag.
🧹 Nitpick comments (1)
.github/workflows/dependabot-license.yml (1)

12-19: ⚡ Quick win

Add a concurrency group to serialize runs per PR.

Each synchronize event will start a new run that fetches, parses problems.md, and pushes to the same branch. Without a concurrency group, two in‑flight runs can race on the same .deps/EXCLUDED/*.md files and produce duplicate appends or a non-fast-forward push.

♻️ Proposed change
 on:
   pull_request:
     types: [opened, synchronize]
     branches:
       - main

+concurrency:
+  group: dependabot-license-${{ github.event.pull_request.number }}
+  cancel-in-progress: true
+
 permissions:
   contents: write
🤖 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/dependabot-license.yml around lines 12 - 19, Add a
top-level concurrency stanza to the workflow to serialize runs per PR: add a
concurrency key with a group value that uses the PR identifier (for example
"dependabot-license-${{ github.event.pull_request.number }}") and set
cancel-in-progress: false so runs queue instead of canceling; this ensures the
workflow (affecting .deps/EXCLUDED/*.md) runs one-at-a-time per pull_request and
prevents race conditions between synchronize events.
🤖 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.

Outside diff comments:
In @.github/workflows/dependabot-license.yml:
- Around line 43-83: The final-attempt logic currently parses .deps/problems.md
and mutates .deps/EXCLUDED/*.md even when attempt == MAX_ATTEMPTS, then
immediately exits so the “Commit and push changes” step never runs; change the
control flow in the retry loop around yarn license:generate so that either (A)
you skip parsing/appending when attempt == MAX_ATTEMPTS (only parse on
intermediate failures), or (B) after parsing on the penultimate attempt you
perform one additional retry (i.e., only treat failure as terminal after
parsing+one more yarn license:generate attempt), ensuring that additions to the
.deps/EXCLUDED files are only made when a subsequent attempt will occur or are
committed before exiting; refer to the loop variables MAX_ATTEMPTS and attempt,
the yarn license:generate invocation, the .deps/problems.md parsing block and
the EXCLUDED file writes when implementing the change.
- Around line 69-77: The append to EXCLUDED_FILE using echo ... >>
"$EXCLUDED_FILE" can glue the new table row to the previous line if the file
lacks a trailing newline; update the loop that writes to EXCLUDED_FILE (using
the EXCLUDED_FILE, SECTION, PKG variables and the input .deps/problems.md) to
ensure a newline boundary before appending—either check for a trailing newline
and add one if missing or write a newline first when creating/appending to
EXCLUDED_FILE so the markdown table row is always on its own line.
- Around line 85-93: The step currently uses the command git diff --quiet .deps/
which only detects changes to tracked files and will miss newly
created/untracked files; replace that check with a command that also detects
untracked entries (for example run git add -N .deps/ to stage intention-to-add
files then run git diff --quiet -- .deps/ or use git status --porcelain .deps/
and test for non-empty output) so that newly generated files under .deps/ are
detected and the subsequent git add/.commit steps run; update the step that runs
git diff --quiet .deps/ accordingly and keep the existing git add .deps/, git
commit, and git push commands.

---

Duplicate comments:
In @.github/workflows/dependabot-license.yml:
- Around line 26-30: Update the actions/checkout usage to pin the action to a
specific commit SHA instead of the version tag (replace uses:
actions/checkout@v4 with the full SHA) and add persist-credentials: false to the
with: block to prevent GITHUB_TOKEN from being written to git config; keep ref:
${{ github.head_ref }} and fetch-depth: 0 as needed, and ensure any later git
push step uses an explicit token (e.g., include the secrets.GITHUB_TOKEN in the
remote URL or re-run a checkout step with credentials only where required).
- Around line 32-35: The workflow currently uses the floating tag
"actions/setup-node@v4" which should be pinned to a commit SHA; update the
"uses" entry replacing actions/setup-node@v4 with a specific commit SHA
(actions/setup-node@<commit-sha>) for the version that supports node-version:
24, fetch the correct SHA from the actions/setup-node v4 release (or GitHub
Actions marketplace), and commit that SHA so the runner pulls an immutable
reference instead of the floating tag.

---

Nitpick comments:
In @.github/workflows/dependabot-license.yml:
- Around line 12-19: Add a top-level concurrency stanza to the workflow to
serialize runs per PR: add a concurrency key with a group value that uses the PR
identifier (for example "dependabot-license-${{ github.event.pull_request.number
}}") and set cancel-in-progress: false so runs queue instead of canceling; this
ensures the workflow (affecting .deps/EXCLUDED/*.md) runs one-at-a-time per
pull_request and prevents race conditions between synchronize events.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0b584e61-48e8-44df-953a-1580ee2ff1a8

📥 Commits

Reviewing files that changed from the base of the PR and between b08237e and 0baa14b.

📒 Files selected for processing (1)
  • .github/workflows/dependabot-license.yml

@svor svor requested a review from olexii4 May 21, 2026 13:49
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