socketsecurity 2.2.89__tar.gz → 2.2.91__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.2.89 → socketsecurity-2.2.91}/.github/workflows/version-check.yml +36 -9
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.gitignore +2 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.hooks/sync_version.py +56 -7
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/CHANGELOG.md +39 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/PKG-INFO +31 -1
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/README.md +30 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/docs/cli-reference.md +1 -1
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/pyproject.toml +1 -1
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/__init__.py +1 -1
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/config.py +75 -1
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/__init__.py +5 -0
- socketsecurity-2.2.91/socketsecurity/fossa_compat.py +459 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/output.py +107 -46
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/socketcli.py +46 -21
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/core/test_package_and_alerts.py +38 -1
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/e2e/validate-reachability.sh +35 -19
- socketsecurity-2.2.91/tests/fixtures/fossa/README.md +18 -0
- socketsecurity-2.2.91/tests/fixtures/fossa/fossa-analyze-empty.json +13 -0
- socketsecurity-2.2.91/tests/fixtures/fossa/fossa-analyze-populated.json +1275 -0
- socketsecurity-2.2.91/tests/fixtures/fossa/fossa-sbom-empty-deep.json +1 -0
- socketsecurity-2.2.91/tests/fixtures/fossa/fossa-sbom-populated.json +1 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_cli_config.py +47 -2
- socketsecurity-2.2.91/tests/unit/test_fossa_compat.py +470 -0
- socketsecurity-2.2.91/tests/unit/test_fossa_parity.py +106 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_output.py +265 -24
- socketsecurity-2.2.91/tests/unit/test_socketcli.py +134 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/uv.lock +4 -4
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.github/CODEOWNERS +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.github/PULL_REQUEST_TEMPLATE/bug-fix.md +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.github/PULL_REQUEST_TEMPLATE/improvement.md +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.github/workflows/docker-stable.yml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.github/workflows/e2e-test.yml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.github/workflows/pr-preview.yml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.github/workflows/python-tests.yml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.github/workflows/release.yml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.github/zizmor.yml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.pre-commit-config.yaml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/.python-version +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/Dockerfile +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/LICENSE +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/Makefile +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/docs/ci-cd.md +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/docs/development.md +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/docs/troubleshooting.md +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/examples/config/sarif-dashboard-parity.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/examples/config/sarif-dashboard-parity.toml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/examples/config/sarif-diff-ci-cd.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/examples/config/sarif-diff-ci-cd.toml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/examples/config/sarif-instance-detail.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/examples/config/sarif-instance-detail.toml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/instructions/gitlab-commit-status/uat.md +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/pytest.ini +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/scripts/build_container.sh +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/scripts/build_container_flexible.sh +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/scripts/deploy-test-docker.sh +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/scripts/deploy-test-pypi.sh +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/scripts/docker-entrypoint.sh +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/scripts/run.sh +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/session.md +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socket.yml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/alert_selection.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/classes.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/cli_client.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/exceptions.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/git_interface.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/helper/__init__.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/helper/socket_facts_loader.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/lazy_file_loader.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/logging.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/messages.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/resource_utils.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/scm/__init__.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/scm/base.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/scm/client.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/scm/github.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/scm/gitlab.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/scm_comments.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/socket_config.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/tools/reachability.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/core/utils.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/plugins/__init__.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/plugins/base.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/plugins/formatters/__init__.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/plugins/formatters/slack.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/plugins/jira.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/plugins/manager.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/plugins/slack.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/plugins/teams.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/socketsecurity/plugins/webhook.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/__init__.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/core/conftest.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/core/create_diff_input.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/core/test_diff_alerts.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/core/test_diff_generation.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/core/test_has_manifest_files.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/core/test_sdk_methods.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/core/test_supporting_methods.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/fullscans/create_response.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/fullscans/diff/stream_diff.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/fullscans/diff/stream_diff_full.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/fullscans/head_scan/metadata.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/fullscans/head_scan/stream_scan.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/fullscans/head_scan/stream_scan_full.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/fullscans/new_scan/metadata.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/fullscans/new_scan/stream_scan.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/repos/repo_info_error.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/repos/repo_info_no_head.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/repos/repo_info_success.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/data/settings/security-policy.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/e2e/fixtures/simple-npm/index.js +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/e2e/fixtures/simple-npm/package.json +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/e2e/fixtures/simple-pypi/requirements.txt +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/e2e/validate-gitlab.sh +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/e2e/validate-json.sh +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/e2e/validate-sarif.sh +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/e2e/validate-scan.sh +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/__init__.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_alert_selection.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_client.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_config.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_dependency_overview.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_disable_ignore.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_gitlab_auth.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_gitlab_auth_fallback.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_gitlab_commit_status.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_gitlab_format.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_ignore_telemetry_filtering.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/tests/unit/test_slack_plugin.py +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/workflows/bitbucket-pipelines.yml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/workflows/buildkite.yml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/workflows/github-actions.yml +0 -0
- {socketsecurity-2.2.89 → socketsecurity-2.2.91}/workflows/gitlab-ci.yml +0 -0
|
@@ -35,16 +35,43 @@ jobs:
|
|
|
35
35
|
MAIN_VERSION=$(git show origin/main:socketsecurity/__init__.py | grep -o "__version__.*" | awk '{print $3}' | tr -d "'")
|
|
36
36
|
echo "MAIN_VERSION=$MAIN_VERSION" >> $GITHUB_ENV
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
export PR_VERSION
|
|
39
|
+
export MAIN_VERSION
|
|
40
|
+
|
|
41
|
+
# Compare against both main and latest published PyPI release.
|
|
42
|
+
python3 <<'PY'
|
|
43
|
+
import json
|
|
44
|
+
import os
|
|
45
|
+
import urllib.request
|
|
40
46
|
from packaging import version
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
|
|
48
|
+
pr_ver = version.parse(os.environ["PR_VERSION"])
|
|
49
|
+
main_ver = version.parse(os.environ["MAIN_VERSION"])
|
|
50
|
+
|
|
51
|
+
with urllib.request.urlopen("https://pypi.org/pypi/socketsecurity/json") as response:
|
|
52
|
+
pypi_data = json.load(response)
|
|
53
|
+
|
|
54
|
+
published_versions = []
|
|
55
|
+
for raw in pypi_data.get("releases", {}).keys():
|
|
56
|
+
parsed = version.parse(raw)
|
|
57
|
+
if not parsed.is_prerelease and not parsed.is_devrelease:
|
|
58
|
+
published_versions.append(parsed)
|
|
59
|
+
|
|
60
|
+
pypi_ver = max(published_versions) if published_versions else version.parse("0.0.0")
|
|
61
|
+
required_floor = max(main_ver, pypi_ver)
|
|
62
|
+
|
|
63
|
+
if pr_ver <= required_floor:
|
|
64
|
+
print(
|
|
65
|
+
f"❌ Version must be greater than main and PyPI! "
|
|
66
|
+
f"Main: {main_ver}, PyPI: {pypi_ver}, PR: {pr_ver}"
|
|
67
|
+
)
|
|
68
|
+
raise SystemExit(1)
|
|
69
|
+
|
|
70
|
+
print(
|
|
71
|
+
f"✅ Version properly incremented. "
|
|
72
|
+
f"Main: {main_ver}, PyPI: {pypi_ver}, PR: {pr_ver}"
|
|
73
|
+
)
|
|
74
|
+
PY
|
|
48
75
|
|
|
49
76
|
- name: Require uv.lock update when pyproject changes
|
|
50
77
|
run: |
|
|
@@ -12,7 +12,9 @@ UV_LOCK_FILE = pathlib.Path("uv.lock")
|
|
|
12
12
|
|
|
13
13
|
VERSION_PATTERN = re.compile(r"__version__\s*=\s*['\"]([^'\"]+)['\"]")
|
|
14
14
|
PYPROJECT_PATTERN = re.compile(r'^version\s*=\s*".*"$', re.MULTILINE)
|
|
15
|
-
|
|
15
|
+
STABLE_VERSION_PATTERN = re.compile(r"^\d+\.\d+\.\d+$")
|
|
16
|
+
PYPI_PROD_API = "https://pypi.org/pypi/socketsecurity/json"
|
|
17
|
+
PYPI_TEST_API = "https://test.pypi.org/pypi/socketsecurity/json"
|
|
16
18
|
|
|
17
19
|
def read_version_from_init(path: pathlib.Path) -> str:
|
|
18
20
|
content = path.read_text()
|
|
@@ -39,17 +41,39 @@ def bump_patch_version(version: str) -> str:
|
|
|
39
41
|
parts[-1] = str(int(parts[-1]) + 1)
|
|
40
42
|
return ".".join(parts)
|
|
41
43
|
|
|
42
|
-
def
|
|
44
|
+
def parse_stable_version(version: str):
|
|
45
|
+
if not STABLE_VERSION_PATTERN.fullmatch(version):
|
|
46
|
+
return None
|
|
47
|
+
return tuple(int(part) for part in version.split("."))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def format_stable_version(version_parts) -> str:
|
|
51
|
+
return ".".join(str(part) for part in version_parts)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def fetch_existing_versions(api_url: str) -> set:
|
|
43
55
|
try:
|
|
44
|
-
with urllib.request.urlopen(
|
|
56
|
+
with urllib.request.urlopen(api_url) as response:
|
|
45
57
|
data = json.load(response)
|
|
46
58
|
return set(data.get("releases", {}).keys())
|
|
47
59
|
except Exception as e:
|
|
48
|
-
print(f"⚠️ Warning: Failed to fetch
|
|
60
|
+
print(f"⚠️ Warning: Failed to fetch versions from {api_url}: {e}")
|
|
49
61
|
return set()
|
|
50
62
|
|
|
63
|
+
|
|
64
|
+
def fetch_latest_stable_pypi_version():
|
|
65
|
+
versions = fetch_existing_versions(PYPI_PROD_API)
|
|
66
|
+
stable_versions = []
|
|
67
|
+
for ver in versions:
|
|
68
|
+
parsed = parse_stable_version(ver)
|
|
69
|
+
if parsed is not None:
|
|
70
|
+
stable_versions.append(parsed)
|
|
71
|
+
if not stable_versions:
|
|
72
|
+
return None
|
|
73
|
+
return max(stable_versions)
|
|
74
|
+
|
|
51
75
|
def find_next_available_dev_version(base_version: str) -> str:
|
|
52
|
-
existing_versions = fetch_existing_versions()
|
|
76
|
+
existing_versions = fetch_existing_versions(PYPI_TEST_API)
|
|
53
77
|
for i in range(1, 100):
|
|
54
78
|
candidate = f"{base_version}.dev{i}"
|
|
55
79
|
if candidate not in existing_versions:
|
|
@@ -57,6 +81,19 @@ def find_next_available_dev_version(base_version: str) -> str:
|
|
|
57
81
|
print("❌ Could not find available .devN slot after 100 attempts.")
|
|
58
82
|
sys.exit(1)
|
|
59
83
|
|
|
84
|
+
|
|
85
|
+
def find_next_stable_patch_version(current_version: str) -> str:
|
|
86
|
+
current_stable = current_version.split(".dev")[0] if ".dev" in current_version else current_version
|
|
87
|
+
current_parts = parse_stable_version(current_stable)
|
|
88
|
+
if current_parts is None:
|
|
89
|
+
print(f"❌ Unsupported version format for stable bump: {current_version}")
|
|
90
|
+
sys.exit(1)
|
|
91
|
+
|
|
92
|
+
latest_pypi_parts = fetch_latest_stable_pypi_version()
|
|
93
|
+
base_parts = max([current_parts, latest_pypi_parts] if latest_pypi_parts else [current_parts])
|
|
94
|
+
next_parts = (base_parts[0], base_parts[1], base_parts[2] + 1)
|
|
95
|
+
return format_stable_version(next_parts)
|
|
96
|
+
|
|
60
97
|
def inject_version(version: str):
|
|
61
98
|
print(f"🔁 Updating version to: {version}")
|
|
62
99
|
|
|
@@ -105,13 +142,25 @@ def main():
|
|
|
105
142
|
print(f"⚠️ Version was unchanged — auto-bumped. Please git add{lock_hint} + commit again.")
|
|
106
143
|
sys.exit(0)
|
|
107
144
|
else:
|
|
108
|
-
new_version =
|
|
145
|
+
new_version = find_next_stable_patch_version(current_version)
|
|
109
146
|
inject_version(new_version)
|
|
110
147
|
uv_lock_changed = run_uv_lock()
|
|
111
148
|
lock_hint = " and uv.lock" if uv_lock_changed else ""
|
|
112
|
-
print(f"⚠️ Version was unchanged — auto-bumped. Please git add{lock_hint} + commit again.")
|
|
149
|
+
print(f"⚠️ Version was unchanged — auto-bumped to {new_version}. Please git add{lock_hint} + commit again.")
|
|
113
150
|
sys.exit(1)
|
|
114
151
|
else:
|
|
152
|
+
if not dev_mode:
|
|
153
|
+
current_parts = parse_stable_version(current_version)
|
|
154
|
+
latest_pypi_parts = fetch_latest_stable_pypi_version()
|
|
155
|
+
if current_parts is not None and latest_pypi_parts is not None and current_parts <= latest_pypi_parts:
|
|
156
|
+
next_parts = (latest_pypi_parts[0], latest_pypi_parts[1], latest_pypi_parts[2] + 1)
|
|
157
|
+
new_version = format_stable_version(next_parts)
|
|
158
|
+
inject_version(new_version)
|
|
159
|
+
uv_lock_changed = run_uv_lock()
|
|
160
|
+
lock_hint = " and uv.lock" if uv_lock_changed else ""
|
|
161
|
+
print(f"⚠️ Version {current_version} is already published on PyPI — auto-bumped to {new_version}. Please git add{lock_hint} + commit again.")
|
|
162
|
+
sys.exit(1)
|
|
163
|
+
|
|
115
164
|
uv_lock_changed = run_uv_lock()
|
|
116
165
|
if uv_lock_changed:
|
|
117
166
|
print("⚠️ Version already bumped, but uv.lock was out of date and has been updated. Please git add uv.lock + commit again.")
|
|
@@ -1,9 +1,48 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.2.90
|
|
4
|
+
|
|
5
|
+
- Migrated license enrichment PURL lookup to the org-scoped endpoint (`POST /v0/orgs/{slug}/purl`) from the deprecated global endpoint (`POST /v0/purl`).
|
|
6
|
+
|
|
3
7
|
## 2.2.83
|
|
4
8
|
|
|
5
9
|
- Fixed branch detection in detached-HEAD CI checkouts. When `git name-rev --name-only HEAD` returned an output with a suffix operator (e.g. `remotes/origin/master~1`, `master^0`), the `~N`/`^N` was previously passed through as the branch name and rejected by the Socket API as an invalid Git ref. The suffix is now stripped before the prefix split, producing the bare branch name.
|
|
6
10
|
|
|
11
|
+
## 2.2.80
|
|
12
|
+
|
|
13
|
+
- Hardened GitHub Actions workflows.
|
|
14
|
+
- Fixed broken links on PyPI page.
|
|
15
|
+
|
|
16
|
+
## 2.2.79
|
|
17
|
+
|
|
18
|
+
- Updated minimum required Python version.
|
|
19
|
+
- Tweaked CI checks.
|
|
20
|
+
|
|
21
|
+
## 2.2.78
|
|
22
|
+
|
|
23
|
+
- Fixed reachability filtering.
|
|
24
|
+
- Added config file support.
|
|
25
|
+
|
|
26
|
+
## 2.2.77
|
|
27
|
+
|
|
28
|
+
- Fixed `has_manifest_files` failing to match root-level manifest files.
|
|
29
|
+
|
|
30
|
+
## 2.2.76
|
|
31
|
+
|
|
32
|
+
- Added SARIF file output support.
|
|
33
|
+
- Improved reachability filtering.
|
|
34
|
+
|
|
35
|
+
## 2.2.75
|
|
36
|
+
|
|
37
|
+
- Fixed `workspace` flag regression by updating SDK dependency.
|
|
38
|
+
|
|
39
|
+
## 2.2.74
|
|
40
|
+
|
|
41
|
+
- Added `--workspace` flag to CLI args.
|
|
42
|
+
- Added GitLab branch protection flag.
|
|
43
|
+
- Added e2e tests for full scans and full scans with reachability.
|
|
44
|
+
- Bumped dependencies: `cryptography`, `virtualenv`, `filelock`, `urllib3`.
|
|
45
|
+
|
|
7
46
|
## 2.2.71
|
|
8
47
|
|
|
9
48
|
- Added `strace` to the Docker image for debugging purposes.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: socketsecurity
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.91
|
|
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>
|
|
@@ -142,6 +142,7 @@ socketcli \
|
|
|
142
142
|
| Use case | Recommended mode | Key flags |
|
|
143
143
|
|:--|:--|:--|
|
|
144
144
|
| Basic policy enforcement in CI | Diff-based policy check | `--strict-blocking` |
|
|
145
|
+
| Legal/compliance artifact generation | Legal preset | `--legal` |
|
|
145
146
|
| Reachable-focused SARIF for reporting | Full-scope grouped SARIF | `--reach --sarif-scope full --sarif-grouping alert --sarif-reachability reachable --sarif-file <path>` |
|
|
146
147
|
| Detailed reachability export for investigations | Full-scope instance SARIF | `--reach --sarif-scope full --sarif-grouping instance --sarif-reachability all --sarif-file <path>` |
|
|
147
148
|
| Net-new PR findings only | Diff-scope SARIF | `--reach --sarif-scope diff --sarif-reachability reachable --sarif-file <path>` |
|
|
@@ -192,6 +193,35 @@ Run:
|
|
|
192
193
|
socketcli --config .socketcli.toml --target-path .
|
|
193
194
|
```
|
|
194
195
|
|
|
196
|
+
Legal/compliance preset example:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
socketcli --legal --target-path .
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
This preset enables license generation and writes default artifacts unless you override them:
|
|
203
|
+
- `socket-report.json`
|
|
204
|
+
- `socket-summary.txt`
|
|
205
|
+
- `socket-report-link.txt`
|
|
206
|
+
- `socket-sbom.json`
|
|
207
|
+
- `socket-license.json`
|
|
208
|
+
|
|
209
|
+
FOSSA-compatibility shaped legal artifacts:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
socketcli --legal-format fossa --target-path .
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
This switches the JSON report and legal artifact payloads to FOSSA-style compatibility shapes:
|
|
216
|
+
- the analyze artifact becomes a `project` / `vulnerability` / `licensing` / `quality` report
|
|
217
|
+
- the SBOM artifact becomes a FOSSA-attribution-style payload with `copyrightsByLicense`, `deepDependencies`, `directDependencies`, `licenses`, and `project` keys
|
|
218
|
+
|
|
219
|
+
When `--legal-format fossa` is used without explicit output paths, the defaults are closer to the FOSSA pipeline contract:
|
|
220
|
+
- `fossa-analyze.json`
|
|
221
|
+
- `fossa-test.txt`
|
|
222
|
+
- `fossa-link.txt`
|
|
223
|
+
- `fossa-sbom.json`
|
|
224
|
+
|
|
195
225
|
Reference sample configs:
|
|
196
226
|
|
|
197
227
|
TOML:
|
|
@@ -84,6 +84,7 @@ socketcli \
|
|
|
84
84
|
| Use case | Recommended mode | Key flags |
|
|
85
85
|
|:--|:--|:--|
|
|
86
86
|
| Basic policy enforcement in CI | Diff-based policy check | `--strict-blocking` |
|
|
87
|
+
| Legal/compliance artifact generation | Legal preset | `--legal` |
|
|
87
88
|
| Reachable-focused SARIF for reporting | Full-scope grouped SARIF | `--reach --sarif-scope full --sarif-grouping alert --sarif-reachability reachable --sarif-file <path>` |
|
|
88
89
|
| Detailed reachability export for investigations | Full-scope instance SARIF | `--reach --sarif-scope full --sarif-grouping instance --sarif-reachability all --sarif-file <path>` |
|
|
89
90
|
| Net-new PR findings only | Diff-scope SARIF | `--reach --sarif-scope diff --sarif-reachability reachable --sarif-file <path>` |
|
|
@@ -134,6 +135,35 @@ Run:
|
|
|
134
135
|
socketcli --config .socketcli.toml --target-path .
|
|
135
136
|
```
|
|
136
137
|
|
|
138
|
+
Legal/compliance preset example:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
socketcli --legal --target-path .
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
This preset enables license generation and writes default artifacts unless you override them:
|
|
145
|
+
- `socket-report.json`
|
|
146
|
+
- `socket-summary.txt`
|
|
147
|
+
- `socket-report-link.txt`
|
|
148
|
+
- `socket-sbom.json`
|
|
149
|
+
- `socket-license.json`
|
|
150
|
+
|
|
151
|
+
FOSSA-compatibility shaped legal artifacts:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
socketcli --legal-format fossa --target-path .
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
This switches the JSON report and legal artifact payloads to FOSSA-style compatibility shapes:
|
|
158
|
+
- the analyze artifact becomes a `project` / `vulnerability` / `licensing` / `quality` report
|
|
159
|
+
- the SBOM artifact becomes a FOSSA-attribution-style payload with `copyrightsByLicense`, `deepDependencies`, `directDependencies`, `licenses`, and `project` keys
|
|
160
|
+
|
|
161
|
+
When `--legal-format fossa` is used without explicit output paths, the defaults are closer to the FOSSA pipeline contract:
|
|
162
|
+
- `fossa-analyze.json`
|
|
163
|
+
- `fossa-test.txt`
|
|
164
|
+
- `fossa-link.txt`
|
|
165
|
+
- `fossa-sbom.json`
|
|
166
|
+
|
|
137
167
|
Reference sample configs:
|
|
138
168
|
|
|
139
169
|
TOML:
|
|
@@ -305,7 +305,7 @@ The CLI will automatically install `@coana-tech/cli` if not present. Use `--reac
|
|
|
305
305
|
| Parameter | Required | Default | Description |
|
|
306
306
|
|:-------------------------|:---------|:--------|:----------------------------------------------------------------------|
|
|
307
307
|
| `--ignore-commit-files` | False | False | Ignore commit files |
|
|
308
|
-
| `--disable-blocking` | False | False |
|
|
308
|
+
| `--disable-blocking` | False | False | Non-blocking CI mode: the CLI always exits **0**, even when blocking alerts are present (including with `--strict-blocking`). Also exits 0 on uncaught runtime errors and Socket API failures, so the job is treated as successful while findings and errors are still logged. Takes precedence over `--strict-blocking`. |
|
|
309
309
|
| `--disable-ignore` | False | False | Disable support for `@SocketSecurity ignore` commands in PR comments. When set, alerts cannot be suppressed via comments and ignore instructions are hidden from comment output. |
|
|
310
310
|
| `--strict-blocking` | False | False | Fail on ANY security policy violations (blocking severity), not just new ones. Only works in diff mode. See [Strict Blocking Mode](#strict-blocking-mode) for details. |
|
|
311
311
|
| `--enable-diff` | False | False | Enable diff mode even when using `--integration api` (forces diff mode without SCM integration) |
|
|
@@ -79,6 +79,7 @@ class CliConfig:
|
|
|
79
79
|
enable_debug: bool = False
|
|
80
80
|
allow_unverified: bool = False
|
|
81
81
|
enable_json: bool = False
|
|
82
|
+
json_file: Optional[str] = None
|
|
82
83
|
enable_sarif: bool = False
|
|
83
84
|
sarif_file: Optional[str] = None
|
|
84
85
|
sarif_scope: str = "diff"
|
|
@@ -86,6 +87,8 @@ class CliConfig:
|
|
|
86
87
|
sarif_reachability: str = "all"
|
|
87
88
|
enable_gitlab_security: bool = False
|
|
88
89
|
gitlab_security_file: Optional[str] = None
|
|
90
|
+
summary_file: Optional[str] = None
|
|
91
|
+
report_link_file: Optional[str] = None
|
|
89
92
|
disable_overview: bool = False
|
|
90
93
|
disable_security_issue: bool = False
|
|
91
94
|
files: str = None
|
|
@@ -137,6 +140,8 @@ class CliConfig:
|
|
|
137
140
|
reach_continue_on_no_source_files: bool = False
|
|
138
141
|
max_purl_batch_size: int = 5000
|
|
139
142
|
enable_commit_status: bool = False
|
|
143
|
+
legal: bool = False
|
|
144
|
+
legal_format: str = "socket"
|
|
140
145
|
config_file: Optional[str] = None
|
|
141
146
|
|
|
142
147
|
@classmethod
|
|
@@ -194,6 +199,7 @@ class CliConfig:
|
|
|
194
199
|
'enable_diff': args.enable_diff,
|
|
195
200
|
'allow_unverified': args.allow_unverified,
|
|
196
201
|
'enable_json': args.enable_json,
|
|
202
|
+
'json_file': args.json_file,
|
|
197
203
|
'enable_sarif': args.enable_sarif,
|
|
198
204
|
'sarif_file': args.sarif_file,
|
|
199
205
|
'sarif_scope': args.sarif_scope,
|
|
@@ -201,6 +207,8 @@ class CliConfig:
|
|
|
201
207
|
'sarif_reachability': args.sarif_reachability,
|
|
202
208
|
'enable_gitlab_security': args.enable_gitlab_security,
|
|
203
209
|
'gitlab_security_file': args.gitlab_security_file,
|
|
210
|
+
'summary_file': args.summary_file,
|
|
211
|
+
'report_link_file': args.report_link_file,
|
|
204
212
|
'disable_overview': args.disable_overview,
|
|
205
213
|
'disable_security_issue': args.disable_security_issue,
|
|
206
214
|
'files': args.files,
|
|
@@ -246,9 +254,40 @@ class CliConfig:
|
|
|
246
254
|
'reach_continue_on_no_source_files': args.reach_continue_on_no_source_files,
|
|
247
255
|
'max_purl_batch_size': args.max_purl_batch_size,
|
|
248
256
|
'enable_commit_status': args.enable_commit_status,
|
|
257
|
+
'legal': args.legal or args.legal_format == "fossa",
|
|
258
|
+
'legal_format': args.legal_format,
|
|
249
259
|
'config_file': args.config_file,
|
|
250
260
|
'version': __version__
|
|
251
261
|
}
|
|
262
|
+
|
|
263
|
+
if config_args['legal']:
|
|
264
|
+
config_args['generate_license'] = True
|
|
265
|
+
if not config_args['json_file']:
|
|
266
|
+
config_args['json_file'] = "socket-report.json"
|
|
267
|
+
if not config_args['summary_file']:
|
|
268
|
+
config_args['summary_file'] = "socket-summary.txt"
|
|
269
|
+
if not config_args['report_link_file']:
|
|
270
|
+
config_args['report_link_file'] = "socket-report-link.txt"
|
|
271
|
+
if not config_args['sbom_file']:
|
|
272
|
+
config_args['sbom_file'] = "socket-sbom.json"
|
|
273
|
+
if config_args['license_file_name'] == "license_output.json":
|
|
274
|
+
config_args['license_file_name'] = "socket-license.json"
|
|
275
|
+
|
|
276
|
+
if config_args['legal_format'] == "fossa":
|
|
277
|
+
if not args.json_file:
|
|
278
|
+
config_args['json_file'] = "fossa-analyze.json"
|
|
279
|
+
if not args.summary_file:
|
|
280
|
+
config_args['summary_file'] = "fossa-test.txt"
|
|
281
|
+
if not args.report_link_file:
|
|
282
|
+
config_args['report_link_file'] = "fossa-link.txt"
|
|
283
|
+
if not args.license_file_name:
|
|
284
|
+
# argparse always provides a default, so this branch is defensive only
|
|
285
|
+
config_args['license_file_name'] = "fossa-sbom.json"
|
|
286
|
+
elif args.license_file_name == "license_output.json":
|
|
287
|
+
config_args['license_file_name'] = "fossa-sbom.json"
|
|
288
|
+
if not args.sbom_file:
|
|
289
|
+
# FOSSA's "SBOM" artifact is the attribution payload; suppress the extra Socket-only SBOM file by default.
|
|
290
|
+
config_args['sbom_file'] = None
|
|
252
291
|
excluded_ecosystems = config_args["excluded_ecosystems"]
|
|
253
292
|
if isinstance(excluded_ecosystems, list):
|
|
254
293
|
config_args["excluded_ecosystems"] = excluded_ecosystems
|
|
@@ -570,6 +609,12 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
570
609
|
action="store_true",
|
|
571
610
|
help="Output in JSON format"
|
|
572
611
|
)
|
|
612
|
+
output_group.add_argument(
|
|
613
|
+
"--json-file",
|
|
614
|
+
dest="json_file",
|
|
615
|
+
metavar="<path>",
|
|
616
|
+
help="Output file path for JSON report"
|
|
617
|
+
)
|
|
573
618
|
output_group.add_argument(
|
|
574
619
|
"--enable-sarif",
|
|
575
620
|
dest="enable_sarif",
|
|
@@ -617,6 +662,18 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
617
662
|
default="gl-dependency-scanning-report.json",
|
|
618
663
|
help="Output file path for GitLab Security report (default: gl-dependency-scanning-report.json)"
|
|
619
664
|
)
|
|
665
|
+
output_group.add_argument(
|
|
666
|
+
"--summary-file",
|
|
667
|
+
dest="summary_file",
|
|
668
|
+
metavar="<path>",
|
|
669
|
+
help="Output file path for a plain-text summary report"
|
|
670
|
+
)
|
|
671
|
+
output_group.add_argument(
|
|
672
|
+
"--report-link-file",
|
|
673
|
+
dest="report_link_file",
|
|
674
|
+
metavar="<path>",
|
|
675
|
+
help="Output file path for the Socket report link"
|
|
676
|
+
)
|
|
620
677
|
output_group.add_argument(
|
|
621
678
|
"--disable-overview",
|
|
622
679
|
dest="disable_overview",
|
|
@@ -695,7 +752,11 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
695
752
|
"--disable-blocking",
|
|
696
753
|
dest="disable_blocking",
|
|
697
754
|
action="store_true",
|
|
698
|
-
help=
|
|
755
|
+
help=(
|
|
756
|
+
"Non-blocking CI mode: always exit 0, even when blocking alerts are present "
|
|
757
|
+
"(including with --strict-blocking), on uncaught errors, or on Socket API failures. "
|
|
758
|
+
"Findings and errors are still logged. Overrides --strict-blocking."
|
|
759
|
+
),
|
|
699
760
|
)
|
|
700
761
|
advanced_group.add_argument(
|
|
701
762
|
"--disable_blocking",
|
|
@@ -746,6 +807,19 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
746
807
|
action="store_true",
|
|
747
808
|
help="Disable SSL certificate verification for API requests"
|
|
748
809
|
)
|
|
810
|
+
advanced_group.add_argument(
|
|
811
|
+
"--legal",
|
|
812
|
+
dest="legal",
|
|
813
|
+
action="store_true",
|
|
814
|
+
help="Enable legal/compliance-friendly defaults and file outputs"
|
|
815
|
+
)
|
|
816
|
+
advanced_group.add_argument(
|
|
817
|
+
"--legal-format",
|
|
818
|
+
dest="legal_format",
|
|
819
|
+
choices=["socket", "fossa"],
|
|
820
|
+
default="socket",
|
|
821
|
+
help="Select the legal artifact format. 'socket' keeps Socket-native outputs; 'fossa' emits compatibility-shaped JSON artifacts."
|
|
822
|
+
)
|
|
749
823
|
config_group.add_argument(
|
|
750
824
|
"--include-module-folders",
|
|
751
825
|
dest="include_module_folders",
|
|
@@ -898,6 +898,7 @@ class Core:
|
|
|
898
898
|
results = self.sdk.purl.post(
|
|
899
899
|
license=True,
|
|
900
900
|
components=batch_components,
|
|
901
|
+
org_slug=self.config.org_slug,
|
|
901
902
|
licenseattrib=True,
|
|
902
903
|
licensedetails=True
|
|
903
904
|
)
|
|
@@ -946,6 +947,8 @@ class Core:
|
|
|
946
947
|
)
|
|
947
948
|
except APIFailure as e:
|
|
948
949
|
log.error(f"API Error: {e}")
|
|
950
|
+
if self.cli_config and self.cli_config.disable_blocking:
|
|
951
|
+
sys.exit(0)
|
|
949
952
|
sys.exit(1)
|
|
950
953
|
except Exception as e:
|
|
951
954
|
import traceback
|
|
@@ -1123,6 +1126,8 @@ class Core:
|
|
|
1123
1126
|
os.unlink(temp_file)
|
|
1124
1127
|
except OSError:
|
|
1125
1128
|
pass
|
|
1129
|
+
if self.cli_config and self.cli_config.disable_blocking:
|
|
1130
|
+
sys.exit(0)
|
|
1126
1131
|
sys.exit(1)
|
|
1127
1132
|
except Exception as e:
|
|
1128
1133
|
import traceback
|