Skip to content

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

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

ci: publish multi-arch Docker image variants#85
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.

Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
@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
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
@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 added 2 commits July 21, 2026 18:30
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
@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 added 2 commits July 21, 2026 21:11
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
@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
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
@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 <noreply@anthropic.com>
@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 <noreply@anthropic.com>
@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 <noreply@anthropic.com>
@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 <noreply@anthropic.com>
@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
… action image ref

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
@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 <noreply@anthropic.com>
@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 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@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 <noreply@anthropic.com>
@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
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