diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 279a658..d694d07 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,3 +37,25 @@ jobs: run: | ./claude.sh --version ./claude-yolo --version + + docker-build: + name: Docker Build Test & Cache + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build Docker image (cache only) + uses: docker/build-push-action@v5 + with: + context: . + platforms: linux/amd64 + push: false + cache-from: | + type=gha + type=registry,ref=ghcr.io/${{ github.repository }}:buildcache + cache-to: type=gha,mode=max diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 3b24156..83f9519 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -1,7 +1,7 @@ name: Claude Code Review on: - pull_request_target: + pull_request: types: [opened, reopened] issue_comment: types: [created] @@ -14,7 +14,7 @@ concurrency: jobs: claude-review: if: | - github.event_name == 'pull_request_target' || + github.event_name == 'pull_request' || (github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, '@claude')) @@ -31,13 +31,13 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 - ref: ${{ github.event.pull_request.head.sha || github.event.pull_request.merge_commit_sha }} - name: Run Claude Code Review id: claude-review uses: anthropics/claude-code-action@beta with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + github_token: ${{ secrets.GITHUB_TOKEN }} # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4) # model: "claude-opus-4-20250514" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cc0d0e4..f16fced 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,8 +56,12 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: | + type=gha + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache + cache-to: | + type=gha,mode=max + type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max release: name: Create GitHub Release diff --git a/CHANGELOG.md b/CHANGELOG.md index f2c7a0f..4f40b9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.2.3] - 2025-06-23 + ### Added - Unified logging system for improved UX - Clean output by default showing only authentication method @@ -18,6 +20,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - claude-trace --run-with syntax (removed unnecessary "claude" argument) - Container shortcuts now properly exit after --ps command +### Performance +- Docker build caching in GitHub Actions (dual GHA + registry cache strategy) +- Added cache warming via CI builds on PRs to accelerate release builds + ### Changed - Consolidated all claude-yolo argument parsing through single parse_args() function - Enhanced claude-trace argument injection for proper --dangerously-skip-permissions placement diff --git a/DEV-LOGS.md b/DEV-LOGS.md index e9ef513..e37c2d0 100644 --- a/DEV-LOGS.md +++ b/DEV-LOGS.md @@ -5,6 +5,53 @@ ## Issue Analysis: 2025-06-23 +### [perf-optimized] Docker build caching in GitHub Actions (Issue #19) + +**Problem**: Docker image builds taking 49+ minutes due to lack of effective caching. + +**Root Cause**: Limited GitHub Actions cache scope, no registry cache, no cache warming. + +**Solution**: Dual caching strategy + cache warming +- Registry cache persists across branches/runners +- CI job warms cache on PRs for release builds +- Combined GHA + registry cache maximizes hit rates + +**Status**: ✅ **COMPLETED** + +--- + +## Issue Analysis: 2025-06-23 + +### [bug-fixed] Root user (UID 0) handling in docker-entrypoint.sh + +**Problem**: `sudo claude-yolo` fails with "usermod: UID '0' already exists" error. + +**Root Cause**: Can't reassign existing UID 0 (root) to claude user. + +**Security Fix**: Handle UID=0 and GID=0 independently to prevent root group assignment. + +**Solution**: Use fallback UID/GID 1000 for proper file ownership with existing collision handling. + +**Status**: ✅ **COMPLETED** - PR #22 + +--- + +## Issue Analysis: 2025-06-23 + +### [bug-fixed] Claude Code Review OIDC token authentication error + +**Problem**: CI failing with "Invalid OIDC token" after changing permissions to write. + +**Solution**: Added explicit `github_token: ${{ secrets.GITHUB_TOKEN }}` to force direct token auth. + +**Cause**: Write permissions trigger GitHub App auth by default, but no App configured. + +**Status**: ✅ **COMPLETED** + +--- + +## Issue Analysis: 2025-06-23 + ### [enhancement-completed] Claude Code Review workflow simplification **Problem**: Overcomplicated workflow with manual duplicate detection using GitHub CLI. diff --git a/claude.sh b/claude.sh index 8689795..4068de8 100755 --- a/claude.sh +++ b/claude.sh @@ -4,7 +4,7 @@ set -e # Claude Starter Script with Docker Support # Runs Claude Code CLI locally or in a Docker container for safe execution -VERSION="0.2.2" +VERSION="0.2.3" DOCKER_IMAGE="${DOCKER_IMAGE:-ghcr.io/lroolle/claude-code-yolo}" DOCKER_TAG="${DOCKER_TAG:-latest}" diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 582f7cf..cb3c4d8 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -59,6 +59,16 @@ setup_nonroot_user() { local current_uid=$(id -u "$CLAUDE_USER") local current_gid=$(id -g "$CLAUDE_USER") + if [ "$CLAUDE_UID" = "0" ]; then + echo "[entrypoint] WARNING: Host user is root (UID=0). Using fallback UID 1000 for security." + CLAUDE_UID=1000 + fi + + if [ "$CLAUDE_GID" = "0" ]; then + echo "[entrypoint] WARNING: Host user is in root group (GID=0). Using fallback GID 1000 for security." + CLAUDE_GID=1000 + fi + if [ "$CLAUDE_GID" != "$current_gid" ]; then [ "$VERBOSE" = "true" ] && echo "[entrypoint] updating $CLAUDE_USER GID: $current_gid -> $CLAUDE_GID" if getent group "$CLAUDE_GID" >/dev/null 2>&1; then