From 77b18a7c24e46cce58e10a3e6e17efe0d94b17de Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Wed, 5 Aug 2026 12:56:32 -0400 Subject: [PATCH 1/8] fix(core): raise on SBOM fetch failure instead of writing empty reports (CE-362) get_sbom_data returned {} when the full-scan stream fetch failed, so report generation continued and produced empty GitLab dependency scanning, license, and SARIF output with exit code 0. Raise APIFailure instead so the failure goes through the CLI's existing API-error handling (exit code 3 by default, still exit 0 with --disable-blocking). Bump the socketdev floor to 3.4.2, the bundled release that adds the missing purl types (e.g. "generic") and per-artifact parse resilience that caused this failure mode. Merge after socketdev 3.4.2 is on PyPI. Co-Authored-By: Claude Fable 5 --- pyproject.toml | 2 +- socketsecurity/core/__init__.py | 10 +++++++--- tests/core/test_sdk_methods.py | 20 +++++++++++++++++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 25fbd17..a2d468d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ dependencies = [ 'GitPython', 'packaging', 'python-dotenv', - "socketdev>=3.3.0,<4.0.0", + "socketdev>=3.4.2,<4.0.0", "bs4>=0.0.2", "markdown>=3.10", "brotli>=1.0.9; platform_python_implementation == 'CPython'", diff --git a/socketsecurity/core/__init__.py b/socketsecurity/core/__init__.py index a372de4..d81b7f7 100644 --- a/socketsecurity/core/__init__.py +++ b/socketsecurity/core/__init__.py @@ -154,9 +154,13 @@ def get_sbom_data(self, full_scan_id: str) -> Dict[str, SocketArtifact]: """Returns SBOM artifacts for a full scan keyed by artifact ID.""" response = self.sdk.fullscans.stream(self.config.org_slug, full_scan_id, use_types=True) if not response.success: - log.debug(f"Failed to get SBOM data for full-scan {full_scan_id}") - log.debug(response.message) - return {} + # Raise instead of returning {} so a failed fetch surfaces as an + # API error (exit code 3 by default) rather than empty reports. + log.error(f"Failed to get SBOM data for full-scan {full_scan_id}") + log.error(response.message) + raise APIFailure( + f"Failed to get SBOM data for full-scan {full_scan_id}: {response.message}" + ) if not hasattr(response, "artifacts") or not response.artifacts: return {} return response.artifacts diff --git a/tests/core/test_sdk_methods.py b/tests/core/test_sdk_methods.py index 9b1ce44..7fbaae4 100644 --- a/tests/core/test_sdk_methods.py +++ b/tests/core/test_sdk_methods.py @@ -1,5 +1,6 @@ import pytest -from socketdev.fullscans import FullScanParams +from socketdev.exceptions import APIFailure +from socketdev.fullscans import FullScanParams, FullScanStreamResponse from socketsecurity.config import CliConfig from socketsecurity.core import Core @@ -263,6 +264,23 @@ def test_get_added_and_removed_packages_license_override(core): include_license_details="true", ) +def test_get_sbom_data_failure_raises(core): + """A failed SBOM stream fetch raises instead of returning {} (CE-362). + + Returning {} let report generation continue and emit empty results with + exit code 0; raising routes the failure through the CLI's API-error + handling instead. + """ + core.sdk.fullscans.stream.side_effect = None + core.sdk.fullscans.stream.return_value = FullScanStreamResponse.from_dict({ + "success": False, + "status": 200, + "message": "Error parsing stream response", + }) + + with pytest.raises(APIFailure, match="Failed to get SBOM data"): + core.get_sbom_data("head") + def test_empty_alerts_preserved(core): """Test that empty alerts arrays stay as empty arrays and don't become None""" # Get the scan that contains dp2 (which has empty alerts array) From 648fd416b666073fd4f945b0dad3e6006ce0e335 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Wed, 5 Aug 2026 22:21:35 -0400 Subject: [PATCH 2/8] chore: lock socketdev 3.4.2 Co-Authored-By: Claude Fable 5 --- uv.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/uv.lock b/uv.lock index ce7c38a..f45261e 100644 --- a/uv.lock +++ b/uv.lock @@ -1281,15 +1281,15 @@ wheels = [ [[package]] name = "socketdev" -version = "3.3.0" +version = "3.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/25/30/16155f7f27d18274f364b3bd3506ee45d17f53fc8938aaea9a618054449b/socketdev-3.3.0.tar.gz", hash = "sha256:3d60bd4ac3201e9d581b1fe02bf2e6aef1b90c13ae75d15a8664aa9ef966734e", size = 181519, upload-time = "2026-06-10T11:41:17.942Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/49/bc163ae945bf2b14848f714f4b4b06700d8c20d20607cd4fef224329bb9c/socketdev-3.4.2.tar.gz", hash = "sha256:41c0ce451826f1e100cd84859ae6114bd33e837bc3bd3ebee261dd80d4a93b7f", size = 190799, upload-time = "2026-08-05T23:29:41.546Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/dd/25622e033182e8c744d2420bb4f056206edc096a1e5ce8e4af4b0a0c0791/socketdev-3.3.0-py3-none-any.whl", hash = "sha256:513c045ce42bdd6cc2bb66a527f5863e0c399e56dbdcb1832cd5d94a5fb1a5e4", size = 67956, upload-time = "2026-06-10T11:41:16.534Z" }, + { url = "https://files.pythonhosted.org/packages/19/7f/6dfa45a9b6fb7bd869397c6ad8b0717b03a1d546154e598060d41322fee7/socketdev-3.4.2-py3-none-any.whl", hash = "sha256:94f86605e0677be0a22a4bfadd586f9b8ca907f664ce69bdeadab9dcc181d6ce", size = 72010, upload-time = "2026-08-05T23:29:39.777Z" }, ] [[package]] @@ -1351,7 +1351,7 @@ requires-dist = [ { name = "python-dotenv" }, { name = "requests" }, { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.3.0" }, - { name = "socketdev", specifier = ">=3.3.0,<4.0.0" }, + { name = "socketdev", specifier = ">=3.4.2,<4.0.0" }, { name = "twine", marker = "extra == 'dev'" }, { name = "uv", marker = "extra == 'dev'", specifier = ">=0.1.0" }, ] From 1fb2f7e76e44dd5e449fb81d1fdce986fd93fd35 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Wed, 5 Aug 2026 22:27:32 -0400 Subject: [PATCH 3/8] chore: bump version to 2.5.11 Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 12 ++++++++++++ pyproject.toml | 2 +- socketsecurity/__init__.py | 2 +- uv.lock | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b7deb2..f77d95f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 2.5.11 + +### Fixed: SBOM fetch failures no longer produce empty reports + +- `Core.get_sbom_data` now raises `APIFailure` when the full-scan stream fetch + fails, so the run exits through the CLI's API-error handling (exit code 3 by + default; `--disable-blocking` still exits 0) instead of writing empty + GitLab dependency-scanning, license, and SARIF reports. +- Requires `socketdev>=3.4.2`, which recognizes the full set of purl types + (e.g. `generic`) and skips individual unparseable artifacts in the stream + instead of failing the whole response. + ## 2.5.9 ### Changed: bump pinned @coana-tech/cli to 15.10.3 diff --git a/pyproject.toml b/pyproject.toml index a2d468d..55d2b1e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "hatchling.build" [project] name = "socketsecurity" -version = "2.5.9" +version = "2.5.11" requires-python = ">= 3.11" license = {"file" = "LICENSE"} dependencies = [ diff --git a/socketsecurity/__init__.py b/socketsecurity/__init__.py index 0189af7..da66ffc 100644 --- a/socketsecurity/__init__.py +++ b/socketsecurity/__init__.py @@ -1,3 +1,3 @@ __author__ = 'socket.dev' -__version__ = '2.5.9' +__version__ = '2.5.11' USER_AGENT = f'SocketPythonCLI/{__version__}' diff --git a/uv.lock b/uv.lock index f45261e..fa7ff50 100644 --- a/uv.lock +++ b/uv.lock @@ -1294,7 +1294,7 @@ wheels = [ [[package]] name = "socketsecurity" -version = "2.5.9" +version = "2.5.11" source = { editable = "." } dependencies = [ { name = "brotli", marker = "platform_python_implementation == 'CPython'" }, From 18e51b0b134478a12f6dcb00f816d23b31bf3453 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Wed, 5 Aug 2026 23:00:22 -0400 Subject: [PATCH 4/8] ci(e2e): retry reachability on empty results, upload diagnostics on failure The e2e-reachability job intermittently fails with 'no components with alerts in .socket.facts.json': the tier-1 reachability backend can return empty results while the CLI reports success (ENG-5093), and the same flake has hit unrelated PRs. - Add a retry-probe hook to the e2e matrix: entries that define it get up to 3 scan attempts, retrying only when the probe says the output looks incomplete. Persistent failures still fail via the validate step. Each retry emits a warning annotation and a step-summary line so flake frequency stays visible. - Add tests/e2e/reach-facts-probe.sh: exits 0 when the facts file has alerted components, non-zero (retry) when empty or missing. - Upload /tmp/e2e-output.log, SARIF/GitLab outputs, and facts files as artifacts when any e2e job fails, so flakes are diagnosable without a re-run. Also bump version to 2.6.2 (2.6.0 and 2.6.1 are being released ahead of this PR). Co-Authored-By: Claude Fable 5 --- .github/workflows/e2e-test.yml | 46 +++++++++++++++++++++++++++++++++- CHANGELOG.md | 2 +- pyproject.toml | 2 +- socketsecurity/__init__.py | 2 +- tests/e2e/reach-facts-probe.sh | 19 ++++++++++++++ uv.lock | 2 +- 6 files changed, 68 insertions(+), 5 deletions(-) create mode 100755 tests/e2e/reach-facts-probe.sh diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 17bdc15..a2bf195 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -46,6 +46,11 @@ jobs: --enable-debug validate: tests/e2e/validate-reachability.sh setup-node: "true" + # The tier-1 reachability backend intermittently returns empty + # results while the CLI reports success (ENG-5093). The probe + # exits 0 when the facts file has alerted components; anything + # else is retried before validation fails the job. + retry-probe: bash tests/e2e/reach-facts-probe.sh tests/e2e/fixtures/simple-npm - name: gitlab args: >- @@ -96,15 +101,54 @@ jobs: - name: Run Socket CLI env: SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_CLI_API_TOKEN }} + RETRY_PROBE: ${{ matrix.retry-probe }} run: | set -o pipefail - socketcli ${{ matrix.args }} 2>&1 | tee /tmp/e2e-output.log + # Entries with retry-probe get up to 3 attempts: the probe exits 0 + # when the scan output looks complete, and a run that fails it is + # re-run on the assumption of a transient backend failure. A + # persistent failure still reaches the validate step, which fails + # the job with full context. Retries are surfaced as warning + # annotations so flake frequency stays visible instead of being + # silently absorbed. + max_attempts=3 + attempt=1 + while :; do + socketcli ${{ matrix.args }} 2>&1 | tee /tmp/e2e-output.log + [ -z "$RETRY_PROBE" ] && break + if bash -c "$RETRY_PROBE"; then + break + fi + if [ "$attempt" -ge "$max_attempts" ]; then + echo "::warning title=e2e-${{ matrix.name }} incomplete results::output still fails the completeness probe after ${max_attempts} attempts; letting validation fail the job" + break + fi + echo "::warning title=e2e-${{ matrix.name }} transient retry::attempt ${attempt} failed the completeness probe (suspected backend transient, see ENG-5093); retrying" + echo "e2e-${{ matrix.name }}: retry after attempt ${attempt} — completeness probe failed (suspected transient)" >> "$GITHUB_STEP_SUMMARY" + attempt=$((attempt+1)) + sleep 30 + done - name: Validate results env: SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_CLI_API_TOKEN }} run: bash ${{ matrix.validate }} + - name: Upload diagnostics on failure + if: failure() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: e2e-${{ matrix.name }}-diagnostics-attempt${{ github.run_attempt }} + path: | + /tmp/e2e-output.log + /tmp/*.sarif + tests/e2e/fixtures/simple-npm/.socket.facts.json + tests/e2e/fixtures/simple-pypi/.socket.facts.json + gl-*.json + license_output.json + if-no-files-found: ignore + retention-days: 14 + # Branch protection requires the e2e-* checks, but the `e2e` job above is # skipped on PRs that can't access repository secrets -- fork PRs and # Dependabot PRs. A job skipped via a job-level `if` never expands its diff --git a/CHANGELOG.md b/CHANGELOG.md index f77d95f..cebbbf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 2.5.11 +## 2.6.2 ### Fixed: SBOM fetch failures no longer produce empty reports diff --git a/pyproject.toml b/pyproject.toml index 55d2b1e..0a77e80 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "hatchling.build" [project] name = "socketsecurity" -version = "2.5.11" +version = "2.6.2" requires-python = ">= 3.11" license = {"file" = "LICENSE"} dependencies = [ diff --git a/socketsecurity/__init__.py b/socketsecurity/__init__.py index da66ffc..c4c8bad 100644 --- a/socketsecurity/__init__.py +++ b/socketsecurity/__init__.py @@ -1,3 +1,3 @@ __author__ = 'socket.dev' -__version__ = '2.5.11' +__version__ = '2.6.2' USER_AGENT = f'SocketPythonCLI/{__version__}' diff --git a/tests/e2e/reach-facts-probe.sh b/tests/e2e/reach-facts-probe.sh new file mode 100755 index 0000000..e13aaa4 --- /dev/null +++ b/tests/e2e/reach-facts-probe.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# Exits 0 when the reachability facts file contains components with alerts. +# +# Used by the e2e workflow's retry-probe hook: a --reach run against the +# known-vulnerable fixture that reports success but yields no alerted +# components is the signature of a transient tier-1 backend failure +# (ENG-5093), so the run is worth repeating before validation fails the job. +set -euo pipefail + +TARGET="${1:?usage: reach-facts-probe.sh }" + +uv run python - "$TARGET" <<'PY' +import sys + +from socketsecurity.core.alert_selection import load_components_with_alerts + +components = load_components_with_alerts(sys.argv[1], ".socket.facts.json") +sys.exit(0 if components else 1) +PY diff --git a/uv.lock b/uv.lock index fa7ff50..74c8ea8 100644 --- a/uv.lock +++ b/uv.lock @@ -1294,7 +1294,7 @@ wheels = [ [[package]] name = "socketsecurity" -version = "2.5.11" +version = "2.6.2" source = { editable = "." } dependencies = [ { name = "brotli", marker = "platform_python_implementation == 'CPython'" }, From 8141b48ddaf1543eafae66e6dae47483e5b7499f Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Wed, 5 Aug 2026 23:50:58 -0400 Subject: [PATCH 5/8] chore: require socketdev 3.5.0 Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 2 +- pyproject.toml | 2 +- uv.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cebbbf3..6f1dff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ fails, so the run exits through the CLI's API-error handling (exit code 3 by default; `--disable-blocking` still exits 0) instead of writing empty GitLab dependency-scanning, license, and SARIF reports. -- Requires `socketdev>=3.4.2`, which recognizes the full set of purl types +- Requires `socketdev>=3.5.0`, which recognizes the full set of purl types (e.g. `generic`) and skips individual unparseable artifacts in the stream instead of failing the whole response. diff --git a/pyproject.toml b/pyproject.toml index 0a77e80..733ed5e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ dependencies = [ 'GitPython', 'packaging', 'python-dotenv', - "socketdev>=3.4.2,<4.0.0", + "socketdev>=3.5.0,<4.0.0", "bs4>=0.0.2", "markdown>=3.10", "brotli>=1.0.9; platform_python_implementation == 'CPython'", diff --git a/uv.lock b/uv.lock index 74c8ea8..9210689 100644 --- a/uv.lock +++ b/uv.lock @@ -1281,15 +1281,15 @@ wheels = [ [[package]] name = "socketdev" -version = "3.4.2" +version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bc/49/bc163ae945bf2b14848f714f4b4b06700d8c20d20607cd4fef224329bb9c/socketdev-3.4.2.tar.gz", hash = "sha256:41c0ce451826f1e100cd84859ae6114bd33e837bc3bd3ebee261dd80d4a93b7f", size = 190799, upload-time = "2026-08-05T23:29:41.546Z" } +sdist = { url = "https://files.pythonhosted.org/packages/64/24/0c11290dc7d59e24b7075035c7e1a3ab87fa17a445cebc88cfa6ee98b22c/socketdev-3.5.0.tar.gz", hash = "sha256:a2b20f9b98f73c25f3d2e97a1ae730504509c91219c0b393f28a9230266b3531", size = 195138, upload-time = "2026-08-06T03:47:14.185Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/7f/6dfa45a9b6fb7bd869397c6ad8b0717b03a1d546154e598060d41322fee7/socketdev-3.4.2-py3-none-any.whl", hash = "sha256:94f86605e0677be0a22a4bfadd586f9b8ca907f664ce69bdeadab9dcc181d6ce", size = 72010, upload-time = "2026-08-05T23:29:39.777Z" }, + { url = "https://files.pythonhosted.org/packages/c3/75/5a8506a473716740e94f2f01b697909333f966c143d8a0a566d278e6118d/socketdev-3.5.0-py3-none-any.whl", hash = "sha256:780f5841770397035ff87de6181d954b6318cd0a07f6fdd304d1376667f33f68", size = 72027, upload-time = "2026-08-06T03:47:12.773Z" }, ] [[package]] @@ -1351,7 +1351,7 @@ requires-dist = [ { name = "python-dotenv" }, { name = "requests" }, { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.3.0" }, - { name = "socketdev", specifier = ">=3.4.2,<4.0.0" }, + { name = "socketdev", specifier = ">=3.5.0,<4.0.0" }, { name = "twine", marker = "extra == 'dev'" }, { name = "uv", marker = "extra == 'dev'", specifier = ">=0.1.0" }, ] From f7d5ab075fffebee53b60704892d2cd291054194 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Thu, 6 Aug 2026 00:10:00 -0400 Subject: [PATCH 6/8] Drop ticket references from e2e comments and note the retry hardening in the changelog Co-Authored-By: Claude Fable 5 Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> --- .github/workflows/e2e-test.yml | 8 ++++---- CHANGELOG.md | 6 ++++++ tests/e2e/reach-facts-probe.sh | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index a2bf195..fd28ea6 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -47,9 +47,9 @@ jobs: validate: tests/e2e/validate-reachability.sh setup-node: "true" # The tier-1 reachability backend intermittently returns empty - # results while the CLI reports success (ENG-5093). The probe - # exits 0 when the facts file has alerted components; anything - # else is retried before validation fails the job. + # results while the CLI reports success. The probe exits 0 when + # the facts file has alerted components; anything else is + # retried before validation fails the job. retry-probe: bash tests/e2e/reach-facts-probe.sh tests/e2e/fixtures/simple-npm - name: gitlab @@ -123,7 +123,7 @@ jobs: echo "::warning title=e2e-${{ matrix.name }} incomplete results::output still fails the completeness probe after ${max_attempts} attempts; letting validation fail the job" break fi - echo "::warning title=e2e-${{ matrix.name }} transient retry::attempt ${attempt} failed the completeness probe (suspected backend transient, see ENG-5093); retrying" + echo "::warning title=e2e-${{ matrix.name }} transient retry::attempt ${attempt} failed the completeness probe (suspected backend transient); retrying" echo "e2e-${{ matrix.name }}: retry after attempt ${attempt} — completeness probe failed (suspected transient)" >> "$GITHUB_STEP_SUMMARY" attempt=$((attempt+1)) sleep 30 diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f1dff8..113bc9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,12 @@ (e.g. `generic`) and skips individual unparseable artifacts in the stream instead of failing the whole response. +### Changed: e2e reachability jobs retry transient empty results + +- The e2e workflow now detects reachability runs that report success with no + alerted components in the facts file — a transient backend condition — and + retries the scan up to three times, uploading run artifacts on failure. + ## 2.5.9 ### Changed: bump pinned @coana-tech/cli to 15.10.3 diff --git a/tests/e2e/reach-facts-probe.sh b/tests/e2e/reach-facts-probe.sh index e13aaa4..c1db4dd 100755 --- a/tests/e2e/reach-facts-probe.sh +++ b/tests/e2e/reach-facts-probe.sh @@ -3,8 +3,8 @@ # # Used by the e2e workflow's retry-probe hook: a --reach run against the # known-vulnerable fixture that reports success but yields no alerted -# components is the signature of a transient tier-1 backend failure -# (ENG-5093), so the run is worth repeating before validation fails the job. +# components is the signature of a transient tier-1 backend failure, +# so the run is worth repeating before validation fails the job. set -euo pipefail TARGET="${1:?usage: reach-facts-probe.sh }" From e3e0f304ffdf3b3f994acb8571778ea239518bb2 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Thu, 6 Aug 2026 00:14:36 -0400 Subject: [PATCH 7/8] Move e2e retry changelog entry out and drop remaining ticket reference The e2e retry hardening ships with the dependency pinning PR instead, so its changelog entry moves there. Co-Authored-By: Claude Fable 5 Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> --- CHANGELOG.md | 6 ------ tests/core/test_sdk_methods.py | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 113bc9b..6f1dff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,12 +12,6 @@ (e.g. `generic`) and skips individual unparseable artifacts in the stream instead of failing the whole response. -### Changed: e2e reachability jobs retry transient empty results - -- The e2e workflow now detects reachability runs that report success with no - alerted components in the facts file — a transient backend condition — and - retries the scan up to three times, uploading run artifacts on failure. - ## 2.5.9 ### Changed: bump pinned @coana-tech/cli to 15.10.3 diff --git a/tests/core/test_sdk_methods.py b/tests/core/test_sdk_methods.py index 7fbaae4..634c014 100644 --- a/tests/core/test_sdk_methods.py +++ b/tests/core/test_sdk_methods.py @@ -265,7 +265,7 @@ def test_get_added_and_removed_packages_license_override(core): ) def test_get_sbom_data_failure_raises(core): - """A failed SBOM stream fetch raises instead of returning {} (CE-362). + """A failed SBOM stream fetch raises instead of returning {}. Returning {} let report generation continue and emit empty results with exit code 0; raising routes the failure through the CLI's API-error From 079fe8785522cef4822ba3b19e676fc1a1647a77 Mon Sep 17 00:00:00 2001 From: lelia <2418071+lelia@users.noreply.github.com> Date: Thu, 6 Aug 2026 17:04:02 -0400 Subject: [PATCH 8/8] docs: changelog phrasing tweak Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a710f71..53adb48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ default; `--disable-blocking` still exits 0) instead of writing empty GitLab dependency-scanning, license, and SARIF reports. - The underlying stream-parse failure was fixed in `socketdev` 3.4.2 (already - pinned at `3.5.0`): unrecognized purl types such as `generic` now resolve + pinned to `3.5.0`): unrecognized purl types such as `generic` now resolve instead of raising, and individual unparseable artifacts are skipped rather than failing the whole response.