forked from claude-did-this/claude-hub
Merge pull request #55 from intelligence-assist/feat/improve-runners
Optimize CI/CD pipelines for better performance and parallelization
This commit is contained in:
204
.github/workflows/ci.yml
vendored
204
.github/workflows/ci.yml
vendored
@@ -12,8 +12,9 @@ env:
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test & Lint
|
||||
# Lint job - fast and independent
|
||||
lint:
|
||||
name: Lint & Format Check
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@@ -25,12 +26,35 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'package-lock.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
run: npm ci --prefer-offline --no-audit
|
||||
|
||||
- name: Run linter
|
||||
run: npm run lint || echo "No lint script found, skipping"
|
||||
run: npm run lint:check || echo "No lint script found, skipping"
|
||||
|
||||
- name: Check formatting
|
||||
run: npm run format:check || echo "No format script found, skipping"
|
||||
|
||||
# Unit tests - fastest test suite
|
||||
test-unit:
|
||||
name: Unit Tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'package-lock.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --prefer-offline --no-audit
|
||||
|
||||
- name: Run unit tests
|
||||
run: npm run test:unit
|
||||
@@ -40,14 +64,51 @@ jobs:
|
||||
GITHUB_WEBHOOK_SECRET: 'test-secret'
|
||||
GITHUB_TOKEN: 'test-token'
|
||||
|
||||
# Integration tests are disabled for now
|
||||
# - name: Run integration tests
|
||||
# run: npm run test:integration
|
||||
# env:
|
||||
# NODE_ENV: test
|
||||
# BOT_USERNAME: '@TestBot'
|
||||
# GITHUB_WEBHOOK_SECRET: 'test-secret'
|
||||
# GITHUB_TOKEN: 'test-token'
|
||||
# Integration tests - moderate complexity
|
||||
test-integration:
|
||||
name: Integration Tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'package-lock.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --prefer-offline --no-audit
|
||||
|
||||
- name: Run integration tests
|
||||
run: npm run test:integration || echo "No integration tests found, skipping"
|
||||
env:
|
||||
NODE_ENV: test
|
||||
BOT_USERNAME: '@TestBot'
|
||||
GITHUB_WEBHOOK_SECRET: 'test-secret'
|
||||
GITHUB_TOKEN: 'test-token'
|
||||
|
||||
# E2E tests - only 1 scenario, run on GitHub for simplicity
|
||||
test-e2e:
|
||||
name: E2E Tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'package-lock.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --prefer-offline --no-audit
|
||||
|
||||
- name: Run e2e tests
|
||||
run: npm run test:e2e
|
||||
@@ -57,6 +118,26 @@ jobs:
|
||||
GITHUB_WEBHOOK_SECRET: 'test-secret'
|
||||
GITHUB_TOKEN: 'test-token'
|
||||
|
||||
# Coverage generation - depends on unit tests
|
||||
coverage:
|
||||
name: Test Coverage
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test-unit]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'package-lock.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --prefer-offline --no-audit
|
||||
|
||||
- name: Generate test coverage
|
||||
run: npm run test:coverage
|
||||
env:
|
||||
@@ -73,6 +154,7 @@ jobs:
|
||||
name: codecov-umbrella
|
||||
fail_ci_if_error: false
|
||||
|
||||
# Security scans - run on GitHub for faster execution
|
||||
security:
|
||||
name: Security Scan
|
||||
runs-on: ubuntu-latest
|
||||
@@ -86,9 +168,10 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'package-lock.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
run: npm ci --prefer-offline --no-audit
|
||||
|
||||
- name: Run npm audit
|
||||
run: npm audit --audit-level=moderate
|
||||
@@ -101,10 +184,36 @@ jobs:
|
||||
with:
|
||||
args: --severity-threshold=high
|
||||
|
||||
# Check if Docker-related files changed
|
||||
changes:
|
||||
name: Detect Changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
docker: ${{ steps.changes.outputs.docker }}
|
||||
src: ${{ steps.changes.outputs.src }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: changes
|
||||
with:
|
||||
filters: |
|
||||
docker:
|
||||
- 'Dockerfile*'
|
||||
- 'scripts/**'
|
||||
- '.dockerignore'
|
||||
- 'claude-config*'
|
||||
src:
|
||||
- 'src/**'
|
||||
- 'package*.json'
|
||||
|
||||
# Docker builds - only when relevant files change
|
||||
docker:
|
||||
name: Docker Build & Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test]
|
||||
runs-on: [self-hosted, Linux, X64]
|
||||
# Security: Only run on self-hosted for trusted sources
|
||||
if: (github.event.pull_request.head.repo.owner.login == 'intelligence-assist' || github.event_name != 'pull_request') && (needs.changes.outputs.docker == 'true' || needs.changes.outputs.src == 'true')
|
||||
# Only need unit tests to pass for Docker builds
|
||||
needs: [test-unit, lint, changes]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -113,6 +222,16 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Start build profiling
|
||||
run: |
|
||||
echo "BUILD_START_TIME=$(date +%s)" >> $GITHUB_ENV
|
||||
echo "🏗️ Docker build started at $(date)"
|
||||
|
||||
- name: Set up Docker layer caching
|
||||
run: |
|
||||
# Create cache mount directories
|
||||
mkdir -p /tmp/.buildx-cache-main /tmp/.buildx-cache-claude
|
||||
|
||||
- name: Build main Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
@@ -121,10 +240,17 @@ jobs:
|
||||
push: false
|
||||
load: true
|
||||
tags: claude-github-webhook:test
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
cache-from: |
|
||||
type=gha,scope=main
|
||||
type=local,src=/tmp/.buildx-cache-main
|
||||
cache-to: |
|
||||
type=gha,mode=max,scope=main
|
||||
type=local,dest=/tmp/.buildx-cache-main-new,mode=max
|
||||
platforms: linux/amd64
|
||||
build-args: |
|
||||
BUILDKIT_INLINE_CACHE=1
|
||||
|
||||
- name: Build Claude Code Docker image
|
||||
- name: Build Claude Code Docker image (parallel)
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
@@ -132,8 +258,46 @@ jobs:
|
||||
push: false
|
||||
load: true
|
||||
tags: claude-code-runner:test
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
cache-from: |
|
||||
type=gha,scope=claudecode
|
||||
type=local,src=/tmp/.buildx-cache-claude
|
||||
cache-to: |
|
||||
type=gha,mode=max,scope=claudecode
|
||||
type=local,dest=/tmp/.buildx-cache-claude-new,mode=max
|
||||
platforms: linux/amd64
|
||||
build-args: |
|
||||
BUILDKIT_INLINE_CACHE=1
|
||||
|
||||
- name: Rotate build caches
|
||||
run: |
|
||||
# Rotate caches to avoid size limits
|
||||
rm -rf /tmp/.buildx-cache-main /tmp/.buildx-cache-claude
|
||||
mv /tmp/.buildx-cache-main-new /tmp/.buildx-cache-main 2>/dev/null || true
|
||||
mv /tmp/.buildx-cache-claude-new /tmp/.buildx-cache-claude 2>/dev/null || true
|
||||
|
||||
- name: Profile build performance
|
||||
run: |
|
||||
BUILD_END_TIME=$(date +%s)
|
||||
BUILD_DURATION=$((BUILD_END_TIME - BUILD_START_TIME))
|
||||
echo "🏁 Docker build completed at $(date)"
|
||||
echo "⏱️ Total build time: ${BUILD_DURATION} seconds"
|
||||
|
||||
# Check image sizes
|
||||
echo "📦 Image sizes:"
|
||||
docker images | grep -E "(claude-github-webhook|claude-code-runner):test" || true
|
||||
|
||||
# Show cache usage
|
||||
echo "💾 Cache statistics:"
|
||||
du -sh /tmp/.buildx-cache-* 2>/dev/null || echo "No local caches found"
|
||||
|
||||
# Performance summary
|
||||
if [ $BUILD_DURATION -lt 120 ]; then
|
||||
echo "✅ Fast build (< 2 minutes)"
|
||||
elif [ $BUILD_DURATION -lt 300 ]; then
|
||||
echo "⚠️ Moderate build (2-5 minutes)"
|
||||
else
|
||||
echo "🐌 Slow build (> 5 minutes) - consider optimization"
|
||||
fi
|
||||
|
||||
- name: Test Docker containers
|
||||
run: |
|
||||
|
||||
44
.github/workflows/deploy.yml
vendored
44
.github/workflows/deploy.yml
vendored
@@ -34,9 +34,10 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'package-lock.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
run: npm ci --prefer-offline --no-audit
|
||||
|
||||
- name: Run linter
|
||||
run: npm run lint
|
||||
@@ -50,10 +51,34 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
# Check if Docker-related files changed
|
||||
changes:
|
||||
name: Detect Changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
docker: ${{ steps.changes.outputs.docker }}
|
||||
src: ${{ steps.changes.outputs.src }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: changes
|
||||
with:
|
||||
filters: |
|
||||
docker:
|
||||
- 'Dockerfile*'
|
||||
- 'scripts/**'
|
||||
- '.dockerignore'
|
||||
- 'claude-config*'
|
||||
src:
|
||||
- 'src/**'
|
||||
- 'package*.json'
|
||||
|
||||
build:
|
||||
name: Build Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
runs-on: [self-hosted, Linux, X64]
|
||||
# Security: Only run on self-hosted for trusted sources AND when files changed
|
||||
if: (github.event.pull_request.head.repo.owner.login == 'intelligence-assist' || github.event_name != 'pull_request') && (needs.changes.outputs.docker == 'true' || needs.changes.outputs.src == 'true')
|
||||
needs: [test, changes]
|
||||
|
||||
outputs:
|
||||
image-tag: ${{ steps.meta.outputs.tags }}
|
||||
@@ -95,10 +120,15 @@ jobs:
|
||||
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,type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=gha,mode=max,type=local,dest=/tmp/.buildx-cache-new,mode=max
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
- name: Move cache
|
||||
run: |
|
||||
rm -rf /tmp/.buildx-cache
|
||||
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
|
||||
|
||||
security-scan:
|
||||
name: Security Scanning
|
||||
runs-on: ubuntu-latest
|
||||
@@ -134,7 +164,7 @@ jobs:
|
||||
name: Deploy to Staging
|
||||
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
||||
needs: [build, security-scan]
|
||||
runs-on: [self-hosted, linux, x64, deployment, webhook-cd]
|
||||
runs-on: [self-hosted, Linux, X64]
|
||||
environment: staging
|
||||
|
||||
steps:
|
||||
@@ -187,7 +217,7 @@ jobs:
|
||||
name: Deploy to Production
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
needs: [build, security-scan]
|
||||
runs-on: [self-hosted, linux, x64, deployment, webhook-cd]
|
||||
runs-on: [self-hosted, Linux, X64]
|
||||
environment:
|
||||
name: production
|
||||
url: https://webhook.yourdomain.com
|
||||
|
||||
33
.github/workflows/docker-publish.yml
vendored
33
.github/workflows/docker-publish.yml
vendored
@@ -7,6 +7,13 @@ on:
|
||||
- master
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
paths:
|
||||
- 'Dockerfile*'
|
||||
- 'package*.json'
|
||||
- '.github/workflows/docker-publish.yml'
|
||||
- 'src/**'
|
||||
- 'scripts/**'
|
||||
- 'claude-config*'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
@@ -17,6 +24,7 @@ on:
|
||||
- '.github/workflows/docker-publish.yml'
|
||||
- 'src/**'
|
||||
- 'scripts/**'
|
||||
- 'claude-config*'
|
||||
|
||||
env:
|
||||
DOCKER_HUB_USERNAME: cheffromspace
|
||||
@@ -25,7 +33,9 @@ env:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: [self-hosted, Linux, X64]
|
||||
# Security: Only run on self-hosted for trusted sources
|
||||
if: github.event.pull_request.head.repo.owner.login == 'intelligence-assist' || github.event_name != 'pull_request'
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
@@ -71,8 +81,12 @@ jobs:
|
||||
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=publish-main
|
||||
type=local,src=/tmp/.buildx-cache-main
|
||||
cache-to: |
|
||||
type=gha,mode=max,scope=publish-main
|
||||
type=local,dest=/tmp/.buildx-cache-main-new,mode=max
|
||||
|
||||
- name: Update Docker Hub Description
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
@@ -86,8 +100,9 @@ jobs:
|
||||
|
||||
# Additional job to build and push the Claude Code container
|
||||
build-claudecode:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'pull_request'
|
||||
runs-on: [self-hosted, Linux, X64]
|
||||
# Security: Only run on self-hosted for trusted sources + not on PRs
|
||||
if: (github.event.pull_request.head.repo.owner.login == 'intelligence-assist' || github.event_name != 'pull_request') && github.event_name != 'pull_request'
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
@@ -124,5 +139,9 @@ jobs:
|
||||
push: true
|
||||
tags: ${{ steps.meta-claudecode.outputs.tags }}
|
||||
labels: ${{ steps.meta-claudecode.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
cache-from: |
|
||||
type=gha,scope=publish-claudecode
|
||||
type=local,src=/tmp/.buildx-cache-claude
|
||||
cache-to: |
|
||||
type=gha,mode=max,scope=publish-claudecode
|
||||
type=local,dest=/tmp/.buildx-cache-claude-new,mode=max
|
||||
10
.github/workflows/security.yml
vendored
10
.github/workflows/security.yml
vendored
@@ -23,9 +23,10 @@ jobs:
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'package-lock.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
run: npm ci --prefer-offline --no-audit
|
||||
|
||||
- name: Run npm audit
|
||||
run: npm audit --audit-level=moderate
|
||||
@@ -68,6 +69,13 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'package-lock.json'
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
|
||||
@@ -9,6 +9,15 @@
|
||||
|
||||
A webhook service that enables Claude Code to respond to GitHub mentions and execute commands within repository contexts. This microservice allows Claude to analyze code, answer questions, and optionally make changes when mentioned in GitHub comments.
|
||||
|
||||
## ⚡ Performance Optimizations
|
||||
|
||||
This repository uses highly optimized CI/CD pipelines:
|
||||
- **Parallel test execution** for faster feedback loops
|
||||
- **Conditional Docker builds** (only when code/Dockerfile changes)
|
||||
- **Strategic runner distribution** (GitHub for tests, self-hosted for heavy builds)
|
||||
- **Advanced caching strategies** for significantly faster subsequent builds
|
||||
- **Build performance profiling** with timing and size metrics
|
||||
|
||||
## Documentation
|
||||
|
||||
For comprehensive documentation, see:
|
||||
|
||||
3
test_runner.md
Normal file
3
test_runner.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Test Runner Access
|
||||
|
||||
This file tests if our self-hosted runner is working properly.
|
||||
Reference in New Issue
Block a user