Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 73 additions & 7 deletions .github/workflows/sandbox-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,28 @@ on:
- main
paths:
- "images/sandbox/**"
- "images/code/**"
pull_request:
paths:
- "images/sandbox/**"
- "images/code/**"
workflow_dispatch:

# NOTE: GitHub Actions ignores `paths` filters on tag pushes, so every
# v* tag triggers a build. This is intentional — the sandbox image is
# published alongside the CLI so consumers can pin both to the same
# version. Branch pushes and PRs still respect the paths filter.

env:
IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/fullsend-sandbox

jobs:
build:
build-base:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
outputs:
image-ref: ${{ steps.ref.outputs.value }}
env:
BASE_IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/fullsend-sandbox
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

Expand All @@ -44,20 +47,83 @@ jobs:
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6
with:
images: ${{ env.IMAGE_NAME }}
images: ${{ env.BASE_IMAGE_NAME }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push
id: push
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7
with:
context: images/sandbox
file: images/sandbox/Containerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
cache-from: type=gha,scope=sandbox
cache-to: type=gha,mode=max,scope=sandbox

# Compute a single image reference for the build-code job.
# On push: use the immutable digest from the pushed image.
# On PR: use the latest published image (the PR build validates
# the Containerfile compiles but doesn't push, so build-code
# needs an already-published base to FROM).
- name: Compute base image ref
id: ref
env:
DIGEST: ${{ steps.push.outputs.digest }}
IMAGE_NAME: ${{ env.BASE_IMAGE_NAME }}
run: |
if [ -n "$DIGEST" ]; then
echo "value=${IMAGE_NAME}@${DIGEST}" >> "$GITHUB_OUTPUT"
else
echo "value=${IMAGE_NAME}:latest" >> "$GITHUB_OUTPUT"
fi

build-code:
needs: build-base
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
env:
CODE_IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/fullsend-code
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Log in to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4

- name: Extract metadata
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6
with:
images: ${{ env.CODE_IMAGE_NAME }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7
with:
context: images/code
file: images/code/Containerfile
build-args: |
BASE_IMAGE=${{ needs.build-base.outputs.image-ref }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=code
cache-to: type=gha,mode=max,scope=code
4 changes: 2 additions & 2 deletions images/code/Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
# The base image already provides Claude Code, rsync, tirith, and LLM Guard.
# See images/sandbox/Containerfile in fullsend-ai/fullsend for the base definition.
#
# This image is built AUTOMATICALLY by .github/workflows/build-images.yml
# on every push to main that touches images/code/Containerfile.
# This image is built AUTOMATICALLY by .github/workflows/sandbox-image.yml
# (build-code job) on every push to main that touches images/code/.
# You can also trigger it manually via workflow_dispatch.
#
# Published to: ghcr.io/fullsend-ai/fullsend-code:latest
Expand Down
Loading