Files
cleveragents-core/.forgejo/workflows/release.yml
brent.edwards 00897be24a feat(ci): CI/CD pipeline definitions (#983)
## Summary

Complete CI/CD pipeline definitions: release workflow, caching, status-check consolidation, and documentation.

### Changes

**New: Release pipeline** (`.forgejo/workflows/release.yml`):
- Triggered on `v*` tags
- 3 jobs: `build-wheel` → `build-docker` → `create-release`
- Builds wheel via `nox -s build`, Docker image via multi-stage Dockerfile
- Creates Forgejo release via API with wheel artifact attached
- Configurable registry push via `REGISTRY_*` secrets

**Updated: CI pipeline** (`.forgejo/workflows/ci.yml`):
- Added `actions/cache@v3` for `~/.cache/uv` on all 8 primary jobs (keyed on `pyproject.toml` hash)
- Added `status-check` consolidation job depending on all required checks — single gate for branch protection

**Updated: CONTRIBUTING.md**:
- New CI/CD section: pipeline overview, job table, required merge checks, release process, secrets documentation

**Tests**:
- 13 new Behave scenarios validating workflow YAML structure, tag triggers, job definitions, dependencies
- 9 new Robot tests validating file existence, content, nox session references

### Quality Gates

| Session | Result |
|---|---|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (10,819 scenarios) |
| `nox -s coverage_report` | 97.9% (>= 97%) |

Closes #858

Reviewed-on: cleveragents/cleveragents-core#983
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-21 00:29:49 +00:00

142 lines
4.8 KiB
YAML

name: Release
on:
push:
tags:
- "v*"
env:
UV_VERSION: "0.8.0"
PYTHON_VERSION: "3.13"
NOX_DEFAULT_VENV_BACKEND: "uv"
jobs:
build-wheel:
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
- name: Upload wheel artifact
uses: actions/upload-artifact@v3
with:
name: wheel
path: dist/*.whl
retention-days: 30
build-docker:
runs-on: docker
container:
image: docker:dind
options: --privileged
needs: [build-wheel]
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: Extract tag name
id: tag
run: |
TAG_NAME="${FORGEJO_REF_NAME:-${GITHUB_REF_NAME:-unknown}}"
echo "TAG_NAME=${TAG_NAME}" >> $FORGEJO_OUTPUT
- name: Build Docker image
run: |
TAG="${{ steps.tag.outputs.TAG_NAME }}"
docker build \
-t "${{ secrets.CONTAINER_REGISTRY }}:${TAG}" \
-t "${{ secrets.CONTAINER_REGISTRY }}:latest" \
.
- name: Push Docker image to registry
if: secrets.CONTAINER_REGISTRY != ''
run: |
TAG="${{ steps.tag.outputs.TAG_NAME }}"
if [ -n "${{ secrets.CONTAINER_REGISTRY_USER }}" ]; then
echo "${{ secrets.CONTAINER_REGISTRY_PASSWORD }}" | \
docker login \
-u "${{ secrets.CONTAINER_REGISTRY_USER }}" \
--password-stdin \
"${{ secrets.CONTAINER_REGISTRY }}"
fi
docker push "${{ secrets.CONTAINER_REGISTRY }}:${TAG}"
docker push "${{ secrets.CONTAINER_REGISTRY }}:latest"
create-release:
runs-on: docker
container:
image: python:3.13-slim
needs: [build-wheel, build-docker]
steps:
- name: Install system dependencies
run: |
apt-get update && apt-get install -y -qq nodejs curl jq && rm -rf /var/lib/apt/lists/*
- uses: actions/checkout@v4
- name: Download wheel artifact
uses: actions/download-artifact@v3
with:
name: wheel
path: dist/
- name: Extract tag name
id: tag
run: |
TAG_NAME="${FORGEJO_REF_NAME:-${GITHUB_REF_NAME:-unknown}}"
echo "TAG_NAME=${TAG_NAME}" >> $FORGEJO_OUTPUT
- name: Create Forgejo release with wheel
env:
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
FORGEJO_URL: ${{ secrets.FORGEJO_URL }}
run: |
TAG="${{ steps.tag.outputs.TAG_NAME }}"
REPO="${{ forgejo.repository }}"
API_URL="${FORGEJO_URL}/api/v1/repos/${REPO}/releases"
# Create the release
RELEASE_ID=$(curl -s -X POST "${API_URL}" \
-H "Authorization: token ${FORGEJO_TOKEN}" \
-H "Content-Type: application/json" \
-d "{
\"tag_name\": \"${TAG}\",
\"name\": \"${TAG}\",
\"body\": \"Release ${TAG}\",
\"draft\": false,
\"prerelease\": false
}" | jq -r '.id')
echo "Created release ID: ${RELEASE_ID}"
# Attach wheel artifacts
for whl in dist/*.whl; do
FILENAME=$(basename "${whl}")
curl -s -X POST \
"${API_URL}/${RELEASE_ID}/assets?name=${FILENAME}" \
-H "Authorization: token ${FORGEJO_TOKEN}" \
-H "Content-Type: application/octet-stream" \
--data-binary "@${whl}"
echo "Attached ${FILENAME} to release"
done