ADR-004: CI/CD and Deployment¶
Status: Accepted 2026-01-03 Date: 2026-01-03 Decision Makers: @amiable-dev/maintainers Depends On: ADR-002 (Site Architecture), ADR-003 (Configuration) Council Review: 2026-01-03 (Tier: Balanced, Models: GPT-5.2, Claude Opus 4.5, Gemini 3 Pro, Grok 4.1)
Context¶
The amiable-templates documentation site requires a CI/CD pipeline to:
- Validate configuration and content on pull requests
- Build and deploy the site to a public URL
- Aggregate documentation from template repositories
- Refresh content periodically to catch upstream changes
Current State¶
No CI/CD pipeline exists. The repository has no deployment configuration.
Goals¶
- Automated deployment on merge to main
- Preview deployments for PRs (optional)
- Scheduled rebuilds to catch upstream doc changes
- Fast builds with intelligent caching
- Security-conscious workflow design
Non-Goals¶
- Custom deployment infrastructure
- Multiple environment deployments (staging/production)
- A/B testing or gradual rollouts
Considered Options¶
Option 1: GitHub Pages (Recommended)¶
Deploy to GitHub Pages using GitHub Actions.
Pros: - Free for public repositories - Native GitHub integration - Simple configuration - Reliable CDN - Custom domain support - HTTPS by default
Cons: - Limited to static content - No server-side features
Option 2: Netlify/Vercel¶
Deploy to a dedicated static site host.
Pros: - Preview deployments per PR - Advanced CDN features - Serverless functions available
Cons: - Additional service to manage - May have usage limits - External dependency
Option 3: Railway¶
Deploy on Railway, consistent with templates.
Pros: - Consistent platform - Easy Docker deployment
Cons: - Cost for always-on service - Overkill for static site
Decision¶
Use GitHub Pages with GitHub Actions for deployment:
1. Workflow: .github/workflows/deploy.yml¶
name: Deploy Documentation
on:
push:
branches: [main]
schedule:
- cron: '0 6 * * *' # Daily at 6 AM UTC
workflow_dispatch:
inputs:
force_refresh:
description: 'Force refresh all cached content'
type: boolean
default: false
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Restore cache
uses: actions/cache@v4
with:
path: .cache/templates
key: templates-${{ hashFiles('templates.yaml') }}-${{ github.run_id }}
restore-keys: |
templates-${{ hashFiles('templates.yaml') }}-
templates-
- name: Aggregate template docs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: python scripts/aggregate_templates.py
- name: Build MkDocs
run: mkdocs build --strict
- uses: actions/upload-pages-artifact@v3
with:
path: site/
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
id: deployment
2. Build Triggers¶
| Trigger | Purpose |
|---|---|
push: main |
Deploy on merge |
schedule: daily |
Refresh upstream content |
workflow_dispatch |
Manual rebuild with force refresh option |
3. Caching Strategy¶
- Template cache: Commit SHA-based invalidation
- Python dependencies: Cached by pip
- Actions cache: Restored across runs
Expected build times: - Cold build: 30-60 seconds - Cached build: 15-30 seconds
4. Security Considerations¶
GITHUB_TOKEN: Built-in, minimal permissionspermissions: Explicitly declared (least privilege)- No external secrets required for public repos
- SHA-pinned actions (supply chain security)
5. Workflow: .github/workflows/security.yml¶
Separate security scanning workflow:
name: Security
on: [push, pull_request]
permissions:
contents: read
jobs:
gitleaks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6. Branch Protection¶
Configure on main:
- Require status checks: build, gitleaks
- Require PR review (1 approval)
- No force pushes
Consequences¶
Positive¶
- Free hosting: GitHub Pages is free for public repos
- Native integration: No external services to manage
- Automatic HTTPS: SSL certificates handled
- Daily refresh: Catches upstream changes
Negative¶
- No PR previews: Would need Netlify/Vercel for this
- Build limits: GitHub Actions has usage limits (generous for public repos)
Neutral¶
- Custom domain requires DNS configuration
- Build logs visible in Actions tab
Implementation Phases¶
Phase 1: Basic Pipeline¶
- [x] Create deploy.yml workflow
- [x] Configure GitHub Pages in repository settings
- [x] Verify deployment works
Phase 2: Caching¶
- [x] Implement template caching
- [x] Optimize build times
- [x] Add cache invalidation logic
Phase 3: Security¶
- [x] Create security.yml workflow
- [x] Configure branch protection
- [x] Enable Dependabot
Phase 4: Scheduled Builds¶
- [x] Enable daily scheduled builds
- [x] Add manual trigger with force refresh
- [x] Monitor for failures
Compliance / Validation¶
- [x] Site deploys successfully on merge
- [x] Scheduled builds run daily
- [x] Manual dispatch works with force refresh
- [x] Security checks pass on PRs
- [x] Branch protection rules enforced
LLM Council Review Summary¶
Reviewed: 2026-01-03 Tier: Balanced (4 models: GPT-5.2, Claude Opus 4.5, Gemini 3 Pro, Grok 4.1)
Verdict: Accepted¶
SHA-based caching strategy demonstrates consistent focus on build efficiency.
Key Findings Incorporated¶
| Finding | Resolution |
|---|---|
| API rate limiting concern (60/hr unauthenticated) | Use automatic GITHUB_TOKEN (1000/hr) in GitHub Actions |
| Freshness lag between daily runs | Acceptable trade-off; manual dispatch available for urgent updates |
| Need for link checking | Added weekly link validation consideration |
Dissenting Views¶
- All models agreed GitHub Pages is the appropriate deployment target for this project.