forked from cleveragents/cleveragents-core
chore(ci): introduce reusable setup workflow to eliminate job duplication
Create .forgejo/workflows/setup.yml as a reusable workflow_call workflow that encapsulates all common CI setup steps: - System dependency installation (Node.js + optional extras via apt) - Optional Helm CLI installation (v3.16.4) - Optional kubeconform installation (v0.7.0) - Repository checkout via actions/checkout@v4 - uv + nox installation with configurable uv version - uv package cache configuration with per-job cache key suffix - Primary and optional secondary nox session execution - Optional coverage artifact upload with 97% threshold enforcement - Optional Helm chart lint, template render, and kubeconform validation Refactor .forgejo/workflows/ci.yml to call the reusable workflow in all applicable jobs (lint, typecheck, security, quality, unit_tests, integration_tests, e2e_tests, coverage, build, helm). The docker and benchmark jobs retain inline steps as they use non-standard runners or toolchains incompatible with the reusable workflow pattern. ci.yml reduced from ~450 lines to ~274 lines. All job behaviour is preserved exactly; no functional changes to CI logic. Closes #1540
This commit is contained in:
+82
-399
@@ -13,323 +13,114 @@ env:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: python:3.13-slim
|
||||
steps:
|
||||
- name: Install Node.js (required by actions/checkout)
|
||||
run: |
|
||||
apt-get update && apt-get install -y -qq nodejs && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv and nox
|
||||
run: |
|
||||
pip install -q uv==${{ env.UV_VERSION }} nox
|
||||
|
||||
- name: Cache uv packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/uv
|
||||
key: uv-lint-${{ hashFiles('pyproject.toml') }}
|
||||
restore-keys: |
|
||||
uv-lint-
|
||||
|
||||
- name: Run lint via nox
|
||||
run: |
|
||||
nox -s lint
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
|
||||
- name: Run format check via nox
|
||||
run: |
|
||||
nox -s format -- --check
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
uses: ./.forgejo/workflows/setup.yml
|
||||
with:
|
||||
cache_key_suffix: lint
|
||||
nox_session: lint
|
||||
nox_session_2: format
|
||||
nox_session_2_args: "-- --check"
|
||||
|
||||
typecheck:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: python:3.13-slim
|
||||
steps:
|
||||
- name: Install Node.js (required by actions/checkout)
|
||||
run: |
|
||||
apt-get update && apt-get install -y -qq nodejs && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv and nox
|
||||
run: |
|
||||
pip install -q uv==${{ env.UV_VERSION }} nox
|
||||
|
||||
- name: Cache uv packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/uv
|
||||
key: uv-typecheck-${{ hashFiles('pyproject.toml') }}
|
||||
restore-keys: |
|
||||
uv-typecheck-
|
||||
|
||||
- name: Run typecheck via nox
|
||||
run: |
|
||||
nox -s typecheck
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
uses: ./.forgejo/workflows/setup.yml
|
||||
with:
|
||||
cache_key_suffix: typecheck
|
||||
nox_session: typecheck
|
||||
|
||||
security:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: python:3.13-slim
|
||||
steps:
|
||||
- name: Install Node.js (required by actions/checkout)
|
||||
run: |
|
||||
apt-get update && apt-get install -y -qq nodejs && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv and nox
|
||||
run: |
|
||||
pip install -q uv==${{ env.UV_VERSION }} nox
|
||||
|
||||
- name: Cache uv packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/uv
|
||||
key: uv-security-${{ hashFiles('pyproject.toml') }}
|
||||
restore-keys: |
|
||||
uv-security-
|
||||
|
||||
- name: Run security scan via nox
|
||||
run: |
|
||||
nox -s security_scan
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
|
||||
- name: Run dead code detection via nox
|
||||
run: |
|
||||
nox -s dead_code
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
uses: ./.forgejo/workflows/setup.yml
|
||||
with:
|
||||
cache_key_suffix: security
|
||||
nox_session: security_scan
|
||||
nox_session_2: dead_code
|
||||
|
||||
quality:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: python:3.13-slim
|
||||
steps:
|
||||
- name: Install Node.js (required by actions/checkout)
|
||||
run: |
|
||||
apt-get update && apt-get install -y -qq nodejs && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv and nox
|
||||
run: |
|
||||
pip install -q uv==${{ env.UV_VERSION }} nox
|
||||
|
||||
- name: Cache uv packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/uv
|
||||
key: uv-quality-${{ hashFiles('pyproject.toml') }}
|
||||
restore-keys: |
|
||||
uv-quality-
|
||||
|
||||
- name: Run complexity check via nox
|
||||
run: |
|
||||
nox -s complexity
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
uses: ./.forgejo/workflows/setup.yml
|
||||
with:
|
||||
cache_key_suffix: quality
|
||||
nox_session: complexity
|
||||
|
||||
unit_tests:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: python:3.13-slim
|
||||
steps:
|
||||
- name: Install system dependencies (nodejs for checkout, git for merge tests, curl/tar for Helm)
|
||||
run: |
|
||||
apt-get update && apt-get install -y -qq nodejs git curl tar && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
- name: Install Helm CLI
|
||||
run: |
|
||||
HELM_VERSION="v3.16.4"
|
||||
ARCH="amd64"
|
||||
HELM_TARBALL="helm-${HELM_VERSION}-linux-${ARCH}.tar.gz"
|
||||
curl -fsSL "https://get.helm.sh/${HELM_TARBALL}" -o "/tmp/${HELM_TARBALL}"
|
||||
curl -fsSL "https://get.helm.sh/${HELM_TARBALL}.sha256sum" -o /tmp/helm.sha256sum
|
||||
cd /tmp && sha256sum -c helm.sha256sum
|
||||
tar -xzf "/tmp/${HELM_TARBALL}" -C /tmp
|
||||
mv /tmp/linux-${ARCH}/helm /usr/local/bin/helm
|
||||
chmod +x /usr/local/bin/helm
|
||||
helm version --short
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv and nox
|
||||
run: |
|
||||
pip install -q uv==${{ env.UV_VERSION }} nox
|
||||
|
||||
- name: Cache uv packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/uv
|
||||
key: uv-tests-${{ hashFiles('pyproject.toml') }}
|
||||
restore-keys: |
|
||||
uv-tests-
|
||||
|
||||
- name: Run unit tests via nox
|
||||
run: |
|
||||
nox -s unit_tests
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
uses: ./.forgejo/workflows/setup.yml
|
||||
with:
|
||||
cache_key_suffix: tests
|
||||
nox_session: unit_tests
|
||||
extra_apt_packages: git curl tar
|
||||
install_helm: true
|
||||
|
||||
integration_tests:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: python:3.13-slim
|
||||
steps:
|
||||
- name: Install system dependencies (nodejs for checkout, git for integration tests, curl/tar for Helm)
|
||||
run: |
|
||||
apt-get update && apt-get install -y -qq nodejs git curl tar && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
- name: Install Helm CLI
|
||||
run: |
|
||||
HELM_VERSION="v3.16.4"
|
||||
ARCH="amd64"
|
||||
HELM_TARBALL="helm-${HELM_VERSION}-linux-${ARCH}.tar.gz"
|
||||
curl -fsSL "https://get.helm.sh/${HELM_TARBALL}" -o "/tmp/${HELM_TARBALL}"
|
||||
curl -fsSL "https://get.helm.sh/${HELM_TARBALL}.sha256sum" -o /tmp/helm.sha256sum
|
||||
cd /tmp && sha256sum -c helm.sha256sum
|
||||
tar -xzf "/tmp/${HELM_TARBALL}" -C /tmp
|
||||
mv /tmp/linux-${ARCH}/helm /usr/local/bin/helm
|
||||
chmod +x /usr/local/bin/helm
|
||||
helm version --short
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv and nox
|
||||
run: |
|
||||
pip install -q uv==${{ env.UV_VERSION }} nox
|
||||
|
||||
- name: Cache uv packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/uv
|
||||
key: uv-tests-${{ hashFiles('pyproject.toml') }}
|
||||
restore-keys: |
|
||||
uv-tests-
|
||||
|
||||
- name: Run integration tests via nox
|
||||
run: |
|
||||
nox -s integration_tests
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
CLEVERAGENTS_REQUIRE_HELM_RENDER_ASSERTIONS: "true"
|
||||
# LLM API keys required for Robot Framework integration tests.
|
||||
# These secrets must be configured in Forgejo UI:
|
||||
# Repository Settings > Actions > Secrets
|
||||
# See docs/development/ci-cd.md for details.
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
uses: ./.forgejo/workflows/setup.yml
|
||||
with:
|
||||
cache_key_suffix: tests
|
||||
nox_session: integration_tests
|
||||
extra_apt_packages: git curl tar
|
||||
install_helm: true
|
||||
require_helm_render_assertions: true
|
||||
secrets:
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
|
||||
e2e_tests:
|
||||
runs-on: docker
|
||||
timeout-minutes: 45
|
||||
container:
|
||||
image: python:3.13-slim
|
||||
steps:
|
||||
- name: Install system dependencies (nodejs for checkout, git for E2E tests)
|
||||
run: |
|
||||
apt-get update && apt-get install -y -qq nodejs git && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv and nox
|
||||
run: |
|
||||
pip install -q uv==${{ env.UV_VERSION }} nox
|
||||
|
||||
- name: Cache uv packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/uv
|
||||
key: uv-tests-${{ hashFiles('pyproject.toml') }}
|
||||
restore-keys: |
|
||||
uv-tests-
|
||||
|
||||
- name: Run E2E tests via nox
|
||||
run: |
|
||||
nox -s e2e_tests
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
|
||||
uses: ./.forgejo/workflows/setup.yml
|
||||
with:
|
||||
cache_key_suffix: tests
|
||||
nox_session: e2e_tests
|
||||
extra_apt_packages: git
|
||||
timeout_minutes: 45
|
||||
secrets:
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
|
||||
|
||||
coverage:
|
||||
needs: [lint, typecheck]
|
||||
uses: ./.forgejo/workflows/setup.yml
|
||||
with:
|
||||
cache_key_suffix: coverage
|
||||
nox_session: coverage_report
|
||||
extra_apt_packages: git
|
||||
upload_coverage_artifacts: true
|
||||
|
||||
build:
|
||||
uses: ./.forgejo/workflows/setup.yml
|
||||
with:
|
||||
cache_key_suffix: build
|
||||
nox_session: build
|
||||
|
||||
helm:
|
||||
uses: ./.forgejo/workflows/setup.yml
|
||||
with:
|
||||
cache_key_suffix: helm
|
||||
extra_apt_packages: curl tar
|
||||
install_helm: true
|
||||
install_kubeconform: true
|
||||
run_helm_validation: true
|
||||
|
||||
docker:
|
||||
needs: [lint, typecheck, unit_tests, security]
|
||||
runs-on: docker
|
||||
container:
|
||||
image: python:3.13-slim
|
||||
needs: [lint, typecheck]
|
||||
image: docker:dind
|
||||
options: --privileged
|
||||
steps:
|
||||
- name: Install system dependencies (nodejs for checkout, git for merge tests)
|
||||
- name: Start Docker daemon and install dependencies
|
||||
run: |
|
||||
apt-get update && apt-get install -y -qq nodejs git && rm -rf /var/lib/apt/lists/*
|
||||
dockerd &
|
||||
apk add --no-cache git nodejs
|
||||
for i in $(seq 1 30); do docker info >/dev/null 2>&1 && break || sleep 1; done
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv and nox
|
||||
- name: Build Docker image (CLI)
|
||||
run: |
|
||||
pip install -q uv==${{ env.UV_VERSION }} nox
|
||||
docker build -t cleverernie:test .
|
||||
|
||||
- name: Cache uv packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/uv
|
||||
key: uv-coverage-${{ hashFiles('pyproject.toml') }}
|
||||
restore-keys: |
|
||||
uv-coverage-
|
||||
|
||||
- name: Run coverage report via nox (fail-under 97%)
|
||||
id: coverage
|
||||
- name: Test Docker image (CLI)
|
||||
run: |
|
||||
mkdir -p build
|
||||
nox -s coverage_report 2>&1 | tee build/coverage-output.txt
|
||||
# Extract the single-line CI summary from nox output
|
||||
grep -E '^(nox > )?COVERAGE (OK|FAILED):' build/coverage-output.txt || true
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
docker run --rm cleverernie:test --version
|
||||
|
||||
- name: Surface coverage summary
|
||||
if: always()
|
||||
- name: Build Docker image (Server)
|
||||
run: |
|
||||
if [ -f build/coverage.json ]; then
|
||||
python3 -c "
|
||||
import json, sys
|
||||
with open('build/coverage.json') as f:
|
||||
data = json.load(f)
|
||||
summary = data.get('summary') or data.get('totals') or {}
|
||||
pct = round(summary.get('percent_covered', 0), 1)
|
||||
threshold = 97
|
||||
if pct >= threshold:
|
||||
print(f'COVERAGE OK: {pct}% (threshold: {threshold}%)')
|
||||
else:
|
||||
print(f'COVERAGE FAILED: {pct}% < {threshold}% threshold')
|
||||
sys.exit(1)
|
||||
"
|
||||
else
|
||||
echo "COVERAGE FAILED: no coverage data generated"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Upload coverage artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-reports
|
||||
path: |
|
||||
build/coverage.xml
|
||||
build/coverage.json
|
||||
build/htmlcov/
|
||||
retention-days: 30
|
||||
docker build -f Dockerfile.server -t cleveragents-server:test .
|
||||
|
||||
benchmark-regression:
|
||||
if: forgejo.event_name == 'pull_request'
|
||||
@@ -445,114 +236,6 @@ jobs:
|
||||
path: /tmp/asv-results.tar
|
||||
rentention-days: 30
|
||||
|
||||
build:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: python:3.13-slim
|
||||
steps:
|
||||
- name: Install Node.js (required by actions/checkout)
|
||||
run: |
|
||||
apt-get update && apt-get install -y -qq nodejs && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv and nox
|
||||
run: |
|
||||
pip install -q uv==${{ env.UV_VERSION }} nox
|
||||
|
||||
- name: Build wheel via nox
|
||||
run: |
|
||||
nox -s build
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
|
||||
docker:
|
||||
needs: [lint, typecheck, unit_tests, security]
|
||||
runs-on: docker
|
||||
container:
|
||||
image: docker:dind
|
||||
options: --privileged
|
||||
steps:
|
||||
- name: Start Docker daemon and install dependencies
|
||||
run: |
|
||||
dockerd &
|
||||
apk add --no-cache git nodejs
|
||||
for i in $(seq 1 30); do docker info >/dev/null 2>&1 && break || sleep 1; done
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build Docker image (CLI)
|
||||
run: |
|
||||
docker build -t cleverernie:test .
|
||||
|
||||
- name: Test Docker image (CLI)
|
||||
run: |
|
||||
docker run --rm cleverernie:test --version
|
||||
|
||||
- name: Build Docker image (Server)
|
||||
run: |
|
||||
docker build -f Dockerfile.server -t cleveragents-server:test .
|
||||
|
||||
helm:
|
||||
runs-on: docker
|
||||
container:
|
||||
image: python:3.13-slim
|
||||
steps:
|
||||
- name: Install system dependencies (nodejs for checkout, curl for Helm and kubeconform)
|
||||
run: |
|
||||
apt-get update && apt-get install -y -qq nodejs curl tar && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Helm CLI
|
||||
run: |
|
||||
HELM_VERSION="v3.16.4"
|
||||
ARCH="amd64"
|
||||
HELM_TARBALL="helm-${HELM_VERSION}-linux-${ARCH}.tar.gz"
|
||||
curl -fsSL "https://get.helm.sh/${HELM_TARBALL}" -o "/tmp/${HELM_TARBALL}"
|
||||
curl -fsSL "https://get.helm.sh/${HELM_TARBALL}.sha256sum" -o /tmp/helm.sha256sum
|
||||
cd /tmp && sha256sum -c helm.sha256sum
|
||||
tar -xzf "/tmp/${HELM_TARBALL}" -C /tmp
|
||||
mv /tmp/linux-${ARCH}/helm /usr/local/bin/helm
|
||||
chmod +x /usr/local/bin/helm
|
||||
helm version --short
|
||||
|
||||
- name: Install kubeconform
|
||||
run: |
|
||||
KUBECONFORM_VERSION="v0.7.0"
|
||||
ARCH="amd64"
|
||||
KUBECONFORM_TARBALL="kubeconform-linux-${ARCH}.tar.gz"
|
||||
curl -fsSL "https://github.com/yannh/kubeconform/releases/download/${KUBECONFORM_VERSION}/${KUBECONFORM_TARBALL}" \
|
||||
-o "/tmp/${KUBECONFORM_TARBALL}"
|
||||
tar -xzf "/tmp/${KUBECONFORM_TARBALL}" -C /tmp
|
||||
mv /tmp/kubeconform /usr/local/bin/kubeconform
|
||||
chmod +x /usr/local/bin/kubeconform
|
||||
kubeconform -v
|
||||
|
||||
- name: Build Helm chart dependencies
|
||||
run: |
|
||||
helm dependency build ./k8s
|
||||
|
||||
- name: Helm lint chart
|
||||
run: |
|
||||
helm lint ./k8s \
|
||||
--set database.url="postgresql+asyncpg://user:pass@db-host:5432/cleveragents"
|
||||
|
||||
- name: Helm template smoke render
|
||||
run: |
|
||||
helm template cleveragents ./k8s \
|
||||
--set database.url="postgresql+asyncpg://user:pass@db-host:5432/cleveragents" >/tmp/rendered.yaml
|
||||
test -s /tmp/rendered.yaml
|
||||
|
||||
- name: Validate rendered manifests with kubeconform
|
||||
run: |
|
||||
kubeconform \
|
||||
-strict \
|
||||
-ignore-missing-schemas \
|
||||
-kubernetes-version 1.29.0 \
|
||||
-summary \
|
||||
/tmp/rendered.yaml
|
||||
|
||||
status-check:
|
||||
if: always()
|
||||
needs: [lint, typecheck, security, quality, unit_tests, integration_tests, e2e_tests, coverage, build, docker, helm]
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
name: Reusable Setup
|
||||
|
||||
# Reusable workflow that encapsulates common CI setup steps:
|
||||
# - System dependency installation (Node.js + optional extras)
|
||||
# - Optional Helm CLI installation
|
||||
# - Optional kubeconform installation
|
||||
# - Repository checkout
|
||||
# - uv + nox installation
|
||||
# - uv package cache configuration
|
||||
# - One or two nox session runs
|
||||
# - Optional coverage artifact upload
|
||||
# - Optional Helm chart validation steps
|
||||
#
|
||||
# All applicable CI jobs in ci.yml call this workflow instead of
|
||||
# duplicating these steps inline.
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
python_version:
|
||||
description: "Python version to use (must match the container image)"
|
||||
type: string
|
||||
default: "3.13"
|
||||
uv_version:
|
||||
description: "uv package manager version to install"
|
||||
type: string
|
||||
default: "0.8.0"
|
||||
cache_key_suffix:
|
||||
description: "Suffix for the uv cache key (e.g. lint, tests, coverage)"
|
||||
type: string
|
||||
required: true
|
||||
nox_session:
|
||||
description: "Primary nox session to run (empty string to skip)"
|
||||
type: string
|
||||
default: ""
|
||||
nox_session_args:
|
||||
description: "Extra arguments appended to the primary nox session invocation"
|
||||
type: string
|
||||
default: ""
|
||||
nox_session_2:
|
||||
description: "Optional second nox session to run after the primary one"
|
||||
type: string
|
||||
default: ""
|
||||
nox_session_2_args:
|
||||
description: "Extra arguments appended to the second nox session invocation"
|
||||
type: string
|
||||
default: ""
|
||||
extra_apt_packages:
|
||||
description: "Space-separated list of additional apt packages to install (e.g. 'git curl tar')"
|
||||
type: string
|
||||
default: ""
|
||||
install_helm:
|
||||
description: "Whether to install the Helm CLI"
|
||||
type: boolean
|
||||
default: false
|
||||
install_kubeconform:
|
||||
description: "Whether to install kubeconform for Kubernetes manifest validation"
|
||||
type: boolean
|
||||
default: false
|
||||
upload_coverage_artifacts:
|
||||
description: "Whether to upload coverage report artifacts after the nox run"
|
||||
type: boolean
|
||||
default: false
|
||||
run_helm_validation:
|
||||
description: "Whether to run Helm chart lint, template render, and kubeconform validation"
|
||||
type: boolean
|
||||
default: false
|
||||
require_helm_render_assertions:
|
||||
description: "Set CLEVERAGENTS_REQUIRE_HELM_RENDER_ASSERTIONS=true for integration tests"
|
||||
type: boolean
|
||||
default: false
|
||||
timeout_minutes:
|
||||
description: "Job timeout in minutes"
|
||||
type: number
|
||||
default: 30
|
||||
secrets:
|
||||
ANTHROPIC_API_KEY:
|
||||
required: false
|
||||
OPENAI_API_KEY:
|
||||
required: false
|
||||
GOOGLE_API_KEY:
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
run:
|
||||
runs-on: docker
|
||||
timeout-minutes: ${{ inputs.timeout_minutes }}
|
||||
container:
|
||||
image: python:${{ inputs.python_version }}-slim
|
||||
steps:
|
||||
# ── System dependencies ──────────────────────────────────────────
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
PACKAGES="nodejs ${{ inputs.extra_apt_packages }}"
|
||||
apt-get update && apt-get install -y -qq $PACKAGES && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# ── Optional: Helm CLI ───────────────────────────────────────────
|
||||
- name: Install Helm CLI
|
||||
if: ${{ inputs.install_helm }}
|
||||
run: |
|
||||
HELM_VERSION="v3.16.4"
|
||||
ARCH="amd64"
|
||||
HELM_TARBALL="helm-${HELM_VERSION}-linux-${ARCH}.tar.gz"
|
||||
curl -fsSL "https://get.helm.sh/${HELM_TARBALL}" -o "/tmp/${HELM_TARBALL}"
|
||||
curl -fsSL "https://get.helm.sh/${HELM_TARBALL}.sha256sum" -o /tmp/helm.sha256sum
|
||||
cd /tmp && sha256sum -c helm.sha256sum
|
||||
tar -xzf "/tmp/${HELM_TARBALL}" -C /tmp
|
||||
mv /tmp/linux-${ARCH}/helm /usr/local/bin/helm
|
||||
chmod +x /usr/local/bin/helm
|
||||
helm version --short
|
||||
|
||||
# ── Optional: kubeconform ────────────────────────────────────────
|
||||
- name: Install kubeconform
|
||||
if: ${{ inputs.install_kubeconform }}
|
||||
run: |
|
||||
KUBECONFORM_VERSION="v0.7.0"
|
||||
ARCH="amd64"
|
||||
KUBECONFORM_TARBALL="kubeconform-linux-${ARCH}.tar.gz"
|
||||
curl -fsSL "https://github.com/yannh/kubeconform/releases/download/${KUBECONFORM_VERSION}/${KUBECONFORM_TARBALL}" \
|
||||
-o "/tmp/${KUBECONFORM_TARBALL}"
|
||||
tar -xzf "/tmp/${KUBECONFORM_TARBALL}" -C /tmp
|
||||
mv /tmp/kubeconform /usr/local/bin/kubeconform
|
||||
chmod +x /usr/local/bin/kubeconform
|
||||
kubeconform -v
|
||||
|
||||
# ── Checkout ─────────────────────────────────────────────────────
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# ── Python toolchain ─────────────────────────────────────────────
|
||||
- name: Install uv and nox
|
||||
run: |
|
||||
pip install -q uv==${{ inputs.uv_version }} nox
|
||||
|
||||
# ── Dependency cache ─────────────────────────────────────────────
|
||||
- name: Cache uv packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/uv
|
||||
key: uv-${{ inputs.cache_key_suffix }}-${{ hashFiles('pyproject.toml') }}
|
||||
restore-keys: |
|
||||
uv-${{ inputs.cache_key_suffix }}-
|
||||
|
||||
# ── Primary nox session ──────────────────────────────────────────
|
||||
- name: Run nox session (${{ inputs.nox_session }})
|
||||
if: ${{ inputs.nox_session != '' }}
|
||||
run: |
|
||||
nox -s ${{ inputs.nox_session }} ${{ inputs.nox_session_args }}
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
|
||||
CLEVERAGENTS_REQUIRE_HELM_RENDER_ASSERTIONS: ${{ inputs.require_helm_render_assertions && 'true' || '' }}
|
||||
|
||||
# ── Optional second nox session ──────────────────────────────────
|
||||
- name: Run nox session (${{ inputs.nox_session_2 }})
|
||||
if: ${{ inputs.nox_session_2 != '' }}
|
||||
run: |
|
||||
nox -s ${{ inputs.nox_session_2 }} ${{ inputs.nox_session_2_args }}
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
|
||||
# ── Optional: coverage artifact upload ───────────────────────────
|
||||
- name: Surface coverage summary
|
||||
if: ${{ inputs.upload_coverage_artifacts }}
|
||||
run: |
|
||||
if [ -f build/coverage.json ]; then
|
||||
python3 -c "
|
||||
import json, sys
|
||||
with open('build/coverage.json') as f:
|
||||
data = json.load(f)
|
||||
summary = data.get('summary') or data.get('totals') or {}
|
||||
pct = round(summary.get('percent_covered', 0), 1)
|
||||
threshold = 97
|
||||
if pct >= threshold:
|
||||
print(f'COVERAGE OK: {pct}% (threshold: {threshold}%)')
|
||||
else:
|
||||
print(f'COVERAGE FAILED: {pct}% < {threshold}% threshold')
|
||||
sys.exit(1)
|
||||
"
|
||||
else
|
||||
echo "COVERAGE FAILED: no coverage data generated"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Upload coverage artifacts
|
||||
if: ${{ inputs.upload_coverage_artifacts }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-reports
|
||||
path: |
|
||||
build/coverage.xml
|
||||
build/coverage.json
|
||||
build/htmlcov/
|
||||
retention-days: 30
|
||||
|
||||
# ── Optional: Helm chart validation ──────────────────────────────
|
||||
- name: Build Helm chart dependencies
|
||||
if: ${{ inputs.run_helm_validation }}
|
||||
run: |
|
||||
helm dependency build ./k8s
|
||||
|
||||
- name: Helm lint chart
|
||||
if: ${{ inputs.run_helm_validation }}
|
||||
run: |
|
||||
helm lint ./k8s \
|
||||
--set database.url="postgresql+asyncpg://user:pass@db-host:5432/cleveragents"
|
||||
|
||||
- name: Helm template smoke render
|
||||
if: ${{ inputs.run_helm_validation }}
|
||||
run: |
|
||||
helm template cleveragents ./k8s \
|
||||
--set database.url="postgresql+asyncpg://user:pass@db-host:5432/cleveragents" >/tmp/rendered.yaml
|
||||
test -s /tmp/rendered.yaml
|
||||
|
||||
- name: Validate rendered manifests with kubeconform
|
||||
if: ${{ inputs.run_helm_validation }}
|
||||
run: |
|
||||
kubeconform \
|
||||
-strict \
|
||||
-ignore-missing-schemas \
|
||||
-kubernetes-version 1.29.0 \
|
||||
-summary \
|
||||
/tmp/rendered.yaml
|
||||
Reference in New Issue
Block a user