Skip to content

Commit 1d8b1f7

Browse files
committed
ci: add dependabot-review workflow with Socket Firewall smoke jobs
For every Dependabot-authored PR, inspect what changed and conditionally run Socket Firewall (sfw) install smoke jobs against the affected manifests. Because sfw uses the anonymous Socket public-data API it needs NO secret, so this runs cleanly under the standard `pull_request` context -- no pull_request_target, no token-leak surface. Jobs (all conditional on file diff): - python-sfw-smoke: pyproject.toml / uv.lock -> `sfw uv sync` plus an import smoke on the modules that depend on the upgraded packages (cryptography, gitpython, requests, ...). Catches API-removal breaks from minor/patch deprecations. - fixture-npm-sfw-smoke: tests/e2e/fixtures/simple-npm/** -> `sfw npm install` in a clean cwd. - fixture-pypi-sfw-smoke: tests/e2e/fixtures/simple-pypi/** -> `sfw pip install -r requirements.txt` in a clean venv. - dockerfile-smoke: `docker build --pull` (no push) when the Dockerfile changes. - workflow-notice: Flag Dependabot PRs that touch workflow or dependabot config files for explicit human review (anti-supply-chain-confusion guardrail). Pattern adapted from SocketDev/socket-basics dependabot-review.yml. Action SHAs match the pins already in python-tests.yml and e2e-test.yml so zizmor stays happy. Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
1 parent eee4a93 commit 1d8b1f7

1 file changed

Lines changed: 205 additions & 0 deletions

File tree

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
name: dependabot-review
2+
3+
# Dependency-update PR guardrails for Dependabot-authored PRs.
4+
#
5+
# Runs only on PRs opened by dependabot[bot]. Inspects which files
6+
# changed, then conditionally runs Socket Firewall (sfw) install smoke
7+
# jobs for the affected manifests. Because sfw uses the free, anonymous
8+
# Socket public-data path it needs NO API key, so we can run it from
9+
# the unprivileged `pull_request` context without pull_request_target
10+
# or any of its security tradeoffs.
11+
#
12+
# Pattern adapted from SocketDev/socket-basics.
13+
14+
on:
15+
pull_request:
16+
types: [opened, synchronize, reopened, ready_for_review]
17+
18+
permissions:
19+
contents: read
20+
21+
concurrency:
22+
group: dependabot-review-${{ github.event.pull_request.number }}
23+
cancel-in-progress: true
24+
25+
jobs:
26+
inspect:
27+
if: github.event.pull_request.user.login == 'dependabot[bot]'
28+
runs-on: ubuntu-latest
29+
timeout-minutes: 5
30+
outputs:
31+
python_deps_changed: ${{ steps.diff.outputs.python_deps_changed }}
32+
fixture_npm_changed: ${{ steps.diff.outputs.fixture_npm_changed }}
33+
fixture_pypi_changed: ${{ steps.diff.outputs.fixture_pypi_changed }}
34+
dockerfile_changed: ${{ steps.diff.outputs.dockerfile_changed }}
35+
workflow_or_action_changed: ${{ steps.diff.outputs.workflow_or_action_changed }}
36+
steps:
37+
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871
38+
with:
39+
fetch-depth: 0
40+
persist-credentials: false
41+
42+
- name: Inspect changed files
43+
id: diff
44+
env:
45+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
46+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
47+
run: |
48+
CHANGED_FILES="$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")"
49+
50+
{
51+
echo "## Changed files"
52+
echo '```'
53+
printf '%s\n' "$CHANGED_FILES"
54+
echo '```'
55+
} >> "$GITHUB_STEP_SUMMARY"
56+
57+
has_file() {
58+
local pattern="$1"
59+
if printf '%s\n' "$CHANGED_FILES" | grep -Eq "$pattern"; then
60+
echo "true"
61+
else
62+
echo "false"
63+
fi
64+
}
65+
66+
{
67+
echo "python_deps_changed=$(has_file '^(pyproject\.toml|uv\.lock)$')"
68+
echo "fixture_npm_changed=$(has_file '^tests/e2e/fixtures/simple-npm/')"
69+
echo "fixture_pypi_changed=$(has_file '^tests/e2e/fixtures/simple-pypi/')"
70+
echo "dockerfile_changed=$(has_file '^Dockerfile$')"
71+
echo "workflow_or_action_changed=$(has_file '^\.github/workflows/|^\.github/dependabot\.yml$')"
72+
} >> "$GITHUB_OUTPUT"
73+
74+
- name: Summarize review expectations
75+
env:
76+
PR_URL: ${{ github.event.pull_request.html_url }}
77+
run: |
78+
{
79+
echo "## Dependabot Review Checklist"
80+
echo "- PR: $PR_URL"
81+
echo "- Confirm upstream release notes before merge"
82+
echo "- Do not treat a Dependabot PR as trusted solely because of the actor"
83+
echo "- This workflow runs in pull_request context only; no publish secrets are exposed"
84+
} >> "$GITHUB_STEP_SUMMARY"
85+
86+
python-sfw-smoke:
87+
needs: inspect
88+
if: needs.inspect.outputs.python_deps_changed == 'true'
89+
runs-on: ubuntu-latest
90+
timeout-minutes: 15
91+
steps:
92+
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871
93+
with:
94+
fetch-depth: 1
95+
persist-credentials: false
96+
97+
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
98+
with:
99+
python-version: "3.12"
100+
101+
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
102+
with:
103+
node-version: "20"
104+
105+
- name: Install Socket Firewall
106+
run: npm install -g sfw
107+
108+
- name: Install uv
109+
run: python -m pip install --upgrade pip uv
110+
111+
- name: Sync project through Socket Firewall
112+
run: sfw uv sync --extra test --extra dev
113+
114+
- name: Import smoke test
115+
run: |
116+
uv run python -c "
117+
from socketsecurity.socketcli import cli, build_socket_sdk
118+
from socketsecurity.core import Core
119+
from socketsecurity.core.exceptions import (
120+
APIFailure, RequestTimeoutExceeded, APIResourceNotFound,
121+
)
122+
from socketsecurity.core.git_interface import Git
123+
from socketsecurity.config import CliConfig
124+
print('import smoke OK')
125+
"
126+
127+
fixture-npm-sfw-smoke:
128+
needs: inspect
129+
if: needs.inspect.outputs.fixture_npm_changed == 'true'
130+
runs-on: ubuntu-latest
131+
timeout-minutes: 15
132+
steps:
133+
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871
134+
with:
135+
fetch-depth: 1
136+
persist-credentials: false
137+
138+
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
139+
with:
140+
node-version: "20"
141+
142+
- name: Install Socket Firewall
143+
run: npm install -g sfw
144+
145+
- name: Install fixture through Socket Firewall
146+
working-directory: tests/e2e/fixtures/simple-npm
147+
run: sfw npm install --no-audit --no-fund --ignore-scripts
148+
149+
fixture-pypi-sfw-smoke:
150+
needs: inspect
151+
if: needs.inspect.outputs.fixture_pypi_changed == 'true'
152+
runs-on: ubuntu-latest
153+
timeout-minutes: 15
154+
steps:
155+
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871
156+
with:
157+
fetch-depth: 1
158+
persist-credentials: false
159+
160+
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
161+
with:
162+
python-version: "3.12"
163+
164+
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
165+
with:
166+
node-version: "20"
167+
168+
- name: Install Socket Firewall
169+
run: npm install -g sfw
170+
171+
- name: Install fixture through Socket Firewall
172+
working-directory: tests/e2e/fixtures/simple-pypi
173+
run: |
174+
python -m venv .venv
175+
# shellcheck disable=SC1091
176+
source .venv/bin/activate
177+
sfw pip install -r requirements.txt
178+
179+
dockerfile-smoke:
180+
needs: inspect
181+
if: needs.inspect.outputs.dockerfile_changed == 'true'
182+
runs-on: ubuntu-latest
183+
timeout-minutes: 20
184+
steps:
185+
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871
186+
with:
187+
fetch-depth: 1
188+
persist-credentials: false
189+
190+
- name: Build the Dockerfile (no push)
191+
run: docker build --pull -t socket-python-cli:dependabot-smoke .
192+
193+
workflow-notice:
194+
needs: inspect
195+
if: needs.inspect.outputs.workflow_or_action_changed == 'true'
196+
runs-on: ubuntu-latest
197+
timeout-minutes: 2
198+
steps:
199+
- name: Flag workflow-sensitive updates
200+
run: |
201+
{
202+
echo "## Sensitive File Notice"
203+
echo "This Dependabot PR changes workflow or dependabot config files."
204+
echo "Require explicit human review before merge."
205+
} >> "$GITHUB_STEP_SUMMARY"

0 commit comments

Comments
 (0)