socketsecurity 2.5.8__tar.gz → 2.6.0__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.5.8 → socketsecurity-2.6.0}/.github/actions/setup-docker/action.yml +5 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/workflows/dependency-review.yml +4 -1
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/workflows/e2e-test.yml +48 -1
- socketsecurity-2.6.0/.github/workflows/package-check.yml +66 -0
- socketsecurity-2.6.0/.github/workflows/pr-preview.yml +306 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/workflows/release.yml +21 -7
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.hooks/sync_version.py +34 -2
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/CHANGELOG.md +32 -0
- socketsecurity-2.6.0/CONTRIBUTING.md +62 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/Dockerfile +27 -7
- socketsecurity-2.6.0/Dockerfile.preview +68 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/PKG-INFO +12 -12
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/docs/cli-reference.md +1 -1
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/pyproject.toml +13 -13
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/__init__.py +1 -1
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/tools/reachability.py +3 -3
- socketsecurity-2.6.0/tests/e2e/reach-facts-probe.sh +19 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/e2e/validate-reachability.sh +19 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/uv.lock +17 -29
- socketsecurity-2.5.8/.github/workflows/pr-preview.yml +0 -169
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/CODEOWNERS +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/PULL_REQUEST_TEMPLATE/bug-fix.md +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/PULL_REQUEST_TEMPLATE/improvement.md +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/actions/setup-hatch/action.yml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/actions/setup-sfw/action.yml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/dependabot.yml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/workflows/docker-stable.yml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/workflows/python-tests.yml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/workflows/version-check.yml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.github/zizmor.yml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.gitignore +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.pre-commit-config.yaml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/.python-version +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/LICENSE +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/Makefile +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/README.md +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/docs/ci-cd.md +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/docs/development.md +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/docs/troubleshooting.md +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/examples/config/sarif-dashboard-parity.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/examples/config/sarif-dashboard-parity.toml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/examples/config/sarif-diff-ci-cd.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/examples/config/sarif-diff-ci-cd.toml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/examples/config/sarif-instance-detail.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/examples/config/sarif-instance-detail.toml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/instructions/gitlab-commit-status/uat.md +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/pytest.ini +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/scripts/build_container.sh +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/scripts/build_container_flexible.sh +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/scripts/deploy-test-docker.sh +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/scripts/deploy-test-pypi.sh +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/scripts/docker-entrypoint.sh +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/scripts/run.sh +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/session.md +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socket.yml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/config.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/__init__.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/alert_selection.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/classes.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/cli_client.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/cli_run.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/exceptions.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/git_interface.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/helper/__init__.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/helper/socket_facts_loader.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/lazy_file_loader.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/log_uploader.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/logging.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/messages.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/resource_utils.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/scm/__init__.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/scm/base.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/scm/client.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/scm/github.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/scm/gitlab.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/scm_comments.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/socket_config.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/streaming.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/core/utils.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/fossa_compat.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/output.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/plugins/__init__.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/plugins/base.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/plugins/formatters/__init__.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/plugins/formatters/slack.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/plugins/jira.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/plugins/manager.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/plugins/slack.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/plugins/teams.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/plugins/webhook.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/socketsecurity/socketcli.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/__init__.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/core/conftest.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/core/create_diff_input.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/core/test_diff_alerts.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/core/test_diff_generation.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/core/test_facts_compression.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/core/test_has_manifest_files.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/core/test_package_and_alerts.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/core/test_sdk_methods.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/core/test_supporting_methods.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/fullscans/create_response.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/fullscans/diff/stream_diff.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/fullscans/diff/stream_diff_full.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/fullscans/head_scan/metadata.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/fullscans/head_scan/stream_scan.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/fullscans/head_scan/stream_scan_full.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/fullscans/new_scan/metadata.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/fullscans/new_scan/stream_scan.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/repos/repo_info_error.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/repos/repo_info_no_head.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/repos/repo_info_success.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/data/settings/security-policy.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/e2e/fixtures/simple-npm/index.js +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/e2e/fixtures/simple-npm/package.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/e2e/fixtures/simple-pypi/requirements.txt +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/e2e/validate-gitlab.sh +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/e2e/validate-json.sh +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/e2e/validate-sarif.sh +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/e2e/validate-scan.sh +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/fixtures/fossa/README.md +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/fixtures/fossa/fossa-analyze-empty.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/fixtures/fossa/fossa-analyze-populated.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/fixtures/fossa/fossa-sbom-empty-deep.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/fixtures/fossa/fossa-sbom-populated.json +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/__init__.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_alert_selection.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_cli_config.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_cli_run.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_client.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_config.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_dependency_overview.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_disable_ignore.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_exclude_paths.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_fossa_compat.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_fossa_parity.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_full_scan_retry.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_gitlab_auth.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_gitlab_auth_fallback.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_gitlab_commit_status.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_gitlab_format.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_ignore_telemetry_filtering.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_include_dirs.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_log_uploader.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_output.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_reachability.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_slack_plugin.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_socketcli.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_streaming.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/tests/unit/test_tier1_finalize.py +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/workflows/bitbucket-pipelines.yml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/workflows/buildkite.yml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/workflows/github-actions.yml +0 -0
- {socketsecurity-2.5.8 → socketsecurity-2.6.0}/workflows/gitlab-ci.yml +0 -0
|
@@ -5,6 +5,10 @@ description: >-
|
|
|
5
5
|
preview, and stable workflows.
|
|
6
6
|
|
|
7
7
|
inputs:
|
|
8
|
+
enable-qemu:
|
|
9
|
+
description: "Set up QEMU for multi-platform builds"
|
|
10
|
+
required: false
|
|
11
|
+
default: "true"
|
|
8
12
|
dockerhub-username:
|
|
9
13
|
description: "Docker Hub username (pass from secrets)"
|
|
10
14
|
required: true
|
|
@@ -16,6 +20,7 @@ runs:
|
|
|
16
20
|
using: "composite"
|
|
17
21
|
steps:
|
|
18
22
|
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
|
|
23
|
+
if: inputs.enable-qemu == 'true'
|
|
19
24
|
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
|
20
25
|
- uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
|
21
26
|
with:
|
|
@@ -571,7 +571,10 @@ jobs:
|
|
|
571
571
|
persist-credentials: false
|
|
572
572
|
|
|
573
573
|
- name: Build the Dockerfile (no push)
|
|
574
|
-
run:
|
|
574
|
+
run: >-
|
|
575
|
+
docker build --pull
|
|
576
|
+
--build-arg USE_LOCAL_INSTALL=true
|
|
577
|
+
-t socket-python-cli:dependabot-smoke .
|
|
575
578
|
|
|
576
579
|
workflow-notice:
|
|
577
580
|
needs: inspect
|
|
@@ -46,6 +46,11 @@ jobs:
|
|
|
46
46
|
--enable-debug
|
|
47
47
|
validate: tests/e2e/validate-reachability.sh
|
|
48
48
|
setup-node: "true"
|
|
49
|
+
# The tier-1 reachability backend intermittently returns empty
|
|
50
|
+
# results while the CLI reports success. The probe exits 0 when
|
|
51
|
+
# the facts file has alerted components; anything else is
|
|
52
|
+
# retried before validation fails the job.
|
|
53
|
+
retry-probe: bash tests/e2e/reach-facts-probe.sh tests/e2e/fixtures/simple-npm
|
|
49
54
|
|
|
50
55
|
- name: gitlab
|
|
51
56
|
args: >-
|
|
@@ -94,17 +99,59 @@ jobs:
|
|
|
94
99
|
run: pip install uv
|
|
95
100
|
|
|
96
101
|
- name: Run Socket CLI
|
|
102
|
+
id: run-cli
|
|
97
103
|
env:
|
|
98
104
|
SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_CLI_API_TOKEN }}
|
|
105
|
+
RETRY_PROBE: ${{ matrix.retry-probe }}
|
|
99
106
|
run: |
|
|
100
107
|
set -o pipefail
|
|
101
|
-
|
|
108
|
+
# Entries with retry-probe get up to 3 attempts: the probe exits 0
|
|
109
|
+
# when the scan output looks complete, and a run that fails it is
|
|
110
|
+
# re-run on the assumption of a transient backend failure. A
|
|
111
|
+
# persistent incomplete result still reaches validation. Validation
|
|
112
|
+
# only treats the explicit zero-project backend signature as
|
|
113
|
+
# inconclusive; any other empty result remains a failure. Retries are
|
|
114
|
+
# surfaced as warning annotations so flake frequency stays visible.
|
|
115
|
+
max_attempts=3
|
|
116
|
+
attempt=1
|
|
117
|
+
while :; do
|
|
118
|
+
socketcli ${{ matrix.args }} 2>&1 | tee /tmp/e2e-output.log
|
|
119
|
+
[ -z "$RETRY_PROBE" ] && break
|
|
120
|
+
if bash -c "$RETRY_PROBE"; then
|
|
121
|
+
break
|
|
122
|
+
fi
|
|
123
|
+
if [ "$attempt" -ge "$max_attempts" ]; then
|
|
124
|
+
echo "::warning title=e2e-${{ matrix.name }} incomplete results::output still fails the completeness probe after ${max_attempts} attempts; letting validation classify the result"
|
|
125
|
+
echo "diagnostics=true" >> "$GITHUB_OUTPUT"
|
|
126
|
+
break
|
|
127
|
+
fi
|
|
128
|
+
echo "::warning title=e2e-${{ matrix.name }} transient retry::attempt ${attempt} failed the completeness probe (suspected backend transient); retrying"
|
|
129
|
+
echo "e2e-${{ matrix.name }}: retry after attempt ${attempt} — completeness probe failed (suspected transient)" >> "$GITHUB_STEP_SUMMARY"
|
|
130
|
+
attempt=$((attempt+1))
|
|
131
|
+
sleep 30
|
|
132
|
+
done
|
|
102
133
|
|
|
103
134
|
- name: Validate results
|
|
104
135
|
env:
|
|
105
136
|
SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_CLI_API_TOKEN }}
|
|
106
137
|
run: bash ${{ matrix.validate }}
|
|
107
138
|
|
|
139
|
+
- name: Upload diagnostics on failure
|
|
140
|
+
if: failure() || steps.run-cli.outputs.diagnostics == 'true'
|
|
141
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
142
|
+
with:
|
|
143
|
+
name: e2e-${{ matrix.name }}-diagnostics-attempt${{ github.run_attempt }}
|
|
144
|
+
path: |
|
|
145
|
+
/tmp/e2e-output.log
|
|
146
|
+
/tmp/*.sarif
|
|
147
|
+
tests/e2e/fixtures/simple-npm/.socket.facts.json
|
|
148
|
+
tests/e2e/fixtures/simple-pypi/.socket.facts.json
|
|
149
|
+
gl-*.json
|
|
150
|
+
license_output.json
|
|
151
|
+
if-no-files-found: ignore
|
|
152
|
+
include-hidden-files: true
|
|
153
|
+
retention-days: 14
|
|
154
|
+
|
|
108
155
|
# Branch protection requires the e2e-* checks, but the `e2e` job above is
|
|
109
156
|
# skipped on PRs that can't access repository secrets -- fork PRs and
|
|
110
157
|
# Dependabot PRs. A job skipped via a job-level `if` never expands its
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Package Check
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: package-check-${{ github.event.pull_request.number || github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
package-check:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
timeout-minutes: 10
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 1
|
|
24
|
+
persist-credentials: false
|
|
25
|
+
|
|
26
|
+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.12"
|
|
29
|
+
|
|
30
|
+
- name: Install build tooling
|
|
31
|
+
uses: ./.github/actions/setup-hatch
|
|
32
|
+
|
|
33
|
+
- name: Install distribution validator
|
|
34
|
+
run: python -m pip install "twine>=4.0.0"
|
|
35
|
+
|
|
36
|
+
- name: Build distributions
|
|
37
|
+
run: hatch build
|
|
38
|
+
|
|
39
|
+
- name: Validate distributions
|
|
40
|
+
run: python -m twine check dist/*
|
|
41
|
+
|
|
42
|
+
- name: Install and inspect wheel without resolving dependencies
|
|
43
|
+
run: |
|
|
44
|
+
python -m venv "$RUNNER_TEMP/package-check"
|
|
45
|
+
"$RUNNER_TEMP/package-check/bin/pip" install --no-deps dist/*.whl
|
|
46
|
+
"$RUNNER_TEMP/package-check/bin/python" - <<'PY'
|
|
47
|
+
import compileall
|
|
48
|
+
import importlib.metadata
|
|
49
|
+
import pathlib
|
|
50
|
+
import sysconfig
|
|
51
|
+
|
|
52
|
+
distribution = importlib.metadata.distribution("socketsecurity")
|
|
53
|
+
entry_points = {entry_point.name for entry_point in distribution.entry_points}
|
|
54
|
+
assert "socketcli" in entry_points
|
|
55
|
+
package = pathlib.Path(sysconfig.get_paths()["purelib"]) / "socketsecurity"
|
|
56
|
+
assert compileall.compile_dir(package, quiet=1)
|
|
57
|
+
print("wheel metadata and bytecode smoke OK", distribution.version)
|
|
58
|
+
PY
|
|
59
|
+
|
|
60
|
+
- name: Upload distributions
|
|
61
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
62
|
+
with:
|
|
63
|
+
name: socketsecurity-${{ github.sha }}
|
|
64
|
+
path: dist/*
|
|
65
|
+
if-no-files-found: error
|
|
66
|
+
retention-days: 14
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
name: Publish PR Preview
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [labeled]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
pr_number:
|
|
9
|
+
description: Pull request number to publish
|
|
10
|
+
required: true
|
|
11
|
+
type: string
|
|
12
|
+
publish_test_pypi:
|
|
13
|
+
description: Publish the Python package to TestPyPI
|
|
14
|
+
required: true
|
|
15
|
+
default: true
|
|
16
|
+
type: boolean
|
|
17
|
+
publish_docker:
|
|
18
|
+
description: Publish socketdev/cli:pr-<number> to Docker Hub
|
|
19
|
+
required: true
|
|
20
|
+
default: false
|
|
21
|
+
type: boolean
|
|
22
|
+
sdk_preview_version:
|
|
23
|
+
description: Optional exact TestPyPI socketdev prerelease for the Docker image
|
|
24
|
+
required: false
|
|
25
|
+
type: string
|
|
26
|
+
|
|
27
|
+
concurrency:
|
|
28
|
+
group: publish-pr-preview-${{ github.event.pull_request.number || github.run_id }}
|
|
29
|
+
cancel-in-progress: false
|
|
30
|
+
|
|
31
|
+
jobs:
|
|
32
|
+
context:
|
|
33
|
+
if: >-
|
|
34
|
+
github.event_name == 'workflow_dispatch' ||
|
|
35
|
+
(github.event.label.name == 'publish-preview' ||
|
|
36
|
+
github.event.label.name == 'publish-docker-preview') &&
|
|
37
|
+
github.event.pull_request.head.repo.full_name == github.repository
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
timeout-minutes: 5
|
|
40
|
+
permissions:
|
|
41
|
+
contents: read
|
|
42
|
+
pull-requests: read
|
|
43
|
+
outputs:
|
|
44
|
+
pr_number: ${{ steps.context.outputs.pr_number }}
|
|
45
|
+
head_sha: ${{ steps.context.outputs.head_sha }}
|
|
46
|
+
steps:
|
|
47
|
+
- name: Validate pull request context
|
|
48
|
+
id: context
|
|
49
|
+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
50
|
+
env:
|
|
51
|
+
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
|
|
52
|
+
EVENT_PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
53
|
+
INPUT_PR_NUMBER: ${{ inputs.pr_number }}
|
|
54
|
+
WORKFLOW_REF: ${{ github.ref }}
|
|
55
|
+
with:
|
|
56
|
+
script: |
|
|
57
|
+
const rawPrNumber = context.eventName === 'workflow_dispatch'
|
|
58
|
+
? process.env.INPUT_PR_NUMBER
|
|
59
|
+
: process.env.EVENT_PR_NUMBER;
|
|
60
|
+
if (!/^[1-9][0-9]*$/.test(rawPrNumber || '')) {
|
|
61
|
+
core.setFailed('Pull request number must contain ASCII digits only.');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (context.eventName === 'workflow_dispatch') {
|
|
66
|
+
const defaultRef = `refs/heads/${process.env.DEFAULT_BRANCH}`;
|
|
67
|
+
if (process.env.WORKFLOW_REF !== defaultRef) {
|
|
68
|
+
core.setFailed(`Run manual previews from ${defaultRef}.`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const prNumber = Number(rawPrNumber);
|
|
74
|
+
if (!Number.isSafeInteger(prNumber)) {
|
|
75
|
+
core.setFailed('Pull request number is outside the supported range.');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const {data: pullRequest} = await github.rest.pulls.get({
|
|
79
|
+
owner: context.repo.owner,
|
|
80
|
+
repo: context.repo.repo,
|
|
81
|
+
pull_number: prNumber,
|
|
82
|
+
});
|
|
83
|
+
if (pullRequest.state !== 'open') {
|
|
84
|
+
core.setFailed(`Pull request #${prNumber} is not open.`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (pullRequest.head.repo?.full_name !== `${context.repo.owner}/${context.repo.repo}`) {
|
|
88
|
+
core.setFailed('Preview publication is limited to branches in this repository.');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
core.setOutput('pr_number', String(prNumber));
|
|
93
|
+
core.setOutput('head_sha', pullRequest.head.sha);
|
|
94
|
+
|
|
95
|
+
build:
|
|
96
|
+
needs: context
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
timeout-minutes: 10
|
|
99
|
+
permissions:
|
|
100
|
+
contents: read
|
|
101
|
+
outputs:
|
|
102
|
+
preview_version: ${{ steps.version.outputs.preview_version }}
|
|
103
|
+
steps:
|
|
104
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
105
|
+
with:
|
|
106
|
+
ref: ${{ needs.context.outputs.head_sha }}
|
|
107
|
+
fetch-depth: 0
|
|
108
|
+
persist-credentials: false
|
|
109
|
+
|
|
110
|
+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
111
|
+
with:
|
|
112
|
+
python-version: "3.12"
|
|
113
|
+
|
|
114
|
+
- name: Install build tooling
|
|
115
|
+
uses: ./.github/actions/setup-hatch
|
|
116
|
+
|
|
117
|
+
- name: Install distribution validator
|
|
118
|
+
run: python -m pip install "twine>=4.0.0"
|
|
119
|
+
|
|
120
|
+
- name: Inject deterministic preview version
|
|
121
|
+
env:
|
|
122
|
+
PREVIEW_ID: ${{ github.run_id }}
|
|
123
|
+
RUN_ATTEMPT: ${{ github.run_attempt }}
|
|
124
|
+
run: |
|
|
125
|
+
PREVIEW_ID=$((PREVIEW_ID * 100 + RUN_ATTEMPT))
|
|
126
|
+
python .hooks/sync_version.py --dev --preview-id "$PREVIEW_ID" --skip-lock
|
|
127
|
+
|
|
128
|
+
- name: Read preview version
|
|
129
|
+
id: version
|
|
130
|
+
run: echo "preview_version=$(hatch version)" >> "$GITHUB_OUTPUT"
|
|
131
|
+
|
|
132
|
+
- name: Build and validate distributions
|
|
133
|
+
run: |
|
|
134
|
+
hatch build
|
|
135
|
+
python -m twine check dist/*
|
|
136
|
+
|
|
137
|
+
- name: Install and inspect wheel locally
|
|
138
|
+
run: |
|
|
139
|
+
python -m venv "$RUNNER_TEMP/preview-check"
|
|
140
|
+
"$RUNNER_TEMP/preview-check/bin/pip" install --no-deps dist/*.whl
|
|
141
|
+
"$RUNNER_TEMP/preview-check/bin/python" - <<'PY'
|
|
142
|
+
import compileall
|
|
143
|
+
import importlib.metadata
|
|
144
|
+
import pathlib
|
|
145
|
+
import sysconfig
|
|
146
|
+
|
|
147
|
+
distribution = importlib.metadata.distribution("socketsecurity")
|
|
148
|
+
entry_points = {entry_point.name for entry_point in distribution.entry_points}
|
|
149
|
+
assert "socketcli" in entry_points
|
|
150
|
+
package = pathlib.Path(sysconfig.get_paths()["purelib"]) / "socketsecurity"
|
|
151
|
+
assert compileall.compile_dir(package, quiet=1)
|
|
152
|
+
print("preview wheel smoke OK", distribution.version)
|
|
153
|
+
PY
|
|
154
|
+
|
|
155
|
+
- name: Upload preview distributions
|
|
156
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
157
|
+
with:
|
|
158
|
+
name: socketsecurity-preview-${{ github.run_id }}-${{ github.run_attempt }}
|
|
159
|
+
path: dist/*
|
|
160
|
+
if-no-files-found: error
|
|
161
|
+
retention-days: 14
|
|
162
|
+
|
|
163
|
+
publish-package:
|
|
164
|
+
needs: [context, build]
|
|
165
|
+
if: >-
|
|
166
|
+
github.event.label.name == 'publish-preview' ||
|
|
167
|
+
(github.event_name == 'workflow_dispatch' && inputs.publish_test_pypi)
|
|
168
|
+
runs-on: ubuntu-latest
|
|
169
|
+
timeout-minutes: 10
|
|
170
|
+
permissions:
|
|
171
|
+
contents: read
|
|
172
|
+
id-token: write
|
|
173
|
+
pull-requests: write
|
|
174
|
+
steps:
|
|
175
|
+
- name: Download preview distributions
|
|
176
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
177
|
+
with:
|
|
178
|
+
name: socketsecurity-preview-${{ github.run_id }}-${{ github.run_attempt }}
|
|
179
|
+
path: dist
|
|
180
|
+
|
|
181
|
+
- name: Publish to TestPyPI
|
|
182
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
183
|
+
with:
|
|
184
|
+
repository-url: https://test.pypi.org/legacy/
|
|
185
|
+
verbose: true
|
|
186
|
+
|
|
187
|
+
- name: Comment on pull request
|
|
188
|
+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
189
|
+
env:
|
|
190
|
+
PREVIEW_VERSION: ${{ needs.build.outputs.preview_version }}
|
|
191
|
+
PR_NUMBER: ${{ needs.context.outputs.pr_number }}
|
|
192
|
+
with:
|
|
193
|
+
script: |
|
|
194
|
+
const marker = '<!-- socketsecurity-pr-preview -->';
|
|
195
|
+
const prNumber = Number(process.env.PR_NUMBER);
|
|
196
|
+
const version = process.env.PREVIEW_VERSION;
|
|
197
|
+
const body = `${marker}
|
|
198
|
+
🚀 CLI preview published: \`socketsecurity==${version}\`
|
|
199
|
+
|
|
200
|
+
\`\`\`bash
|
|
201
|
+
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple socketsecurity==${version}
|
|
202
|
+
\`\`\`
|
|
203
|
+
|
|
204
|
+
TestPyPI's package index can take several minutes to expose a newly uploaded version.`;
|
|
205
|
+
const {data: comments} = await github.rest.issues.listComments({
|
|
206
|
+
owner: context.repo.owner,
|
|
207
|
+
repo: context.repo.repo,
|
|
208
|
+
issue_number: prNumber,
|
|
209
|
+
});
|
|
210
|
+
const existing = comments.find(comment =>
|
|
211
|
+
comment.user.type === 'Bot' && comment.body.includes(marker)
|
|
212
|
+
);
|
|
213
|
+
if (existing) {
|
|
214
|
+
await github.rest.issues.updateComment({
|
|
215
|
+
owner: context.repo.owner,
|
|
216
|
+
repo: context.repo.repo,
|
|
217
|
+
comment_id: existing.id,
|
|
218
|
+
body,
|
|
219
|
+
});
|
|
220
|
+
} else {
|
|
221
|
+
await github.rest.issues.createComment({
|
|
222
|
+
owner: context.repo.owner,
|
|
223
|
+
repo: context.repo.repo,
|
|
224
|
+
issue_number: prNumber,
|
|
225
|
+
body,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
publish-docker:
|
|
230
|
+
needs: [context, build]
|
|
231
|
+
if: >-
|
|
232
|
+
github.event.label.name == 'publish-docker-preview' ||
|
|
233
|
+
(github.event_name == 'workflow_dispatch' && inputs.publish_docker)
|
|
234
|
+
runs-on: ubuntu-latest
|
|
235
|
+
timeout-minutes: 15
|
|
236
|
+
permissions:
|
|
237
|
+
contents: read
|
|
238
|
+
pull-requests: write
|
|
239
|
+
steps:
|
|
240
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
241
|
+
with:
|
|
242
|
+
# Keep the Dockerfile and credential-handling action on trusted code.
|
|
243
|
+
# The pull request enters this job only through the built wheel.
|
|
244
|
+
ref: ${{ github.event.repository.default_branch }}
|
|
245
|
+
fetch-depth: 1
|
|
246
|
+
persist-credentials: false
|
|
247
|
+
|
|
248
|
+
- name: Download preview distributions
|
|
249
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
250
|
+
with:
|
|
251
|
+
name: socketsecurity-preview-${{ github.run_id }}-${{ github.run_attempt }}
|
|
252
|
+
path: dist
|
|
253
|
+
|
|
254
|
+
- name: Set up Docker publishing
|
|
255
|
+
uses: ./.github/actions/setup-docker
|
|
256
|
+
with:
|
|
257
|
+
enable-qemu: "false"
|
|
258
|
+
dockerhub-username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
259
|
+
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
260
|
+
|
|
261
|
+
- name: Build and push Docker preview
|
|
262
|
+
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
|
263
|
+
with:
|
|
264
|
+
file: Dockerfile.preview
|
|
265
|
+
push: true
|
|
266
|
+
pull: true
|
|
267
|
+
platforms: linux/amd64
|
|
268
|
+
tags: socketdev/cli:pr-${{ needs.context.outputs.pr_number }}
|
|
269
|
+
build-args: |
|
|
270
|
+
SDK_PREVIEW_VERSION=${{ inputs.sdk_preview_version }}
|
|
271
|
+
|
|
272
|
+
- name: Comment on pull request
|
|
273
|
+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
274
|
+
env:
|
|
275
|
+
PR_NUMBER: ${{ needs.context.outputs.pr_number }}
|
|
276
|
+
with:
|
|
277
|
+
script: |
|
|
278
|
+
const marker = '<!-- socketsecurity-docker-preview -->';
|
|
279
|
+
const prNumber = Number(process.env.PR_NUMBER);
|
|
280
|
+
const body = `${marker}
|
|
281
|
+
🐳 Docker preview published: \`socketdev/cli:pr-${prNumber}\`
|
|
282
|
+
|
|
283
|
+
This mutable tag is only created when a Docker preview is explicitly requested.`;
|
|
284
|
+
const {data: comments} = await github.rest.issues.listComments({
|
|
285
|
+
owner: context.repo.owner,
|
|
286
|
+
repo: context.repo.repo,
|
|
287
|
+
issue_number: prNumber,
|
|
288
|
+
});
|
|
289
|
+
const existing = comments.find(comment =>
|
|
290
|
+
comment.user.type === 'Bot' && comment.body.includes(marker)
|
|
291
|
+
);
|
|
292
|
+
if (existing) {
|
|
293
|
+
await github.rest.issues.updateComment({
|
|
294
|
+
owner: context.repo.owner,
|
|
295
|
+
repo: context.repo.repo,
|
|
296
|
+
comment_id: existing.id,
|
|
297
|
+
body,
|
|
298
|
+
});
|
|
299
|
+
} else {
|
|
300
|
+
await github.rest.issues.createComment({
|
|
301
|
+
owner: context.repo.owner,
|
|
302
|
+
repo: context.repo.repo,
|
|
303
|
+
issue_number: prNumber,
|
|
304
|
+
body,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
@@ -79,17 +79,31 @@ jobs:
|
|
|
79
79
|
env:
|
|
80
80
|
VERSION: ${{ env.VERSION }}
|
|
81
81
|
run: |
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
# The first lookup can race PyPI's Simple-index propagation, and a delayed
|
|
83
|
+
# CDN purge can leave the index stale well after a successful upload.
|
|
84
|
+
# pip caches HTTP responses by default, so without --no-cache-dir every
|
|
85
|
+
# retry can reuse that initial stale response instead of checking whether
|
|
86
|
+
# the release has appeared. Budget: 30 minutes.
|
|
87
|
+
MAX_ATTEMPTS=60
|
|
88
|
+
for i in $(seq 1 "$MAX_ATTEMPTS"); do
|
|
89
|
+
if python -m pip install \
|
|
90
|
+
--no-cache-dir \
|
|
91
|
+
--index-url https://pypi.org/simple/ \
|
|
92
|
+
"socketsecurity==${VERSION}"; then
|
|
84
93
|
echo "Package ${VERSION} is now available and installable on PyPI"
|
|
85
|
-
pip uninstall -y socketsecurity
|
|
86
|
-
echo "success=true" >> $GITHUB_OUTPUT
|
|
94
|
+
python -m pip uninstall -y socketsecurity
|
|
95
|
+
echo "success=true" >> "$GITHUB_OUTPUT"
|
|
87
96
|
exit 0
|
|
88
97
|
fi
|
|
89
|
-
|
|
90
|
-
|
|
98
|
+
if curl -s -f "https://pypi.org/pypi/socketsecurity/${VERSION}/json" > /dev/null; then
|
|
99
|
+
echo "Release ${VERSION} exists on PyPI (JSON API) but is not in the Simple index yet - CDN propagation delay"
|
|
100
|
+
fi
|
|
101
|
+
if [ "$i" -lt "$MAX_ATTEMPTS" ]; then
|
|
102
|
+
echo "Attempt $i: Package not yet installable, waiting 30s... (${i}/${MAX_ATTEMPTS})"
|
|
103
|
+
sleep 30
|
|
104
|
+
fi
|
|
91
105
|
done
|
|
92
|
-
echo "success=false" >> $GITHUB_OUTPUT
|
|
106
|
+
echo "success=false" >> "$GITHUB_OUTPUT"
|
|
93
107
|
exit 1
|
|
94
108
|
|
|
95
109
|
- name: Build & Push Docker
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
import
|
|
2
|
+
import json
|
|
3
3
|
import pathlib
|
|
4
4
|
import re
|
|
5
|
+
import subprocess
|
|
5
6
|
import sys
|
|
6
7
|
import urllib.request
|
|
7
|
-
import json
|
|
8
8
|
|
|
9
9
|
INIT_FILE = pathlib.Path("socketsecurity/__init__.py")
|
|
10
10
|
PYPROJECT_FILE = pathlib.Path("pyproject.toml")
|
|
@@ -125,13 +125,45 @@ def run_uv_lock() -> bool:
|
|
|
125
125
|
after = UV_LOCK_FILE.read_bytes() if UV_LOCK_FILE.exists() else b""
|
|
126
126
|
return before != after
|
|
127
127
|
|
|
128
|
+
|
|
129
|
+
def read_preview_id():
|
|
130
|
+
if "--preview-id" not in sys.argv:
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
option_index = sys.argv.index("--preview-id")
|
|
134
|
+
try:
|
|
135
|
+
preview_id = sys.argv[option_index + 1]
|
|
136
|
+
except IndexError:
|
|
137
|
+
print("❌ `--preview-id` requires a numeric value.")
|
|
138
|
+
sys.exit(1)
|
|
139
|
+
|
|
140
|
+
if not preview_id.isascii() or not preview_id.isdigit():
|
|
141
|
+
print("❌ `--preview-id` must contain ASCII digits only.")
|
|
142
|
+
sys.exit(1)
|
|
143
|
+
return preview_id
|
|
144
|
+
|
|
145
|
+
|
|
128
146
|
def main():
|
|
129
147
|
dev_mode = "--dev" in sys.argv
|
|
148
|
+
skip_lock = "--skip-lock" in sys.argv
|
|
149
|
+
preview_id = read_preview_id()
|
|
130
150
|
current_version = read_version_from_init(INIT_FILE)
|
|
131
151
|
previous_version = read_version_from_git("socketsecurity/__init__.py")
|
|
132
152
|
|
|
133
153
|
print(f"Current: {current_version}, Previous: {previous_version}")
|
|
134
154
|
|
|
155
|
+
if preview_id is not None:
|
|
156
|
+
if not dev_mode:
|
|
157
|
+
print("❌ `--preview-id` can only be used with `--dev`.")
|
|
158
|
+
sys.exit(1)
|
|
159
|
+
base_version = current_version.split(".dev")[0]
|
|
160
|
+
new_version = f"{base_version}.dev{preview_id}"
|
|
161
|
+
inject_version(new_version)
|
|
162
|
+
if not skip_lock:
|
|
163
|
+
run_uv_lock()
|
|
164
|
+
print(f"✅ Prepared deterministic preview version {new_version}.")
|
|
165
|
+
sys.exit(0)
|
|
166
|
+
|
|
135
167
|
if current_version == previous_version:
|
|
136
168
|
if dev_mode:
|
|
137
169
|
base_version = current_version.split(".dev")[0] if ".dev" in current_version else current_version
|
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.6.0
|
|
4
|
+
|
|
5
|
+
### Changed: pin all Python dependencies
|
|
6
|
+
|
|
7
|
+
- Pinned every runtime dependency in `pyproject.toml` to an exact version;
|
|
8
|
+
several were previously unpinned or open ranges.
|
|
9
|
+
- Replaced the `bs4` shim package with a direct, pinned `beautifulsoup4`
|
|
10
|
+
dependency (the shim provided no version control over the actual library).
|
|
11
|
+
- Pinned the bundled `socketdev` SDK to `3.5.0` (previously `>=3.3.0,<4.0.0`).
|
|
12
|
+
- Docker images now install Python dependencies from the committed `uv.lock`
|
|
13
|
+
with pip hash verification (`--require-hashes`), so image builds no longer
|
|
14
|
+
resolve dependency versions from PyPI at build time. `pip check` validates
|
|
15
|
+
the environment after install.
|
|
16
|
+
- Pinned the `hatchling` build backend and the `uv` binary used in the
|
|
17
|
+
Dockerfile.
|
|
18
|
+
|
|
19
|
+
### Changed: e2e reachability jobs retry transient empty results
|
|
20
|
+
|
|
21
|
+
- Reachability e2e runs that report success with no alerted components in the
|
|
22
|
+
facts file are retried up to three times as a suspected transient backend
|
|
23
|
+
failure. After retries, only the known zero-project backend signature is
|
|
24
|
+
classified as inconclusive — any other empty result still fails — and e2e
|
|
25
|
+
jobs upload their logs and reports as diagnostics on failure.
|
|
26
|
+
|
|
27
|
+
## 2.5.9
|
|
28
|
+
|
|
29
|
+
### Changed: bump pinned @coana-tech/cli to 15.10.3
|
|
30
|
+
|
|
31
|
+
- Bumped the pinned reachability engine (`@coana-tech/cli`) from `15.10.2` to
|
|
32
|
+
`15.10.3`. See the [Coana changelogs](https://docs.coana.tech/changelogs) for
|
|
33
|
+
engine changes.
|
|
34
|
+
|
|
3
35
|
## 2.5.8
|
|
4
36
|
|
|
5
37
|
### Changed: bump pinned @coana-tech/cli to 15.10.2
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Development setup
|
|
4
|
+
|
|
5
|
+
Use Python 3.11 or newer and install
|
|
6
|
+
[`uv`](https://docs.astral.sh/uv/getting-started/installation/). From the
|
|
7
|
+
repository root, create the environment and install all development
|
|
8
|
+
dependencies:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
uv sync --all-extras
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Before opening a pull request, run:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
make test
|
|
18
|
+
uv run hatch build
|
|
19
|
+
uv run python -m twine check dist/*
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
To develop against a local SDK checkout, set `SOCKET_SDK_PATH` if it is not at
|
|
23
|
+
`../socketdev`, then run `make first-time-local-setup`.
|
|
24
|
+
|
|
25
|
+
## Pull request validation
|
|
26
|
+
|
|
27
|
+
The `Package Check` workflow runs automatically for pull requests. It builds
|
|
28
|
+
and validates the distributions, smoke-tests the wheel, and uploads the
|
|
29
|
+
distributions as workflow artifacts. It does not publish a package or Docker
|
|
30
|
+
image.
|
|
31
|
+
|
|
32
|
+
## Publishing pull request previews
|
|
33
|
+
|
|
34
|
+
Preview publication is intentionally opt-in. Only request previews for code
|
|
35
|
+
that is trusted to run with the repository's publishing permissions.
|
|
36
|
+
|
|
37
|
+
For a pull request from this repository, apply the label for the artifact that
|
|
38
|
+
needs testing:
|
|
39
|
+
|
|
40
|
+
- `publish-preview` publishes a uniquely versioned `socketsecurity` prerelease
|
|
41
|
+
to TestPyPI and adds or updates a pull request comment with the exact version
|
|
42
|
+
and installation command.
|
|
43
|
+
- `publish-docker-preview` publishes the mutable
|
|
44
|
+
`socketdev/cli:pr-<pull-request-number>` image to Docker Hub and adds or
|
|
45
|
+
updates a pull request comment with the image tag.
|
|
46
|
+
|
|
47
|
+
Both label-triggered and manually dispatched previews are limited to open pull
|
|
48
|
+
requests whose branches belong to this repository. Each label is handled as a
|
|
49
|
+
separate event, so applying both labels starts two workflow runs. Use manual
|
|
50
|
+
dispatch instead when both artifacts should be published in a single run.
|
|
51
|
+
|
|
52
|
+
The workflow reacts when a label is added; pushing another commit while the
|
|
53
|
+
label remains on the pull request does not publish a new preview. To publish the
|
|
54
|
+
new pull request head or retry a failed publication, remove the relevant label
|
|
55
|
+
and apply it again.
|
|
56
|
+
|
|
57
|
+
Maintainers can also open **Actions > Publish PR Preview > Run workflow**, run
|
|
58
|
+
it from the repository's default branch, enter the pull request number, and
|
|
59
|
+
choose whether to publish to TestPyPI, Docker Hub, or both. When testing the CLI
|
|
60
|
+
against an SDK preview, enter the exact TestPyPI `socketdev` prerelease in
|
|
61
|
+
`sdk_preview_version`; publish the SDK preview first and allow time for
|
|
62
|
+
TestPyPI to expose it before starting the CLI Docker preview.
|