Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
18 changes: 13 additions & 5 deletions .github/workflows/build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build Image with buildah script
id: build
env:
STORAGE_DRIVER: vfs
run: |
Expand All @@ -34,12 +35,19 @@ jobs:

# Run the build script
VERSION=$(./devops/build-image.sh -repo-name $REPO_NAME | tail -n2 | head -n1 | cut -d: -f2)

# Tag the image for GHCR
buildah tag claude-code \
"ghcr.io/$REPO_NAME/claude-code:$VERSION" \
"ghcr.io/$REPO_NAME/claude-code:latest"

# Push to GitHub Container Registry
buildah push "ghcr.io/$REPO_NAME/claude-code:$VERSION"
buildah push "ghcr.io/$REPO_NAME/claude-code:latest"

echo "repo_name=$REPO_NAME" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Test image
run: ./tests/test-image.sh "${{ steps.build.outputs.version }}"

- name: Push to GitHub Container Registry
run: |
buildah push "ghcr.io/${{ steps.build.outputs.repo_name }}/claude-code:${{ steps.build.outputs.version }}"
buildah push "ghcr.io/${{ steps.build.outputs.repo_name }}/claude-code:latest"
10 changes: 10 additions & 0 deletions bin/claude
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ while [[ $# -gt 0 ]]; do
--init-script FILE Execute initialization script
--apk-packages LIST Install additional Alpine packages (comma or space separated)
--podman-arg ARG Pass additional argument to podman
--version Show the Claude Code version in the image
--help Display this help message
EOT
exit 0
Expand Down Expand Up @@ -52,6 +53,15 @@ while [[ $# -gt 0 ]]; do
PODMAN_ARGS="$PODMAN_ARGS $2"
shift 2
;;
--version)
podman run \
--rm \
--user claude \
--userns=keep-id:uid=1001,gid=1001 \
$PODMAN_ARGS \
"$IMAGE" --version
exit 0
;;
*)
break
;;
Expand Down
2 changes: 1 addition & 1 deletion devops/build-image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ buildah commit \
--rm \
"$CONTAINER" "$IMAGE"

buildah tag "$IMAGE" "$CLAUDE_VERSION"
buildah tag "$IMAGE" "$IMAGE:$CLAUDE_VERSION"

echo Done!
echo ${IMAGE}:${CLAUDE_VERSION}
Expand Down
65 changes: 65 additions & 0 deletions tests/test-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/bash
set -euo pipefail

IMAGE="localhost/claude-code:${1:-latest}"
PASS=0
FAIL=0

run_test() {
local name="$1"
shift
printf "TEST: %s ... " "$name"
if "$@"; then
echo "PASS"
PASS=$((PASS + 1))
else
echo "FAIL"
FAIL=$((FAIL + 1))
fi
}

# 1. Image exists
run_test "Image exists" \
podman image exists "$IMAGE"

# 2. Claude binary runs and outputs a version
test_claude_version() {
local output
output=$(podman run --rm --entrypoint "" "$IMAGE" \
/home/claude/.local/bin/claude --version 2>&1)
echo "$output" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+'
}
run_test "Claude binary outputs version" \
test_claude_version

# 3. Entrypoint is set correctly
test_entrypoint() {
local entrypoint
entrypoint=$(podman inspect --format '{{range .Config.Entrypoint}}{{.}}{{end}}' "$IMAGE")
[ "$entrypoint" = "/home/claude/.local/bin/claude" ]
}
run_test "Entrypoint is /home/claude/.local/bin/claude" \
test_entrypoint

# 4. Claude user exists with UID 1000
test_claude_uid() {
local output
output=$(podman run --rm --entrypoint "" "$IMAGE" id claude 2>&1)
echo "$output" | grep -q "uid=1000"
}
run_test "Claude user has UID 1000" \
test_claude_uid

# 5. Wrapper script starts claude and it responds
test_wrapper() {
local output
output=$(timeout 30 ./bin/claude --local --version 2>&1)
echo "$output" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+'
}
run_test "Wrapper script starts claude" \
test_wrapper

# Summary
echo ""
echo "Results: $PASS passed, $FAIL failed"
[ "$FAIL" -eq 0 ]