-
Notifications
You must be signed in to change notification settings - Fork 24
dt-url-markdown #148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dt-url-markdown #148
Conversation
WalkthroughBumps package to 1.31.5; adds Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant U as User
participant CLI as scanoss CLI
participant PV as ProjectViolation
participant S as DependencyTrackService
U->>CLI: run inspect dt project violations --format {json|md|jira_md}
CLI->>PV: initialize generator with (url, project_id, format)
PV->>PV: normalize url (url.strip().rstrip('/'))
PV->>S: request project/violations using normalized url
S-->>PV: return project / violations
alt format == json
PV-->>CLI: emit JSON
else format == md or jira_md
PV->>PV: build summary and details
note right of PV #aef1d8: Append "View project in Dependency Track"\nlink: {url}/projects/{project_id}
PV-->>CLI: emit Markdown (md or jira_md)
end
CLI-->>U: Output
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
SCANOSS SCAN Completed 🚀
View more details on SCANOSS Action Summary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/scanoss/services/dependency_track_service.py (1)
31-48
: Add HTTP client timeouts to avoid hangs and propagate CLI timeoutRequests are issued without a timeout, which can hang indefinitely on network issues. The CLI and policy checker already accept a timeout; thread it into this service and use it in requests.get.
Apply this diff:
class DependencyTrackService(ScanossBase): def __init__( self, api_key: str, url: str, debug: bool = False, trace: bool = False, quiet: bool = False, + timeout: float = 300.0, ): super().__init__(debug=debug, trace=trace, quiet=quiet) if not url: raise ValueError("Error: Dependency Track URL is required") self.url = url.strip().rstrip('/') if not api_key: raise ValueError("Error: Dependency Track API key is required") self.api_key = api_key + self.timeout = timeout @@ try: if params: - response = requests.get(uri, headers=req_headers, params=params) + response = requests.get(uri, headers=req_headers, params=params, timeout=self.timeout) else: - response = requests.get(uri, headers=req_headers) + response = requests.get(uri, headers=req_headers, timeout=self.timeout) response.raise_for_status() # Raises an HTTPError for bad responses return response.json()Follow-up: Update the caller in DependencyTrackProjectViolationPolicyCheck to pass
timeout=self.timeout
(see separate comment in that file).Also applies to: 118-133
🧹 Nitpick comments (3)
src/scanoss/cli.py (1)
801-802
: Use “Jira” casing in help for consistencyMinor terminology nit: Atlassian branding uses “Jira”, not “JIRA”.
Apply:
- help='Output format: json (default), md (Markdown) or jira_md (JIRA Markdown)' + help='Output format: json (default), md (Markdown) or jira_md (Jira Markdown)'CHANGELOG.md (1)
12-16
: Polish phrasing and branding in 1.31.5 entriesUse “Jira Markdown” for consistency with other docs/help.
Apply:
-### Added -- Added jira markdown option for DT -- Added Dependency Track project link to markdown summary +### Added +- Added Jira Markdown option for DT +- Added Dependency Track project link to Markdown summarysrc/scanoss/inspection/dependency_track/project_violation.py (1)
212-229
: Docstring says “either” but implementation requires both timestamps to be ≥ last importThe return condition checks both vulnerability analysis and last occurrence, except for the empty SBOM shortcut. Update the docstring to match actual logic.
Suggested doc tweak:
- “A project is considered updated when both the vulnerability analysis and the metrics’ last occurrence timestamps are greater than or equal to the last BOM import timestamp (with a special-case for empty SBOMs).”
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
CHANGELOG.md
(2 hunks)src/scanoss/__init__.py
(1 hunks)src/scanoss/cli.py
(1 hunks)src/scanoss/inspection/dependency_track/project_violation.py
(7 hunks)src/scanoss/services/dependency_track_service.py
(1 hunks)
🧰 Additional context used
🪛 LanguageTool
CHANGELOG.md
[grammar] ~12-~12: There might be a mistake here.
Context: ...ing changes... ## [1.31.5] - 2025-08-19 ### Added - Added jira markdown option for D...
(QB_NEW_EN)
[grammar] ~13-~13: There might be a mistake here.
Context: ...s... ## [1.31.5] - 2025-08-19 ### Added - Added jira markdown option for DT - Adde...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (9)
src/scanoss/__init__.py (1)
25-25
: Version bump to 1.31.5 — LGTMThe version constant update is correct and aligns with the PR scope.
src/scanoss/services/dependency_track_service.py (1)
44-44
: Normalize base URL by trimming whitespace and trailing slashes — LGTMThis prevents double slashes and stray spaces when composing endpoints.
src/scanoss/cli.py (2)
797-802
: Add jira_md format for DT project-violations — LGTMThe new choice is wired with a clear help string and keeps json as default.
797-802
: jira_md formatter support confirmedThe ‘jira_md’ format is fully supported in the PolicyCheck machinery:
- In src/scanoss/inspection/policy_check.py,
VALID_FORMATS
includes'jira_md'
, and_get_formatter
returns the_jira_markdown
method whenformat_type == 'jira_md'
.- In src/scanoss/inspection/dependency_track/project_violation.py,
DependencyTrackProjectViolationPolicyCheck
implements the required_jira_markdown
renderer alongside its_json
and_markdown
methods, ensuring JIRA Markdown output is generated correctly.No further changes are required.
CHANGELOG.md (2)
12-18
: Confirm release dates ordering for 1.31.5 vs 1.31.41.31.5 is dated 2025-08-19 while 1.31.4 is 2025-08-20, which reads as a newer patch (1.31.5) dated before an older patch. Please verify intended dates and adjust if needed to keep chronological order.
656-656
: Added compare link for 1.31.5 — LGTMThe reference link matches the new tag progression.
src/scanoss/inspection/dependency_track/project_violation.py (3)
46-55
: ResolvedLicenseDict addition — LGTMTypedDict enhances clarity around expected license fields from DT.
235-244
: Robust timestamp coercion — LGTMThe helper safely handles None/str/numeric and logs invalid values; good defensive coding.
375-377
: Violation sorting by type priority — LGTMClear priority mapping and simpler descending sort. Consider adding “SECURITY”, “LICENSE”, “OTHER” constants if this logic is reused elsewhere, but fine as-is.
self.url = url.strip().rstrip('/') if url else None | ||
self.dep_track_service = DependencyTrackService(self.api_key, self.url, debug=debug, trace=trace, quiet=quiet) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Thread CLI timeout into DependencyTrackService
You normalize the URL here and construct the service, but the service currently doesn’t receive the CLI timeout. Pass it through so HTTP calls respect user-provided timeouts.
Apply:
- self.url = url.strip().rstrip('/') if url else None
- self.dep_track_service = DependencyTrackService(self.api_key, self.url, debug=debug, trace=trace, quiet=quiet)
+ self.url = url.strip().rstrip('/') if url else None
+ self.dep_track_service = DependencyTrackService(
+ self.api_key,
+ self.url,
+ timeout=self.timeout,
+ debug=debug,
+ trace=trace,
+ quiet=quiet,
+ )
📝 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.
self.url = url.strip().rstrip('/') if url else None | |
self.dep_track_service = DependencyTrackService(self.api_key, self.url, debug=debug, trace=trace, quiet=quiet) | |
self.url = url.strip().rstrip('/') if url else None | |
self.dep_track_service = DependencyTrackService( | |
self.api_key, | |
self.url, | |
timeout=self.timeout, | |
debug=debug, | |
trace=trace, | |
quiet=quiet, | |
) |
🤖 Prompt for AI Agents
In src/scanoss/inspection/dependency_track/project_violation.py around lines
170-172, you normalize the URL and instantiate DependencyTrackService but don’t
pass the CLI timeout through; update the constructor call to include the timeout
parameter (e.g., timeout=cli_timeout or the variable name used for the CLI
timeout) so the service forwards it to HTTP calls; keep the url normalization
as-is and ensure the timeout variable is defined in scope or passed into this
function before constructing DependencyTrackService.
return { | ||
"details": f'### Dependency Track Project Violations\n{table_generator(headers, rows, c_cols)}\n', | ||
"summary": f'{len(project_violations)} policy violations were found.\n', | ||
"details": f'### Dependency Track Project Violations\n{table_generator(headers, rows, c_cols)}\n\n' | ||
f'View project in Dependency Track [here]({self.url}/projects/{self.project_id}).\n', | ||
"summary": f'{len(project_violations)} policy violations were found.\n' | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix mixed Markdown/Jira markup in details header and project link
Currently, Jira output uses Markdown header/link (“### …” and here), while the empty-results branch uses Jira’s “h3.” header even for Markdown. Harmonize output based on format to avoid malformed rendering in Jira and MD.
Apply:
- return {
- "details": f'### Dependency Track Project Violations\n{table_generator(headers, rows, c_cols)}\n\n'
- f'View project in Dependency Track [here]({self.url}/projects/{self.project_id}).\n',
- "summary": f'{len(project_violations)} policy violations were found.\n'
- }
+ is_jira = (self.format_type == 'jira_md')
+ header = 'h3. Dependency Track Project Violations' if is_jira else '### Dependency Track Project Violations'
+ project_url = f'{self.url}/projects/{self.project_id}' if self.url and self.project_id else ''
+ link = (
+ f'View project in Dependency Track [here|{project_url}].'
+ if is_jira else
+ f'View project in Dependency Track [here]({project_url}).'
+ )
+ return {
+ "details": f'{header}\n{table_generator(headers, rows, c_cols)}\n\n{link}\n',
+ "summary": f'{len(project_violations)} policy violations were found.\n',
+ }
Additionally, mirror the same header logic in the empty-results branch to avoid Jira wiki markup leaking into MD output. For example:
# Replace the hard-coded "h3." in the None-case with:
is_jira = (self.format_type == 'jira_md')
header = 'h3. Dependency Track Project Violations' if is_jira else '### Dependency Track Project Violations'
return {
"details": f"{header}\n\nNo policy violations found.\n",
"summary": "0 policy violations were found.\n",
}
🤖 Prompt for AI Agents
In src/scanoss/inspection/dependency_track/project_violation.py around lines
426-430, the details string mixes Markdown and Jira wiki markup (uses "###" and
[here](...) while other branch uses "h3."), causing malformed rendering; make
output format-aware by detecting is_jira = (self.format_type == 'jira_md') and
then: use header = 'h3. Dependency Track Project Violations' if is_jira else
'### Dependency Track Project Violations', and format the project link as '[View
project|{self.url}/projects/{self.project_id}]' when is_jira else as
'[here]({self.url}/projects/{self.project_id})'; also apply the same header
logic to the empty-results branch so both branches consistently use Jira wiki or
Markdown depending on self.format_type.
SCANOSS SCAN Completed 🚀
View more details on SCANOSS Action Summary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 18
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
src/scanoss/threadeddependencies.py (5)
125-127
: Fix critical threading bug: target callable is being invoked immediately
target=self.scan_dependencies(dep_scope, dep_scope_include, dep_scope_exclude)
calls the function synchronously and passesNone
as the thread target. This blocksrun()
and spawns a no-op thread.Apply:
- self._thread = threading.Thread( - target=self.scan_dependencies(dep_scope, dep_scope_include, dep_scope_exclude), daemon=True - ) + self._thread = threading.Thread( + target=self.scan_dependencies, + args=(dep_scope, dep_scope_include, dep_scope_exclude), + daemon=True, + )
63-65
: Queues are shared across instances; allocate per-instance to avoid cross-talkClass-level
queue.Queue()
defaults are singletons across instances (dataclass won’t fix this because you provided a custom__init__
). This can corrupt results when multiple instances are used.Apply:
@@ - inputs: queue.Queue = queue.Queue() - output: queue.Queue = queue.Queue() + inputs: queue.Queue + output: queue.Queue @@ def __init__( - self._thread = None + self.inputs = queue.Queue() + self.output = queue.Queue() + self._thread: Optional[threading.Thread] = NoneAlso applies to: 76-83
197-198
: Don’t use str.strip() to remove a prefix
strip()
removes any of the characters in the set at both ends, not the exact prefix (can mangle paths). Use slicing (orremoveprefix()
if available).- deps = self.sc_deps.load_from_file(what_to_scan.strip(DEP_FILE_PREFIX)) + # remove exact prefix only + deps = self.sc_deps.load_from_file(what_to_scan[len(DEP_FILE_PREFIX):])
85-93
: responses property returns only the first item; return all or renameDocstring says “Get all responses,” but code returns the first only. Return the list to match semantics. Note: accessing
self.output.queue
is an internal attribute; it’s acceptable post-complete(), but consider a safer accessor later.- responses = list(self.output.queue) - if responses: - for resp in responses: - return resp - return None + responses = list(self.output.queue) + return responses if responses else None
150-183
: Normalize blank include/exclude; simplify conditions; improve readability of the filter lambdaEmpty strings should behave like “not provided,” otherwise you fall into the final
None
path. Also dropdep_scope == ''
checks (typed as Enum).- def filter_dependencies_by_scopes( - self, deps: json, dep_scope: SCOPE = None, dep_scope_include: str = None, dep_scope_exclude: str = None - ) -> json: + def filter_dependencies_by_scopes( + self, + deps: Dict[str, Any], + dep_scope: Optional[SCOPE] = None, + dep_scope_include: Optional[str] = None, + dep_scope_exclude: Optional[str] = None, + ) -> Dict[str, Any]: @@ - include_all = (dep_scope is None or dep_scope == '') and dep_scope_include is None and dep_scope_exclude is None + # Treat blank strings as None + dep_scope_include = (dep_scope_include or '').strip() or None + dep_scope_exclude = (dep_scope_exclude or '').strip() or None + include_all = dep_scope is None and dep_scope_include is None and dep_scope_exclude is None @@ - if (dep_scope is not None and dep_scope != '') and dep_scope_include is None and dep_scope_exclude is None: + if dep_scope is not None and dep_scope_include is None and dep_scope_exclude is None: return self.filter_dependencies( deps, - lambda purl: (dep_scope == SCOPE.PRODUCTION and purl not in DEV_DEPENDENCIES) - or dep_scope == SCOPE.DEVELOPMENT - and purl in DEV_DEPENDENCIES, + lambda scope: ( + (dep_scope == SCOPE.PRODUCTION and scope not in DEV_DEPENDENCIES) + or (dep_scope == SCOPE.DEVELOPMENT and scope in DEV_DEPENDENCIES) + ), ) @@ - exclude = set(dep_scope_exclude.split(',')) if dep_scope_exclude else set() - include = set(dep_scope_include.split(',')) if dep_scope_include else set() + exclude = {s.strip() for s in dep_scope_exclude.split(',')} if dep_scope_exclude else set() + include = {s.strip() for s in dep_scope_include.split(',')} if dep_scope_include else set() @@ - return self.filter_dependencies( - deps, lambda purl: (exclude and purl not in exclude) or (not exclude and purl in include) - ) + return self.filter_dependencies( + deps, lambda scope: (exclude and scope not in exclude) or (not exclude and scope in include) + )
🧹 Nitpick comments (22)
src/scanoss/threadeddependencies.py (6)
25-35
: Satisfy Ruff I001/F401: sort imports and drop unused; add types used belowRuff flagged import order and unused
Optional/Set
. Also you’ll needAny
,Callable
,List
for improved hints below.-import threading -import queue -import json -from enum import Enum -from typing import Dict, Optional, Set -from dataclasses import dataclass +import json +import queue +import threading +from dataclasses import dataclass +from enum import Enum +from typing import Any, Callable, Dict, List, Optional @@ -from .scancodedeps import ScancodeDeps -from .scanossbase import ScanossBase -from .scanossgrpc import ScanossGrpc +from .scancodedeps import ScancodeDeps +from .scanossbase import ScanossBase +from .scanossgrpc import ScanossGrpc
135-149
: Use concrete typing instead of-> json
; minor safety on scope extractionReturn/param types should not be
json
(a module). Tighten typing and guard for missing ‘scope’.- def filter_dependencies(self, deps, filter_dep) -> json: + def filter_dependencies(self, deps: Dict[str, Any], filter_dep: Callable[[Optional[str]], bool]) -> Dict[str, Any]: @@ - file['purls'] = [ - {key: value for key, value in purl.items() if key != 'scope'} - for purl in file['purls'] - if filter_dep(purl.get('scope')) - ] + file['purls'] = [ + {k: v for k, v in purl.items() if k != 'scope'} + for purl in file['purls'] + if filter_dep(purl.get('scope')) + ]
196-210
: Flatten nested else/if (Ruff PLR5501) for readabilityThis reduces indentation and satisfies the linter without changing logic.
- if what_to_scan.startswith(DEP_FILE_PREFIX): # We have a pre-parsed dependency file, load it - deps = self.sc_deps.load_from_file(what_to_scan.strip(DEP_FILE_PREFIX)) - else: # Search the file/folder for dependency files to parse - if not self.sc_deps.run_scan(what_to_scan=what_to_scan): - self._errors = True - else: - deps = self.sc_deps.produce_from_file() + if what_to_scan.startswith(DEP_FILE_PREFIX): # We have a pre-parsed dependency file, load it + deps = self.sc_deps.load_from_file(what_to_scan[len(DEP_FILE_PREFIX):]) + elif not self.sc_deps.run_scan(what_to_scan=what_to_scan): # Search the file/folder for dependency files + self._errors = True + else: + deps = self.sc_deps.produce_from_file()
185-241
: Consider trimming branches in scan_dependencies (Ruff PLR0912) by extracting filtering/loggingNot urgent, but extracting the “filtering + debug prints” into a helper (e.g.,
_apply_scope_filters
) will reduce branching and aid testability.
66-74
: Too many args in init (Ruff PLR0913)Optional: group logging flags into a small config object or a
**kwargs
with validation to get under the limit. Not a blocker.
95-104
: Too many args in run() (Ruff PLR0913)Optional: encapsulate scope filtering into a dataclass (e.g.,
ScopeFilter(include: Optional[str], exclude: Optional[str], scope: Optional[SCOPE])
) and pass a single argument.src/scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py (1)
4-4
: Remove unused import.warnings is imported but never used.
Apply:
-import warnings
src/scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2.py (1)
27-28
: Verify availability of protoc_gen_openapiv2 annotations.Confirm protoc_gen_openapiv2.options.annotations_pb2 is present or provided by a dependency.
Use the same repo checks as above; vendor if necessary.
src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py (1)
27-28
: Verify protoc_gen_openapiv2 annotations presence.Same checks and remediation as noted for scanning/geoprovenance.
src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py (1)
4-4
: Remove unused import.warnings is not used.
Apply:
-import warnings
src/scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2_grpc.py (1)
4-4
: Remove unused import (warnings)Not used in this module.
-import warnings
src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py (2)
4-4
: Unused importwarnings isn’t used.
-import warnings
30-32
: Docstrings say “Cryptography” — should be “Semgrep”Minor copy/paste typo in user-facing docstrings.
- """ - Expose all of the SCANOSS Cryptography RPCs here - """ + """ + Expose all of the SCANOSS Semgrep RPCs here + """Apply in both SemgrepStub and SemgrepServicer.
Also applies to: 53-55
src/scanoss/api/components/v2/scanoss_components_pb2_grpc.py (1)
4-4
: Unused importwarnings can be dropped.
-import warnings
src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py (2)
45-45
: Typo in embedded example JSON keys (“requirement=”/“version=”)In the serialized OpenAPI example, keys contain trailing “=”. This will confuse consumers of generated docs.
Please fix the proto comments/examples and re-generate.
51-51
: Typo in example JSON: source “NDV” → “NVD”User-facing doc string should reference NVD correctly. Fix in proto and re-generate.
src/scanoss/api/common/v2/scanoss_common_pb2_grpc.py (2)
4-4
: Remove unused import
warnings
is imported but not used.-import warnings
11-16
: Avoid relying on grpc private API for version compare
grpc._utilities.first_version_is_lower
is private and may disappear. Optional: fall back topackaging.version
if the import fails instead of hard-failing solely due to the missing private helper.try: - from grpc._utilities import first_version_is_lower - _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) except ImportError: - _version_not_supported = True + try: + from packaging.version import Version as _V + _version_not_supported = _V(GRPC_VERSION) < _V(GRPC_GENERATED_VERSION) + except Exception: + _version_not_supported = Truesrc/scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py (1)
4-4
: Remove unused import
warnings
is unused.-import warnings
src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py (3)
31-32
: Pluralize service docstrings to match class/service name.Use “Vulnerabilities Service Definition” for consistency with the class and package.
- Vulnerability Service Definition + Vulnerabilities Service DefinitionAlso applies to: 79-80, 216-217
9-26
: Make grpc version check resilient to internal API changes.Don’t hard-fail solely because grpc._utilities.first_version_is_lower is unavailable. Fall back to packaging.version when possible.
-try: - from grpc._utilities import first_version_is_lower - _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) -except ImportError: - _version_not_supported = True +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except Exception: + try: + from packaging.version import Version + except Exception: + _version_not_supported = True + else: + _version_not_supported = Version(GRPC_VERSION) < Version(GRPC_GENERATED_VERSION)
181-205
: Guard server.add_registered_method_handlers for broader compatibility.Even with gating, a light guard avoids surprises on environments slightly below the target.
- server.add_registered_method_handlers('scanoss.api.vulnerabilities.v2.Vulnerabilities', rpc_method_handlers) + if hasattr(server, 'add_registered_method_handlers'): + server.add_registered_method_handlers('scanoss.api.vulnerabilities.v2.Vulnerabilities', rpc_method_handlers)Also applies to: 210-210
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (22)
CHANGELOG.md
(2 hunks)src/scanoss/api/common/v2/scanoss_common_pb2.py
(1 hunks)src/scanoss/api/common/v2/scanoss_common_pb2_grpc.py
(1 hunks)src/scanoss/api/components/v2/scanoss_components_pb2.py
(1 hunks)src/scanoss/api/components/v2/scanoss_components_pb2_grpc.py
(7 hunks)src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py
(1 hunks)src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py
(9 hunks)src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py
(1 hunks)src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py
(6 hunks)src/scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2.py
(1 hunks)src/scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2_grpc.py
(6 hunks)src/scanoss/api/licenses/__init__.py
(1 hunks)src/scanoss/api/licenses/v2/__init__.py
(1 hunks)src/scanoss/api/licenses/v2/scanoss_licenses_pb2.py
(1 hunks)src/scanoss/api/licenses/v2/scanoss_licenses_pb2_grpc.py
(1 hunks)src/scanoss/api/scanning/v2/scanoss_scanning_pb2.py
(2 hunks)src/scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py
(5 hunks)src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py
(1 hunks)src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py
(5 hunks)src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py
(1 hunks)src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py
(6 hunks)src/scanoss/threadeddependencies.py
(1 hunks)
✅ Files skipped from review due to trivial changes (4)
- src/scanoss/api/licenses/init.py
- src/scanoss/api/licenses/v2/init.py
- src/scanoss/api/licenses/v2/scanoss_licenses_pb2.py
- src/scanoss/api/licenses/v2/scanoss_licenses_pb2_grpc.py
🧰 Additional context used
🧬 Code graph analysis (1)
src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py (2)
src/scanoss/api/components/v2/scanoss_components_pb2_grpc.py (2)
Echo
(67-72)Echo
(132-156)src/scanoss/api/licenses/v2/scanoss_licenses_pb2_grpc.py (2)
Echo
(72-78)Echo
(170-194)
🪛 GitHub Actions: Build/Test Local Python Package
src/scanoss/api/common/v2/scanoss_common_pb2.py
[error] 25-25: ModuleNotFoundError: No module named 'protoc_gen_openapiv2'
🪛 GitHub Actions: Lint
src/scanoss/threadeddependencies.py
[error] 25-34: Ruff I001: Import block is un-sorted or un-formatted.
[error] 29-29: Ruff F401: 'Optional' imported but unused.
[error] 29-29: Ruff F401: 'Set' imported but unused.
[error] 66-66: Ruff PLR0913: Too many arguments in function definition (6 > 5).
[error] 95-95: Ruff PLR0913: Too many arguments in function definition (6 > 5).
[error] 185-185: Ruff PLR0912: Too many branches (15 > 12).
[error] 198-198: Ruff PLR5501: Use elif
instead of else
then if
, to reduce indentation.
🪛 LanguageTool
CHANGELOG.md
[grammar] ~12-~12: There might be a mistake here.
Context: ...ing changes... ## [1.31.5] - 2025-08-27 ### Added - Added jira markdown option for D...
(QB_NEW_EN)
[grammar] ~13-~13: There might be a mistake here.
Context: ...s... ## [1.31.5] - 2025-08-27 ### Added - Added jira markdown option for DT - Adde...
(QB_NEW_EN)
[grammar] ~14-~14: There might be a mistake here.
Context: ...dded - Added jira markdown option for DT - Added Dependency Track project link to m...
(QB_NEW_EN)
[grammar] ~15-~15: There might be a mistake here.
Context: ...y Track project link to markdown summary - Updated protobuf client definitions - Ad...
(QB_NEW_EN)
[grammar] ~16-~16: There might be a mistake here.
Context: ...ry - Updated protobuf client definitions - Added date field to `scanoss-py comp ver...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (25)
CHANGELOG.md (2)
658-658
: LGTM: compare link for 1.31.5The new compare reference is correct and in chronological order.
12-18
: CHANGELOG.md – Standardize 1.31.5 entries and surface URL normalizationFile: CHANGELOG.md (lines 12–18)
Apply the following diff to match existing style and note that URL normalization shipped:
## [1.31.5] – 2025-08-27 ### Added -- Added jira markdown option for DT -- Added Dependency Track project link to markdown summary +- Added Jira Markdown format for Dependency Track +- Added Dependency Track project link to Markdown summary +- Normalized Dependency Track URLs (trim whitespace and trailing slashes) - Updated protobuf client definitions - Added date field to `scanoss-py comp versions` responsesrc/scanoss/threadeddependencies.py (1)
183-183
: Explicitreturn None
— LGTMClarifies the fallback path and makes intent explicit.
src/scanoss/api/scanning/v2/scanoss_scanning_pb2.py (1)
44-59
: Generated descriptor offsets — no action needed.src/scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py (2)
40-50
: Registered method usage on client/server looks correct._channel.unary_unary(..., _registered_method=True) and server.add_registered_method_handlers(...) are consistent with the version gate.
Also applies to: 88-89
108-123
: Experimental wrapper updates LGTM.Passing _registered_method=True mirrors the stub behavior.
Also applies to: 135-150
src/scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2.py (1)
32-60
: Generated descriptor wiring/offsets — no action needed.src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py (1)
32-66
: Generated descriptor offsets — no action needed.src/scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py (2)
40-55
: Client/server registered-method additions LGTM.Also applies to: 105-106
125-140
: Experimental wrappers updated correctly.Also applies to: 152-167, 179-194
src/scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2_grpc.py (3)
40-55
: Stub methods now register with the channel — good changePassing _registered_method=True aligns with newer grpc interceptors and improves handler resolution.
125-139
: Experimental client wrappers updated to registered methods — goodConsistent with the stub/server wiring; no API break.
Also applies to: 152-166, 179-193
105-105
: Update grpcio dependency to ≥1.73.1The generated gRPC code relies on
add_registered_method_handlers
, which was introduced ingrpcio
v1.73.1. Current constraints (grpcio>1.42.0
) will not guarantee this API is available.Please update the following dependency declarations:
- requirements.txt (around line 5)
- setup.cfg (around line 32)
Suggested diff:
--- requirements.txt - grpcio>1.42.0 + grpcio>=1.73.1 --- setup.cfg - grpcio>1.42.0 + grpcio>=1.73.1Likely an incorrect or invalid review comment.
src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py (1)
32-35
: Dynamic builder/globals wiring — looks correctMatches modern protobuf codegen patterns; no concerns.
Also applies to: 36-51
src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py (1)
40-50
: Registered-method wiring and explicit server registration — goodMatches newer grpc semantics and improves interceptor compatibility.
Confirm repo declares grpcio>=1.73.1 as a dependency (same check script as above).
Also applies to: 88-88, 108-122, 135-149
src/scanoss/api/components/v2/scanoss_components_pb2.py (1)
32-35
: Modern descriptor/globals wiring — goodConsistent with updated generator output; no functional issues spotted.
Also applies to: 36-71
src/scanoss/api/components/v2/scanoss_components_pb2_grpc.py (1)
40-60
: Registered-method stubs/experimental wrappers and explicit server registration — goodImproves interceptor compatibility; no API changes.
Confirm grpcio>=1.73.1 declared in dependencies (same script as above).
Also applies to: 122-122, 142-156, 169-184, 196-210, 223-237
src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py (2)
9-20
: Runtime/version guard and descriptor build pattern look goodThe protobuf runtime check and switch to builder/globals-based descriptor construction are consistent and correct.
Also applies to: 32-35
27-27
: I’ve added a broader search to locate any packaging/config files (including requirements.txt, Pipfile, etc.) and to scan the entire repo for any references toprotoc_gen_openapiv2
. This should clarify where dependencies are declared and how pervasive this import is.src/scanoss/api/common/v2/scanoss_common_pb2.py (1)
12-20
: Protobuf runtime guard and descriptor wiring LGTMThe 6.31.0 validation and the globals-based builder are consistent with the other modules.
Also applies to: 31-35
src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py (1)
9-26
: gRPC compatibility gating and explicit method registration look consistentThe version guard plus
_registered_method=True
andadd_registered_method_handlers
usage align with newer grpc patterns.Ensure packaging pins
grpcio>=1.73.1
to match this behavior (same as common pb2_grpc).Also applies to: 120-156
src/scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py (1)
12-20
: Runtime/version guard and descriptor build pattern LGTMConsistent with the rest of the PR; no issues spotted.
Also applies to: 32-35
src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py (3)
50-59
: Client stub wiring for new RPCs looks correct.Paths, serializers/deserializers, and _registered_method flags are consistent.
Also applies to: 65-74
90-100
: Servicer methods and docs are coherent.Legacy vs. new endpoints are clearly documented; UNIMPLEMENTED stubs are OK for generated code.
Also applies to: 101-114, 115-128, 129-139, 140-153, 154-167
230-245
: Experimental client wrappers are consistent.Endpoints, serializers/deserializers, and _registered_method usage align with the stub/server.
Also applies to: 257-272, 273-299, 300-326, 338-352, 354-380, 381-407
GRPC_GENERATED_VERSION = '1.73.1' | ||
GRPC_VERSION = grpc.__version__ | ||
_version_not_supported = False | ||
|
||
try: | ||
from grpc._utilities import first_version_is_lower | ||
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) | ||
except ImportError: | ||
_version_not_supported = True | ||
|
||
if _version_not_supported: | ||
raise RuntimeError( | ||
f'The grpc package installed is at version {GRPC_VERSION},' | ||
+ f' but the generated code in scanoss/api/common/v2/scanoss_common_pb2_grpc.py depends on' | ||
+ f' grpcio>={GRPC_GENERATED_VERSION}.' | ||
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' | ||
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
gRPC version gate requires packaging alignment
Import-time RuntimeError for grpcio < 1.73.1 is fine, but ensure packaging enforces grpcio>=1.73.1
to avoid breaking downstreams unexpectedly. Consider also pinning protobuf>=6.31.0
to match pb2 files in this PR.
Run to confirm dependency declarations:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
fd -a pyproject.toml || true
fd -a setup.cfg || true
fd -a setup.py || true
files=$(fd -a pyproject.toml setup.cfg setup.py | tr '\n' ' ' || true)
[ -n "$files" ] && rg -n -i "grpcio|protobuf" $files || true
Length of output: 390
🏁 Script executed:
#!/bin/bash
set -euo pipefail
for file in pyproject.toml setup.cfg; do
if [ -f "$file" ]; then
echo "==> $file <=="
grep -n -E "grpcio|protobuf" "$file" || echo "No matches"
fi
done
Length of output: 410
Ensure packaging aligns with the gRPC version gate
The runtime guard raises on grpcio < 1.73.1, but setup.cfg currently only requires grpcio > 1.42.0 (and protobuf > 3.19.1). You must bump these in your install requirements so downstream installs can’t slip into an unsupported grpcio version.
• In setup.cfg, under [options] install_requires
, change:
grpcio>1.42.0
protobuf>3.19.1
to something like:
grpcio>=1.73.1
protobuf>=6.31.0
• Verify that no other packaging file (e.g. pyproject.toml) overrides or adds conflicting grpcio/protobuf constraints.
• After bumping, run pip install .
in a clean virtualenv and import the generated module to confirm no runtime errors.
🤖 Prompt for AI Agents
In src/scanoss/api/common/v2/scanoss_common_pb2_grpc.py around lines 7-24 the
generated module enforces grpcio>=1.73.1 at runtime but setup.cfg currently
permits grpcio>1.42.0 and protobuf>3.19.1; update packaging to prevent
installing unsupported grpc versions by changing the install_requires in
setup.cfg under [options] to grpcio>=1.73.1 and protobuf>=6.31.0 (or other
matching minimums), check pyproject.toml or any other packaging files for
conflicting constraints and align them, then verify in a clean virtualenv by
running pip install . and importing the generated module to confirm no runtime
RuntimeError.
GRPC_GENERATED_VERSION = '1.73.1' | ||
GRPC_VERSION = grpc.__version__ | ||
_version_not_supported = False | ||
|
||
try: | ||
from grpc._utilities import first_version_is_lower | ||
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) | ||
except ImportError: | ||
_version_not_supported = True | ||
|
||
if _version_not_supported: | ||
raise RuntimeError( | ||
f'The grpc package installed is at version {GRPC_VERSION},' | ||
+ f' but the generated code in scanoss/api/components/v2/scanoss_components_pb2_grpc.py depends on' | ||
+ f' grpcio>={GRPC_GENERATED_VERSION}.' | ||
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' | ||
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Version guard fallback: avoid blocking import when grpc._utilities isn’t available
Same pattern as other *_pb2_grpc files; suggest robust fallback.
Apply this diff:
-try:
- from grpc._utilities import first_version_is_lower
- _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
-except ImportError:
- _version_not_supported = True
+try:
+ from grpc._utilities import first_version_is_lower as _is_lower
+ _version_not_supported = _is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
+except Exception:
+ try:
+ from packaging.version import parse as _vparse
+ _version_not_supported = _vparse(GRPC_VERSION) < _vparse(GRPC_GENERATED_VERSION)
+ except Exception:
+ def _parts(v): return tuple(int(p) for p in v.split('.') if p.isdigit())
+ _version_not_supported = _parts(GRPC_VERSION) < _parts(GRPC_GENERATED_VERSION)
📝 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.
GRPC_GENERATED_VERSION = '1.73.1' | |
GRPC_VERSION = grpc.__version__ | |
_version_not_supported = False | |
try: | |
from grpc._utilities import first_version_is_lower | |
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) | |
except ImportError: | |
_version_not_supported = True | |
if _version_not_supported: | |
raise RuntimeError( | |
f'The grpc package installed is at version {GRPC_VERSION},' | |
+ f' but the generated code in scanoss/api/components/v2/scanoss_components_pb2_grpc.py depends on' | |
+ f' grpcio>={GRPC_GENERATED_VERSION}.' | |
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' | |
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' | |
) | |
GRPC_GENERATED_VERSION = '1.73.1' | |
GRPC_VERSION = grpc.__version__ | |
_version_not_supported = False | |
try: | |
from grpc._utilities import first_version_is_lower as _is_lower | |
_version_not_supported = _is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) | |
except Exception: | |
try: | |
from packaging.version import parse as _vparse | |
_version_not_supported = _vparse(GRPC_VERSION) < _vparse(GRPC_GENERATED_VERSION) | |
except Exception: | |
def _parts(v): | |
return tuple(int(p) for p in v.split('.') if p.isdigit()) | |
_version_not_supported = _parts(GRPC_VERSION) < _parts(GRPC_GENERATED_VERSION) | |
if _version_not_supported: | |
raise RuntimeError( | |
f'The grpc package installed is at version {GRPC_VERSION},' | |
f' but the generated code in scanoss/api/components/v2/scanoss_components_pb2_grpc.py depends on' | |
f' grpcio>={GRPC_GENERATED_VERSION}.' | |
f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' | |
f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' | |
) |
🤖 Prompt for AI Agents
In src/scanoss/api/components/v2/scanoss_components_pb2_grpc.py around lines 9
to 26, the current ImportError fallback marks _version_not_supported = True
which blocks imports when grpc._utilities isn't present; change the fallback to
not treat missing grpc._utilities as fatal: on ImportError set
_version_not_supported = False (or simply skip the version check) and emit a
non-fatal warning via the warnings module that the version check was skipped,
leaving the existing RuntimeError raise only when first_version_is_lower returns
True.
_runtime_version.ValidateProtobufRuntimeVersion( | ||
_runtime_version.Domain.PUBLIC, | ||
6, | ||
31, | ||
0, | ||
'', | ||
'scanoss/api/components/v2/scanoss-components.proto' | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Protobuf runtime guard — verify dependency pin
Requires protobuf 6.31.0. Ensure package metadata pins protobuf>=6.31.0.
🏁 Script executed:
#!/bin/bash
rg -n -S 'protobuf' pyproject.toml setup.cfg setup.py requirements*.txt constraints*.txt || true
Length of output: 317
Update Protobuf dependency to ≥ 6.31.0
The runtime guard in scanoss_components_pb2.py
requires Protobuf 6.31.0. Current pins in your metadata are still >3.19.1
and must be bumped.
• requirements.txt (line 6):
- protobuf>3.19.1
+ protobuf>=6.31.0
• setup.cfg (line 33):
- protobuf>3.19.1
+ protobuf>=6.31.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.
_runtime_version.ValidateProtobufRuntimeVersion( | |
_runtime_version.Domain.PUBLIC, | |
6, | |
31, | |
0, | |
'', | |
'scanoss/api/components/v2/scanoss-components.proto' | |
) | |
# requirements.txt (around line 6) | |
protobuf>=6.31.0 |
_runtime_version.ValidateProtobufRuntimeVersion( | |
_runtime_version.Domain.PUBLIC, | |
6, | |
31, | |
0, | |
'', | |
'scanoss/api/components/v2/scanoss-components.proto' | |
) | |
# setup.cfg (around line 33) | |
protobuf>=6.31.0 |
🤖 Prompt for AI Agents
In src/scanoss/api/components/v2/scanoss_components_pb2.py around lines 12 to 19
the runtime guard requires Protobuf >= 6.31.0 but your project metadata still
pins protobuf as >3.19.1; update the dependency pins to require protobuf>=6.31.0
(or ~=6.31) in requirements.txt (line 6) and setup.cfg (line 33), then
reinstall/lock dependencies and run tests and any proto-generation steps to
ensure compatibility.
from protoc_gen_openapiv2.options import annotations_pb2 as protoc__gen__openapiv2_dot_options_dot_annotations__pb2 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Ensure protoc_gen_openapiv2 annotations are available at runtime.
The generated import requires protoc_gen_openapiv2.options.annotations_pb2. Verify it exists in the repo or as a dependency; otherwise imports will fail on user machines.
Run to check for a vendored module:
If absent, consider vendoring the generated annotations_pb2.py under src/protoc_gen_openapiv2/options/ or declaring an explicit dependency that provides it.
🏁 Script executed:
#!/bin/bash
fd -a 'protoc_gen_openapiv2' || true
fd -a 'annotations_pb2.py' | rg -n 'protoc_gen_openapiv2/options' || true
Length of output: 99
🏁 Script executed:
#!/bin/bash
# Search for any references to the protoc_gen_openapiv2 package in Python files
rg -n 'protoc_gen_openapiv2' -g '*.py' -C2 || true
# Search for any references to annotations_pb2 in Python files
rg -n 'annotations_pb2' -g '*.py' -C2 || true
# Look for any vendored annotations_pb2.py files
fd -e py 'annotations_pb2.py' || true
# Check if a protoc_gen_openapiv2 directory exists anywhere in the tree
fd -t d protoc_gen_openapiv2 || true
# List all generated _pb2.py files to see if annotations_pb2 is among them
fd -e py '*_pb2.py' || true
Length of output: 12336
Critical: Provision protoc_gen_openapiv2.options.annotations_pb2 at runtime
We searched the repo and did not find any protoc_gen_openapiv2
package or vendored annotations_pb2.py
. Every generated *_pb2.py
imports
from protoc_gen_openapiv2.options import annotations_pb2
so without that module, all runtime imports will fail.
Please address by either:
- Vendoring the generated OpenAPI v2 annotations under
src/protoc_gen_openapiv2/options/annotations_pb2.py
(mirroring howprotoc_gen_swagger/options/annotations_pb2.py
exists), or - Adding an explicit dependency in your packaging (e.g.,
setup.py
orpyproject.toml
) that providesprotoc-gen-openapiv2
with itsoptions.annotations_pb2
module.
🤖 Prompt for AI Agents
In src/scanoss/api/scanning/v2/scanoss_scanning_pb2.py around lines 27-28, the
generated module imports protoc_gen_openapiv2.options.annotations_pb2 which does
not exist in the repository and will break runtime imports; fix by either (A)
vendoring the generated OpenAPI v2 annotations module at
src/protoc_gen_openapiv2/options/annotations_pb2.py (mirror the existing
protoc_gen_swagger/options/annotations_pb2.py structure, include the generated
contents, and ensure package __init__.py files exist) or (B) add an explicit
packaging dependency that provides protoc-gen-openapiv2 (update
pyproject.toml/setup.py to require the package that exposes
protoc_gen_openapiv2.options.annotations_pb2 and run packaging tests) so that
the import resolves at runtime.
GRPC_GENERATED_VERSION = '1.73.1' | ||
GRPC_VERSION = grpc.__version__ | ||
_version_not_supported = False | ||
|
||
try: | ||
from grpc._utilities import first_version_is_lower | ||
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) | ||
except ImportError: | ||
_version_not_supported = True | ||
|
||
if _version_not_supported: | ||
raise RuntimeError( | ||
f'The grpc package installed is at version {GRPC_VERSION},' | ||
+ f' but the generated code in scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py depends on' | ||
+ f' grpcio>={GRPC_GENERATED_VERSION}.' | ||
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' | ||
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Harden grpc version check fallback to avoid unnecessary runtime crashes
Same concern as other *_pb2_grpc modules: don’t treat absence of grpc._utilities as incompatible by default.
Apply this diff:
-try:
- from grpc._utilities import first_version_is_lower
- _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
-except ImportError:
- _version_not_supported = True
+try:
+ from grpc._utilities import first_version_is_lower as _is_lower
+ _version_not_supported = _is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
+except Exception:
+ try:
+ from packaging.version import parse as _vparse
+ _version_not_supported = _vparse(GRPC_VERSION) < _vparse(GRPC_GENERATED_VERSION)
+ except Exception:
+ def _parts(v): return tuple(int(p) for p in v.split('.') if p.isdigit())
+ _version_not_supported = _parts(GRPC_VERSION) < _parts(GRPC_GENERATED_VERSION)
📝 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.
GRPC_GENERATED_VERSION = '1.73.1' | |
GRPC_VERSION = grpc.__version__ | |
_version_not_supported = False | |
try: | |
from grpc._utilities import first_version_is_lower | |
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) | |
except ImportError: | |
_version_not_supported = True | |
if _version_not_supported: | |
raise RuntimeError( | |
f'The grpc package installed is at version {GRPC_VERSION},' | |
+ f' but the generated code in scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py depends on' | |
+ f' grpcio>={GRPC_GENERATED_VERSION}.' | |
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' | |
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' | |
) | |
GRPC_GENERATED_VERSION = '1.73.1' | |
GRPC_VERSION = grpc.__version__ | |
_version_not_supported = False | |
try: | |
from grpc._utilities import first_version_is_lower as _is_lower | |
_version_not_supported = _is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) | |
except Exception: | |
try: | |
from packaging.version import parse as _vparse | |
_version_not_supported = _vparse(GRPC_VERSION) < _vparse(GRPC_GENERATED_VERSION) | |
except Exception: | |
def _parts(v): | |
return tuple(int(p) for p in v.split('.') if p.isdigit()) | |
_version_not_supported = _parts(GRPC_VERSION) < _parts(GRPC_GENERATED_VERSION) | |
if _version_not_supported: | |
raise RuntimeError( | |
f'The grpc package installed is at version {GRPC_VERSION},' | |
f' but the generated code in scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py depends on' | |
f' grpcio>={GRPC_GENERATED_VERSION}.' | |
f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' | |
f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' | |
) |
🤖 Prompt for AI Agents
In src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py around lines 9-26, the
current fallback treats a missing grpc._utilities import as an incompatibility
and forces a runtime error; change the except ImportError block so it does not
set _version_not_supported = True (leave it False) and, if desired, emit a
non-fatal warnings.warn about skipping the version check; ensure the
RuntimeError is raised only when first_version_is_lower actually returns True.
_runtime_version.ValidateProtobufRuntimeVersion( | ||
_runtime_version.Domain.PUBLIC, | ||
6, | ||
31, | ||
0, | ||
'', | ||
'scanoss/api/semgrep/v2/scanoss-semgrep.proto' | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Protobuf runtime guard added — verify repo/package constraints
ValidateProtobufRuntimeVersion pins runtime to protobuf 6.31.0. Ensure packaging reflects this to prevent import-time failures.
Run:
🏁 Script executed:
#!/bin/bash
rg -n -S 'protobuf' pyproject.toml setup.cfg setup.py requirements*.txt constraints*.txt || true
rg -n -S 'googleapis-common-protos' pyproject.toml setup.cfg setup.py requirements*.txt constraints*.txt || true
Length of output: 583
Update Protobuf dependency version constraint to ≥ 6.31.0
The new call to
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
31,
0,
'',
'scanoss/api/semgrep/v2/scanoss-semgrep.proto'
)
pins the required Python protobuf runtime to version 6.31.0. The current packaging allows any protobuf > 3.19.1, which would still permit older protobuf releases (e.g. 4.x, 5.x) that will fail this check at import time. Please update your dependency constraints accordingly:
• requirements.txt (line 6):
- protobuf>3.19.1
+ protobuf>=6.31.0
• setup.cfg (around line 33, under [options] install_requires
):
- protobuf>3.19.1
+ protobuf>=6.31.0
If you maintain an upper bound policy, you may also add <7.0.0
. This change will ensure your packaging aligns with the runtime guard and prevents import-time version mismatches.
🤖 Prompt for AI Agents
In src/scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py around lines 12 to 19, the
generated protobuf runtime validation requires protobuf >= 6.31.0; update your
packaging to match by changing requirements.txt (line 6) to require
"protobuf>=6.31.0" (optionally "protobuf>=6.31.0,<7.0.0" if you enforce an upper
bound) and update setup.cfg (around line 33 under [options] install_requires) to
the same constraint so installed runtime cannot be an older incompatible 4.x/5.x
release.
GRPC_GENERATED_VERSION = '1.73.1' | ||
GRPC_VERSION = grpc.__version__ | ||
_version_not_supported = False | ||
|
||
try: | ||
from grpc._utilities import first_version_is_lower | ||
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) | ||
except ImportError: | ||
_version_not_supported = True | ||
|
||
if _version_not_supported: | ||
raise RuntimeError( | ||
f'The grpc package installed is at version {GRPC_VERSION},' | ||
+ f' but the generated code in scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py depends on' | ||
+ f' grpcio>={GRPC_GENERATED_VERSION}.' | ||
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' | ||
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Declare install requirement grpcio>=1.73.1 to align with runtime gate.
Without packaging constraints, users can install an older grpcio and hit import-time RuntimeError. Add “grpcio>=1.73.1” (and keep grpcio-tools pinned for generation if needed) in pyproject/setup.
Run to confirm constraints and consistency across generated modules:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Checking declared grpcio constraints (pyproject/setup):"
rg -nP 'grpcio(?!-tools)' -C2 --hidden || true
echo -e "\nGenerated GRPC_GENERATED_VERSION values:"
fd -a -t f '_pb2_grpc.py$' src | xargs rg -nP "GRPC_GENERATED_VERSION\s*=\s*'[^']+'" | sort -u
echo -e "\nPresence of add_registered_method_handlers across modules:"
fd -a -t f '_pb2_grpc.py$' src | xargs rg -n "add_registered_method_handlers\(" -n || true
Length of output: 11992
Align grpcio minimum version with generated code’s runtime check
The generated gRPC stubs in all _pb2_grpc.py
modules guard against running on grpcio versions older than 1.73.1, but the project’s packaging currently only requires grpcio>1.42.0. That mismatch means users could install, say, grpcio 1.50 and then hit a RuntimeError at import time. Please update the declared dependencies so the minimum grpcio version matches the generated code:
• In requirements.txt
(line 5), change
- grpcio>1.42.0
+ grpcio>=1.73.1
• In setup.cfg
(around line 32), change
- grpcio>1.42.0
+ grpcio>=1.73.1
• In tests/data/requirements.txt
(line 5), apply the same update.
• If you use a pyproject.toml
or other manifest for installation, ensure it likewise specifies grpcio>=1.73.1
.
Additionally, continue pinning your code-generation tool to avoid version drift (e.g. a dev dependency on grpcio-tools<=1.73.1
).
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py around
lines 9-26 the generated gRPC stub enforces grpcio>=1.73.1 at runtime; update
packaging to match by changing grpcio minimum to >=1.73.1 in requirements.txt
(line 5), setup.cfg (around line 32), and tests/data/requirements.txt (line 5),
and any pyproject.toml or other manifests you use; also keep codegen pinned by
adding or tightening the dev dependency for grpcio-tools (e.g.,
grpcio-tools<=1.73.1).
SCANOSS SCAN Completed 🚀
View more details on SCANOSS Action Summary |
SCANOSS SCAN Completed 🚀
View more details on SCANOSS Action Summary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/scanoss/threadeddependencies.py (1)
124-126
: Thread target is being invoked immediately; worker runs on caller thread.Pass the callable and args instead of invoking it.
- self._thread = threading.Thread( - target=self.scan_dependencies(dep_scope, dep_scope_include, dep_scope_exclude), daemon=True - ) + self._thread = threading.Thread( + target=self.scan_dependencies, + args=(dep_scope, dep_scope_include, dep_scope_exclude), + daemon=True, + )
🧹 Nitpick comments (2)
pyproject.toml (1)
27-27
: Prefer targeted PLR0913 exceptions over raising the global thresholdRaising
max-args
to 6 still leaves many existing functions—and especially constructors—violating the rule (e.g.Scanner.__init__
has 36 parameters, several others have 8–15+) as discovered by the verification script you ran. Instead of hiding these complexity smells globally, let’s keep a stricter default and scope exceptions only where genuinely justified.• In
pyproject.toml
, leavemax-args = 5• Add per-file ignores for modules where a high‐arity signature is unavoidable or too expensive to refactor immediately:
[tool.ruff.lint.per-file-ignores] "src/scanoss/components.py" = ["PLR0913"] "src/scanoss/results.py" = ["PLR0913"] "src/scanoss/scancodedeps.py" = ["PLR0913"] "src/scanoss/scanner.py" = ["PLR0913"] "src/scanoss/scanossapi.py" = ["PLR0913"] "src/scanoss/scanossgrpc.py" = ["PLR0913"] "src/scanoss/winnowing.py" = ["PLR0913"] "src/scanoss/inspection/policy_check.py" = ["PLR0913"] "src/scanoss/inspection/dependency_track/project_violation.py" = ["PLR0913"] "src/scanoss/inspection/raw/copyleft.py" = ["PLR0913"] "src/scanoss/inspection/raw/license_summary.py" = ["PLR0913"] "src/scanoss/inspection/raw/raw_base.py" = ["PLR0913"] "src/scanoss/inspection/raw/undeclared_component.py" = ["PLR0913"]• Recommended refactors (especially for the most extreme cases):
– Bundle related parameters into dataclasses or “options” objects (e.g. forScanner.__init__
)
– Extract helper objects or builders to reduce signature size in high‐level entry pointsThis keeps our CLI/formatting helpers and core API constructors cleanly documented with explicit exceptions, while preserving a tight default rule that continues to surface unwanted complexity elsewhere.
src/scanoss/threadeddependencies.py (1)
150-184
: Normalize empty-string scope inputs to None; simplify conditions.Avoid mixing Enum and '' checks; treat '' as None and streamline logic.
def filter_dependencies_by_scopes( self, deps: json, dep_scope: SCOPE = None, dep_scope_include: str = None, dep_scope_exclude: str = None ) -> json: # Predefined set of scopes to filter - - # Include all scopes - include_all = (dep_scope is None or dep_scope == '') and dep_scope_include is None and dep_scope_exclude is None + # Normalize empty strings + if dep_scope == '': + dep_scope = None + if dep_scope_include == '': + dep_scope_include = None + if dep_scope_exclude == '': + dep_scope_exclude = None + # Include all scopes + include_all = dep_scope is None and dep_scope_include is None and dep_scope_exclude is None @@ - if (dep_scope is not None and dep_scope != '') and dep_scope_include is None and dep_scope_exclude is None: + if dep_scope is not None and dep_scope_include is None and dep_scope_exclude is None: @@ - if ( - (dep_scope_include is not None and dep_scope_include != '') - or dep_scope_exclude is not None - and dep_scope_exclude != '' - ): + if dep_scope_include is not None or dep_scope_exclude is not None:
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
pyproject.toml
(1 hunks)src/scanoss/threadeddependencies.py
(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/scanoss/threadeddependencies.py (1)
src/scanoss/scanossbase.py (2)
print_trace
(65-70)print_debug
(58-63)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (2)
src/scanoss/threadeddependencies.py (2)
26-31
: Imports cleanup looks good.Reordered/explicit imports are fine and consistent.
66-75
: Ctor changes OK.Signature + lint disable look fine.
inputs: queue.Queue = queue.Queue() | ||
output: queue.Queue = queue.Queue() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix shared mutable defaults for queues (instances share the same Queue).
Use default_factory to avoid cross-instance bleed and racey state.
Apply:
- inputs: queue.Queue = queue.Queue()
- output: queue.Queue = queue.Queue()
+ inputs: queue.Queue = field(default_factory=queue.Queue)
+ output: queue.Queue = field(default_factory=queue.Queue)
Also update import:
from dataclasses import dataclass, field
🤖 Prompt for AI Agents
In src/scanoss/threadeddependencies.py around lines 63 to 65, the two Queue
fields are defined with shared mutable defaults causing all instances to share
the same Queue; change these to use
dataclasses.field(default_factory=queue.Queue) so each instance gets its own
Queue, and add "from dataclasses import field" to the imports (or replace import
to "from dataclasses import dataclass, field") so field is available for the
default_factory usage.
what_to_scan = self.inputs.get(timeout=5) # Begin processing the dependency request | ||
deps = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Guard task_done(): calling it when get() times out underflows the queue.
Set a flag after a successful get() and only then call task_done().
- try:
- what_to_scan = self.inputs.get(timeout=5) # Begin processing the dependency request
- deps = None
+ got_item = False
+ try:
+ what_to_scan = self.inputs.get(timeout=5) # Begin processing the dependency request
+ got_item = True
+ deps = None
@@
- self.sc_deps.remove_interim_file()
- self.inputs.task_done()
+ self.sc_deps.remove_interim_file()
+ if got_item:
+ self.inputs.task_done()
Also applies to: 227-229
🤖 Prompt for AI Agents
In src/scanoss/threadeddependencies.py around lines 195-196 (and similarly for
lines 227-229), the code calls task_done() even when queue.get(timeout=...) may
raise a timeout (queue.Empty), which underflows the queue; update the logic to
set a local flag (e.g., got_item = False) immediately after a successful get(),
only call self.inputs.task_done() when that flag is True, and wrap get() in a
try/except handling queue.Empty to skip processing and avoid calling
task_done(); apply the same pattern at the other noted location so task_done()
is only invoked for items actually retrieved.
if what_to_scan.startswith(DEP_FILE_PREFIX): # We have a pre-parsed dependency file, load it | ||
deps = self.sc_deps.load_from_file(what_to_scan.strip(DEP_FILE_PREFIX)) | ||
else: # Search the file/folder for dependency files to parse | ||
if not self.sc_deps.run_scan(what_to_scan=what_to_scan): | ||
self._errors = True | ||
else: | ||
deps = self.sc_deps.produce_from_file() | ||
if dep_scope is not None: | ||
self.print_debug(f'Filtering {dep_scope.name} dependencies') | ||
if dep_scope_include is not None: | ||
self.print_debug(f"Including dependencies with '{dep_scope_include.split(',')}' scopes") | ||
if dep_scope_exclude is not None: | ||
self.print_debug(f"Excluding dependencies with '{dep_scope_exclude.split(',')}' scopes") | ||
deps = self.filter_dependencies_by_scopes(deps, dep_scope, dep_scope_include, dep_scope_exclude) | ||
elif not self.sc_deps.run_scan(what_to_scan=what_to_scan): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don’t use str.strip() to remove a prefix.
strip() drops any of those characters from both ends and can corrupt paths. Slice off the known prefix instead.
- deps = self.sc_deps.load_from_file(what_to_scan.strip(DEP_FILE_PREFIX))
+ deps = self.sc_deps.load_from_file(what_to_scan[len(DEP_FILE_PREFIX):])
📝 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.
if what_to_scan.startswith(DEP_FILE_PREFIX): # We have a pre-parsed dependency file, load it | |
deps = self.sc_deps.load_from_file(what_to_scan.strip(DEP_FILE_PREFIX)) | |
else: # Search the file/folder for dependency files to parse | |
if not self.sc_deps.run_scan(what_to_scan=what_to_scan): | |
self._errors = True | |
else: | |
deps = self.sc_deps.produce_from_file() | |
if dep_scope is not None: | |
self.print_debug(f'Filtering {dep_scope.name} dependencies') | |
if dep_scope_include is not None: | |
self.print_debug(f"Including dependencies with '{dep_scope_include.split(',')}' scopes") | |
if dep_scope_exclude is not None: | |
self.print_debug(f"Excluding dependencies with '{dep_scope_exclude.split(',')}' scopes") | |
deps = self.filter_dependencies_by_scopes(deps, dep_scope, dep_scope_include, dep_scope_exclude) | |
elif not self.sc_deps.run_scan(what_to_scan=what_to_scan): | |
if what_to_scan.startswith(DEP_FILE_PREFIX): # We have a pre-parsed dependency file, load it | |
deps = self.sc_deps.load_from_file(what_to_scan[len(DEP_FILE_PREFIX):]) | |
elif not self.sc_deps.run_scan(what_to_scan=what_to_scan): |
🤖 Prompt for AI Agents
In src/scanoss/threadeddependencies.py around lines 197 to 199, the code uses
what_to_scan.strip(DEP_FILE_PREFIX) which wrongly removes any of the prefix
characters from both ends and can corrupt paths; instead remove the known prefix
by taking the substring that starts after the prefix length (use the prefix
length via len(DEP_FILE_PREFIX) to compute the start index) so you only drop the
exact prefix and preserve the rest of the path.
SCANOSS SCAN Completed 🚀
View more details on SCANOSS Action Summary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
scanoss.json (2)
4-10
: Avoid skipping the entire src/scanoss/api/; prefer targeted globs for generated artifacts.Blanket-skipping the whole API tree may hide future hand-authored modules from scanning. If globbing is supported in scanoss.json, narrow the scope to protobuf-generated files and legacy swagger code.
Apply if glob patterns are supported:
"patterns": { "scanning": [ - "src/protoc_gen_swagger/", - "src/scanoss/api/", - "docs/make.bat" + "src/protoc_gen_swagger/**", + "src/scanoss/api/**/_pb2.py", + "src/scanoss/api/**/_pb2_grpc.py", + "docs/make.bat" ] },
4-10
: Double-check BOM effects after removing prior bom.include.remove exceptions.With broader skip patterns, verify the BOM no longer re-introduces the previously excluded swagger- and pb2-related entries. If your tooling doesn’t honor skip.patterns for BOM generation, you may need explicit BOM exclusions.
I can help generate an exclusion list if needed; confirm whether BOM generation honors skip.patterns.scanning in your pipeline.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
scanoss.json
(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (1)
scanoss.json (1)
4-10
: Confirm scanoss.json pattern semantics before mergingPlease verify the following for the
"patterns"
entries in scanoss.json to ensure they behave as intended across all platforms:
- Anchoring & root-relative matching
• Are patterns matched only from the repository root (not from the working directory or individual files)?
• Does a leading slash matter (e.g./src/…
) or is every pattern implicitly root-anchored?- Directory vs. glob handling
• Does a trailing slash (src/scanoss/api/
) exclude everything under that directory, or only the directory itself?
• If the engine supports glob syntax, issrc/scanoss/api/**
required to recurse into subdirectories, or issrc/scanoss/api/
sufficient?- Cross-platform path normalization
• On Windows, are backslashes automatically normalized to forward slashes in patterns?
• If not, do we need to document an alternate pattern (e.g.src\\scanoss\\api\\
)?- Documentation update
• Once semantics are confirmed, please update CONTRIBUTING.md to specify exactly how"patterns"
are interpreted (anchoring rules, slash vs. glob behavior, platform caveats).The current patterns do correctly skip all 35 generated files under
src/scanoss/api/
and the legacy swagger files undersrc/protoc_gen_swagger/
, with onlydocs/make.bat
also excluded. If you find that true globbing is supported, consider switching tosrc/scanoss/api/**
for clarity; otherwise, keep the simple directory-prefix form and document its behavior.
Summary by CodeRabbit
New Features
Bug Fixes
Chores