Skip to content

SP-4167: Improve settings file loading#209

Merged
Alex-1089 merged 35 commits into
mainfrom
feat/alex/SP-4167-improve-settings-file-load
Jul 7, 2026
Merged

SP-4167: Improve settings file loading#209
Alex-1089 merged 35 commits into
mainfrom
feat/alex/SP-4167-improve-settings-file-load

Conversation

@Alex-1089

@Alex-1089 Alex-1089 commented May 22, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Added --scan-root (-scr) across scan commands to target subpaths safely, restrict traversal, and validate resolved paths stay within the chosen root.
    • Settings discovery now uses the scan root first, then an explicit target, then the current working directory.
    • Improved HTTP resilience by honoring Retry-After for transient 429/503 responses.
  • Tests
    • Added coverage for filter_path-style folder scoping, settings-file discovery, dependency-scan scoping, and retry/backoff behavior.
  • Chores
    • Updated CI/workflow action versions and adjusted container test phases.
  • Documentation
    • Updated CHANGELOG.md and bumped the package version for the release.

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds --scan-root path resolution for scan and fingerprint commands, changes scanoss.json discovery order, restricts scanning to subtrees, adds file-id overrides, updates retry handling for 429/503 responses, and refreshes release metadata and CI workflow action versions.

Changes

Scan Root Feature and Settings/Filtering Refactor

Layer / File(s) Summary
Version bump and changelog
CHANGELOG.md, src/scanoss/__init__.py
Version and changelog entries are updated for the 1.54.0 release.
Settings discovery
src/scanoss/scanoss_settings.py, tests/test_scanoss_settings.py
load_json_file() now selects scanoss.json from scan-root-aware candidates and the tests cover scan-root, CWD, file-parent, and empty-result cases.
Subtree filtering and scan targeting
src/scanoss/file_filters.py, src/scanoss/scanner.py, tests/test_file_filters.py, tests/test_scanoss_settings.py, tests/cli-test.py
filter_path is threaded through folder filtering and scanner entry points, file_id is threaded through file scanning and WFP generation, and tests cover subtree selection behavior plus dependency-scope routing.
CLI scan-root dispatch
src/scanoss/cli.py
--scan-root is added to scan, fingerprint, dependency, folder-scan, and folder-hash commands; the handlers validate resolved targets, prevent escape from the scan root, and dispatch scanner calls with the derived scan path.
Retry-after handling
src/scanoss/scanossapi.py, tests/scanossapi-test.py
ScanossApi.scan() now treats 429 and 503 as transient, parses retry-after hints from headers or JSON, and the tests cover parsing and retry behavior.

Scan Root Feature and Settings/Filtering Refactor

Layer / File(s) Summary
Version bump and changelog
CHANGELOG.md, src/scanoss/__init__.py
Version and changelog entries are updated for the 1.54.0 release.
Settings discovery
src/scanoss/scanoss_settings.py, tests/test_scanoss_settings.py
load_json_file() now selects scanoss.json from scan-root-aware candidates and the tests cover scan-root, CWD, file-parent, and empty-result cases.
Subtree filtering and scan targeting
src/scanoss/file_filters.py, src/scanoss/scanner.py, tests/test_file_filters.py, tests/test_scanoss_settings.py, tests/cli-test.py
filter_path is threaded through folder filtering and scanner entry points, file_id is threaded through file scanning and WFP generation, and tests cover subtree selection behavior plus dependency-scope routing.
CLI scan-root dispatch
src/scanoss/cli.py
--scan-root is added to scan, fingerprint, dependency, folder-scan, and folder-hash commands; the handlers validate resolved targets, prevent escape from the scan root, and dispatch scanner calls with the derived scan path.
Retry-after handling
src/scanoss/scanossapi.py, tests/scanossapi-test.py
ScanossApi.scan() now treats 429 and 503 as transient, parses retry-after hints from headers or JSON, and the tests cover parsing and retry behavior.

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

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Validator as validate_scan_root
  participant Settings as ScanossSettings.load_json_file
  participant Scanner
  participant Filters as FileFilters.get_filtered_files_from_folder

  CLI->>Validator: validate --scan-root and target path
  Validator->>Settings: resolve scanoss.json candidate
  CLI->>Scanner: scan/wfp with filter_path or file_id
  Scanner->>Filters: get_filtered_files_from_folder(scan_dir, filter_path)
  Filters-->>Scanner: filtered files
  Scanner-->>CLI: scan or fingerprint result
Loading

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: eeisegn

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is relevant and concise, though it only covers part of the broader scan-root and CLI changes.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/alex/SP-4167-improve-settings-file-load

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.

@github-actions

Copy link
Copy Markdown

SCANOSS SCAN Completed 🚀

  • Detected components: 2
  • Undeclared components: 0
  • Declared components: 2
  • Detected files: 111
  • Detected files undeclared: 0
  • Detected files declared: 111
  • Licenses detected: 1
  • Licenses detected with copyleft: 0
  • Policies: ✅ 1 pass (1 total)

View more details on SCANOSS Action Summary

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

🧹 Nitpick comments (1)
tests/test_file_filters.py (1)

344-373: ⚡ Quick win

Add a filter_path='.' regression test.

This suite should include the root-subtree case ('.') to lock down behavior used by --scan-root scans.

🤖 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 `@tests/test_file_filters.py` around lines 344 - 373, Add a regression test
that calls self.file_filters.get_filtered_files_from_folder(self.test_dir, '.')
to ensure filter_path='.' returns files from the repository root subtree; use
self._create to set up files (e.g. files at root and in subfolders) and assert
the returned list matches the expected sorted set (use same conventions as
existing tests like test_filter_path_none_returns_all and
test_filter_path_allows_nested_subdir), e.g., create ['a.c', 'sub/b.c'] and
assert '.' returns ['a.c', 'sub/b.c'] (or sorted equivalent) to lock down
--scan-root behavior.
🤖 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 `@src/scanoss/cli.py`:
- Around line 1741-1766: The code forwards args.scan_dir verbatim to
scanner.scan_folder_with_options (filter_path) and
scanner.scan_file_with_options (file_id), which can cause mismatches for inputs
like "./sub/file.c" or "sub/../file.c"; normalize the path before passing it.
Compute a normalized target: if scan_root is provided, derive a relative,
normalized path from scan_root to effective_path (e.g.,
os.path.relpath(effective_path, scan_root) then os.path.normpath), otherwise use
os.path.normpath(args.scan_dir); pass that normalized value as filter_path to
scan_folder_with_options and as file_id to scan_file_with_options instead of the
raw args.scan_dir.

In `@src/scanoss/file_filters.py`:
- Around line 353-355: The filter logic mishandles '.' and path-separator
differences; normalize filter_path with os.path.normpath and os.path.normcase,
treat '.' or empty result as "no filter" (skip filtering), and then filter files
by comparing each file's normalized/normcased path to the normalized filter
using equality or startswith(normalized + os.sep); update the block that sets
normalized and filters files (variables filter_path, normalized, files) to use
os.path.normpath/os.path.normcase and the special-case for '.'/'' so separators
and platforms are handled correctly.

In `@src/scanoss/scanoss_settings.py`:
- Line 27: Remove the unused getcwd import to fix the F401 lint error: edit the
import statement that currently reads "from os import getcwd" and either delete
it or replace it with only the actually used os imports in this module so no
unused symbol (getcwd) remains referenced in scanoss_settings.py.

---

Nitpick comments:
In `@tests/test_file_filters.py`:
- Around line 344-373: Add a regression test that calls
self.file_filters.get_filtered_files_from_folder(self.test_dir, '.') to ensure
filter_path='.' returns files from the repository root subtree; use self._create
to set up files (e.g. files at root and in subfolders) and assert the returned
list matches the expected sorted set (use same conventions as existing tests
like test_filter_path_none_returns_all and
test_filter_path_allows_nested_subdir), e.g., create ['a.c', 'sub/b.c'] and
assert '.' returns ['a.c', 'sub/b.c'] (or sorted equivalent) to lock down
--scan-root behavior.
🪄 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: 28e7c9e0-1958-4b79-a940-323435297e92

📥 Commits

Reviewing files that changed from the base of the PR and between d24f64a and 3d32828.

📒 Files selected for processing (8)
  • CHANGELOG.md
  • src/scanoss/__init__.py
  • src/scanoss/cli.py
  • src/scanoss/file_filters.py
  • src/scanoss/scanner.py
  • src/scanoss/scanoss_settings.py
  • tests/test_file_filters.py
  • tests/test_scanoss_settings.py

Comment thread src/scanoss/cli.py
Comment thread src/scanoss/file_filters.py Outdated
Comment thread src/scanoss/scanoss_settings.py Outdated
@github-actions

Copy link
Copy Markdown

SCANOSS SCAN Completed 🚀

  • Detected components: 2
  • Undeclared components: 0
  • Declared components: 2
  • Detected files: 111
  • Detected files undeclared: 0
  • Detected files declared: 111
  • Licenses detected: 1
  • Licenses detected with copyleft: 0
  • Policies: ✅ 1 pass (1 total)

View more details on SCANOSS Action Summary

@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: 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/container-local-test.yml:
- Line 24: Replace all tag-pinned GitHub Action references (e.g., the literal
string "uses: actions/checkout@v6" and the other "uses: ...@v4" / "...@v7"
entries) with the corresponding action pinned to a full commit SHA; locate each
"uses:" line in the workflow (the ones ending with `@v6`, `@v4`, `@v7`) and update
them to the full immutable commit SHA from the upstream action repository
release you intend to use (copy the commit SHA from the action's GitHub
tags/releases and substitute it in place of the tag).

In @.github/workflows/container-publish-ghcr.yml:
- Line 27: Pin every GitHub Action reference in the workflow to an immutable
commit SHA instead of mutable major tags: replace actions/checkout@v6,
actions/setup-python@v6, docker/setup-qemu-action@v4,
docker/setup-buildx-action@v4, docker/metadata-action@v6,
docker/build-push-action@v7 (and the other listed uses entries) with their
corresponding full commit SHAs retrieved from each action's repo, and ensure the
already-commented pinned SHA for docker/setup-buildx-action is applied; update
each uses: line to the exact "owner/repo@<full-commit-sha>" form so the workflow
is deterministic.

In @.github/workflows/python-local-test.yml:
- Line 23: Replace the mutable tag "actions/checkout@v6" with the corresponding
immutable commit SHA: locate the actions/checkout repository tag v6 on GitHub,
copy the commit SHA for that tag, and update the workflow's uses line to
"actions/checkout@<COMMIT_SHA>" so the workflow references the exact commit
instead of the moving tag; ensure you replace the value in the uses: entry that
currently reads actions/checkout@v6.

In @.github/workflows/python-publish-pypi.yml:
- Line 17: The workflow uses floating action refs (actions/checkout@v6,
actions/setup-python@v6, pypa/gh-action-pypi-publish@release/v1,
softprops/action-gh-release@v3, nick-fields/retry@v4) which must be pinned to
immutable commit SHAs; update each uses: entry to reference the corresponding
full 40-character commit SHA for the specific released tag you want to consume
(replace e.g. actions/checkout@v6 with actions/checkout@<commit-sha>), verifying
the SHA against the action repo release/tag and keeping the tag name in a
comment if helpful.

In @.github/workflows/python-publish-testpypi.yml:
- Line 16: Workflow uses mutable action tags; replace actions/checkout@v6,
actions/setup-python@v6, and pypa/gh-action-pypi-publish@release/v1 with their
corresponding full commit SHAs to pin to immutable revisions: locate the three
usages of actions/checkout@v6, actions/setup-python@v6 (two occurrences), and
pypa/gh-action-pypi-publish@release/v1 in the TestPyPI workflow and replace each
tag with the exact commit SHA from the action repository (ensure you copy the
full 40-character SHA), then verify the workflow file's YAML remains valid and
run the workflow to confirm success.

In @.github/workflows/scanoss.yml:
- Line 23: Replace tag-based action refs with immutable commit SHAs: update the
two uses: entries that reference actions/checkout@v6 and
scanoss/gha-code-scan@v1 to point to their corresponding full commit SHA values
(replace the tag with the specific commit hash) so the workflow pins to exact
revisions; locate the uses lines for "actions/checkout@v6" and
"scanoss/gha-code-scan@v1" in the scanoss.yml and substitute each tag with the
verified commit SHA for that action.

In @.github/workflows/version-tag.yml:
- Around line 19-22: Update the checkout step that uses actions/checkout@v6 to
include persist-credentials: false so the SC_GH_TAG_TOKEN is not stored in the
job git config, and then modify the later git push --tags step to authenticate
explicitly (e.g., use the token from secrets in the push command or configure a
remote with https://<token>`@github.com/`... before pushing) so tag push uses only
the explicit credentials rather than persisted ones; look for the
actions/checkout@v6 step and the job step that runs git push --tags to make
these changes.
- Line 19: The workflow uses floating tags for actions and leaves checkout
credentials implicit: replace uses: actions/checkout@v6 and uses:
actions/setup-python@v6 with their immutable commit SHAs (pin both to specific
commit refs) and explicitly set actions/checkout persist-credentials to false in
the checkout step; then create a dedicated git-auth step that calls
actions/checkout or configures git with token: ${{ secrets.SC_GH_TAG_TOKEN }}
only for the push step (or set persist-credentials true only in that single
push-related checkout), ensuring the token is not written into local git config
for earlier steps.
🪄 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: ffab5bed-492b-45ef-a91a-291fc5b75775

📥 Commits

Reviewing files that changed from the base of the PR and between 2ff8271 and e5d4072.

📒 Files selected for processing (10)
  • .github/workflows/container-local-test.yml
  • .github/workflows/container-publish-ghcr.yml
  • .github/workflows/lint.yml
  • .github/workflows/python-local-test.yml
  • .github/workflows/python-publish-pypi.yml
  • .github/workflows/python-publish-testpypi.yml
  • .github/workflows/scanoss.yml
  • .github/workflows/version-tag.yml
  • src/scanoss/cli.py
  • src/scanoss/scanner.py

steps:
- name: Checkout Repository
uses: actions/checkout@v4
uses: actions/checkout@v6

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/container-local-test.yml"

echo "== File = $FILE =="
if [ ! -f "$FILE" ]; then
  echo "Missing file: $FILE" >&2
  exit 1
fi

echo "== Lines 1-120 =="
nl -ba "$FILE" | sed -n '1,140p'

echo "== Extract uses: entries (with line numbers) =="
nl -ba "$FILE" | rg -n "uses:\s" || true

echo "== Specific requested lines (24,28,41,46,57,68) =="
for L in 24 28 41 46 57 68; do
  echo "-- line $L --"
  nl -ba "$FILE" | sed -n "${L}p"
done

Repository: scanoss/scanoss.py

Length of output: 198


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/container-local-test.yml"

echo "== ls workspace =="
ls -la .github/workflows || true
echo

echo "== sanity check =="
if [ ! -f "$FILE" ]; then
  echo "Missing file: $FILE" >&2
  exit 1
fi
echo "Found: $FILE"
echo

echo "== show first 120 lines (numbered via awk) =="
awk '{printf "%d:%s\n", NR, $0}' "$FILE" | sed -n '1,140p'
echo

echo "== extract all uses: lines (with line numbers) =="
awk '/uses:/{printf "%d:%s\n", NR, $0}' "$FILE"
echo

echo "== print requested lines =="
for L in 24 28 41 46 57 68; do
  echo "-- line $L --"
  sed -n "${L}p" "$FILE" | cat
done

Repository: scanoss/scanoss.py

Length of output: 5234


Pin GitHub Actions uses: references to immutable commit SHAs

These steps are tag-pinned (@v6/@v4/@v7) in .github/workflows/container-local-test.yml (lines 24, 28, 41, 46, 57, 68), which leaves the workflow exposed to upstream tag retargeting. Pin them to full commit SHAs for the same actions.

Suggested hardening pattern
- uses: actions/checkout@v6
+ uses: actions/checkout@<full_commit_sha>

- uses: actions/setup-python@v6
+ uses: actions/setup-python@<full_commit_sha>

- uses: docker/setup-buildx-action@v4
+ uses: docker/setup-buildx-action@<full_commit_sha>

- uses: docker/build-push-action@v7
+ uses: docker/build-push-action@<full_commit_sha>
🧰 Tools
🪛 zizmor (1.25.2)

[error] 24-24: 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/container-local-test.yml at line 24, Replace all
tag-pinned GitHub Action references (e.g., the literal string "uses:
actions/checkout@v6" and the other "uses: ...@v4" / "...@v7" entries) with the
corresponding action pinned to a full commit SHA; locate each "uses:" line in
the workflow (the ones ending with `@v6`, `@v4`, `@v7`) and update them to the full
immutable commit SHA from the upstream action repository release you intend to
use (copy the commit SHA from the action's GitHub tags/releases and substitute
it in place of the tag).

steps:
- name: Checkout Repository
uses: actions/checkout@v4
uses: actions/checkout@v6

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/container-publish-ghcr.yml"
echo "== File = $FILE =="
wc -l "$FILE"

echo
echo "== uses: lines =="
rg -n "^\s*uses:\s*" "$FILE" || true

echo
echo "== Check referenced line ranges (27,31,45,50,63,70,85,92,107,114) =="
python3 - <<'PY'
import itertools, re, pathlib
p=pathlib.Path(".github/workflows/container-publish-ghcr.yml")
lines=p.read_text().splitlines()
targets=[27,31,45,50,63,70,85,92,107,114]
for t in targets:
    i=t-1
    if 0<=i<len(lines):
        print(f"--- line {t} ---")
        for j in range(max(0,i-2), min(len(lines), i+3)):
            mark=">>" if j==i else "  "
            print(f"{mark}{j+1:4d}: {lines[j]}")
PY

Repository: scanoss/scanoss.py

Length of output: 3045


Pin immutable SHA GitHub Actions in this publish workflow.

All uses: refs in .github/workflows/container-publish-ghcr.yml are still on mutable major tags (actions/checkout@v6, actions/setup-python@v6, docker/setup-qemu-action@v4, docker/setup-buildx-action@v4, docker/metadata-action@v6, docker/build-push-action@v7). Pin each to a full commit SHA (the pinned SHA shown for docker/setup-buildx-action is only commented out).
Lines: 27, 31, 45, 50, 63, 70, 85, 92, 107, 114

🧰 Tools
🪛 zizmor (1.25.2)

[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/container-publish-ghcr.yml at line 27, Pin every GitHub
Action reference in the workflow to an immutable commit SHA instead of mutable
major tags: replace actions/checkout@v6, actions/setup-python@v6,
docker/setup-qemu-action@v4, docker/setup-buildx-action@v4,
docker/metadata-action@v6, docker/build-push-action@v7 (and the other listed
uses entries) with their corresponding full commit SHAs retrieved from each
action's repo, and ensure the already-commented pinned SHA for
docker/setup-buildx-action is applied; update each uses: line to the exact
"owner/repo@<full-commit-sha>" form so the workflow is deterministic.

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

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

Pin actions/checkout to an immutable commit SHA
.github/workflows/python-local-test.yml line 23 still uses the mutable tag actions/checkout@v6. Update the uses: value to the corresponding commit SHA.

🧰 Tools
🪛 zizmor (1.25.2)

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

(artipacked)


[error] 23-23: 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/python-local-test.yml at line 23, Replace the mutable tag
"actions/checkout@v6" with the corresponding immutable commit SHA: locate the
actions/checkout repository tag v6 on GitHub, copy the commit SHA for that tag,
and update the workflow's uses line to "actions/checkout@<COMMIT_SHA>" so the
workflow references the exact commit instead of the moving tag; ensure you
replace the value in the uses: entry that currently reads actions/checkout@v6.

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

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

Release workflow actions must be SHA-pinned.

.github/workflows/python-publish-pypi.yml uses non-SHA floating refs in uses: across the publish/release path (not 40-hex commit SHAs): actions/checkout@v6 (17, 82), actions/setup-python@v6 (20, 85), pypa/gh-action-pypi-publish@release/v1 (64), softprops/action-gh-release@v3 (72), nick-fields/retry@v4 (90).

🧰 Tools
🪛 zizmor (1.25.2)

[warning] 17-17: 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/python-publish-pypi.yml at line 17, The workflow uses
floating action refs (actions/checkout@v6, actions/setup-python@v6,
pypa/gh-action-pypi-publish@release/v1, softprops/action-gh-release@v3,
nick-fields/retry@v4) which must be pinned to immutable commit SHAs; update each
uses: entry to reference the corresponding full 40-character commit SHA for the
specific released tag you want to consume (replace e.g. actions/checkout@v6 with
actions/checkout@<commit-sha>), verifying the SHA against the action repo
release/tag and keeping the tag name in a comment if helpful.

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/python-publish-testpypi.yml"
echo "== File: $FILE =="
if [ ! -f "$FILE" ]; then
  echo "Missing file: $FILE"
  exit 1
fi

# Show file with line numbers
nl -ba "$FILE" | sed -n '1,120p'

echo
echo "== All uses: lines =="
rg -n "^\s*uses:\s*" "$FILE" || true

echo
echo "== uses: lines with actions/checkout@ or actions/* around likely lines =="
nl -ba "$FILE" | awk '($2 ~ /uses:/) {print}'

Repository: scanoss/scanoss.py

Length of output: 182


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/python-publish-testpypi.yml"
echo "== File: $FILE =="

if [ ! -f "$FILE" ]; then
  echo "Missing file: $FILE"
  exit 1
fi

echo "== File first 120 lines (with line numbers via cat -n) =="
cat -n "$FILE" | sed -n '1,120p'

echo
echo "== All uses: lines =="
rg -n "^\s*uses:\s*" "$FILE" || true

echo
echo "== uses: lines with actions/checkout@ or other actions/* (context) =="
rg -n "^\s*uses:\s*actions/" "$FILE" || true

echo
echo "== Exact lines 10-25, 60-75 for the originally referenced locations =="
awk 'NR>=10 && NR<=25 {printf "%6d  %s\n", NR, $0} NR>=60 && NR<=75 {printf "%6d  %s\n", NR, $0}' "$FILE"

Repository: scanoss/scanoss.py

Length of output: 5336


Pin GitHub Actions to immutable commit SHAs in TestPyPI workflow (avoid @v*/tags): update actions/checkout@v6 (lines 16, 66), actions/setup-python@v6 (lines 19, 69), and pypa/gh-action-pypi-publish@release/v1 (line 53) to full commit SHAs.

🧰 Tools
🪛 zizmor (1.25.2)

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

(artipacked)


[error] 16-16: 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/python-publish-testpypi.yml at line 16, Workflow uses
mutable action tags; replace actions/checkout@v6, actions/setup-python@v6, and
pypa/gh-action-pypi-publish@release/v1 with their corresponding full commit SHAs
to pin to immutable revisions: locate the three usages of actions/checkout@v6,
actions/setup-python@v6 (two occurrences), and
pypa/gh-action-pypi-publish@release/v1 in the TestPyPI workflow and replace each
tag with the exact commit SHA from the action repository (ensure you copy the
full 40-character SHA), then verify the workflow file's YAML remains valid and
run the workflow to confirm success.

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/scanoss.yml"
if [ ! -f "$FILE" ]; then
  echo "Missing file: $FILE" >&2
  exit 1
fi

nl -ba "$FILE" | sed -n '1,120p'

Repository: scanoss/scanoss.py

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/scanoss.yml"
if [ ! -f "$FILE" ]; then
  echo "Missing file: $FILE" >&2
  exit 1
fi

# Print around the referenced lines (23 and 27)
cat -n "$FILE" | sed -n '15,40p'

Repository: scanoss/scanoss.py

Length of output: 594


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/scanoss.yml"
rg -n '^\s*uses:\s*' "$FILE" || true

Repository: scanoss/scanoss.py

Length of output: 141


Pin checkout and SCANOSS action refs to immutable commit SHAs.

In .github/workflows/scanoss.yml, actions/checkout@v6 (line 23) and scanoss/gha-code-scan@v1 (line 27) are still tag-based; pin both uses: references to full commit SHAs.

🧰 Tools
🪛 zizmor (1.25.2)

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

(artipacked)


[error] 23-23: 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/scanoss.yml at line 23, Replace tag-based action refs with
immutable commit SHAs: update the two uses: entries that reference
actions/checkout@v6 and scanoss/gha-code-scan@v1 to point to their corresponding
full commit SHA values (replace the tag with the specific commit hash) so the
workflow pins to exact revisions; locate the uses lines for
"actions/checkout@v6" and "scanoss/gha-code-scan@v1" in the scanoss.yml and
substitute each tag with the verified commit SHA for that action.

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the workflow file
ls -la .github/workflows/version-tag.yml

# Print relevant sections around the cited lines
nl -ba .github/workflows/version-tag.yml | sed -n '1,120p'

Repository: scanoss/scanoss.py

Length of output: 206


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Workflow file ==="
ls -la .github/workflows/version-tag.yml

echo "=== Lines 1-120 (with numbers via cat -n) ==="
cat -n .github/workflows/version-tag.yml | sed -n '1,120p'

echo "=== Grep for checkout/setup-python and token/persist-credentials ==="
rg -n "uses:\s*(actions/checkout|actions/setup-python)|token:\s*\$\{\{\s*secrets\.|persist-credentials:" .github/workflows/version-tag.yml || true

Repository: scanoss/scanoss.py

Length of output: 1774


🌐 Web query:

actions/checkout persist-credentials default value

💡 Result:

The default value for the persist-credentials input in the actions/checkout GitHub Action is true [1][2][3]. When set to true (the default), the action configures the repository's local Git configuration (.git/config) with the credentials (such as the GITHUB_TOKEN or a provided SSH key) used to perform the checkout [1][3][4]. This allows subsequent steps in the workflow to execute authenticated Git commands using those credentials [1][4]. Because this behavior can potentially expose credentials to other steps or if artifacts are improperly handled, it is a common security best practice to set persist-credentials: false in workflows that do not require the ability to push changes or perform authenticated Git operations [5][6][7].

Citations:


Pin checkout/setup-python to immutable SHAs and explicitly manage checkout credential persistence.

  • actions/checkout@v6 (line 19) and actions/setup-python@v6 (line 24) use floating major tags; pin both to commit SHAs.
  • Checkout passes token: ${{ secrets.SC_GH_TAG_TOKEN }} (line 22) while persist-credentials is left unset; actions/checkout defaults persist-credentials: true, so the token is written into local git config. Since the workflow later runs git push --tags, set persist-credentials explicitly and limit/configure credentials only for the push step.
      - uses: actions/checkout@v6

Also applies to: 24-24

🧰 Tools
🪛 zizmor (1.25.2)

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

(artipacked)


[error] 19-19: 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/version-tag.yml at line 19, The workflow uses floating
tags for actions and leaves checkout credentials implicit: replace uses:
actions/checkout@v6 and uses: actions/setup-python@v6 with their immutable
commit SHAs (pin both to specific commit refs) and explicitly set
actions/checkout persist-credentials to false in the checkout step; then create
a dedicated git-auth step that calls actions/checkout or configures git with
token: ${{ secrets.SC_GH_TAG_TOKEN }} only for the push step (or set
persist-credentials true only in that single push-related checkout), ensuring
the token is not written into local git config for earlier steps.

Comment thread .github/workflows/version-tag.yml
…ersisting credentials in checkout in version-tag workflow.
@github-actions

Copy link
Copy Markdown

SCANOSS SCAN Completed 🚀

  • Detected components: 2
  • Undeclared components: 0
  • Declared components: 2
  • Detected files: 111
  • Detected files undeclared: 0
  • Detected files declared: 111
  • Licenses detected: 1
  • Licenses detected with copyleft: 0
  • Policies: ✅ 1 pass (1 total)

View more details on SCANOSS Action Summary

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

Caution

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

⚠️ Outside diff range comments (1)
src/scanoss/cli.py (1)

1801-1805: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reject --scan-root when --container is used.

This branch returns before validate_scan_root(args) and get_scanoss_settings_from_args(args), so dependencies --container ... --scan-root ... accepts the new flag but ignores it entirely. Please fail fast on that combination, or plumb scan_root/settings into the container path as well.

Suggested guard
     # Workaround to return syft scan results converted to our dependency output format
     if args.container:
+        if args.scan_root:
+            print_stderr('ERROR: --scan-root is only supported with a FILE/DIR target.')
+            sys.exit(1)
         args.scan_loc = args.container
         return container_scan(parser, args, only_interim_results=True)
🤖 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 `@src/scanoss/cli.py` around lines 1801 - 1805, Add a fast-fail guard for the
invalid combination of --container and --scan-root: before you set args.scan_loc
or call container_scan(parser, args, ...), check if args.container and
args.scan_root are both provided and call parser.error(...) (or raise SystemExit
with a clear message) to reject the combination. Modify the branch around
args.container / container_scan in the CLI so the check runs first; reference
the args.container, args.scan_loc assignment, and the container_scan(parser,
args, only_interim_results=True) call when making the change.
🤖 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 `@src/scanoss/cli.py`:
- Around line 1801-1805: Add a fast-fail guard for the invalid combination of
--container and --scan-root: before you set args.scan_loc or call
container_scan(parser, args, ...), check if args.container and args.scan_root
are both provided and call parser.error(...) (or raise SystemExit with a clear
message) to reject the combination. Modify the branch around args.container /
container_scan in the CLI so the check runs first; reference the args.container,
args.scan_loc assignment, and the container_scan(parser, args,
only_interim_results=True) call when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 176b960c-f491-48a8-9329-584f50a7a59a

📥 Commits

Reviewing files that changed from the base of the PR and between e5d4072 and 7e336b3.

📒 Files selected for processing (2)
  • .github/workflows/version-tag.yml
  • src/scanoss/cli.py

@github-actions

Copy link
Copy Markdown

SCANOSS SCAN Completed 🚀

  • Detected components: 2
  • Undeclared components: 0
  • Declared components: 2
  • Detected files: 111
  • Detected files undeclared: 0
  • Detected files declared: 111
  • Licenses detected: 1
  • Licenses detected with copyleft: 0
  • Policies: ✅ 1 pass (1 total)

View more details on SCANOSS Action Summary

@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: 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/python-local-test.yml:
- Around line 113-116: The echo in the if block that checks the variable
`hash_names` is missing its closing double-quote and will cause a Bash parse
error; fix the `echo` line used to report "Error: Folder hash failed to generate
HPFM hashes. Failing." by terminating the string with a closing `"` (and keep
`exit 1` on its own line), so the `if [ "$hash_names" = "" ]; then` ... `fi`
block contains a properly quoted echo followed by `exit 1`.
🪄 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: 984ded59-bce7-42cd-a1e0-13fa4c5e906d

📥 Commits

Reviewing files that changed from the base of the PR and between 7e336b3 and ea6e658.

📒 Files selected for processing (3)
  • .github/workflows/container-local-test.yml
  • .github/workflows/python-local-test.yml
  • src/scanoss/cli.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/scanoss/cli.py

Comment thread .github/workflows/python-local-test.yml
@github-actions

Copy link
Copy Markdown

SCANOSS SCAN Completed 🚀

  • Detected components: 2
  • Undeclared components: 0
  • Declared components: 2
  • Detected files: 111
  • Detected files undeclared: 0
  • Detected files declared: 111
  • Licenses detected: 1
  • Licenses detected with copyleft: 0
  • Policies: ✅ 1 pass (1 total)

View more details on SCANOSS Action Summary

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

SCANOSS SCAN Completed 🚀

  • Detected components: 2
  • Undeclared components: 0
  • Declared components: 2
  • Detected files: 111
  • Detected files undeclared: 0
  • Detected files declared: 111
  • Licenses detected: 1
  • Licenses detected with copyleft: 0
  • Policies: ✅ 1 pass (1 total)

View more details on SCANOSS Action Summary

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

SCANOSS SCAN Completed 🚀

  • Detected components: 2
  • Undeclared components: 0
  • Declared components: 2
  • Detected files: 111
  • Detected files undeclared: 0
  • Detected files declared: 111
  • Licenses detected: 1
  • Licenses detected with copyleft: 0
  • Policies: ✅ 1 pass (1 total)

View more details on SCANOSS Action Summary

@matiasdaloia

Copy link
Copy Markdown
Contributor

Hi @Alex-1089, couple things:

  1. scan --scan-root <root> <subdir> --dependencies looks like it will fingerprint only <subdir>, but dependency scanning still receives the full scan root. That can pull in dependencies from sibling paths and change existing scoped-scan behavior.
  2. The dependencies command used to reject --settings together with --skip-settings-file. With the shared settings helper, that conflict now gets silently accepted.
  3. The CHANGELOG.md has 1.54.0 twice, and it is dated before 1.53.1, so the release history reads out of order.

The first one is the main behavior risk. The other two should be small cleanup fixes.

…ngs and --skip-settings-file conflict check to the shared settings helper. Fixed CHANGELOG.md.
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

SCANOSS SCAN Completed 🚀

  • Detected components: 2
  • Undeclared components: 0
  • Declared components: 2
  • Detected files: 111
  • Detected files undeclared: 0
  • Detected files declared: 111
  • Licenses detected: 1
  • Licenses detected with copyleft: 0
  • Policies: ✅ 1 pass (1 total)

View more details on SCANOSS Action Summary

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

🧹 Nitpick comments (1)
tests/cli-test.py (1)

141-157: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding coverage for the happy-path/scan_root pass-through.

Current tests only cover the conflict-rejection and skip-only branches. Given the docstring's stated goal of preventing silent regressions across multiple commands, consider also asserting that scan_root (or scan_dir fallback) is correctly forwarded into ScanossSettings.load_json_file when skip_settings_file is False, since that's the other half of the contract shown in src/scanoss/cli.py:2967-2989.

🤖 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 `@tests/cli-test.py` around lines 141 - 157, Add a happy-path test for
get_scanoss_settings_from_args in tests/cli-test.py that verifies scan_root is
passed through (and scan_dir fallback if applicable) to
ScanossSettings.load_json_file when skip_settings_file is False. Use the
existing _args helper plus get_scanoss_settings_from_args and assert the
load_json_file call receives the expected scan_root/scan_dir value, since
current coverage only checks the conflict and skip-only branches.
🤖 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.

Nitpick comments:
In `@tests/cli-test.py`:
- Around line 141-157: Add a happy-path test for get_scanoss_settings_from_args
in tests/cli-test.py that verifies scan_root is passed through (and scan_dir
fallback if applicable) to ScanossSettings.load_json_file when
skip_settings_file is False. Use the existing _args helper plus
get_scanoss_settings_from_args and assert the load_json_file call receives the
expected scan_root/scan_dir value, since current coverage only checks the
conflict and skip-only branches.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 533ec479-413d-4f80-aceb-9dd3b080f826

📥 Commits

Reviewing files that changed from the base of the PR and between 7e336b3 and 1c99c28.

📒 Files selected for processing (7)
  • .github/workflows/container-local-test.yml
  • .github/workflows/python-local-test.yml
  • CHANGELOG.md
  • src/scanoss/cli.py
  • src/scanoss/scanner.py
  • tests/cli-test.py
  • tests/test_scanoss_settings.py
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • .github/workflows/python-local-test.yml
  • .github/workflows/container-local-test.yml
  • src/scanoss/scanner.py
  • src/scanoss/cli.py

isasmendiagus and others added 3 commits July 7, 2026 13:46
The gateway's token-bucket rate limiter returns rate-limit rejections as
HTTP 503 (with a Retry-After header and a retry_after JSON body field).
Previously the POST retry loop special-cased 503 and raised immediately,
so a scan under the per-second limit aborted with no backoff.

Treat 503 (and 429) as retryable: back off honouring Retry-After (header
first, then the retry_after body field, then a 5s default), capped at 60s,
respecting the existing retry_limit, and only abort once retries are
exhausted (keeping the original clear error message). Non-rate-limit
errors are unchanged.

Adds a parse_retry_after helper plus unit tests for the parsing and the
503-then-200 retry / retries-exhausted behaviour.
…g every 503

Builds on the SP-4482 retry/Retry-After work. Previously every 503 (and now
429) raised the hardcoded "service limits being exceeded" message, conflating
genuine outages (backend down, gateway circuit breaker) with rate limiting and
misleading users (see SP-4489 / Siemens 2026-06-19).

Now that the gateway returns 429 for rate limits (and reserves 503 for real
unavailability), the client keys off the status code:
- 429  -> rate limit: retry honouring Retry-After, and on exhaustion report
          "service limits/rate limit exceeded" + the real server response body.
- 503  -> transient unavailability: retry honouring Retry-After, and on
          exhaustion report "currently unavailable" + the real server body,
          without claiming a rate limit.

The raised error now surfaces the actual server response instead of discarding
it. All other retry paths (timeout, empty response, other 4xx/5xx) are
unchanged. Verified live against api.scanoss.com: a burst-limited scan now
rides out 429s honouring each Retry-After and completes.

Tests updated to reflect the 429 rate-limit path, per-retry Retry-After, and a
generic 503 that must not be reported as a rate limit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Alex-1089 Alex-1089 requested a review from matiasdaloia July 7, 2026 13:51
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

SCANOSS SCAN Completed 🚀

  • Detected components: 2
  • Undeclared components: 0
  • Declared components: 2
  • Detected files: 110
  • Detected files undeclared: 0
  • Detected files declared: 110
  • Licenses detected: 1
  • Licenses detected with copyleft: 0
  • Policies: ✅ 1 pass (1 total)

View more details on SCANOSS Action Summary

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

🧹 Nitpick comments (2)
src/scanoss/scanossapi.py (2)

56-68: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Docstring overstates the clamp floor.

Docstring states the result is "clamped to [0, maximum]", but negative parsed values fall back to default (line 89), not to 0. If default itself were configured >0 (as it is: DEFAULT_RETRY_AFTER=5), the effective floor is default, not 0.

✏️ Suggested docstring fix
-    neither is available, uses the supplied default. The result is clamped to [0, maximum].
+    neither is available, uses the supplied default. Negative values fall back to the
+    default, and the final result is capped at `maximum`.
🤖 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 `@src/scanoss/scanossapi.py` around lines 56 - 68, The parse_retry_after
docstring overstates the lower bound of the returned delay. Update the
documentation for parse_retry_after to match the actual behavior: negative or
invalid values do not clamp to 0, they fall back to the default retry delay, so
the effective minimum is the default value (unless changed by the caller), while
the maximum still remains capped by maximum.

284-311: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Retry-exhausted 429/503 path skips save_bad_req_wfp.

Both the "no response" branch (lines 276-280) and the generic >= 400 branch (lines 313-318) persist the offending WFP via self.save_bad_req_wfp(...) before raising once retries are exhausted. The new 429/503 exhaustion path (lines 293-303) raises directly without saving the WFP, losing debugging capability for the exact failure class this PR targets (rate-limit/outage exhaustion).

🛡️ Proposed fix
                     if retry > self.retry_limit:  # Exhausted retries, fail surfacing the real response
+                        self.save_bad_req_wfp(scan_files, request_id, scan_id)
                         if rate_limited:
                             raise Exception(
🤖 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 `@src/scanoss/scanossapi.py` around lines 284 - 311, The retry-exhausted
429/503 branch in `SCANOSSAPI` skips persisting the failing WFP, unlike the
no-response and generic error paths. Update the exhausted-retry logic in the
`r.status_code in (...)` block to call `self.save_bad_req_wfp(...)` before
raising, using the same request/WFP context as the other failure branches so the
exact rate-limit/outage case is captured for debugging.
🤖 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.

Nitpick comments:
In `@src/scanoss/scanossapi.py`:
- Around line 56-68: The parse_retry_after docstring overstates the lower bound
of the returned delay. Update the documentation for parse_retry_after to match
the actual behavior: negative or invalid values do not clamp to 0, they fall
back to the default retry delay, so the effective minimum is the default value
(unless changed by the caller), while the maximum still remains capped by
maximum.
- Around line 284-311: The retry-exhausted 429/503 branch in `SCANOSSAPI` skips
persisting the failing WFP, unlike the no-response and generic error paths.
Update the exhausted-retry logic in the `r.status_code in (...)` block to call
`self.save_bad_req_wfp(...)` before raising, using the same request/WFP context
as the other failure branches so the exact rate-limit/outage case is captured
for debugging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b08eab1e-de7e-4642-89e8-f14b359cc8e6

📥 Commits

Reviewing files that changed from the base of the PR and between 1c99c28 and e083689.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • src/scanoss/scanossapi.py
  • tests/scanossapi-test.py
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md

@Alex-1089 Alex-1089 merged commit 3f245bf into main Jul 7, 2026
6 checks passed
@Alex-1089 Alex-1089 deleted the feat/alex/SP-4167-improve-settings-file-load branch July 7, 2026 14:58
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.

4 participants