From af851491e8c219985e6a81097f114910398471ba Mon Sep 17 00:00:00 2001 From: Cheffromspace Date: Sun, 1 Jun 2025 12:54:58 -0500 Subject: [PATCH] feat: Improve Claude authentication setup experience (#153) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Improve Claude authentication setup experience - Replace 'claude login' with 'claude --dangerously-skip-permissions' - Fix path references from /auth-output to actual authentication location - Simplify user instructions to be more accessible - Add automatic authentication execution (no manual typing required) - Add comprehensive validation for authentication success - Check file existence, size, and timestamp - Provide clear error messages for different failure scenarios - Remove deprecated setup-claude-auth.sh script - Update CLAUDE.md to reference correct build script path - Exclude todos directory from authentication capture ๐Ÿค– Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * remove self-hosted runners from ci --------- Co-authored-by: Claude --- .env.example | 2 +- .github/workflows/deploy.yml | 2 +- .github/workflows/docker-publish.yml | 31 +------- .github/workflows/main.yml | 2 +- .github/workflows/pull-request.yml | 2 +- .gitignore | 4 +- CLAUDE.md | 2 +- Dockerfile.claude-setup | 76 +++++++++++-------- scripts/setup/setup-claude-auth.sh | 14 ---- scripts/setup/setup-claude-interactive.sh | 90 +++++++++++++++-------- 10 files changed, 118 insertions(+), 107 deletions(-) delete mode 100755 scripts/setup/setup-claude-auth.sh diff --git a/.env.example b/.env.example index 9f62c64..9acc1b2 100644 --- a/.env.example +++ b/.env.example @@ -85,4 +85,4 @@ PR_REVIEW_MAX_WAIT_MS=1800000 PR_REVIEW_CONDITIONAL_TIMEOUT_MS=300000 # Test Configuration -TEST_REPO_FULL_NAME=owner/repo \ No newline at end of file +TEST_REPO_FULL_NAME=owner/repo diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4001b4a..473266f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -154,7 +154,7 @@ jobs: sarif_file: 'trivy-results.sarif' # ============================================ - # CD Jobs - Run on self-hosted runners + # CD Jobs - Run on GitHub-hosted runners # ============================================ deploy-staging: diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 6d7e7a9..d7e51d4 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -16,13 +16,11 @@ env: DOCKER_HUB_USERNAME: ${{ vars.DOCKER_HUB_USERNAME || 'cheffromspace' }} DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION || 'intelligenceassist' }} IMAGE_NAME: ${{ vars.DOCKER_IMAGE_NAME || 'claude-hub' }} - # Runner configuration - set USE_SELF_HOSTED to 'false' to force GitHub-hosted runners - USE_SELF_HOSTED: ${{ vars.USE_SELF_HOSTED || 'true' }} jobs: build: - # Use self-hosted runners by default, with ability to override via repository variable - runs-on: ${{ vars.USE_SELF_HOSTED == 'false' && 'ubuntu-latest' || fromJSON('["self-hosted", "linux", "x64", "docker"]') }} + # Always use GitHub-hosted runners + runs-on: ubuntu-latest timeout-minutes: 30 permissions: contents: read @@ -118,7 +116,7 @@ jobs: # Build claudecode separately build-claudecode: - runs-on: ${{ vars.USE_SELF_HOSTED == 'false' && 'ubuntu-latest' || fromJSON('["self-hosted", "linux", "x64", "docker"]') }} + runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 30 permissions: @@ -170,25 +168,4 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max - # Fallback job if self-hosted runners timeout - build-fallback: - needs: [build, build-claudecode] - if: | - always() && - (needs.build.result == 'failure' || needs.build-claudecode.result == 'failure') && - vars.USE_SELF_HOSTED != 'false' - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - security-events: write - - steps: - - name: Trigger rebuild on GitHub-hosted runners - run: | - echo "Self-hosted runner build failed. To retry with GitHub-hosted runners:" - echo "1. Set the repository variable USE_SELF_HOSTED to 'false'" - echo "2. Re-run this workflow" - echo "" - echo "Or manually trigger a new workflow run with GitHub-hosted runners." - exit 1 \ No newline at end of file + # Note: Fallback job removed since we're always using GitHub-hosted runners \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 274b764..d397ed6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,7 +42,7 @@ jobs: extra_args: --debug --only-verified build: - runs-on: [self-hosted, docker] + runs-on: ubuntu-latest needs: [test, security] permissions: contents: read diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index ef006a6..51f3f3f 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -29,7 +29,7 @@ jobs: - run: ./scripts/security/credential-audit.sh docker: - runs-on: [self-hosted, docker] + runs-on: ubuntu-latest if: contains(github.event.pull_request.changed_files, 'Dockerfile') || contains(github.event.pull_request.changed_files, 'src/') steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 6419b4d..4c109e9 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,8 @@ service-account.json # Claude authentication output .claude-hub/ +claude-config/ +claude-config* # Docker secrets secrets/ @@ -93,4 +95,4 @@ secrets/ # Root level clutter prevention /test-*.js /PR_SUMMARY.md -/*-proposal.md \ No newline at end of file +/*-proposal.md diff --git a/CLAUDE.md b/CLAUDE.md index a43b0ea..605e328 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -46,7 +46,7 @@ This repository contains a webhook service that integrates Claude with GitHub, a - **View logs**: `docker compose logs -f webhook` - **Restart**: `docker compose restart webhook` - Build Claude container: `./build-claude-container.sh` -- Build Claude Code container: `./scripts/build/build-claudecode.sh` +- Build Claude Code container: `./scripts/build/build.sh claudecode` - Update production image: `./update-production-image.sh` ### AWS Credential Management diff --git a/Dockerfile.claude-setup b/Dockerfile.claude-setup index cb2fb41..891df64 100644 --- a/Dockerfile.claude-setup +++ b/Dockerfile.claude-setup @@ -8,7 +8,8 @@ RUN apt update && apt install -y \ curl \ vim \ nano \ - gh + gh \ + rsync # Set up npm global directory RUN mkdir -p /usr/local/share/npm-global && \ @@ -32,34 +33,31 @@ RUN mkdir -p /auth-setup && chown -R node:node /auth-setup ENV SHELL /bin/zsh WORKDIR /auth-setup -# Create setup script that captures authentication state -RUN cat > /setup-claude-auth.sh << 'EOF' +# Create setup script +COPY <<'EOF' /setup-claude-auth.sh #!/bin/bash set -e -echo "๐Ÿ”ง Claude Authentication Setup Container" -echo "========================================" +echo "๐Ÿ”ง Claude Authentication Setup" +echo "==============================" echo "" -echo "This container allows you to authenticate with Claude interactively" -echo "and capture the authentication state for use in other containers." +echo "This will help you connect Claude to your account." echo "" -echo "Instructions:" -echo "1. Run: claude login" -echo "2. Follow the authentication flow" -echo "3. Test with: claude status" -echo "4. Type 'exit' when authentication is working" +echo "Quick setup - just run this command:" echo "" -echo "The ~/.claude directory will be preserved in /auth-output" +echo " claude --dangerously-skip-permissions && exit" +echo "" +echo "This will authenticate Claude and save your setup automatically." echo "" # Function to copy authentication state copy_auth_state() { if [ -d "/home/node/.claude" ] && [ -d "/auth-output" ]; then - echo "๐Ÿ’พ Copying authentication state..." - cp -r /home/node/.claude/* /auth-output/ 2>/dev/null || true - cp -r /home/node/.claude/.* /auth-output/ 2>/dev/null || true - chown -R node:node /auth-output - echo "โœ… Authentication state copied to /auth-output" + echo "๐Ÿ’พ Saving your authentication..." + # Copy authentication files, excluding todos + rsync -a --exclude='todos/' /home/node/.claude/ /auth-output/ 2>/dev/null || \ + cp -r /home/node/.claude/. /auth-output/ 2>/dev/null || true + echo "โœ… Authentication saved successfully!" fi } @@ -70,21 +68,41 @@ trap copy_auth_state EXIT sudo -u node mkdir -p /home/node/.claude echo "๐Ÿ” Starting interactive shell as 'node' user..." -echo "๐Ÿ’ก Tip: Run 'claude --version' to verify Claude CLI is available" +echo "" echo "" -# Switch to node user and start interactive shell -sudo -u node bash -c ' - export HOME=/home/node - export PATH=/usr/local/share/npm-global/bin:$PATH - cd /home/node - echo "Environment ready! Claude CLI is available at: $(which claude || echo "/usr/local/share/npm-global/bin/claude")" - echo "Run: claude login" - exec bash -i -' +# Check if we should run automatically +if [ "$1" = "--auto" ]; then + echo "Running authentication automatically..." + echo "" + sudo -u node bash -c ' + export HOME=/home/node + export PATH=/usr/local/share/npm-global/bin:$PATH + cd /home/node + claude --dangerously-skip-permissions + exit_code=$? + if [ $exit_code -ne 0 ]; then + echo "" + echo "โŒ Authentication command failed with exit code $exit_code" + exit $exit_code + fi + ' +else + # Switch to node user and start interactive shell + sudo -u node bash -c ' + export HOME=/home/node + export PATH=/usr/local/share/npm-global/bin:$PATH + cd /home/node + echo "Ready! Run this command to authenticate and exit:" + echo "" + echo " claude --dangerously-skip-permissions && exit" + echo "" + exec bash -i + ' +fi EOF RUN chmod +x /setup-claude-auth.sh # Set entrypoint to setup script -ENTRYPOINT ["/setup-claude-auth.sh"] \ No newline at end of file +ENTRYPOINT ["/bin/bash", "/setup-claude-auth.sh"] \ No newline at end of file diff --git a/scripts/setup/setup-claude-auth.sh b/scripts/setup/setup-claude-auth.sh deleted file mode 100755 index 3f877e8..0000000 --- a/scripts/setup/setup-claude-auth.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -echo "Setting up Claude Code authentication..." - -# Build the setup container -docker build -f Dockerfile.setup -t claude-setup . - -# Run it interactively with AWS credentials mounted -docker run -it -v $HOME/.aws:/root/.aws:ro claude-setup - -echo "" -echo "After completing the authentication in the container:" -echo "1. Run 'docker ps -a' to find the container ID" -echo "2. Run 'docker cp :/root/.claude ./claude-config'" -echo "3. Then run './update-production-image.sh'" \ No newline at end of file diff --git a/scripts/setup/setup-claude-interactive.sh b/scripts/setup/setup-claude-interactive.sh index be040c4..68be718 100755 --- a/scripts/setup/setup-claude-interactive.sh +++ b/scripts/setup/setup-claude-interactive.sh @@ -19,48 +19,76 @@ echo "๐Ÿ“ฆ Building Claude setup container..." docker build -f "$PROJECT_ROOT/Dockerfile.claude-setup" -t claude-setup:latest "$PROJECT_ROOT" echo "" -echo "๐Ÿš€ Starting interactive Claude authentication container..." +echo "๐Ÿš€ Starting Claude authentication..." echo "" -echo "IMPORTANT: This will open an interactive shell where you can:" -echo " 1. Run 'claude --dangerously-skip-permissions' to authenticate" -echo " 2. Follow the authentication flow" -echo " 3. Type 'exit' when done to preserve authentication state" +echo "What happens next:" +echo " 1. Claude will open your browser for authentication" +echo " 2. Complete the authentication in your browser" +echo " 3. Return here when done - the container will exit automatically" echo "" -echo "The authenticated ~/.claude directory will be saved to:" -echo " $AUTH_OUTPUT_DIR" -echo "" -read -p "Press Enter to continue or Ctrl+C to cancel..." +read -p "Press Enter to start authentication..." -# Run the interactive container +# Run the container with automatic authentication docker run -it --rm \ -v "$AUTH_OUTPUT_DIR:/auth-output" \ -v "$HOME/.gitconfig:/home/node/.gitconfig:ro" \ --name claude-auth-setup \ - claude-setup:latest + claude-setup:latest --auto + +# Capture the exit code +DOCKER_EXIT_CODE=$? echo "" echo "๐Ÿ“‹ Checking authentication output..." -if [ -f "$AUTH_OUTPUT_DIR/.credentials.json" ] || [ -f "$AUTH_OUTPUT_DIR/settings.local.json" ]; then - echo "โœ… Authentication files found in $AUTH_OUTPUT_DIR" +# First check if docker command failed +if [ $DOCKER_EXIT_CODE -ne 0 ]; then + echo "โŒ Authentication process failed (exit code: $DOCKER_EXIT_CODE)" echo "" - echo "๐Ÿ“ Captured authentication files:" - find "$AUTH_OUTPUT_DIR" -type f -name "*.json" -o -name "*.db" | head -10 - echo "" - echo "๐Ÿ”„ To use this authentication in your webhook service:" - echo " 1. Copy files to your ~/.claude directory:" - echo " cp -r $AUTH_OUTPUT_DIR/* ~/.claude/" - echo " 2. Or update docker-compose.yml to mount the auth directory:" - echo " - $AUTH_OUTPUT_DIR:/home/node/.claude:ro" - echo "" -else - echo "โš ๏ธ No authentication files found. You may need to:" - echo " 1. Run the container again and complete the authentication flow" - echo " 2. Ensure you ran 'claude --dangerously-skip-permissions' and completed authentication" - echo " 3. Check that you have an active Claude Code subscription" + echo "Please check the error messages above and try again." + exit 1 +fi + +# Check if authentication was successful +if [ -f "$AUTH_OUTPUT_DIR/.credentials.json" ]; then + # Get file size + FILE_SIZE=$(stat -f%z "$AUTH_OUTPUT_DIR/.credentials.json" 2>/dev/null || stat -c%s "$AUTH_OUTPUT_DIR/.credentials.json" 2>/dev/null || echo "0") + + # Check if file has reasonable content (at least 100 bytes for a valid JSON) + if [ "$FILE_SIZE" -gt 100 ]; then + # Check if file was written recently (within last 5 minutes) + if [ "$(find "$AUTH_OUTPUT_DIR/.credentials.json" -mmin -5 2>/dev/null)" ]; then + echo "โœ… Success! Your Claude authentication is saved." + echo "" + echo "The webhook service will use this automatically when you run:" + echo " docker compose up -d" + echo "" + exit 0 + else + echo "โš ๏ธ Found old authentication files. The authentication may not have completed." + echo "Please run the setup again to refresh your authentication." + exit 1 + fi + else + echo "โŒ Authentication file is too small (${FILE_SIZE} bytes). The authentication did not complete." + echo "" + echo "Common causes:" + echo " - Browser authentication was cancelled" + echo " - Network connection issues" + echo " - Claude Code subscription not active" + echo "" + echo "Please run the setup again and complete the browser authentication." + exit 1 + fi +else + echo "โŒ Authentication failed - no credentials were saved." + echo "" + echo "This can happen if:" + echo " - The browser authentication was not completed" + echo " - The container exited before authentication finished" + echo " - There was an error during the authentication process" + echo "" + echo "Please run './scripts/setup/setup-claude-interactive.sh' again." + exit 1 fi -echo "" -echo "๐Ÿงช Testing authentication..." -echo "You can test the captured authentication with:" -echo " docker run --rm -v \"$AUTH_OUTPUT_DIR:/home/node/.claude:ro\" claude-setup:latest claude --dangerously-skip-permissions --print 'test'" \ No newline at end of file