Merge pull request #55 from intelligence-assist/feat/improve-runners

Optimize CI/CD pipelines for better performance and parallelization
This commit is contained in:
Cheffromspace
2025-05-25 17:05:53 -05:00
committed by GitHub
6 changed files with 268 additions and 35 deletions

View File

@@ -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: |

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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
View File

@@ -0,0 +1,3 @@
# Test Runner Access
This file tests if our self-hosted runner is working properly.