Skip to content

ci: add CI, release, and security workflows#2

Merged
nixrajput merged 3 commits into
masterfrom
chore/ci-workflows
Jun 29, 2026
Merged

ci: add CI, release, and security workflows#2
nixrajput merged 3 commits into
masterfrom
chore/ci-workflows

Conversation

@nixrajput

@nixrajput nixrajput commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Standardizes repo automation: CI (build/lint/test), version-check (enforces a package.json bump per PR), release (auto tag + GitHub Release on merge), dependency-review + OpenSSF Scorecard (supply-chain security), and stale + labeler (maintenance). Version bumped 0.1.0 → 0.1.1 to pass the new version-check.

Part of a fleet-wide workflow standardization.

Summary by CodeRabbit

  • New Features

    • Added automated checks for pull requests, including version validation, dependency review, and label management.
    • Introduced release automation to publish tagged releases from the current version.
  • Bug Fixes

    • Added safeguards to prevent outdated or lower version changes from being merged.
    • Improved CI reliability by handling different package managers and skipping unavailable scripts gracefully.
  • Chores

    • Added scheduled cleanup for inactive issues and pull requests.
    • Added security scanning and project health reporting in the background.

- Add CI (lint/typecheck/build/test via the repo's package manager),
  version-check (enforce a package.json bump per PR), and release
  (tag + GitHub Release on merge) workflows.
- Add dependency-review and OpenSSF Scorecard for supply-chain
  security, plus stale and labeler maintenance workflows.
- Bump version to 0.1.1 to satisfy the new version-check gate.
@vercel

vercel Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
github-analytics Ready Ready Preview, Comment Jun 29, 2026 10:40am

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@nixrajput, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 43 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c952c11c-3f1c-4d8f-ac95-bbbb195e232c

📥 Commits

Reviewing files that changed from the base of the PR and between 8778056 and b76a984.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml
  • .github/workflows/version-check.yml
📝 Walkthrough

Walkthrough

Seven GitHub Actions workflows are added: CI build, dependency review, auto-labeler, automated release, OpenSSF Scorecard, stale issue management, and version-bump enforcement. A supporting labeler config file is added, and package.json is bumped from 0.1.0 to 0.1.1.

Changes

GitHub Actions Workflows and Config

Layer / File(s) Summary
CI build and dependency install
.github/workflows/ci.yml
Detects package manager from lockfiles, installs dependencies with a frozen/CI command, and conditionally runs scripts (lint, ts:check, typecheck, build, test) only if they exist in package.json.
PR-time checks: dependency review and version enforcement
.github/workflows/dependency-review.yml, .github/workflows/version-check.yml, package.json
Dependency review fails PRs on high-severity findings and comments on failure; version-check enforces a semver bump by comparing PR vs base branch package.json, rejecting unchanged or downgraded versions. Version bumped to 0.1.1.
Auto-labeler config and workflow
.github/labeler.yml, .github/workflows/labeler.yml
Path-based label rules for documentation, ci, dependencies, and tests; labeler workflow syncs labels on pull_request_target events using actions/labeler@v5.
Automated release workflow
.github/workflows/release.yml
On master push or manual dispatch, reads version from package.json, skips if the tag/release already exists, otherwise creates a GitHub Release with generated notes.
Stale management and OpenSSF Scorecard
.github/workflows/stale.yml, .github/workflows/scorecard.yml
Stale marks issues/PRs after 60 days and closes after 14 more, exempting pinned/security/blocked items. Scorecard runs weekly and on master push, produces SARIF, and uploads to GitHub code scanning.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hoppity-hop, the pipelines appear,
Labels and releases now crystal clear!
Stale issues beware, I'll close you with care,
Scorecards and semver checks fill the air.
CI detects your lockfile with flair~ 🌟

🚥 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 reflects the main change: adding CI, release, and security automation 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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/ci-workflows

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.

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

🧹 Nitpick comments (2)
.github/workflows/ci.yml (1)

47-52: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Avoid template expression in shell command for cleanliness.

Although steps.pm.outputs.pm is internally controlled, moving it to an env var silences the zizmor warning and is a good practice:

       - name: Install
+        env:
+          PM: ${{ steps.pm.outputs.pm }}
         run: |
-          case "${{ steps.pm.outputs.pm }}" in
+          case "$PM" in
             bun) bun install --frozen-lockfile ;;
             pnpm) pnpm install --frozen-lockfile ;;
             yarn) yarn install --frozen-lockfile ;;
             npm) npm ci ;;
           esac
🤖 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/ci.yml around lines 47 - 52, The shell switch in the CI
workflow is using a template expression directly inside the script, which
triggers the warning. Move the value from steps.pm.outputs.pm into an
environment variable in the job or step, then update the install case block to
read from that env var instead; keep the existing install commands in place and
use the same pm selection logic.
.github/workflows/version-check.yml (1)

21-27: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Move github.base_ref to an env var to avoid template injection.

zizmor flags this as template-injection. While github.base_ref is the target branch (not directly from PR diff content), placing it in an env var is cleaner and silences the warning:

       - name: Read versions
+        env:
+          BASE_REF: ${{ github.base_ref }}
         id: v
         run: |
-          pr=$(jq -r .version package.json)
-          base=$(git show "origin/${{ github.base_ref }}:package.json" | jq -r .version)
+          pr=$(jq -r .version package.json)
+          base=$(git show "origin/$BASE_REF:package.json" | jq -r .version)
           echo "pr=$pr" >> "$GITHUB_OUTPUT"
           echo "base=$base" >> "$GITHUB_OUTPUT"
🤖 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/version-check.yml around lines 21 - 27, The version-check
workflow step that reads versions is using github.base_ref directly inside the
shell command, which triggers the template-injection warning. Update the Read
versions step by passing github.base_ref into an environment variable first,
then reference that env var in the git show command inside the same step. Keep
the logic in the v step unchanged otherwise, and ensure the base package.json is
still read via git show using the env-based branch name.
🤖 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/labeler.yml:
- Around line 10-11: The dependency label glob in the labeler config is missing
npm lockfiles, so PRs that only update resolved dependencies in
package-lock.json won’t get the dependencies label. Update the
any-glob-to-any-file list in the label configuration to include
package-lock.json alongside the existing dependency manifest and lockfile
patterns, keeping the rule name and glob structure consistent.

In @.github/workflows/labeler.yml:
- Around line 16-18: The workflow step using actions/labeler is pinned to a
mutable version tag, so update the uses reference in the labeler job to the
recommended commit SHA instead of actions/labeler@v5. Keep the existing
sync-labels setting unchanged, and make the change in the labeler workflow entry
so the action version is fixed to the provided hash.

In @.github/workflows/release.yml:
- Around line 34-39: The release workflow currently treats any existing tag as a
success, which can hide version collisions between different commits. Update the
release step in the release job so it only skips when gh release view or git
ls-remote confirms the tag already points to github.sha; if the tag exists on a
different commit, fail the workflow instead of exiting 0. Keep the logic
localized around the tag-existence check and gh release create flow.

In @.github/workflows/scorecard.yml:
- Around line 22-30: The workflow uses privileged actions by tag, which can
drift over time; update the job in the scorecard workflow to pin
actions/checkout, ossf/scorecard-action, and github/codeql-action/upload-sarif
to immutable full commit SHAs while keeping the current release tags as comments
for reference. Use the existing action references in the workflow step list to
locate and replace the versioned uses entries, and preserve the current inputs
for checkout, scorecard, and SARIF upload.
- Around line 18-20: The job-level permissions block for the Scorecard workflow
currently replaces the default repository read access, which breaks
actions/checkout. Update the workflow’s permissions stanza to include contents:
read alongside the existing security-events and id-token scopes, and keep any
additional read scopes only if the Scorecard job actually requires them.

In @.github/workflows/stale.yml:
- Line 17: The stale workflow currently references actions/stale with a floating
version tag, which should be replaced with the pinned full commit SHA to keep
this write-capable action immutable. Update the actions/stale step in the
workflow to use the provided commit reference instead of v9, and keep the rest
of the workflow unchanged.

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 47-52: The shell switch in the CI workflow is using a template
expression directly inside the script, which triggers the warning. Move the
value from steps.pm.outputs.pm into an environment variable in the job or step,
then update the install case block to read from that env var instead; keep the
existing install commands in place and use the same pm selection logic.

In @.github/workflows/version-check.yml:
- Around line 21-27: The version-check workflow step that reads versions is
using github.base_ref directly inside the shell command, which triggers the
template-injection warning. Update the Read versions step by passing
github.base_ref into an environment variable first, then reference that env var
in the git show command inside the same step. Keep the logic in the v step
unchanged otherwise, and ensure the base package.json is still read via git show
using the env-based branch name.
🪄 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: de36311f-8c7f-4049-9924-fb2e8e59ef2b

📥 Commits

Reviewing files that changed from the base of the PR and between 774261e and 8778056.

📒 Files selected for processing (9)
  • .github/labeler.yml
  • .github/workflows/ci.yml
  • .github/workflows/dependency-review.yml
  • .github/workflows/labeler.yml
  • .github/workflows/release.yml
  • .github/workflows/scorecard.yml
  • .github/workflows/stale.yml
  • .github/workflows/version-check.yml
  • package.json

Comment thread .github/labeler.yml
Comment on lines +10 to +11
- any-glob-to-any-file:
["**/package.json", "**/pubspec.yaml", "**/go.mod", "**/*.lock", "**/*lock.yaml"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Include package-lock.json in the dependency globs.

Line 11 misses npm lockfile-only updates, because package-lock.json matches neither **/*.lock nor **/*lock.yaml. Those PRs will skip the dependencies label even though they only change resolved dependencies.

Suggested patch
 dependencies:
   - changed-files:
       - any-glob-to-any-file:
-          ["**/package.json", "**/pubspec.yaml", "**/go.mod", "**/*.lock", "**/*lock.yaml"]
+          ["**/package.json", "**/package-lock.json", "**/pubspec.yaml", "**/go.mod", "**/*.lock", "**/*lock.yaml"]
📝 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
- any-glob-to-any-file:
["**/package.json", "**/pubspec.yaml", "**/go.mod", "**/*.lock", "**/*lock.yaml"]
- any-glob-to-any-file:
["**/package.json", "**/package-lock.json", "**/pubspec.yaml", "**/go.mod", "**/*.lock", "**/*lock.yaml"]
🤖 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/labeler.yml around lines 10 - 11, The dependency label glob in the
labeler config is missing npm lockfiles, so PRs that only update resolved
dependencies in package-lock.json won’t get the dependencies label. Update the
any-glob-to-any-file list in the label configuration to include
package-lock.json alongside the existing dependency manifest and lockfile
patterns, keeping the rule name and glob structure consistent.

Comment on lines +16 to +18
- uses: actions/labeler@v5
with:
sync-labels: true

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 | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Mutable action refs in workflows:"
rg -n 'uses:\s+[^@]+@(main|master|v[0-9]+(\.[0-9]+)?)\b' .github/workflows

echo
echo "Resolve the current commit behind actions/labeler v5 before pinning it:"
gh api repos/actions/labeler/git/ref/tags/v5 --jq '.object.sha'

Repository: nixrajput/github-analytics

Length of output: 1235


Pin actions/labeler to a commit SHA.

actions/labeler@v5 is a mutable ref; pinning avoids supply-chain drift. v5 currently resolves to 8558fd74291d67161a8a78ce36a881fa63b766a9.

🤖 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/labeler.yml around lines 16 - 18, The workflow step using
actions/labeler is pinned to a mutable version tag, so update the uses reference
in the labeler job to the recommended commit SHA instead of actions/labeler@v5.
Keep the existing sync-labels setting unchanged, and make the change in the
labeler workflow entry so the action version is fixed to the provided hash.

Comment on lines +34 to +39
if gh release view "$TAG" >/dev/null 2>&1 \
|| git ls-remote --tags origin "refs/tags/$TAG" | grep -q .; then
echo "Tag $TAG already exists — skipping."
exit 0
fi
gh release create "$TAG" --target "${{ github.sha }}" --title "$TAG" --generate-notes

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

Fail on version/tag collisions instead of silently skipping.

If two PRs merge with the same package.json version, the first merge creates vX.Y.Z and the second merge lands on master with a different github.sha. This branch exits 0, so that later merge ships without a corresponding GitHub Release even though .github/workflows/version-check.yml:16-28 and package.json:1-5 define a shared version→tag contract. Treat “tag exists on another commit” as an error, and only skip when the existing tag already points at the current SHA.

Suggested fix
       - name: Release if new
         env:
           GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           TAG: ${{ steps.v.outputs.tag }}
         run: |
-          if gh release view "$TAG" >/dev/null 2>&1 \
-            || git ls-remote --tags origin "refs/tags/$TAG" | grep -q .; then
-            echo "Tag $TAG already exists — skipping."
-            exit 0
-          fi
+          remote_sha="$(git ls-remote --tags origin "refs/tags/$TAG" | awk '{print $1}')"
+          if [ -n "$remote_sha" ]; then
+            if [ "$remote_sha" != "${{ github.sha }}" ]; then
+              echo "::error::Tag $TAG already points to $remote_sha, but this push is ${{ github.sha }}. Bump package.json before merging."
+              exit 1
+            fi
+            echo "Tag $TAG already exists for this commit — skipping."
+            exit 0
+          fi
+
+          if gh release view "$TAG" >/dev/null 2>&1; then
+            echo "Release $TAG already exists — skipping."
+            exit 0
+          fi
+
           gh release create "$TAG" --target "${{ github.sha }}" --title "$TAG" --generate-notes
           echo "Released $TAG ✓"
📝 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
if gh release view "$TAG" >/dev/null 2>&1 \
|| git ls-remote --tags origin "refs/tags/$TAG" | grep -q .; then
echo "Tag $TAG already exists — skipping."
exit 0
fi
gh release create "$TAG" --target "${{ github.sha }}" --title "$TAG" --generate-notes
remote_sha="$(git ls-remote --tags origin "refs/tags/$TAG" | awk '{print $1}')"
if [ -n "$remote_sha" ]; then
if [ "$remote_sha" != "${{ github.sha }}" ]; then
echo "::error::Tag $TAG already points to $remote_sha, but this push is ${{ github.sha }}. Bump package.json before merging."
exit 1
fi
echo "Tag $TAG already exists for this commit — skipping."
exit 0
fi
if gh release view "$TAG" >/dev/null 2>&1; then
echo "Release $TAG already exists — skipping."
exit 0
fi
gh release create "$TAG" --target "${{ github.sha }}" --title "$TAG" --generate-notes
echo "Released $TAG ✓"
🤖 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.yml around lines 34 - 39, The release workflow
currently treats any existing tag as a success, which can hide version
collisions between different commits. Update the release step in the release job
so it only skips when gh release view or git ls-remote confirms the tag already
points to github.sha; if the tag exists on a different commit, fail the workflow
instead of exiting 0. Keep the logic localized around the tag-existence check
and gh release create flow.

Comment on lines +18 to +20
permissions:
security-events: write # upload SARIF to code scanning
id-token: write # publish results to the OpenSSF API

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== .github/workflows/scorecard.yml =="
nl -ba .github/workflows/scorecard.yml | sed -n '1,120p'

echo
echo "== Search for scorecard workflow references =="
rg -n "scorecard|checkout@|permissions:" .github/workflows . -g '!**/node_modules/**' -g '!**/dist/**' -g '!**/build/**' || true

echo
echo "== Exact action refs in workflow =="
python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/scorecard.yml')
text = p.read_text()
for i, line in enumerate(text.splitlines(), 1):
    if 'uses:' in line or 'permissions:' in line:
        print(f"{i}: {line}")
PY

Repository: nixrajput/github-analytics

Length of output: 242


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/scorecard.yml')
text = p.read_text().splitlines()
for i, line in enumerate(text, 1):
    print(f"{i:4} {line}")
PY

echo
echo "== uses: lines =="
python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/scorecard.yml')
for i, line in enumerate(p.read_text().splitlines(), 1):
    if 'uses:' in line or 'permissions:' in line:
        print(f"{i:4} {line}")
PY

echo
echo "== repo files matching scorecard workflow references =="
python3 - <<'PY'
from pathlib import Path
for path in Path('.github/workflows').glob('*.yml'):
    text = path.read_text()
    if 'scorecard' in text.lower():
        print(path)
PY

Repository: nixrajput/github-analytics

Length of output: 1504


🌐 Web query:

GitHub Actions workflow permissions job-level permissions override unspecified scopes none checkout requires contents: read scorecard action private repo queries permissions

💡 Result:

In GitHub Actions, workflow permissions follow these principles: Job-level permissions override, rather than merge with, workflow-level permissions [1]. If a permissions key is defined at the job level, it completely replaces any permissions configured at the workflow level for that specific job [1]. When you explicitly define the permissions key (at either the workflow or job level), all unspecified permissions are set to none [2][3][4]. The only exception is the metadata scope, which always receives read access [3]. Regarding the checkout action and scorecard: 1. The actions/checkout action requires contents: read permission to successfully clone your repository [5][6][7]. If you have defined a permissions block in your workflow or job and do not include contents: read, the checkout action will fail [8]. 2. For private repositories, if you use the Scorecard action, it also typically requires specific permissions (often read access to contents, pull-requests, and potentially security-events) to analyze the repository [4][8]. Because job-level permissions do not merge with workflow-level settings, ensure that if you override permissions at the job level, you include all required scopes for both checkout and any other actions running in that job [1]. Best practice suggests setting permissions at the job level to adhere to the principle of least privilege [1][9]. If you define them at the job level, you must manually list every permission required by the steps within that job, as they will not inherit from any top-level definitions [1].

Citations:


Restore contents: read on the job. The job-level permissions block replaces read-all, so actions/checkout loses repository read access without contents: read. Add that scope here and keep any other read scopes only if Scorecard actually needs them.

🤖 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/scorecard.yml around lines 18 - 20, The job-level
permissions block for the Scorecard workflow currently replaces the default
repository read access, which breaks actions/checkout. Update the workflow’s
permissions stanza to include contents: read alongside the existing
security-events and id-token scopes, and keep any additional read scopes only if
the Scorecard job actually requires them.

Comment on lines +22 to +30
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: ossf/scorecard-action@v2.4.0
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- uses: github/codeql-action/upload-sarif@v3

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 | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
git ls-remote https://github.com/actions/checkout.git 'refs/tags/v6^{}' 'refs/tags/v6'
git ls-remote https://github.com/ossf/scorecard-action.git 'refs/tags/v2.4.0^{}' 'refs/tags/v2.4.0'
git ls-remote https://github.com/github/codeql-action.git 'refs/tags/v3^{}' 'refs/tags/v3'

Repository: nixrajput/github-analytics

Length of output: 448


🏁 Script executed:

#!/bin/bash
set -euo pipefail
cat -n .github/workflows/scorecard.yml | sed -n '1,120p'

Repository: nixrajput/github-analytics

Length of output: 1268


Pin the privileged workflow actions to full commit SHAs

security-events: write and id-token: write make this job sensitive to supply-chain drift. Keep the release tags as comments, but use immutable SHAs for actions/checkout, ossf/scorecard-action, and github/codeql-action/upload-sarif.

Suggested shape
-      - uses: actions/checkout@v6
+      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
...
-      - uses: ossf/scorecard-action@v2.4.0
+      - uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
...
-      - uses: github/codeql-action/upload-sarif@v3
+      - uses: github/codeql-action/upload-sarif@dd903d2e4f5405488e5ef1422510ee31c8b32357 # v3
📝 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
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: ossf/scorecard-action@v2.4.0
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- uses: github/codeql-action/upload-sarif@v3
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- uses: github/codeql-action/upload-sarif@dd903d2e4f5405488e5ef1422510ee31c8b32357 # v3
🤖 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/scorecard.yml around lines 22 - 30, The workflow uses
privileged actions by tag, which can drift over time; update the job in the
scorecard workflow to pin actions/checkout, ossf/scorecard-action, and
github/codeql-action/upload-sarif to immutable full commit SHAs while keeping
the current release tags as comments for reference. Use the existing action
references in the workflow step list to locate and replace the versioned uses
entries, and preserve the current inputs for checkout, scorecard, and SARIF
upload.

stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9

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 | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
git ls-remote https://github.com/actions/stale.git 'refs/tags/v9^{}' 'refs/tags/v9'

Repository: nixrajput/github-analytics

Length of output: 218


🏁 Script executed:

#!/bin/bash
set -euo pipefail
cat -n .github/workflows/stale.yml

Repository: nixrajput/github-analytics

Length of output: 1303


🏁 Script executed:

#!/bin/bash
set -euo pipefail
git ls-remote https://github.com/actions/stale.git 'refs/tags/v9^{}' 'refs/tags/v9'

Repository: nixrajput/github-analytics

Length of output: 218


Pin actions/stale to the full commit SHA. Replace actions/stale@v9 with actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 so this write-capable workflow uses an immutable reference.

Suggested shape
-      - uses: actions/stale@v9
+      - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
📝 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
- uses: actions/stale@v9
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
🤖 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/stale.yml at line 17, The stale workflow currently
references actions/stale with a floating version tag, which should be replaced
with the pinned full commit SHA to keep this write-capable action immutable.
Update the actions/stale step in the workflow to use the provided commit
reference instead of v9, and keep the rest of the workflow unchanged.

@nixrajput nixrajput merged commit 04a6110 into master Jun 29, 2026
6 checks passed
@nixrajput nixrajput deleted the chore/ci-workflows branch June 29, 2026 12:59
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