5151
5252jobs :
5353 # ---------------------------------------------------------------------------
54- # Job 1: Build & test amd64 image (gate for all subsequent jobs)
54+ # Job 1: Extract version and metadata for downstream jobs
5555 # ---------------------------------------------------------------------------
56- build-test :
57- name : Build Test Image (amd64)
56+ prepare :
57+ name : Prepare metadata
5858 runs-on : ubuntu-latest
59- timeout-minutes : 30
59+ timeout-minutes : 5
6060 outputs :
6161 version : ${{ steps.version.outputs.version }}
6262 oci_description : ${{ steps.oci-description.outputs.description }}
6363 permissions :
6464 contents : read
65- packages : read
6665
6766 steps :
68- - name : Disk + Docker usage
69- run : |
70- df -h
71- df -i
72- docker system df || true
73-
74- - name : Free disk space
75- run : |
76- set -euo pipefail
77- echo "Before:"
78- df -h
79- sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc || true
80- sudo rm -rf /usr/local/share/boost || true
81- sudo apt-get clean
82- sudo rm -rf /var/lib/apt/lists/*
83- sudo rm -rf "$AGENT_TOOLSDIRECTORY" || true
84- docker system prune -af || true
85- echo "After:"
86- df -h
87-
8867 - uses : actions/checkout@v6
8968 with :
90- # If ref is not provided: when triggered by tag push, checkout uses the tag automatically;
91- # when called via workflow_call, defaults to the commit that triggered the workflow
9269 ref : ${{ inputs.ref }}
9370
9471 # NOTE: We parse the description label from the Dockerfile so the
@@ -115,92 +92,6 @@ jobs:
11592 echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
11693 echo "Building version: ${VERSION}"
11794
118- - name : Set up Docker Buildx
119- uses : docker/setup-buildx-action@v3
120-
121- - name : Extract Dockerfile from embedded location
122- run : |
123- # The Dockerfile is embedded in the Rust source
124- cp packages/core/src/docker/Dockerfile .
125-
126- - name : Build test image (amd64 only)
127- uses : docker/build-push-action@v6
128- env :
129- BUILDKIT_PROGRESS : plain
130- with :
131- context : .
132- push : false
133- load : true
134- platforms : linux/amd64
135- build-args : |
136- OPENCODE_CLOUD_VERSION=${{ steps.version.outputs.version }}
137- tags : |
138- ${{ env.IMAGE_NAME_GHCR }}:test
139- # Separate GHA scope to avoid overwriting the main publish build cache.
140- # Also pull from the amd64 publish scope and registry cache for cross-build reuse
141- # (e.g. reuse base/broker-deps layers from the last publish build).
142- cache-from : |
143- type=gha,scope=opencode-cloud-sandbox-test,version=2
144- type=gha,scope=opencode-cloud-sandbox-amd64,version=2
145- type=registry,ref=${{ env.IMAGE_NAME_GHCR }}:buildcache-amd64
146- cache-to : type=gha,scope=opencode-cloud-sandbox-test,mode=min,version=2
147-
148- # Temporary disabled smoke test
149- # - name: Smoke test - verify container starts and becomes healthy
150- # run: |
151- # echo "Starting container for smoke test..."
152- # # Note: systemd in containers requires:
153- # # - --privileged OR specific capabilities
154- # # - --cgroupns=host for cgroups v2 (GitHub Actions runners)
155- # # - rw cgroup mount for systemd to manage cgroups
156- # docker run -d \
157- # --name smoke-test \
158- # --privileged \
159- # --cgroupns=host \
160- # --tmpfs /run \
161- # --tmpfs /tmp \
162- # -v /sys/fs/cgroup:/sys/fs/cgroup:rw \
163- # -p 3000:3000 \
164- # -e USE_SYSTEMD=1 \
165- # ${{ env.IMAGE_NAME_GHCR }}:test
166-
167- # echo "Container started, checking status..."
168- # docker ps -a --filter name=smoke-test
169-
170- # echo "Waiting for container to become healthy (max 90 seconds)..."
171- # for i in {1..90}; do
172- # # Check if container is still running
173- # if ! docker ps --filter name=smoke-test --filter status=running -q | grep -q .; then
174- # echo "✗ Container exited unexpectedly"
175- # echo "Container status:"
176- # docker ps -a --filter name=smoke-test
177- # echo "Container logs:"
178- # docker logs smoke-test 2>&1 || echo "(no logs)"
179- # docker rm smoke-test || true
180- # exit 1
181- # fi
182-
183- # if curl -sf http://localhost:3000/health > /dev/null 2>&1; then
184- # echo "✓ Container is healthy after ${i} seconds"
185- # docker logs smoke-test --tail 20
186- # docker stop smoke-test
187- # docker rm smoke-test
188- # exit 0
189- # fi
190- # sleep 1
191- # done
192-
193- # echo "✗ Container failed to become healthy within 90 seconds"
194- # echo "Container status:"
195- # docker ps -a --filter name=smoke-test
196- # echo "Container logs:"
197- # docker logs smoke-test 2>&1 || echo "(no logs)"
198- # echo "Checking systemd status inside container:"
199- # docker exec smoke-test systemctl status || echo "(systemctl failed)"
200- # docker stop smoke-test || true
201- # docker rm smoke-test || true
202- # exit 1
203-
20495 # ---------------------------------------------------------------------------
20596 # Jobs 2+3: Build each platform natively and push by digest
20697 # ---------------------------------------------------------------------------
@@ -212,7 +103,7 @@ jobs:
212103 # https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
213104 build-platform :
214105 name : Build ${{ matrix.platform }}
215- needs : [build-test ]
106+ needs : [prepare ]
216107 strategy :
217108 fail-fast : true
218109 matrix :
@@ -287,10 +178,10 @@ jobs:
287178 context : .
288179 platforms : ${{ matrix.platform }}
289180 build-args : |
290- OPENCODE_CLOUD_VERSION=${{ needs.build-test .outputs.version }}
181+ OPENCODE_CLOUD_VERSION=${{ needs.prepare .outputs.version }}
291182 labels : ${{ steps.meta.outputs.labels }}
292183 annotations : |
293- org.opencontainers.image.description=${{ needs.build-test .outputs.oci_description }}
184+ org.opencontainers.image.description=${{ needs.prepare .outputs.oci_description }}
294185 sbom : true
295186 provenance : mode=max
296187 # push-by-digest pushes the image without tags; the merge job
@@ -331,7 +222,7 @@ jobs:
331222 # Docker Scout analysis and updates the Docker Hub description.
332223 merge-and-publish :
333224 name : Merge Manifest & Publish
334- needs : [build-test , build-platform]
225+ needs : [prepare , build-platform]
335226 runs-on : ubuntu-latest
336227 timeout-minutes : 15
337228 outputs :
@@ -377,7 +268,7 @@ jobs:
377268 ${{ env.IMAGE_NAME_GHCR }}
378269 ${{ env.IMAGE_NAME_DOCKERHUB }}
379270 tags : |
380- type=semver,pattern={{version}},value=${{ needs.build-test .outputs.version }}
271+ type=semver,pattern={{version}},value=${{ needs.prepare .outputs.version }}
381272 type=raw,value=latest
382273
383274 # Merge per-platform digests into a single multi-arch manifest and
@@ -397,19 +288,19 @@ jobs:
397288 # docker/metadata-action outputs one tag per line; convert to -t flags.
398289 docker buildx imagetools create \
399290 $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< '${{ steps.meta.outputs.json }}') \
400- --annotation 'index:org.opencontainers.image.description=${{ needs.build-test .outputs.oci_description }}' \
291+ --annotation 'index:org.opencontainers.image.description=${{ needs.prepare .outputs.oci_description }}' \
401292 ${SOURCES}
402293
403294 - name : Inspect manifest
404295 run : |
405- docker buildx imagetools inspect "${{ env.IMAGE_NAME_GHCR }}:${{ needs.build-test .outputs.version }}"
296+ docker buildx imagetools inspect "${{ env.IMAGE_NAME_GHCR }}:${{ needs.prepare .outputs.version }}"
406297
407298 - name : Docker Scout Quickview
408299 continue-on-error : true
409300 uses : docker/scout-action@v1
410301 with :
411302 command : quickview
412- image : ${{ env.IMAGE_NAME_DOCKERHUB }}:${{ needs.build-test .outputs.version }}
303+ image : ${{ env.IMAGE_NAME_DOCKERHUB }}:${{ needs.prepare .outputs.version }}
413304 summary : true
414305 write-comment : false
415306
@@ -436,7 +327,7 @@ jobs:
436327
437328 set +e
438329 docker scout policy \
439- "${IMAGE_NAME_DOCKERHUB}:${{ needs.build-test .outputs.version }}" \
330+ "${IMAGE_NAME_DOCKERHUB}:${{ needs.prepare .outputs.version }}" \
440331 --org "${org}" --exit-code
441332 scout_exit_code=$?
442333 set -e
@@ -453,7 +344,7 @@ jobs:
453344 - name : Summarize Docker Scout Policy
454345 if : always()
455346 env :
456- VERSIONED_IMAGE : ${{ env.IMAGE_NAME_DOCKERHUB }}:${{ needs.build-test .outputs.version }}
347+ VERSIONED_IMAGE : ${{ env.IMAGE_NAME_DOCKERHUB }}:${{ needs.prepare .outputs.version }}
457348 SCOUT_POLICY_STATUS : ${{ steps.scout-policy.outputs.status }}
458349 SCOUT_POLICY_EXIT_CODE : ${{ steps.scout-policy.outputs.exit_code }}
459350 run : |
@@ -480,16 +371,16 @@ jobs:
480371 run : |
481372 echo "## 🐳 Sandbox Docker Images Published" >> $GITHUB_STEP_SUMMARY
482373 echo "" >> $GITHUB_STEP_SUMMARY
483- echo "**Version:** ${{ needs.build-test .outputs.version }}" >> $GITHUB_STEP_SUMMARY
374+ echo "**Version:** ${{ needs.prepare .outputs.version }}" >> $GITHUB_STEP_SUMMARY
484375 echo "" >> $GITHUB_STEP_SUMMARY
485376 echo "**GHCR (GitHub Container Registry):**" >> $GITHUB_STEP_SUMMARY
486377 echo "- https://github.com/pRizz/opencode-cloud/pkgs/container/opencode-cloud-sandbox" >> $GITHUB_STEP_SUMMARY
487- echo "- \`${{ env.IMAGE_NAME_GHCR }}:${{ needs.build-test .outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
378+ echo "- \`${{ env.IMAGE_NAME_GHCR }}:${{ needs.prepare .outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
488379 echo "- \`${{ env.IMAGE_NAME_GHCR }}:latest\`" >> $GITHUB_STEP_SUMMARY
489380 echo "" >> $GITHUB_STEP_SUMMARY
490381 echo "**Docker Hub:**" >> $GITHUB_STEP_SUMMARY
491382 echo "- https://hub.docker.com/r/${{ vars.DOCKERHUB_USERNAME }}/opencode-cloud-sandbox" >> $GITHUB_STEP_SUMMARY
492- echo "- \`${{ env.IMAGE_NAME_DOCKERHUB }}:${{ needs.build-test .outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
383+ echo "- \`${{ env.IMAGE_NAME_DOCKERHUB }}:${{ needs.prepare .outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
493384 echo "- \`${{ env.IMAGE_NAME_DOCKERHUB }}:latest\`" >> $GITHUB_STEP_SUMMARY
494385 echo "" >> $GITHUB_STEP_SUMMARY
495386 echo "**Platforms:** linux/amd64, linux/arm64" >> $GITHUB_STEP_SUMMARY
0 commit comments