chore: ci setup for pytests#118
Conversation
WalkthroughAdds two GitHub Actions workflows (pr-checks.yml, update-badge.yml) for running pytest with coverage on PRs and pushes to main, adds pytest-related test dependencies to requirements-test.txt, and updates README.md with coverage comment markers replacing a placeholder. ChangesCI and Test Tooling
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant Developer
participant GitHubActions
participant Pytest
participant CoverageComment
participant README
Developer->>GitHubActions: push to main
GitHubActions->>GitHubActions: checkout code, setup Python 3.11
GitHubActions->>Pytest: install deps, run pytest with coverage
Pytest-->>GitHubActions: pytest.xml + pytest-coverage.txt
GitHubActions->>CoverageComment: post hidden coverage comment
CoverageComment-->>GitHubActions: coverageHtml output
GitHubActions->>README: sed replace coverage markers, git-auto-commit
Suggested labels: Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ 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 |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Coverage Report
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@CodeRabbit review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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/ci.yml:
- Around line 19-20: Disable credential persistence in the Checkout Code step by
updating the actions/checkout@v4 usage in the CI workflow to explicitly set
persist-credentials to false. This change should be made on the Checkout Code
action invocation itself, since no later job step needs git push access or the
scoped GITHUB_TOKEN stored in local git config.
- Around line 38-43: The Pytest coverage comment workflow step is using a
mutable third-party action reference, so update the `uses` value in the `Pytest
coverage comment` step from `MishaKav/pytest-coverage-comment@main` to a pinned
release tag or, preferably, a specific commit SHA. Keep the rest of the step
(`pytest-coverage-path`, `junitxml-path`, and the `pull_request` condition)
unchanged while ensuring the action reference in `.github/workflows/ci.yml` is
immutable.
- Around line 3-9: Add a workflow-level concurrency block to the CI workflow so
newer runs cancel older ones on the same ref. Update the GitHub Actions
configuration near the existing on/push/pull_request triggers by adding a
concurrency group that uniquely keys on the branch or PR ref, and set
cancel-in-progress so superseded runs stop automatically. Use the workflow
file’s top-level configuration and keep the change aligned with the current ci
workflow triggers.
In `@scripts/setup-hooks.sh`:
- Line 4: Guard the initial directory change in the setup script so it fails
fast if the target path cannot be entered. Update the startup logic around the
cd command in the script to stop execution on failure, using the same setup flow
that computes the repo root from dirname "$0".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: ebc909e1-618e-4882-8937-e7fa09e40365
📒 Files selected for processing (3)
.github/workflows/ci.ymlrequirements-dev.txtscripts/setup-hooks.sh
| on: | ||
| pull_request: | ||
| branches: | ||
| - main | ||
| push: | ||
| branches: | ||
| - main |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win
Add a concurrency group to cancel superseded runs.
Without a concurrency block, rapid pushes/PR updates queue overlapping workflow runs on the same ref, wasting CI minutes and delaying feedback.
♻️ Suggested addition
on:
pull_request:
branches:
- main
push:
branches:
- main
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: trueAs per static analysis hints, zizmor flagged (concurrency-limits): workflow is missing concurrency setting.
📝 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.
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| push: | |
| branches: | |
| - main | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| push: | |
| branches: | |
| - main | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true |
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 3-9: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting
(concurrency-limits)
🤖 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 3 - 9, Add a workflow-level
concurrency block to the CI workflow so newer runs cancel older ones on the same
ref. Update the GitHub Actions configuration near the existing
on/push/pull_request triggers by adding a concurrency group that uniquely keys
on the branch or PR ref, and set cancel-in-progress so superseded runs stop
automatically. Use the workflow file’s top-level configuration and keep the
change aligned with the current ci workflow triggers.
Source: Linters/SAST tools
| - name: Checkout Code | ||
| uses: actions/checkout@v4 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Disable credential persistence on checkout.
actions/checkout@v4 defaults to persist-credentials: true, leaving the scoped GITHUB_TOKEN (which has pull-requests: write) in the local git config for the rest of the job. Since later steps run pip install against requirements.txt/requirements-dev.txt and then execute the full pytest suite, any malicious/compromised dependency or test could read .git/config and exfiltrate the token. Set persist-credentials: false since no step in this job needs to push or use the checkout credentials.
🔒 Proposed fix
- name: Checkout Code
uses: actions/checkout@v4
+ with:
+ persist-credentials: falseAs per static analysis hints, zizmor flagged (artipacked): does not set persist-credentials: false.
📝 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.
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false |
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 19-20: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 20-20: 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/ci.yml around lines 19 - 20, Disable credential
persistence in the Checkout Code step by updating the actions/checkout@v4 usage
in the CI workflow to explicitly set persist-credentials to false. This change
should be made on the Checkout Code action invocation itself, since no later job
step needs git push access or the scoped GITHUB_TOKEN stored in local git
config.
Source: Linters/SAST tools
| #!/bin/sh | ||
|
|
||
| # Ensure we are in the root directory | ||
| cd "$(dirname "$0")/.." |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Guard against cd failure.
If dirname "$0"/.. doesn't resolve (unusual invocation context), the script silently continues in the wrong directory and writes/overwrites files at an unintended location.
🛡️ Proposed fix
-cd "$(dirname "$0")/.."
+cd "$(dirname "$0")/.." || exit 1As per static analysis hints, shellcheck flagged SC2164: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.
📝 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.
| cd "$(dirname "$0")/.." | |
| cd "$(dirname "$0")/.." || exit 1 |
🧰 Tools
🪛 Shellcheck (0.11.0)
[warning] 4-4: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.
(SC2164)
🤖 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 `@scripts/setup-hooks.sh` at line 4, Guard the initial directory change in the
setup script so it fails fast if the target path cannot be entered. Update the
startup logic around the cd command in the script to stop execution on failure,
using the same setup flow that computes the repo root from dirname "$0".
Source: Linters/SAST tools
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/ci.yml:
- Around line 46-50: The README update step in the ci workflow is vulnerable
because `coverageComment.outputs.coverageHtml` is interpolated directly into the
`run` script, so fix `Update README with Coverage Html` by passing that output
through `env:` and consuming it as a normal shell variable inside the script
instead of `${{ }}` expansion. Keep the `sed`-based replacement logic in the
same workflow step but refactor it so the untrusted coverage HTML is handled as
data, not template text, and verify the change around `coverageComment` and the
README update command.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: e92427be-ca97-4ec5-b785-1cbc87ac6fab
📒 Files selected for processing (2)
.github/workflows/ci.ymlREADME.md
| - name: Update README with Coverage Html | ||
| if: github.ref == 'refs/heads/main' | ||
| run: | | ||
| sed -i '/<!-- Pytest Coverage Comment:Begin -->/,/<!-- Pytest Coverage Comment:End -->/c\<!-- Pytest Coverage Comment:Begin -->\n\${{ steps.coverageComment.outputs.coverageHtml }}\n<!-- Pytest Coverage Comment:End -->' ./README.md | ||
|
|
There was a problem hiding this comment.
🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win
Shell/command injection via direct expression interpolation.
${{ steps.coverageComment.outputs.coverageHtml }} is expanded at workflow "compile time" directly into the run: script text before bash ever sees it. Any coverage HTML content containing shell metacharacters (backticks, $(), &&, quotes from file/function names in the coverage report) is executed verbatim on the runner. GitHub's own security guidance recommends routing untrusted/step-output values through env: and referencing them as ordinary shell/language variables instead of ${{ }} inside run:.
🔒 Proposed fix using env var + Python substitution (avoids shell interpolation entirely)
- name: Update README with Coverage Html
if: github.ref == 'refs/heads/main'
+ env:
+ COVERAGE_HTML: ${{ steps.coverageComment.outputs.coverageHtml }}
run: |
- sed -i '/<!-- Pytest Coverage Comment:Begin -->/,/<!-- Pytest Coverage Comment:End -->/c\<!-- Pytest Coverage Comment:Begin -->\n\${{ steps.coverageComment.outputs.coverageHtml }}\n<!-- Pytest Coverage Comment:End -->' ./README.md
+ python3 - <<'PYEOF'
+ import os
+ begin, end = "<!-- Pytest Coverage Comment:Begin -->", "<!-- Pytest Coverage Comment:End -->"
+ with open("README.md") as f:
+ content = f.read()
+ start = content.index(begin) + len(begin)
+ stop = content.index(end)
+ content = content[:start] + "\n" + os.environ["COVERAGE_HTML"] + "\n" + content[stop:]
+ with open("README.md", "w") as f:
+ f.write(content)
+ PYEOFAs per static analysis hints, zizmor flagged [info] 49-49: code injection via template expansion (template-injection).
📝 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.
| - name: Update README with Coverage Html | |
| if: github.ref == 'refs/heads/main' | |
| run: | | |
| sed -i '/<!-- Pytest Coverage Comment:Begin -->/,/<!-- Pytest Coverage Comment:End -->/c\<!-- Pytest Coverage Comment:Begin -->\n\${{ steps.coverageComment.outputs.coverageHtml }}\n<!-- Pytest Coverage Comment:End -->' ./README.md | |
| - name: Update README with Coverage Html | |
| if: github.ref == 'refs/heads/main' | |
| env: | |
| COVERAGE_HTML: ${{ steps.coverageComment.outputs.coverageHtml }} | |
| run: | | |
| python3 - <<'PYEOF' | |
| import os | |
| begin, end = "<!-- Pytest Coverage Comment:Begin -->", "<!-- Pytest Coverage Comment:End -->" | |
| with open("README.md") as f: | |
| content = f.read() | |
| start = content.index(begin) + len(begin) | |
| stop = content.index(end) | |
| content = content[:start] + "\n" + os.environ["COVERAGE_HTML"] + "\n" + content[stop:] | |
| with open("README.md", "w") as f: | |
| f.write(content) | |
| PYEOF |
🧰 Tools
🪛 zizmor (1.26.1)
[info] 49-49: 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/ci.yml around lines 46 - 50, The README update step in the
ci workflow is vulnerable because `coverageComment.outputs.coverageHtml` is
interpolated directly into the `run` script, so fix `Update README with Coverage
Html` by passing that output through `env:` and consuming it as a normal shell
variable inside the script instead of `${{ }}` expansion. Keep the `sed`-based
replacement logic in the same workflow step but refactor it so the untrusted
coverage HTML is handled as data, not template text, and verify the change
around `coverageComment` and the README update command.
Source: Linters/SAST tools
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 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/pr-checks.yml:
- Line 17: Pin the third-party GitHub Actions used in the workflow by replacing
the mutable tags in the checkout, setup-python, and pytest coverage comment
steps with their corresponding commit SHAs; update the steps referencing
actions/checkout, actions/setup-python, and MishaKav/pytest-coverage-comment so
CI uses fixed revisions instead of version tags.
- Around line 3-6: The workflow trigger in pr-checks.yml is missing a
concurrency block, so repeated pushes to the same pull request can start
overlapping runs. Add a workflow-level concurrency group tied to the pull
request using the existing pull_request trigger context, and enable
cancel-in-progress so older runs are stopped when a new push arrives. Keep the
change alongside the current on: pull_request configuration so the pr-checks
workflow is deduplicated correctly.
- Around line 16-19: The Checkout Code step in the workflow should disable
persisted git credentials because this job only reads the repository and never
pushes. Update the actions/checkout usage to include persist-credentials set to
false, matching the approach used in update-badge.yml and keeping the checkout
configuration consistent.
- Around line 11-13: The coverage comment step is running under a fork-safe
pull_request context, so the GITHUB_TOKEN only has read access and
MishaKav/pytest-coverage-comment cannot update the PR. Adjust the workflow in
pr-checks.yml by changing the trigger/job context to one that can write comments
for external PRs, such as using pull_request_target with appropriate safeguards
or otherwise enabling write tokens for forked runs, and verify the permissions
for the coverage-comment job still allow pull-requests: write when the action
runs.
In @.github/workflows/update-badge.yml:
- Line 13: The workflow uses mutable action tags that should be pinned to commit
SHAs for safety. Update the referenced uses entries in update-badge.yml for
actions/checkout, actions/setup-python, MishaKav/pytest-coverage-comment, and
stefanzweifel/git-auto-commit-action to fixed commit SHAs instead of version
tags, matching the same hardening used in pr-checks.yml. Keep the job behavior
unchanged while replacing each tag with its pinned digest.
- Around line 6-7: The workflow-level contents: write permission is too broad;
move it from the top-level workflow permissions into the specific job that
performs the badge update commit. Update the update-badge workflow so only the
relevant job has write access, keeping the rest of the jobs at the default
least-privilege scope.
- Around line 2-4: The update-badge workflow can run multiple overlapping
instances on rapid pushes to main, which can cause git-auto-commit-action to
race and fail. Add a workflow-level concurrency setting to the update-badge job
so only one run for the same branch can execute at a time, and make sure it uses
a stable group keyed by the workflow name or ref with cancel-in-progress
enabled.
- Around line 42-44: The Update README step in the workflow is interpolating the
raw `steps.coverage.outputs.coverageHtml` directly inside the shell `sed`
command, which should be removed from the script text. Move that output into an
`env` variable for the step, then have the `run:` block read from the
environment when updating `README.md`. Keep the change localized to the Update
README step and preserve the existing `coverageHtml`/README replacement behavior
without shell interpolation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: fab31199-8af5-421c-a3fc-5ce99dd487fd
📒 Files selected for processing (3)
.github/workflows/pr-checks.yml.github/workflows/update-badge.ymlrequirements-test.txt
💤 Files with no reviewable changes (1)
- requirements-test.txt
| on: | ||
| pull_request: | ||
| branches: | ||
| - main |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win
Add a concurrency group.
Without a concurrency block, multiple pushes to the same PR queue redundant, overlapping test runs, wasting CI minutes and potentially producing out-of-order coverage comments.
♻️ Proposed addition
on:
pull_request:
branches:
- main
+
+concurrency:
+ group: pr-checks-${{ github.ref }}
+ cancel-in-progress: true📝 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.
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| concurrency: | |
| group: pr-checks-${{ github.ref }} | |
| cancel-in-progress: true |
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 3-6: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting
(concurrency-limits)
🤖 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/pr-checks.yml around lines 3 - 6, The workflow trigger in
pr-checks.yml is missing a concurrency block, so repeated pushes to the same
pull request can start overlapping runs. Add a workflow-level concurrency group
tied to the pull request using the existing pull_request trigger context, and
enable cancel-in-progress so older runs are stopped when a new push arrives.
Keep the change alongside the current on: pull_request configuration so the
pr-checks workflow is deduplicated correctly.
Source: Linters/SAST tools
| permissions: | ||
| contents: read | ||
| pull-requests: write |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
Does GitHub restrict GITHUB_TOKEN to read-only for pull_request workflows from forked repositories even when permissions: pull-requests: write is set?
💡 Result:
Yes, GitHub restricts the GITHUB_TOKEN to read-only permissions for workflows triggered by pull requests from forked repositories by default, regardless of any write permissions explicitly set in the workflow YAML file [1][2][3]. This restriction is a security measure designed to prevent untrusted code (which controls the workflow file in the pull request) from gaining write access to the base repository [3]. When a pull request originates from a fork, any write permissions defined in the workflow are automatically adjusted to read-only [1][2][4]. There are two primary ways to bypass this restriction: 1. Repository Settings: An administrator can modify the repository's GitHub Actions settings to enable the option "Send write tokens to workflows from pull requests" [1][2][4]. This allows write tokens to be sent to workflows triggered by forked pull requests [1]. 2. Use pull_request_target: If the workflow is changed to use the pull_request_target event instead of the pull_request event, it will run with the base repository's context and permissions [2][3]. Because pull_request_target workflows execute code from the base repository's default branch rather than the untrusted fork, they are granted a read/write GITHUB_TOKEN and access to secrets [3]. Note that using pull_request_target requires careful security practices to prevent malicious code injection [3].
Citations:
- 1: https://docs.github.com/en/enterprise-server@3.13/actions/security-guides/automatic-token-authentication
- 2: Clarify Permissions Calculation for Workflow Jobs in Documentation github/docs#33566
- 3: https://docs.github.com/en/actions/reference/security/securely-using-pull_request_target
- 4: Clarify
How the permissions are calculated for a workflow jobgithub/docs#32398
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file=".github/workflows/pr-checks.yml"
echo "=== file exists ==="
test -f "$file" && echo yes
echo "=== relevant lines ==="
nl -ba "$file" | sed -n '1,120p'
echo "=== search for workflow trigger and comment step ==="
rg -n "pull_request|pull_request_target|MishaKav/pytest-coverage-comment|permissions:|pull-requests: write|contents: read" "$file"Repository: StabilityNexus/MiniChain
Length of output: 249
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file=".github/workflows/pr-checks.yml"
echo "=== file ==="
sed -n '1,120p' "$file"
echo "=== matches ==="
rg -n "pull_request|pull_request_target|MishaKav/pytest-coverage-comment|permissions:|pull-requests: write|contents: read" "$file"Repository: StabilityNexus/MiniChain
Length of output: 1331
Fork PRs won’t be able to post this comment
Lines 11-13, 38: pull-requests: write is reduced to read-only on pull_request runs from forks, so MishaKav/pytest-coverage-comment won’t update coverage comments for external contributors unless write tokens are enabled for fork PRs or the job moves to pull_request_target.
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 13-13: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment
(undocumented-permissions)
🤖 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/pr-checks.yml around lines 11 - 13, The coverage comment
step is running under a fork-safe pull_request context, so the GITHUB_TOKEN only
has read access and MishaKav/pytest-coverage-comment cannot update the PR.
Adjust the workflow in pr-checks.yml by changing the trigger/job context to one
that can write comments for external PRs, such as using pull_request_target with
appropriate safeguards or otherwise enabling write tokens for forked runs, and
verify the permissions for the coverage-comment job still allow pull-requests:
write when the action runs.
| - name: Checkout Code | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win
Set persist-credentials: false on checkout.
This job never pushes, yet the default checkout leaves the GITHUB_TOKEN persisted in the local git config (flagged by zizmor as artipacked). The sibling workflow update-badge.yml already disables this at line 15 — apply the same here for consistency and reduced credential-exposure risk.
🔒️ Proposed fix
- name: Checkout Code
uses: actions/checkout@v4
with:
+ persist-credentials: false
fetch-depth: 0📝 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.
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| fetch-depth: 0 |
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 16-19: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 17-17: 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/pr-checks.yml around lines 16 - 19, The Checkout Code step
in the workflow should disable persisted git credentials because this job only
reads the repository and never pushes. Update the actions/checkout usage to
include persist-credentials set to false, matching the approach used in
update-badge.yml and keeping the checkout configuration consistent.
Source: Linters/SAST tools
|
|
||
| steps: | ||
| - name: Checkout Code | ||
| uses: actions/checkout@v4 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win
Pin third-party/GitHub actions to a commit SHA.
zizmor flags actions/checkout@v4, actions/setup-python@v5, and MishaKav/pytest-coverage-comment@v1 as unpinned. Tags are mutable; pinning to a SHA prevents a compromised/retagged release from silently running in CI.
Also applies to: 22-22, 38-38
🧰 Tools
🪛 zizmor (1.26.1)
[error] 17-17: 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/pr-checks.yml at line 17, Pin the third-party GitHub
Actions used in the workflow by replacing the mutable tags in the checkout,
setup-python, and pytest coverage comment steps with their corresponding commit
SHAs; update the steps referencing actions/checkout, actions/setup-python, and
MishaKav/pytest-coverage-comment so CI uses fixed revisions instead of version
tags.
Source: Linters/SAST tools
| on: | ||
| push: | ||
| branches: [main] |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win
Add a concurrency group.
Rapid successive pushes to main can trigger overlapping runs of this workflow; two concurrent git-auto-commit-action executions racing to commit/push README changes can produce conflicting commits or push failures.
♻️ Proposed addition
on:
push:
branches: [main]
+
+concurrency:
+ group: update-badge-${{ github.ref }}
+ cancel-in-progress: false📝 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.
| on: | |
| push: | |
| branches: [main] | |
| on: | |
| push: | |
| branches: [main] | |
| concurrency: | |
| group: update-badge-${{ github.ref }} | |
| cancel-in-progress: false |
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 2-4: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting
(concurrency-limits)
🤖 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/update-badge.yml around lines 2 - 4, The update-badge
workflow can run multiple overlapping instances on rapid pushes to main, which
can cause git-auto-commit-action to race and fail. Add a workflow-level
concurrency setting to the update-badge job so only one run for the same branch
can execute at a time, and make sure it uses a stable group keyed by the
workflow name or ref with cancel-in-progress enabled.
Source: Linters/SAST tools
| permissions: | ||
| contents: write |
There was a problem hiding this comment.
🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win
Scope contents: write to the job, not the workflow.
Workflow-level permissions apply to every job in the file; scoping to the job that actually needs to commit follows least privilege and is flagged by zizmor as excessive-permissions.
🔒️ Proposed fix
-permissions:
- contents: write
-
jobs:
update-badge:
runs-on: ubuntu-latest
+ permissions:
+ contents: write
steps:🧰 Tools
🪛 zizmor (1.26.1)
[error] 7-7: overly broad permissions (excessive-permissions): contents: write is overly broad at the workflow level
(excessive-permissions)
[warning] 7-7: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment
(undocumented-permissions)
🤖 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/update-badge.yml around lines 6 - 7, The workflow-level
contents: write permission is too broad; move it from the top-level workflow
permissions into the specific job that performs the badge update commit. Update
the update-badge workflow so only the relevant job has write access, keeping the
rest of the jobs at the default least-privilege scope.
Source: Linters/SAST tools
| update-badge: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win
Pin actions to a commit SHA.
Same concern as in pr-checks.yml: actions/checkout@v4, actions/setup-python@v5, MishaKav/pytest-coverage-comment@v1, and stefanzweifel/git-auto-commit-action@v5 are all unpinned tags per zizmor, allowing a retagged/compromised release to run silently in a job with write access to the repo.
Also applies to: 19-19, 36-36, 47-47
🧰 Tools
🪛 zizmor (1.26.1)
[error] 13-13: 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/update-badge.yml at line 13, The workflow uses mutable
action tags that should be pinned to commit SHAs for safety. Update the
referenced uses entries in update-badge.yml for actions/checkout,
actions/setup-python, MishaKav/pytest-coverage-comment, and
stefanzweifel/git-auto-commit-action to fixed commit SHAs instead of version
tags, matching the same hardening used in pr-checks.yml. Keep the job behavior
unchanged while replacing each tag with its pinned digest.
Source: Linters/SAST tools
| - name: Update README | ||
| run: | | ||
| sed -i '/<!-- Pytest Coverage Comment:Begin -->/,/<!-- Pytest Coverage Comment:End -->/c\<!-- Pytest Coverage Comment:Begin -->\n\${{ steps.coverage.outputs.coverageHtml }}\n<!-- Pytest Coverage Comment:End -->' ./README.md |
There was a problem hiding this comment.
🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== update-badge workflow excerpt ==\n'
nl -ba .github/workflows/update-badge.yml | sed -n '1,140p'
printf '\n== search for coverageHtml definition/usages ==\n'
rg -n "coverageHtml|coverageHtml" .github/workflows .github -SRepository: StabilityNexus/MiniChain
Length of output: 239
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== update-badge workflow excerpt ==\n'
cat -n .github/workflows/update-badge.yml | sed -n '1,160p'
printf '\n== search for coverageHtml definition/usages ==\n'
rg -n "coverageHtml" .github/workflows .github -SRepository: StabilityNexus/MiniChain
Length of output: 2602
🌐 Web query:
MishaKav pytest-coverage-comment coverageHtml output documentation sanitized raw HTML
💡 Result:
The pytest-coverage-comment GitHub Action by MishaKav provides a coverageHtml output, which is an HTML string containing the full coverage report with clickable links to uncovered lines [1][2]. Regarding the handling of this output as raw HTML: 1. HTML Sanitization: The coverageHtml output contains raw HTML elements (such as links and table structures). If you intend to use this output in contexts that require sanitized or safe HTML—such as displaying it in a GitHub Actions job summary—you generally do not need to sanitize it yourself if you are using standard tools like actions/github-script, which can handle raw HTML strings correctly [3]. 2. Displaying Raw HTML: If you want to include this HTML in a GitHub workflow summary, you can use the actions/github-script tool to write the raw output directly to the job summary [3]. The recommended approach is: - name: Add Summary uses: actions/github-script@v6 with: script: | core.summary.addRaw('${{ steps.coverageComment.outputs.coverageHtml }}').write 3. Troubleshooting Empty Output: If you encounter an empty coverageHtml output, ensure you are using a recent version of the action (v1.1.57 or later), as a known issue regarding empty HTML output when using XML coverage files was resolved in that version [4][5]. Additionally, ensure your pytest command generates the appropriate report files (e.g., --cov-report term-missing) to provide the necessary data for the action to parse [3]. The action also provides options like remove-links-to-files and remove-links-to-lines if you prefer a simpler text-based representation over the default HTML links [2].
Citations:
- 1: https://github.com/marketplace/actions/pytest-coverage-comment
- 2: https://github.com/MishaKav/pytest-coverage-comment?search=1
- 3: Error: Error on generating summary report. Cannot read properties of undefined (reading 'testsuite') MishaKav/pytest-coverage-comment#90
- 4: coverageHtml is empty MishaKav/pytest-coverage-comment#204
- 5: https://github.com/MishaKav/pytest-coverage-comment/blob/main/CHANGELOG.md
🌐 Web query:
GitHub Actions escape ${{ in run block backslash expression interpolation
💡 Result:
In GitHub Actions, there is no direct mechanism to "escape" the ${{ sequence within a run block to prevent it from being interpreted as an expression [1][2]. The ${{ }} syntax is processed by the GitHub Actions runner before the shell executes your script [3][2]. Security Best Practice Because ${{ }} is evaluated as a macro before your code runs, attempting to use it for data can lead to serious security vulnerabilities, such as shell injection [3][4][2]. The recommended and secure way to handle data that contains ${{ or other sensitive characters is to avoid interpolating it directly into the run script [4][2]. Instead, you should: 1. Assign the value to an environment variable in the env block of the step [4][2]. 2. Reference that environment variable in your shell script using standard shell syntax (e.g., $MY_VAR) [4][2]. Example of the secure approach: jobs: example-job: runs-on: ubuntu-latest steps: - name: Use data safely env: # Assign the potentially problematic value to an environment variable UNTRUSTED_INPUT: ${{ github.event.pull_request.title }} run: | # Use the environment variable; the shell treats this as data, not code echo "The PR title is: $UNTRUSTED_INPUT" By using this approach, the GitHub Actions evaluator treats the ${{ }} block as a single unit during environment variable assignment, and the shell later treats the variable content strictly as data, effectively neutralizing the risk of code injection [4][2].
Citations:
- 1: https://github.com/orgs/community/discussions/26621
- 2: https://orbisappsec.com/blog/github-actions-shell-injection-how-context-variables-can-compromise-your-cicd-pipeline
- 3: https://github.com/github/docs/blob/main/content/actions/concepts/security/script-injections.md
- 4: https://github.blog/security/supply-chain-security/four-tips-to-keep-your-github-actions-workflows-secure/
Move coverageHtml out of the run: script
steps.coverage.outputs.coverageHtml is raw HTML and is interpolated directly into the sed command here. That keeps untrusted content in shell text and can turn report content into command execution in a job with contents: write. Pass it through an env variable and write the README from there instead.
🧰 Tools
🪛 zizmor (1.26.1)
[info] 44-44: 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/update-badge.yml around lines 42 - 44, The Update README
step in the workflow is interpolating the raw
`steps.coverage.outputs.coverageHtml` directly inside the shell `sed` command,
which should be removed from the script text. Move that output into an `env`
variable for the step, then have the `run:` block read from the environment when
updating `README.md`. Keep the change localized to the Update README step and
preserve the existing `coverageHtml`/README replacement behavior without shell
interpolation.
Source: Linters/SAST tools
Addressed Issues:
This pr adds ci after pushing also it adds a badge to readme for pytest coverage
Screenshots/Recordings:
Additional Notes:
AI Usage Disclosure:
We encourage contributors to use AI tools responsibly when creating Pull Requests. While AI can be a valuable aid, it is essential to ensure that your contributions meet the task requirements, build successfully, include relevant tests, and pass all linters. Submissions that do not meet these standards may be closed without warning to maintain the quality and integrity of the project. Please take the time to understand the changes you are proposing and their impact. AI slop is strongly discouraged and may lead to banning and blocking. Do not spam our repos with AI slop.
Check one of the checkboxes below:
I have used the following AI models and tools: TODO
Checklist
Summary by CodeRabbit