socketsecurity 2.4.20__tar.gz → 2.5.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/CHANGELOG.md +30 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/PKG-INFO +25 -3
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/README.md +24 -2
- socketsecurity-2.5.1/docs/ci-cd.md +167 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/docs/cli-reference.md +35 -1
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/pyproject.toml +1 -1
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/__init__.py +1 -1
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/config.py +29 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/__init__.py +94 -8
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/tools/reachability.py +3 -3
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/core/test_sdk_methods.py +132 -1
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_config.py +51 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/uv.lock +1 -1
- socketsecurity-2.4.20/docs/ci-cd.md +0 -119
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/CODEOWNERS +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/PULL_REQUEST_TEMPLATE/bug-fix.md +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/PULL_REQUEST_TEMPLATE/improvement.md +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/actions/setup-docker/action.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/actions/setup-hatch/action.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/actions/setup-sfw/action.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/dependabot.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/workflows/dependency-review.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/workflows/docker-stable.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/workflows/e2e-test.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/workflows/pr-preview.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/workflows/python-tests.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/workflows/release.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/workflows/version-check.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.github/zizmor.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.gitignore +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.hooks/sync_version.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.pre-commit-config.yaml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/.python-version +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/Dockerfile +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/LICENSE +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/Makefile +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/docs/development.md +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/docs/troubleshooting.md +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/examples/config/sarif-dashboard-parity.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/examples/config/sarif-dashboard-parity.toml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/examples/config/sarif-diff-ci-cd.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/examples/config/sarif-diff-ci-cd.toml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/examples/config/sarif-instance-detail.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/examples/config/sarif-instance-detail.toml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/instructions/gitlab-commit-status/uat.md +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/pytest.ini +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/scripts/build_container.sh +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/scripts/build_container_flexible.sh +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/scripts/deploy-test-docker.sh +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/scripts/deploy-test-pypi.sh +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/scripts/docker-entrypoint.sh +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/scripts/run.sh +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/session.md +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socket.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/alert_selection.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/classes.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/cli_client.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/cli_run.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/exceptions.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/git_interface.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/helper/__init__.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/helper/socket_facts_loader.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/lazy_file_loader.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/log_uploader.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/logging.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/messages.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/resource_utils.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/scm/__init__.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/scm/base.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/scm/client.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/scm/github.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/scm/gitlab.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/scm_comments.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/socket_config.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/streaming.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/core/utils.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/fossa_compat.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/output.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/plugins/__init__.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/plugins/base.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/plugins/formatters/__init__.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/plugins/formatters/slack.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/plugins/jira.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/plugins/manager.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/plugins/slack.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/plugins/teams.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/plugins/webhook.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/socketsecurity/socketcli.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/__init__.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/core/conftest.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/core/create_diff_input.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/core/test_diff_alerts.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/core/test_diff_generation.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/core/test_facts_compression.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/core/test_has_manifest_files.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/core/test_package_and_alerts.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/core/test_supporting_methods.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/fullscans/create_response.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/fullscans/diff/stream_diff.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/fullscans/diff/stream_diff_full.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/fullscans/head_scan/metadata.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/fullscans/head_scan/stream_scan.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/fullscans/head_scan/stream_scan_full.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/fullscans/new_scan/metadata.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/fullscans/new_scan/stream_scan.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/repos/repo_info_error.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/repos/repo_info_no_head.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/repos/repo_info_success.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/data/settings/security-policy.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/e2e/fixtures/simple-npm/index.js +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/e2e/fixtures/simple-npm/package.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/e2e/fixtures/simple-pypi/requirements.txt +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/e2e/validate-gitlab.sh +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/e2e/validate-json.sh +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/e2e/validate-reachability.sh +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/e2e/validate-sarif.sh +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/e2e/validate-scan.sh +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/fixtures/fossa/README.md +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/fixtures/fossa/fossa-analyze-empty.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/fixtures/fossa/fossa-analyze-populated.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/fixtures/fossa/fossa-sbom-empty-deep.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/fixtures/fossa/fossa-sbom-populated.json +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/__init__.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_alert_selection.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_cli_config.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_cli_run.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_client.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_dependency_overview.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_disable_ignore.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_exclude_paths.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_fossa_compat.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_fossa_parity.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_full_scan_retry.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_gitlab_auth.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_gitlab_auth_fallback.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_gitlab_commit_status.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_gitlab_format.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_ignore_telemetry_filtering.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_include_dirs.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_log_uploader.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_output.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_reachability.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_slack_plugin.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_socketcli.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_streaming.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/tests/unit/test_tier1_finalize.py +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/workflows/bitbucket-pipelines.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/workflows/buildkite.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/workflows/github-actions.yml +0 -0
- {socketsecurity-2.4.20 → socketsecurity-2.5.1}/workflows/gitlab-ci.yml +0 -0
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.5.1
|
|
4
|
+
|
|
5
|
+
### Changed: bump pinned @coana-tech/cli to 15.9.0
|
|
6
|
+
|
|
7
|
+
- Bumped the pinned reachability engine (`@coana-tech/cli`) from `15.8.8` to
|
|
8
|
+
`15.9.0`. See the [Coana changelogs](https://docs.coana.tech/changelogs) for
|
|
9
|
+
engine changes.
|
|
10
|
+
|
|
11
|
+
## 2.5.0
|
|
12
|
+
|
|
13
|
+
### Added: `--base-scan-id` / `--base-commit-sha` diff baseline overrides
|
|
14
|
+
|
|
15
|
+
- New mutually exclusive flags to control which full scan a diff is compared
|
|
16
|
+
against, instead of always using the repository's latest head scan:
|
|
17
|
+
- `--base-scan-id <id>` diffs against that full scan ID verbatim.
|
|
18
|
+
- `--base-commit-sha <sha>` diffs against the most recent full scan created
|
|
19
|
+
from that commit — e.g. the PR's merge base from
|
|
20
|
+
`git merge-base origin/main HEAD` — so PR diffs are not polluted by
|
|
21
|
+
default-branch commits the PR never branched from.
|
|
22
|
+
- A `--base-commit-sha` with no matching full scan is a hard error (exit code 3,
|
|
23
|
+
or `--exit-code-on-api-error`; exit 0 with `--disable-blocking`) rather than a
|
|
24
|
+
silent fallback to the head scan, since diffing against the wrong baseline
|
|
25
|
+
misreports which alerts a PR introduces.
|
|
26
|
+
- Both flags are also settable via `--config` files (`base_scan_id`,
|
|
27
|
+
`base_commit_sha`).
|
|
28
|
+
- **Requirement:** `--base-commit-sha` looks up an existing scan — it does not
|
|
29
|
+
create one. Using it requires CI to run `socketcli` on every commit that lands
|
|
30
|
+
on the default branch; see the "Diffing against the merge base" note in
|
|
31
|
+
`docs/cli-reference.md` for the failure modes and a backfill pattern.
|
|
32
|
+
|
|
3
33
|
## 2.4.20
|
|
4
34
|
|
|
5
35
|
### Changed: bump pinned @coana-tech/cli to 15.8.8
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: socketsecurity
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.1
|
|
4
4
|
Summary: Socket Security CLI for CI/CD
|
|
5
5
|
Project-URL: Homepage, https://socket.dev
|
|
6
6
|
Author-email: Douglas Coburn <douglas@socket.dev>
|
|
@@ -102,6 +102,26 @@ socketcli --target-path .
|
|
|
102
102
|
socketcli --enable-gitlab-security --gitlab-security-file gl-dependency-scanning-report.json
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
+
### PR scan diffed against the merge base
|
|
106
|
+
|
|
107
|
+
By default, PR scans are diffed against the repository's latest head scan. To diff against
|
|
108
|
+
the exact commit your PR branched from instead, pass the merge base as the baseline:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
BASE_SHA=$(git merge-base origin/main HEAD)
|
|
112
|
+
socketcli --pr-number 123 --base-commit-sha "$BASE_SHA"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
> **Requirement:** `--base-commit-sha` only works if Socket already has a full scan for that
|
|
116
|
+
> exact commit. In practice this means your CI must run `socketcli` on **every commit that
|
|
117
|
+
> lands on your default branch** — not just some of them. If merges can land without a scan
|
|
118
|
+
> (skipped/canceled builds, `[skip ci]`, path-filtered pipelines), the PR scan will fail with
|
|
119
|
+
> exit code 3 rather than silently diff against the wrong baseline. See
|
|
120
|
+
> [`docs/cli-reference.md`](https://github.com/SocketDev/socket-python-cli/blob/main/docs/cli-reference.md)
|
|
121
|
+
> for the full requirements and a backfill pattern that makes PR jobs self-sufficient.
|
|
122
|
+
|
|
123
|
+
A specific full scan ID also works: `--base-scan-id <id>`.
|
|
124
|
+
|
|
105
125
|
## SARIF use cases
|
|
106
126
|
|
|
107
127
|
### Full-scope reachable SARIF (grouped alerts)
|
|
@@ -264,8 +284,10 @@ Minimal pattern:
|
|
|
264
284
|
| `3` | Infrastructure or API error (timeout, network failure, unexpected error) |
|
|
265
285
|
|
|
266
286
|
`--exit-code-on-api-error <N>` remaps the infrastructure-error code (`3`) to any
|
|
267
|
-
value — e.g. a Buildkite
|
|
268
|
-
`
|
|
287
|
+
value — e.g. a Buildkite
|
|
288
|
+
[`soft_fail`](https://buildkite.com/docs/pipelines/configure/step-types/command-step)
|
|
289
|
+
code, or `0` to swallow infra errors. Exit `3` is a Socket convention, not an
|
|
290
|
+
industry standard.
|
|
269
291
|
|
|
270
292
|
### How these options interact
|
|
271
293
|
|
|
@@ -42,6 +42,26 @@ socketcli --target-path .
|
|
|
42
42
|
socketcli --enable-gitlab-security --gitlab-security-file gl-dependency-scanning-report.json
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
### PR scan diffed against the merge base
|
|
46
|
+
|
|
47
|
+
By default, PR scans are diffed against the repository's latest head scan. To diff against
|
|
48
|
+
the exact commit your PR branched from instead, pass the merge base as the baseline:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
BASE_SHA=$(git merge-base origin/main HEAD)
|
|
52
|
+
socketcli --pr-number 123 --base-commit-sha "$BASE_SHA"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
> **Requirement:** `--base-commit-sha` only works if Socket already has a full scan for that
|
|
56
|
+
> exact commit. In practice this means your CI must run `socketcli` on **every commit that
|
|
57
|
+
> lands on your default branch** — not just some of them. If merges can land without a scan
|
|
58
|
+
> (skipped/canceled builds, `[skip ci]`, path-filtered pipelines), the PR scan will fail with
|
|
59
|
+
> exit code 3 rather than silently diff against the wrong baseline. See
|
|
60
|
+
> [`docs/cli-reference.md`](https://github.com/SocketDev/socket-python-cli/blob/main/docs/cli-reference.md)
|
|
61
|
+
> for the full requirements and a backfill pattern that makes PR jobs self-sufficient.
|
|
62
|
+
|
|
63
|
+
A specific full scan ID also works: `--base-scan-id <id>`.
|
|
64
|
+
|
|
45
65
|
## SARIF use cases
|
|
46
66
|
|
|
47
67
|
### Full-scope reachable SARIF (grouped alerts)
|
|
@@ -204,8 +224,10 @@ Minimal pattern:
|
|
|
204
224
|
| `3` | Infrastructure or API error (timeout, network failure, unexpected error) |
|
|
205
225
|
|
|
206
226
|
`--exit-code-on-api-error <N>` remaps the infrastructure-error code (`3`) to any
|
|
207
|
-
value — e.g. a Buildkite
|
|
208
|
-
`
|
|
227
|
+
value — e.g. a Buildkite
|
|
228
|
+
[`soft_fail`](https://buildkite.com/docs/pipelines/configure/step-types/command-step)
|
|
229
|
+
code, or `0` to swallow infra errors. Exit `3` is a Socket convention, not an
|
|
230
|
+
industry standard.
|
|
209
231
|
|
|
210
232
|
### How these options interact
|
|
211
233
|
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# CI/CD guide
|
|
2
|
+
|
|
3
|
+
Use this guide for pipeline-focused CLI usage across platforms.
|
|
4
|
+
|
|
5
|
+
## Recommended patterns
|
|
6
|
+
|
|
7
|
+
### Dashboard-style reachable SARIF
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
socketcli \
|
|
11
|
+
--reach \
|
|
12
|
+
--sarif-file results.sarif \
|
|
13
|
+
--sarif-scope full \
|
|
14
|
+
--sarif-grouping alert \
|
|
15
|
+
--sarif-reachability reachable \
|
|
16
|
+
--disable-blocking
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Diff-based gating on new reachable findings
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
socketcli \
|
|
23
|
+
--reach \
|
|
24
|
+
--sarif-file results.sarif \
|
|
25
|
+
--sarif-scope diff \
|
|
26
|
+
--sarif-reachability reachable \
|
|
27
|
+
--strict-blocking
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Config file usage in CI
|
|
31
|
+
|
|
32
|
+
Use `--config .socketcli.toml` or `--config .socketcli.json` to keep pipeline commands small.
|
|
33
|
+
|
|
34
|
+
Precedence order:
|
|
35
|
+
|
|
36
|
+
`CLI flags` > `environment variables` > `config file` > `built-in defaults`
|
|
37
|
+
|
|
38
|
+
Example:
|
|
39
|
+
|
|
40
|
+
```toml
|
|
41
|
+
[socketcli]
|
|
42
|
+
reach = true
|
|
43
|
+
sarif_scope = "full"
|
|
44
|
+
sarif_grouping = "alert"
|
|
45
|
+
sarif_reachability = "reachable"
|
|
46
|
+
sarif_file = "results.sarif"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Equivalent JSON:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"socketcli": {
|
|
54
|
+
"reach": true,
|
|
55
|
+
"sarif_scope": "full",
|
|
56
|
+
"sarif_grouping": "alert",
|
|
57
|
+
"sarif_reachability": "reachable",
|
|
58
|
+
"sarif_file": "results.sarif"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Platform examples
|
|
64
|
+
|
|
65
|
+
### GitHub Actions
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
- name: Run Socket CLI
|
|
69
|
+
run: socketcli --config .socketcli.toml --target-path .
|
|
70
|
+
env:
|
|
71
|
+
SOCKET_SECURITY_API_TOKEN: ${{ secrets.SOCKET_SECURITY_API_TOKEN }}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Buildkite
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
steps:
|
|
78
|
+
- label: "Socket scan"
|
|
79
|
+
command: "socketcli --config .socketcli.toml --target-path ."
|
|
80
|
+
env:
|
|
81
|
+
SOCKET_SECURITY_API_TOKEN: "${SOCKET_SECURITY_API_TOKEN}"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
#### Merge-base baselines in Buildkite (dynamic pipelines)
|
|
85
|
+
|
|
86
|
+
Notes for using `--base-commit-sha` (see the
|
|
87
|
+
[merge-base note in the CLI reference](cli-reference.md#pull-request-and-commit))
|
|
88
|
+
when your steps are emitted by a
|
|
89
|
+
[dynamic pipeline](https://buildkite.com/docs/pipelines/configure/dynamic-pipelines)
|
|
90
|
+
generator rather than a static YAML file:
|
|
91
|
+
|
|
92
|
+
- **Compute the merge base at generation time, not step time.** The generator runs
|
|
93
|
+
with a full checkout; step agents may have shallow or fresh clones where
|
|
94
|
+
`git merge-base` fails or needs an extra fetch. Resolve it once in the generator and
|
|
95
|
+
bake it into the emitted step's `env`. Diff against the PR's *target* branch, which
|
|
96
|
+
isn't always the default branch (see Buildkite's
|
|
97
|
+
[environment variables](https://buildkite.com/docs/pipelines/configure/environment-variables)):
|
|
98
|
+
|
|
99
|
+
```shell
|
|
100
|
+
TARGET="${BUILDKITE_PULL_REQUEST_BASE_BRANCH:-$BUILDKITE_PIPELINE_DEFAULT_BRANCH}"
|
|
101
|
+
BASE_SHA=$(git merge-base "origin/${TARGET}" HEAD)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- **Emit the backfill step conditionally from the generator.** The generator is the
|
|
105
|
+
natural place for the "does a baseline scan exist?" check
|
|
106
|
+
(`GET /orgs/{org}/full-scans?repo=<repo>&commit_hash=$BASE_SHA&per_page=1`): only
|
|
107
|
+
emit the baseline-scan step when it returns nothing. The emitted pipeline then shows
|
|
108
|
+
in the UI whether a backfill will run.
|
|
109
|
+
|
|
110
|
+
- **Keep the backfill inside one command step.** The checkout-base → scan →
|
|
111
|
+
checkout-PR sequence must not be split across steps — steps can land on different
|
|
112
|
+
agents with different checkouts. Prefer
|
|
113
|
+
[`git worktree`](https://git-scm.com/docs/git-worktree) over mutating the step's
|
|
114
|
+
checkout: `git worktree add /tmp/socket-base "$BASE_SHA"` then
|
|
115
|
+
`socketcli --target-path /tmp/socket-base --branch "$TARGET" --disable-blocking`.
|
|
116
|
+
|
|
117
|
+
- **Soft-fail infra errors, not findings.** A missing baseline (or any API error)
|
|
118
|
+
exits with code 3 (`--exit-code-on-api-error` to change it); real findings exit 1.
|
|
119
|
+
[`soft_fail: [{exit_status: 3}]`](https://buildkite.com/docs/pipelines/configure/step-types/command-step)
|
|
120
|
+
on the PR scan step keeps infra errors from blocking merges while security findings
|
|
121
|
+
still do.
|
|
122
|
+
|
|
123
|
+
- **["Cancel intermediate builds"](https://buildkite.com/docs/pipelines/configure/canceling-builds#cancel-running-intermediate-builds)
|
|
124
|
+
on the default branch is the main source of baseline gaps.** Canceled builds never
|
|
125
|
+
scan their commit, so merge-base lookups for PRs based on those commits fail. The
|
|
126
|
+
conditional backfill step above is the remedy; there is no per-step exemption from
|
|
127
|
+
build cancellation in Buildkite. If you need strict scan-once semantics for
|
|
128
|
+
concurrent backfills of the same merge base, serialize the backfill step with a
|
|
129
|
+
[concurrency group](https://buildkite.com/docs/pipelines/configure/workflows/controlling-concurrency)
|
|
130
|
+
keyed on the merge-base SHA.
|
|
131
|
+
|
|
132
|
+
### GitLab CI
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
socket_scan:
|
|
136
|
+
script:
|
|
137
|
+
- socketcli --config .socketcli.toml --target-path .
|
|
138
|
+
variables:
|
|
139
|
+
SOCKET_SECURITY_API_TOKEN: $SOCKET_SECURITY_API_TOKEN
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Bitbucket Pipelines
|
|
143
|
+
|
|
144
|
+
```yaml
|
|
145
|
+
pipelines:
|
|
146
|
+
default:
|
|
147
|
+
- step:
|
|
148
|
+
script:
|
|
149
|
+
- socketcli --config .socketcli.toml --target-path .
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Workflow templates
|
|
153
|
+
|
|
154
|
+
Prebuilt examples in this repo:
|
|
155
|
+
|
|
156
|
+
- [`../workflows/github-actions.yml`](../workflows/github-actions.yml)
|
|
157
|
+
- [`../workflows/buildkite.yml`](../workflows/buildkite.yml)
|
|
158
|
+
- [`../workflows/gitlab-ci.yml`](../workflows/gitlab-ci.yml)
|
|
159
|
+
- [`../workflows/bitbucket-pipelines.yml`](../workflows/bitbucket-pipelines.yml)
|
|
160
|
+
|
|
161
|
+
## CI gotchas
|
|
162
|
+
|
|
163
|
+
- `--strict-blocking` enables strict diff behavior (`new + unchanged`) for blocking evaluation and diff-based output selection.
|
|
164
|
+
- `--sarif-scope full` requires `--reach`.
|
|
165
|
+
- `--sarif-grouping alert` currently applies to `--sarif-scope full`.
|
|
166
|
+
- Diff-based SARIF can validly be empty when there are no matching net-new alerts.
|
|
167
|
+
- Keep API tokens in secret stores (`SOCKET_SECURITY_API_TOKEN`), not in config files.
|
|
@@ -146,6 +146,7 @@ This will simultaneously generate:
|
|
|
146
146
|
socketcli [-h] [--api-token API_TOKEN] [--repo REPO] [--workspace WORKSPACE] [--repo-is-public] [--branch BRANCH] [--integration {api,github,gitlab,azure,bitbucket}]
|
|
147
147
|
[--config <path>]
|
|
148
148
|
[--owner OWNER] [--pr-number PR_NUMBER] [--commit-message COMMIT_MESSAGE] [--commit-sha COMMIT_SHA] [--committers [COMMITTERS ...]]
|
|
149
|
+
[--base-scan-id BASE_SCAN_ID | --base-commit-sha BASE_COMMIT_SHA]
|
|
149
150
|
[--target-path TARGET_PATH] [--sbom-file SBOM_FILE] [--license-file-name LICENSE_FILE_NAME] [--save-submitted-files-list SAVE_SUBMITTED_FILES_LIST]
|
|
150
151
|
[--save-manifest-tar SAVE_MANIFEST_TAR] [--files FILES] [--sub-path SUB_PATH] [--workspace-name WORKSPACE_NAME]
|
|
151
152
|
[--excluded-ecosystems EXCLUDED_ECOSYSTEMS] [--exclude-paths EXCLUDE_PATHS] [--include-dirs INCLUDE_DIRS] [--default-branch] [--pending-head] [--generate-license] [--enable-debug]
|
|
@@ -191,6 +192,39 @@ If you don't want to provide the Socket API Token every time then you can use th
|
|
|
191
192
|
| `--pr-number` | False | "0" | Pull request number |
|
|
192
193
|
| `--commit-message` | False | *auto* | Commit message (auto-detected from git) |
|
|
193
194
|
| `--commit-sha` | False | *auto* | Commit SHA (auto-detected from git) |
|
|
195
|
+
| `--base-scan-id` | False | | Full scan ID to diff against, overriding the repository's head scan as the baseline. Mutually exclusive with `--base-commit-sha` |
|
|
196
|
+
| `--base-commit-sha`| False | | Commit SHA to diff against, overriding the repository's head scan as the baseline. The most recent full scan for that commit is used; the CLI errors (exit code 3, or `--exit-code-on-api-error`) if no scan exists for it. Mutually exclusive with `--base-scan-id` |
|
|
197
|
+
|
|
198
|
+
> **Diffing against the merge base** — by default, PR scans are diffed against the repository's *latest* head scan, which may include newer default-branch commits than your PR branched from. To diff against the exact commit your PR is based on, compute the merge base and pass it as the baseline:
|
|
199
|
+
>
|
|
200
|
+
> ```shell
|
|
201
|
+
> BASE_SHA=$(git merge-base origin/main HEAD)
|
|
202
|
+
> socketcli --pr-number 123 --base-commit-sha "$BASE_SHA"
|
|
203
|
+
> ```
|
|
204
|
+
>
|
|
205
|
+
> **Requirement: a full scan must already exist for the merge-base commit.** `--base-commit-sha` does not create a scan of that commit; it looks up an existing one. That lookup only succeeds if your CI runs `socketcli` on **every commit that lands on your default branch** — every merge and direct push, not just periodic or latest-only scans. Common ways commits slip through without a scan:
|
|
206
|
+
>
|
|
207
|
+
> - CI settings that cancel or skip intermediate builds when newer commits land (e.g. Buildkite's ["cancel intermediate builds"](https://buildkite.com/docs/pipelines/configure/canceling-builds#cancel-running-intermediate-builds))
|
|
208
|
+
> - `[skip ci]` commits, path-filtered pipelines, or failed/canceled scan steps
|
|
209
|
+
> - merge-base commits that predate your Socket rollout
|
|
210
|
+
>
|
|
211
|
+
> If no scan exists for the commit, the CLI **fails** (exit code 3, or your `--exit-code-on-api-error` value; exit 0 with `--disable-blocking`) instead of silently falling back to the head scan — a wrong baseline would misreport which alerts the PR introduces. Don't adopt this flag without default-branch scan coverage in place; you'll fail PR builds on lookup misses.
|
|
212
|
+
>
|
|
213
|
+
> **Backfill pattern** — if your default-branch coverage has gaps, the PR job can create the missing baseline itself before scanning:
|
|
214
|
+
>
|
|
215
|
+
> ```shell
|
|
216
|
+
> BASE_SHA=$(git merge-base origin/main HEAD)
|
|
217
|
+
> # Create the baseline only if Socket doesn't have one for this commit yet
|
|
218
|
+
> # (check: GET /orgs/{org}/full-scans?repo=<repo>&commit_hash=$BASE_SHA&per_page=1)
|
|
219
|
+
> git checkout "$BASE_SHA"
|
|
220
|
+
> socketcli --branch main --disable-blocking
|
|
221
|
+
> git checkout -
|
|
222
|
+
> socketcli --pr-number 123 --base-commit-sha "$BASE_SHA"
|
|
223
|
+
> ```
|
|
224
|
+
>
|
|
225
|
+
> Run the baseline step with `--disable-blocking` (findings on the default branch must not fail the PR job) and an explicit `--branch`, since branch auto-detection is unreliable at a detached HEAD.
|
|
226
|
+
>
|
|
227
|
+
> Buildkite users with dynamically generated pipelines: see [Merge-base baselines in Buildkite](ci-cd.md#merge-base-baselines-in-buildkite-dynamic-pipelines) for generation-time vs. step-time guidance.
|
|
194
228
|
|
|
195
229
|
#### Path and File
|
|
196
230
|
| Parameter | Required | Default | Description |
|
|
@@ -241,7 +275,7 @@ If you don't want to provide the Socket API Token every time then you can use th
|
|
|
241
275
|
| Parameter | Required | Default | Description |
|
|
242
276
|
|:---------------------------------|:---------|:--------|:---------------------------------------------------------------------------------------------------------------------------|
|
|
243
277
|
| `--reach` | False | False | Enable reachability analysis to identify which vulnerable functions are actually called by your code. Creates a full application reachability scan (`scan_type=socket_tier1`). |
|
|
244
|
-
| `--reach-version` | False | 15.
|
|
278
|
+
| `--reach-version` | False | 15.9.0 | Version of @coana-tech/cli to use. Defaults to the pinned version that ships with this CLI release, so the engine only changes when you upgrade the Socket CLI. Pass `latest` to always use the newest published version (opt-in auto-update), or an explicit version (e.g. `1.2.3`) to pin it. |
|
|
245
279
|
| `--reach-analysis-timeout` | False | 10m | Timeout for each reachability analysis run, e.g. `90s`, `10m` or `1h`. Omitted by default, so coana applies its own default (`10m`). Alias: `--reach-timeout` |
|
|
246
280
|
| `--reach-analysis-memory-limit` | False | 8GB | Memory limit for each reachability analysis run, e.g. `512MB` or `8GB`. Omitted by default, so coana applies its own default (`8GB`). Alias: `--reach-memory-limit` |
|
|
247
281
|
| `--reach-concurrency` | False | 1 | Control parallel analysis execution (must be >= 1). Omitted by default, so coana applies its own default. |
|
|
@@ -119,6 +119,8 @@ class CliConfig:
|
|
|
119
119
|
scm: str = "api"
|
|
120
120
|
sbom_file: Optional[str] = None
|
|
121
121
|
commit_sha: str = ""
|
|
122
|
+
base_scan_id: Optional[str] = None
|
|
123
|
+
base_commit_sha: Optional[str] = None
|
|
122
124
|
generate_license: bool = False
|
|
123
125
|
enable_debug: bool = False
|
|
124
126
|
allow_unverified: bool = False
|
|
@@ -265,6 +267,8 @@ class CliConfig:
|
|
|
265
267
|
'scm': args.scm,
|
|
266
268
|
'sbom_file': args.sbom_file,
|
|
267
269
|
'commit_sha': args.commit_sha,
|
|
270
|
+
'base_scan_id': args.base_scan_id,
|
|
271
|
+
'base_commit_sha': args.base_commit_sha,
|
|
268
272
|
'generate_license': args.generate_license,
|
|
269
273
|
'enable_debug': args.enable_debug,
|
|
270
274
|
'enable_diff': args.enable_diff,
|
|
@@ -406,6 +410,12 @@ class CliConfig:
|
|
|
406
410
|
logging.error("--workspace-name requires --sub-path to be specified")
|
|
407
411
|
exit(1)
|
|
408
412
|
|
|
413
|
+
# argparse only enforces the mutually exclusive group for real CLI args;
|
|
414
|
+
# this also catches both values arriving via a --config file.
|
|
415
|
+
if args.base_scan_id and args.base_commit_sha:
|
|
416
|
+
logging.error("--base-scan-id and --base-commit-sha are mutually exclusive")
|
|
417
|
+
exit(1)
|
|
418
|
+
|
|
409
419
|
if args.sarif_scope == "full" and not args.reach:
|
|
410
420
|
logging.error("--sarif-scope full requires --reach to be specified")
|
|
411
421
|
exit(1)
|
|
@@ -560,6 +570,25 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
560
570
|
help="Committer for the commit (comma separated)",
|
|
561
571
|
nargs="*"
|
|
562
572
|
)
|
|
573
|
+
base_scan_group = pr_group.add_mutually_exclusive_group()
|
|
574
|
+
base_scan_group.add_argument(
|
|
575
|
+
"--base-scan-id",
|
|
576
|
+
dest="base_scan_id",
|
|
577
|
+
metavar="<id>",
|
|
578
|
+
default=None,
|
|
579
|
+
help="Full scan ID to diff the new scan against, overriding the repository's "
|
|
580
|
+
"head scan as the baseline. Mutually exclusive with --base-commit-sha."
|
|
581
|
+
)
|
|
582
|
+
base_scan_group.add_argument(
|
|
583
|
+
"--base-commit-sha",
|
|
584
|
+
dest="base_commit_sha",
|
|
585
|
+
metavar="<sha>",
|
|
586
|
+
default=None,
|
|
587
|
+
help="Commit SHA to diff the new scan against, overriding the repository's head "
|
|
588
|
+
"scan as the baseline. The most recent full scan matching this commit (e.g. "
|
|
589
|
+
"the merge base from 'git merge-base origin/main HEAD') is used; the CLI "
|
|
590
|
+
"errors if no scan exists for it. Mutually exclusive with --base-scan-id."
|
|
591
|
+
)
|
|
563
592
|
|
|
564
593
|
# Path and File options
|
|
565
594
|
path_group = parser.add_argument_group('Path and File')
|
|
@@ -1154,6 +1154,94 @@ class Core:
|
|
|
1154
1154
|
repo_info = self.get_repo_info(repo_slug)
|
|
1155
1155
|
return repo_info.head_full_scan_id if repo_info.head_full_scan_id else None
|
|
1156
1156
|
|
|
1157
|
+
def get_full_scan_id_by_commit(
|
|
1158
|
+
self,
|
|
1159
|
+
repo_slug: str,
|
|
1160
|
+
commit_sha: str,
|
|
1161
|
+
workspace: Optional[str] = None,
|
|
1162
|
+
scan_type: Optional[str] = None
|
|
1163
|
+
) -> Optional[str]:
|
|
1164
|
+
"""
|
|
1165
|
+
Finds the most recent full scan for a repository + commit SHA.
|
|
1166
|
+
|
|
1167
|
+
Used by --base-commit-sha to resolve the diff baseline (e.g. the merge-base
|
|
1168
|
+
commit of a PR). When the same commit was scanned more than once, the newest
|
|
1169
|
+
scan wins.
|
|
1170
|
+
|
|
1171
|
+
Args:
|
|
1172
|
+
repo_slug: Repository slug the scan belongs to
|
|
1173
|
+
commit_sha: Commit SHA the scan was created from
|
|
1174
|
+
workspace: Socket workspace the scan belongs to, if any
|
|
1175
|
+
scan_type: Socket scan type to match, if any
|
|
1176
|
+
|
|
1177
|
+
Returns:
|
|
1178
|
+
Full scan ID if one exists for that commit, None otherwise
|
|
1179
|
+
"""
|
|
1180
|
+
query_params = {
|
|
1181
|
+
"repo": repo_slug,
|
|
1182
|
+
"commit_hash": commit_sha,
|
|
1183
|
+
"sort": "created_at",
|
|
1184
|
+
"direction": "desc",
|
|
1185
|
+
"per_page": 1,
|
|
1186
|
+
}
|
|
1187
|
+
if workspace:
|
|
1188
|
+
query_params["workspace"] = workspace
|
|
1189
|
+
if scan_type:
|
|
1190
|
+
query_params["scan_type"] = scan_type
|
|
1191
|
+
|
|
1192
|
+
response = self.sdk.fullscans.get(
|
|
1193
|
+
self.config.org_slug,
|
|
1194
|
+
query_params,
|
|
1195
|
+
)
|
|
1196
|
+
results = response.get("results") if isinstance(response, dict) else None
|
|
1197
|
+
if not results:
|
|
1198
|
+
return None
|
|
1199
|
+
return results[0].get("id")
|
|
1200
|
+
|
|
1201
|
+
def resolve_base_full_scan_id(self, params: FullScanParams) -> Optional[str]:
|
|
1202
|
+
"""
|
|
1203
|
+
Resolves the baseline full scan ID to diff a new scan against.
|
|
1204
|
+
|
|
1205
|
+
Priority: --base-scan-id (used verbatim), then --base-commit-sha (newest
|
|
1206
|
+
full scan for that commit), then the repository's current head scan. A
|
|
1207
|
+
--base-commit-sha with no matching full scan is a hard error rather than a
|
|
1208
|
+
silent fallback to the head scan, because diffing against the wrong
|
|
1209
|
+
baseline silently misreports which alerts a PR introduces.
|
|
1210
|
+
|
|
1211
|
+
Returns:
|
|
1212
|
+
Full scan ID to use as the diff baseline, or None when the repository
|
|
1213
|
+
has no head scan yet (caller creates an empty baseline scan).
|
|
1214
|
+
"""
|
|
1215
|
+
if self.cli_config and self.cli_config.base_scan_id:
|
|
1216
|
+
log.info(f"Using full scan {self.cli_config.base_scan_id} as diff baseline (--base-scan-id)")
|
|
1217
|
+
return self.cli_config.base_scan_id
|
|
1218
|
+
|
|
1219
|
+
if self.cli_config and self.cli_config.base_commit_sha:
|
|
1220
|
+
commit_sha = self.cli_config.base_commit_sha
|
|
1221
|
+
scan_id = self.get_full_scan_id_by_commit(
|
|
1222
|
+
params.repo,
|
|
1223
|
+
commit_sha,
|
|
1224
|
+
workspace=params.workspace,
|
|
1225
|
+
scan_type=params.scan_type,
|
|
1226
|
+
)
|
|
1227
|
+
if scan_id is None:
|
|
1228
|
+
log.error(
|
|
1229
|
+
f"No full scan found for commit {commit_sha} in repo {params.repo} "
|
|
1230
|
+
"(--base-commit-sha). Ensure a scan was created for that commit "
|
|
1231
|
+
"(e.g. the CLI runs on default-branch pushes), or pass "
|
|
1232
|
+
"--base-scan-id instead."
|
|
1233
|
+
)
|
|
1234
|
+
if self.cli_config.disable_blocking:
|
|
1235
|
+
sys.exit(0)
|
|
1236
|
+
sys.exit(self.cli_config.exit_code_on_api_error)
|
|
1237
|
+
log.info(f"Using full scan {scan_id} (commit {commit_sha}) as diff baseline (--base-commit-sha)")
|
|
1238
|
+
return scan_id
|
|
1239
|
+
|
|
1240
|
+
try:
|
|
1241
|
+
return self.get_head_scan_for_repo(params.repo)
|
|
1242
|
+
except APIResourceNotFound:
|
|
1243
|
+
return None
|
|
1244
|
+
|
|
1157
1245
|
@staticmethod
|
|
1158
1246
|
def update_package_values(pkg: Package) -> Package:
|
|
1159
1247
|
pkg.purl = f"{pkg.name}@{pkg.version}"
|
|
@@ -1242,8 +1330,8 @@ class Core:
|
|
|
1242
1330
|
OVERWRITES whatever the diff embedded, before anything reads it.
|
|
1243
1331
|
Either way the embedded license payload is dead weight, and on
|
|
1244
1332
|
large dependency trees it inflated the diff response past ~2.3MB
|
|
1245
|
-
and truncated it mid-string, crashing ``response.json()
|
|
1246
|
-
|
|
1333
|
+
and truncated it mid-string, crashing ``response.json()``.
|
|
1334
|
+
Defaulting to ``False`` keeps the
|
|
1247
1335
|
diff lean with zero change to any output artifact. The parameter
|
|
1248
1336
|
is retained as an explicit override seam, not wired to the
|
|
1249
1337
|
``--exclude-license-details`` user flag (which still governs the
|
|
@@ -1388,11 +1476,9 @@ class Core:
|
|
|
1388
1476
|
log.info("No supported manifest files found - creating empty scan for diff comparison")
|
|
1389
1477
|
scan_files = Core.empty_head_scan_file()
|
|
1390
1478
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
except APIResourceNotFound:
|
|
1395
|
-
head_full_scan_id = None
|
|
1479
|
+
# Resolve the baseline scan: --base-scan-id / --base-commit-sha override
|
|
1480
|
+
# the repository's head scan (None only when the repo has no head scan yet).
|
|
1481
|
+
head_full_scan_id = self.resolve_base_full_scan_id(params)
|
|
1396
1482
|
|
|
1397
1483
|
# If no head scan exists, create an empty baseline scan
|
|
1398
1484
|
if head_full_scan_id is None:
|
|
@@ -1475,7 +1561,7 @@ class Core:
|
|
|
1475
1561
|
# (the --exclude-license-details user flag) into the diff request. The
|
|
1476
1562
|
# diff path never consumes embedded license data (see
|
|
1477
1563
|
# get_added_and_removed_packages docstring), so requesting it only bloats
|
|
1478
|
-
# the response and risks the
|
|
1564
|
+
# the response and risks the truncation crash on large repos. The
|
|
1479
1565
|
# user flag still controls the dashboard report URL below; it just no
|
|
1480
1566
|
# longer gates this internal diff payload.
|
|
1481
1567
|
(
|
|
@@ -18,7 +18,7 @@ log = logging.getLogger(__name__)
|
|
|
18
18
|
# Pinned @coana-tech/cli version. Bumped deliberately per Python CLI release so the
|
|
19
19
|
# reachability engine version only changes through a standard pip upgrade (advance notice).
|
|
20
20
|
# Pass --reach-version latest to opt into the newest published version instead.
|
|
21
|
-
DEFAULT_COANA_CLI_VERSION: Final = "15.
|
|
21
|
+
DEFAULT_COANA_CLI_VERSION: Final = "15.9.0"
|
|
22
22
|
|
|
23
23
|
# Resolved @coana-tech/cli script paths from the npm-install fallback, keyed by version.
|
|
24
24
|
# Lives for the process lifetime so repeated fallback invocations install only once
|
|
@@ -55,7 +55,7 @@ class ReachabilityAnalyzer:
|
|
|
55
55
|
|
|
56
56
|
def _resolve_coana_package_spec(self, version: Optional[str] = None) -> str:
|
|
57
57
|
"""
|
|
58
|
-
Resolve the @coana-tech/cli package spec to run (e.g. '@coana-tech/cli@15.
|
|
58
|
+
Resolve the @coana-tech/cli package spec to run (e.g. '@coana-tech/cli@15.9.0').
|
|
59
59
|
|
|
60
60
|
Args:
|
|
61
61
|
version: Coana CLI version to use.
|
|
@@ -64,7 +64,7 @@ class ReachabilityAnalyzer:
|
|
|
64
64
|
- '<semver>': that exact version.
|
|
65
65
|
|
|
66
66
|
Returns:
|
|
67
|
-
str: The package specifier to use with npx (e.g. '@coana-tech/cli@15.
|
|
67
|
+
str: The package specifier to use with npx (e.g. '@coana-tech/cli@15.9.0').
|
|
68
68
|
"""
|
|
69
69
|
return f"@coana-tech/cli@{self._resolve_coana_version(version)}"
|
|
70
70
|
|