Skip to content

ci: publish multi-arch Docker image variants - #85

Merged
lelia merged 19 commits into
mainfrom
issue-69
Jul 30, 2026
Merged

lelia merged 19 commits into
mainfrom
issue-69

Conversation

@lelia

@lelia lelia commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Publish socket-basics from native amd64/arm64 builds, merged into multi-arch manifest lists per release tag.
  • Add a heavy image variant that bundles socket-basics with the pinned Python Socket CLI release.
  • All variants publish to the single socket-basics repository on each registry, distinguished by tag suffix (2.1.0 vs 2.1.0-heavy) — no separate -heavy repo, so existing registry credentials and GHCR package visibility carry over unchanged.
  • Keep release publishing explicit and versioned; no floating heavy tag or cross-repo automation.

This follows the direction from #69: prefer native per-arch Docker publishing and keep the image release path simple to maintain.

Closes #69


Note

Medium Risk
Touches the production Docker publish path (multi-arch manifests and new variant tags); mitigated by expanded CI matrices, digest validation, and post-publish platform inspection.

Overview
Docker release now builds main and heavy images on native linux/amd64 and linux/arm64 runners, runs smoke/integration per matrix cell, pushes per-arch by digest to GHCR and Docker Hub, then merge-manifests assembles 2.x.y and 2.x.y-heavy tags on the single socket-basics repo (no separate heavy repository).

The reusable _docker-pipeline workflow gains runs_on, arch_label, push_name, checkout ref, and digest artifacts; tagging moves from per-build metadata-action to docker buildx imagetools create. resolve-version validates semver and resolves manual dispatch tags before checkout.

Dockerfile.heavy plus docker-heavy-entrypoint.sh install pinned socketsecurity and dispatch socket-basics / socketcli; smoke CI adds a heavy check set and LICENSE.md is included in image builds.

Reviewed by Cursor Bugbot for commit fbf94ea. Configure here.

@lelia
lelia requested a review from a team as a code owner June 26, 2026 21:29
@lelia lelia added enhancement New feature or request github-actions labels Jun 26, 2026
@lelia lelia changed the title ci: publish multi-arch Docker images ci: publish multi-arch Docker image variants Jul 21, 2026
Comment thread .github/workflows/publish-docker.yml Outdated
Comment thread .github/workflows/publish-docker.yml
@lelia

lelia commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Dispatch republish wrong checkout ref
    • Exported the resolved tag ref as a resolve-version output and plumbed it through a new ref input to the reusable pipeline's checkout so build-test-push builds from the specified tag instead of the default branch HEAD.

Create PR

Or push these changes by commenting:

@cursor push 4d512fb46b
Preview (4d512fb46b)
diff --git a/.github/workflows/_docker-pipeline.yml b/.github/workflows/_docker-pipeline.yml
--- a/.github/workflows/_docker-pipeline.yml
+++ b/.github/workflows/_docker-pipeline.yml
@@ -56,6 +56,11 @@ on:
         type: string
         required: false
         default: "dev"
+      ref:
+        description: "Git ref to check out (e.g. refs/tags/v2.0.3). Empty checks out the caller's default ref — used by the publish workflow to build from the resolved release tag on workflow_dispatch."
+        type: string
+        required: false
+        default: ""
     secrets:
       DOCKERHUB_USERNAME:
         required: false

@@ -56,6 +56,11 @@ on:
         type: string
         required: false
         default: "dev"
+      ref:
+        description: "Git ref to check out (e.g. refs/tags/v2.0.3). Empty checks out the caller's default ref — used by the publish workflow to build from the resolved release tag on workflow_dispatch."
+        type: string
+        required: false
+        default: ""
     secrets:
       DOCKERHUB_USERNAME:
         required: false
@@ -71,6 +76,7 @@ jobs:
       - name: Checkout
         uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
         with:
+          ref: ${{ inputs.ref }}
           persist-credentials: false
 
       - name: 🔨 Set up Docker Buildx

@@ -71,6 +76,7 @@ jobs:
       - name: Checkout
         uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
         with:
+          ref: ${{ inputs.ref }}
           persist-credentials: false
 
       - name: 🔨 Set up Docker Buildx

diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml
--- a/.github/workflows/publish-docker.yml
+++ b/.github/workflows/publish-docker.yml
@@ -43,6 +43,7 @@ jobs:
     runs-on: ubuntu-latest
     outputs:
       version: ${{ steps.version.outputs.clean }}
+      ref: ${{ steps.version.outputs.ref }}
     steps:
       - name: 🏷️ Resolve version
         id: version

@@ -43,6 +43,7 @@ jobs:
     runs-on: ubuntu-latest
     outputs:
       version: ${{ steps.version.outputs.clean }}
+      ref: ${{ steps.version.outputs.ref }}
     steps:
       - name: 🏷️ Resolve version
         id: version
@@ -130,6 +131,7 @@ jobs:
       arch_label: ${{ matrix.arch }}
       push: true
       version: ${{ needs.resolve-version.outputs.version }}
+      ref: ${{ needs.resolve-version.outputs.ref }}
     secrets:
       DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
       DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}

@@ -130,6 +131,7 @@ jobs:
       arch_label: ${{ matrix.arch }}
       push: true
       version: ${{ needs.resolve-version.outputs.version }}
+      ref: ${{ needs.resolve-version.outputs.ref }}
     secrets:
       DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
       DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}

You can send follow-ups to the cloud agent here.

Comment thread .github/workflows/publish-docker.yml
Comment thread scripts/smoke-test-docker.sh
@lelia

lelia commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

bugbot run

Comment thread .github/workflows/_docker-pipeline.yml
Comment thread .github/workflows/publish-docker.yml
@lelia

lelia commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

bugbot run

Comment thread .github/workflows/publish-docker.yml
Comment thread .github/workflows/_docker-pipeline.yml Outdated
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 <[email protected]>
@lelia

lelia commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

1 issue from previous review remains unresolved.

Fix All in Cursor

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit fbf94ea. Configure here.

Resolves conflicts with PR #78 (dependency hardening):
- keep the metadata step removal (tagging moved to merge-manifests)
- adopt bumped docker action pins in the by-digest push and merge job
- revert Dockerfile/.dockerignore to LICENSE (main renamed LICENSE.md back)
- update pipeline header for dependabot-review.yml -> dependency-review.yml

Co-Authored-By: Claude Fable 5 <[email protected]>
@lelia
lelia temporarily deployed to socket-firewall July 22, 2026 23:37 — with GitHub Actions Inactive
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 <[email protected]>
@lelia
lelia temporarily deployed to socket-firewall July 29, 2026 19:25 — with GitHub Actions Inactive
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 <[email protected]>
@lelia
lelia temporarily deployed to socket-firewall July 29, 2026 20:10 — with GitHub Actions Inactive
lelia and others added 2 commits July 29, 2026 16:25
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 <[email protected]>
lelia and others added 2 commits July 29, 2026 17:10
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 <[email protected]>
Resolves Dependabot pin-bump conflicts: keep the moved/deleted steps
from this branch, adopt main's new action pins (checkout v7, buildx
v4.2.0, login v4.4.0, metadata v6.2.0, build-push v7.3.0) including in
the merge-manifests job main doesn't know about.

Co-Authored-By: Claude Fable 5 <[email protected]>
@lelia
lelia had a problem deploying to socket-firewall July 29, 2026 21:33 — with GitHub Actions Failure
@lelia
lelia temporarily deployed to socket-firewall July 29, 2026 21:33 — with GitHub Actions Inactive
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 <[email protected]>
@lelia
lelia had a problem deploying to socket-firewall July 29, 2026 21:36 — with GitHub Actions Failure
@lelia
lelia temporarily deployed to socket-firewall July 29, 2026 21:37 — with GitHub Actions Inactive
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 <[email protected]>
@lelia
lelia had a problem deploying to socket-firewall July 30, 2026 01:01 — with GitHub Actions Failure
@lelia
lelia temporarily deployed to socket-firewall July 30, 2026 01:01 — with GitHub Actions Inactive
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.

Co-Authored-By: Claude Fable 5 <[email protected]>
@lelia
lelia temporarily deployed to socket-firewall July 30, 2026 01:10 — with GitHub Actions Inactive
@lelia
lelia temporarily deployed to socket-firewall July 30, 2026 01:10 — with GitHub Actions Inactive
@lelia
lelia merged commit 0d3f141 into main Jul 30, 2026
18 checks passed

This branch was previously deployed

1 inactive deployment
socket-firewall — 2f8c5dae Deployed Jul 30, 2026 by lelia via python-sfw-smoke-enterprise #29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request github-actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ARM builds

2 participants