feat: 🐳 multi-stage Docker builds, immutable release pipeline, CHANGELOG automation - #46
Conversation
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
… upates Signed-off-by: lelia <lelia@socket.dev>
…ease workflow Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
|
one major thing missing here, is version bumping the |
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
…parate doc Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
…list Signed-off-by: lelia <lelia@socket.dev>
true, it's sort of a chicken-and-egg issue with the initial overhaul that this PR introduces. but the idea will be, once this is merged in and tested, that we create a second PR to actually switch everything over to the new |
I'v previously relied on automated versioning with conventional commit messaging (see example with to enforce using conventional commits:
|
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
got it, thanks for the example, I've incorporated this approach into |
CHANGELOG automationCHANGELOG automation
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
Signed-off-by: lelia <lelia@socket.dev>
… Unreleased for PR Signed-off-by: lelia <lelia@socket.dev>
Restores the guarantee lost when .hooks/version-check.py was removed in #46: resolve-version now fails fast if version.py, pyproject.toml, or the action.yml image tag disagree with the tag being published. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: publish multi-arch Docker images Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * ci: publish socket-basics heavy image Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * docs(changelog): add 2.1.0 release notes Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * fix(ci): harden Docker release publishing Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * fix(ci): address Docker publish review findings Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * fix(ci): harden Docker manifest publishing Signed-off-by: lelia <2418071+lelia@users.noreply.github.com> * fix(ci): publish heavy variant as tag suffix in the shared repo All image variants now publish to the single socket-basics repository per registry, distinguished by tag suffix (2.1.0 vs 2.1.0-heavy) instead of a separate socket-basics-heavy repository. This follows the standard Docker variant convention (like :slim/:alpine), requires no new Docker Hub repo, token rescoping, or GHCR package visibility changes, and makes retiring the POC variant trivial. - _docker-pipeline.yml: new push_name input decouples the registry repo from the local build/artifact name - publish-docker.yml: merge-manifests iterates variants with a tag_suffix, tags via metadata-action flavor suffix, and inspects both suffixed tags Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: move unreleased changelog entries out of the shipped 2.1.0 section v2.1.0 was released from main with different content; this PR's entries now sit under [Unreleased] and get stamped as 2.2.0 at release time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: correct 2.1.0 changelog date to actual release date (2026-07-22) The 2026-06-02 date reflected when the bundled commits were authored, not when v2.1.0 was actually tagged and released. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore(release): prep v2.2.0 — stamp changelog, bump version files and action image ref Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: gate publishing on version files matching the release tag Restores the guarantee lost when .hooks/version-check.py was removed in #46: resolve-version now fails fast if version.py, pyproject.toml, or the action.yml image tag disagree with the tag being published. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(scripts): add prep_release.py for mechanical release-prep PRs One command bumps version.py, pyproject.toml, action.yml, refreshes uv.lock, and stamps the [Unreleased] changelog section — so the final release PR is a five-file diff that always satisfies the publish workflow's version gate. Validates everything before writing anything; a failure leaves the tree untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(release): sync __init__.py version and derive bumps from pyproject The sync_release_version.py check from main caught socket_basics/ __init__.py still at 2.0.3 — a duplicate version field prep_release.py didn't know about. prep_release.py now bumps only pyproject.toml (the canonical source) and delegates derived files to sync_release_version.py so the two scripts can never disagree. The publish version gate also checks __init__.py now. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(core-tool-watch): opt into fail-closed purl batch semantics The batch purl endpoints default to fail-open: inputs with pending or failed resolution are silently omitted unless the caller opts in. Fresh pins (socketdev 3.3.0) fell into that omission path and tripped the unverified-pin guard with a misleading message. - purl.post now sends poll=true + timeoutSec=120 + alerts=true (extra kwargs pass through as query params on SDK 3.0.29 and 3.3.0) - client timeout raised 60->180s so the bounded server poll can finish - synthetic pendingScan/notFound rows are mapped to a status field before severity classification (never through MALWARE_ALERT_TYPES / CRITICAL_SEVERITIES) and fail closed with distinct, precise messages - OpenGrep's pkg:github coverage-gap exemption carries over: its pin now returns a notFound row instead of being omitted, and stays exempt - log the endpoint choice + org slug for forensics Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: changelog entry for core-tool-watch fail-closed purl fix Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(core-tool-watch): calibrate alert thresholds for the full alert set alerts=true exposed the complete informational alert firehose for the first time (the old fail-open responses carried no alert data, so the malware gate never actually saw alerts). Calibrated against real batch data from run 30504424787: - drop capability/heuristic signals from MALWARE_ALERT_TYPES: shellAccess fires on all four tools (security CLIs spawn subprocesses), gptMalware/gptSecurity/obfuscatedFile fire on the OpenGrep repo artifact (SAST engines bundle malicious-looking test fixtures by design) - hard-fail severity gate is critical-only; high-severity rows (cve on trivy, gpt heuristics) stay visible in the report for human review Verified: replaying the failing run's report through the new rules yields green while keeping true compromise signals fail-worthy. --------- Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
Summary
Overhauls the Docker build and release infrastructure for
socket-basics: multi-stage Dockerfiles with pinned binary deps, a full GHCR + Docker Hub publish pipeline with fail-fast testing, and automatedCHANGELOG+ release notes. Establishes an opinionated immutable release posture — no:latestor floatingv2tag — with SHA pinning + Dependabot as the recommended consumption pattern.Adds
Dockerfileandapp_tests/Dockerfile— Trivy, TruffleHog, Go, uv pulledvia named
FROMstages (Dependabot-trackable);python:3.12-slimbase; BuildKit cache mountspublish-docker.yml— build → smoke test → integration test → push to GHCR + Docker Hub→ GitHub Release + CHANGELOG update; fail-fast, per-job least-privilege permissions
docs/releasing.md— maintainer release process guide including immutable tag setup.github/PULL_REQUEST_TEMPLATE.md— release checklist baked into every PRcommit-lint.yml+.commitlintrc.yml— Conventional Commits enforcement on PR titlesCHANGELOG.mdfrom1.0.2; automated update on every release viascripts/update_changelog.pyChanges
v-prefix (v2.0.0) with immutable-only releases;:latestandfloating major tags (
v2) intentionally not publisheddocs/github-action.mdpinning strategies rewritten — SHA + Dependabot leads,includes security philosophy section explaining why we're opinionated
python-tests.ymlgains two CI assertions: version file sync +action.ymlimageref matches
pyproject.toml(auto-activates once pre-built image switch lands)smoke-test.ymlandpython-tests.ymlsimplified to flat jobs (no matrix overheadwhile only one Docker image is in CI scope)
Removes
.hooks/version-check.py+.claude/commands/bump-version.md— auto-bump-on-commitantipattern; replaced by the CI assertions above
version.py/pyproject.tomlaction.ymlswitch fromimage: Dockerfiletoimage: docker://ghcr.io/socketdev/socket-basics:2.0.0