feat: Add comprehensive Gitea CI/CD workflows for multi-arch container builds
- Add build-container.yml: Main build pipeline with multi-arch support - Add pr-check.yml: Pull request validation with comprehensive testing - Add release.yml: Automated release pipeline with security scanning - Add nightly.yml: Daily builds with performance testing - Add health_check.sh: Container health validation script - Add setup-ci.sh: Local CI/CD environment setup script - Add comprehensive CI/CD documentation Features: - Multi-architecture builds (linux/amd64, linux/arm64) - Security scanning with Trivy - Automated PyPI publishing for releases - Container registry integration - Performance testing and validation - Artifact management and cleanup - Build caching and optimization Supports full development workflow from PR to production deployment.
This commit is contained in:
296
.gitea/workflows/nightly.yml
Normal file
296
.gitea/workflows/nightly.yml
Normal file
@@ -0,0 +1,296 @@
|
||||
name: Nightly Build
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run every night at 2 AM UTC
|
||||
- cron: "0 2 * * *"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force_build:
|
||||
description: "Force build even if no changes"
|
||||
required: false
|
||||
default: "false"
|
||||
type: boolean
|
||||
|
||||
env:
|
||||
REGISTRY: gitea-http.taildb3494.ts.net
|
||||
IMAGE_NAME: will/unitforge
|
||||
|
||||
jobs:
|
||||
check-changes:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_build: ${{ steps.changes.outputs.should_build }}
|
||||
commit_sha: ${{ steps.changes.outputs.commit_sha }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Check for changes
|
||||
id: changes
|
||||
run: |
|
||||
# Get the latest commit from the last 24 hours
|
||||
YESTERDAY=$(date -d "24 hours ago" --iso-8601)
|
||||
RECENT_COMMITS=$(git log --since="$YESTERDAY" --format="%H" | wc -l)
|
||||
|
||||
FORCE_BUILD="${{ github.event.inputs.force_build }}"
|
||||
|
||||
if [[ "$FORCE_BUILD" == "true" ]] || [[ $RECENT_COMMITS -gt 0 ]]; then
|
||||
echo "should_build=true" >> $GITHUB_OUTPUT
|
||||
echo "Found $RECENT_COMMITS commits in the last 24 hours or force build requested"
|
||||
else
|
||||
echo "should_build=false" >> $GITHUB_OUTPUT
|
||||
echo "No changes in the last 24 hours, skipping build"
|
||||
fi
|
||||
|
||||
echo "commit_sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
nightly-tests:
|
||||
needs: check-changes
|
||||
runs-on: ubuntu-latest
|
||||
if: needs.check-changes.outputs.should_build == 'true'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
version: "latest"
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
run: uv python install ${{ matrix.python-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
uv venv --python ${{ matrix.python-version }}
|
||||
uv pip install -e ".[dev]"
|
||||
|
||||
- name: Run comprehensive tests
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
|
||||
# Run all checks
|
||||
make lint
|
||||
make type-check
|
||||
make security-check
|
||||
make test-cov
|
||||
|
||||
# Additional nightly-specific tests
|
||||
echo "Running extended test suite..."
|
||||
python -m pytest tests/ -v --durations=10 --tb=short
|
||||
|
||||
- name: Upload coverage for Python ${{ matrix.python-version }}
|
||||
uses: codecov/codecov-action@v3
|
||||
if: matrix.python-version == '3.11'
|
||||
with:
|
||||
file: ./htmlcov/coverage.xml
|
||||
flags: nightly-${{ matrix.python-version }}
|
||||
|
||||
build-nightly:
|
||||
needs: [check-changes, nightly-tests]
|
||||
runs-on: ubuntu-latest
|
||||
if: needs.check-changes.outputs.should_build == 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver-opts: network=host
|
||||
|
||||
- name: Log in to Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.CONTAINER_REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Generate nightly tags
|
||||
id: tags
|
||||
run: |
|
||||
COMMIT_SHA="${{ needs.check-changes.outputs.commit_sha }}"
|
||||
DATE=$(date +%Y%m%d)
|
||||
SHORT_SHA=${COMMIT_SHA:0:7}
|
||||
|
||||
echo "nightly_tag=nightly-${DATE}-${SHORT_SHA}" >> $GITHUB_OUTPUT
|
||||
echo "nightly_latest=nightly-latest" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Verify vendor assets
|
||||
run: |
|
||||
assets=(
|
||||
"frontend/static/vendor/bootstrap/css/bootstrap.min.css"
|
||||
"frontend/static/vendor/bootstrap/js/bootstrap.bundle.min.js"
|
||||
"frontend/static/vendor/fontawesome/css/all.min.css"
|
||||
"frontend/static/vendor/fontawesome/webfonts/fa-solid-900.woff2"
|
||||
"frontend/static/img/osi-logo.svg"
|
||||
)
|
||||
|
||||
for asset in "${assets[@]}"; do
|
||||
if [ ! -f "$asset" ]; then
|
||||
echo "Error: Missing required asset: $asset"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "All vendor assets verified"
|
||||
|
||||
- name: Build and push nightly image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.nightly_tag }}
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tags.outputs.nightly_latest }}
|
||||
labels: |
|
||||
org.opencontainers.image.title=UnitForge Nightly
|
||||
org.opencontainers.image.description=Nightly build of UnitForge
|
||||
org.opencontainers.image.version=nightly-${{ steps.tags.outputs.nightly_tag }}
|
||||
org.opencontainers.image.revision=${{ needs.check-changes.outputs.commit_sha }}
|
||||
org.opencontainers.image.created=${{ github.event.repository.pushed_at }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
BUILDKIT_INLINE_CACHE=1
|
||||
|
||||
performance-test:
|
||||
needs: [check-changes, build-nightly]
|
||||
runs-on: ubuntu-latest
|
||||
if: needs.check-changes.outputs.should_build == 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run performance tests
|
||||
run: |
|
||||
# Pull the nightly image
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-latest
|
||||
|
||||
# Start the container
|
||||
docker run -d --name unitforge-perf \
|
||||
-p 8000:8000 \
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-latest
|
||||
|
||||
# Wait for startup
|
||||
sleep 15
|
||||
|
||||
# Basic performance test
|
||||
echo "Running basic performance test..."
|
||||
for i in {1..10}; do
|
||||
curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" \
|
||||
http://localhost:8000/
|
||||
done
|
||||
|
||||
# Memory usage check
|
||||
echo "Checking memory usage..."
|
||||
docker stats unitforge-perf --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"
|
||||
|
||||
# Cleanup
|
||||
docker stop unitforge-perf
|
||||
docker rm unitforge-perf
|
||||
|
||||
security-scan-nightly:
|
||||
needs: [check-changes, build-nightly]
|
||||
runs-on: ubuntu-latest
|
||||
if: needs.check-changes.outputs.should_build == 'true'
|
||||
|
||||
steps:
|
||||
- name: Run comprehensive security scan
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-latest
|
||||
format: "sarif"
|
||||
output: "trivy-nightly.sarif"
|
||||
|
||||
- name: Upload security scan results
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
if: always()
|
||||
with:
|
||||
sarif_file: "trivy-nightly.sarif"
|
||||
|
||||
- name: Generate security report
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-latest
|
||||
format: "json"
|
||||
output: "security-report.json"
|
||||
|
||||
- name: Upload security report
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nightly-security-report
|
||||
path: security-report.json
|
||||
|
||||
cleanup-old-nightlies:
|
||||
needs: [check-changes, build-nightly]
|
||||
runs-on: ubuntu-latest
|
||||
if: needs.check-changes.outputs.should_build == 'true'
|
||||
|
||||
steps:
|
||||
- name: Clean up old nightly images
|
||||
run: |
|
||||
echo "Cleaning up nightly images older than 7 days..."
|
||||
|
||||
# Note: This would require registry API access or container registry-specific tools
|
||||
# For now, we'll just log what would be cleaned
|
||||
|
||||
CUTOFF_DATE=$(date -d "7 days ago" +%Y%m%d)
|
||||
echo "Would clean images tagged before: nightly-${CUTOFF_DATE}"
|
||||
|
||||
# Add actual cleanup logic here based on your registry
|
||||
# Examples:
|
||||
# - Use registry API to list and delete old tags
|
||||
# - Use container registry CLI tools
|
||||
# - Use registry-specific cleanup policies
|
||||
|
||||
notify-results:
|
||||
needs:
|
||||
[
|
||||
check-changes,
|
||||
nightly-tests,
|
||||
build-nightly,
|
||||
performance-test,
|
||||
security-scan-nightly,
|
||||
]
|
||||
runs-on: ubuntu-latest
|
||||
if: always() && needs.check-changes.outputs.should_build == 'true'
|
||||
|
||||
steps:
|
||||
- name: Generate build report
|
||||
run: |
|
||||
echo "## Nightly Build Report - $(date)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Component | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|-----------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Tests | ${{ needs.nightly-tests.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Build | ${{ needs.build-nightly.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Performance | ${{ needs.performance-test.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Security | ${{ needs.security-scan-nightly.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [[ "${{ needs.nightly-tests.result }}" == "success" && "${{ needs.build-nightly.result }}" == "success" ]]; then
|
||||
echo "🌙 Nightly build completed successfully!" >> $GITHUB_STEP_SUMMARY
|
||||
echo "📦 Image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-latest" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ Nightly build encountered issues. Check failed jobs above." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
- name: Send notification
|
||||
if: failure()
|
||||
run: |
|
||||
echo "🚨 Nightly build failed!"
|
||||
echo "Check the workflow run for details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
|
||||
# Add notification logic here (webhook, email, Slack, etc.)
|
||||
Reference in New Issue
Block a user