Skip to content

Latest commit

 

History

History
134 lines (96 loc) · 8.91 KB

File metadata and controls

134 lines (96 loc) · 8.91 KB

CI/CD workflows

GitHub Actions and CI/CD helpers for this repository (see .github/ for workflow YAML).

Workflows

File Role
workflows/ci.yml Umbrella CI — runs on push/PR to main and develop
workflows/cd.yml Deploy — after CI succeeds on push to develop (staging) or main (production); inline SSH script parameterized by branch
workflows/promote-main.yml Promote to production — manual workflow_dispatch; ff-only developmain via PROMOTE_PAT so CI and cd.yml run on main
workflows/release.yml Release — manual workflow_dispatch only; tags main from pyproject.toml (v<version>) and creates a GitHub Release with Weblate compatibility metadata
workflows/ci-lint.yml Lint and format (prek)
workflows/ci-test.yml Unit tests and coverage
workflows/ci-benchmark.yml QuickBook parser benchmarks (pytest-benchmark; JSON artifact; regression gate vs .benchmarks/)
workflows/ci-package.yml Build and package checks
workflows/ci-dependencies.yml Dependency and license audit
workflows/ci-weblate-pin.yml Weblate version sync — callable from CI; runs scripts/check-weblate-pin-sync.sh so pyproject.toml and Dockerfile.weblate-plugin pins match
workflows/weblate-pin-bump.yml Scheduled Weblate pin bump (PyPI + Docker + uv.lock)
workflows/ci-plugin-smoke.yml Plugin smoke (Docker stack)
workflows/ci-plugin-functional.yml Plugin functional tests
workflows/ci-plugin-auth.yml Plugin auth tests

Callable workflows (ci-*, ci-plugin-*) are triggered only via workflow_call from ci.yml, not directly on push.

Plugin integration jobs

Three callable workflows exercise the live Weblate Docker stack (docker/docker-compose.ci.yml). Each job builds the image, runs compose up -d --wait, probes /healthz/ and the Boost ping endpoint, creates an API token (with retry), then runs pytest with pytest-timeout and one rerun on failure.

Job Workflow Typical duration Hard limit (timeout-minutes) Notes
Plugin smoke ci-plugin-smoke.yml ~8–12 min 15 Stack image build dominates
Plugin functional ci-plugin-functional.yml ~15–22 min 25 GitHub E2E needs repository secret
Plugin auth ci-plugin-auth.yml ~8–12 min 10 Auth + rate-limit tests

Secrets and environment

Variable Where Purpose
GH_TEST_REPO_TOKEN Repository secret (functional job only) Classic PAT with repo scope for ephemeral GitHub repos in tests/plugin/test_functional.py. If unset, GitHub/Celery E2E tests are skipped.
HEALTH_TIMEOUT CI workflow env / shell default Seconds to wait for /healthz/ after compose --wait. Defaults: smoke/auth 240, functional 300.
PYTEST_PLUGIN_OPTS Optional override in entrypoint scripts Default includes --timeout, --timeout-method=thread, --reruns 1, --reruns-delay 5. Smoke/auth use --timeout=120; functional uses --timeout=300.
WEBLATE_PORT Optional Host port for Weblate (default 8080).

Local reproduction

bash scripts/plugin-smoke.sh
bash scripts/plugin-auth.sh
GH_TEST_REPO_TOKEN=<classic PAT with repo> bash scripts/plugin-functional.sh

Skip slow plugin tests during local iteration: add -m "not slow" to the pytest invocation in the script, or set PYTEST_PLUGIN_OPTS accordingly.

QuickBook parser benchmarks

ci-benchmark.yml runs pytest-benchmark against synthetic .qbk documents (100 KB, 500 KB, 1 MB) in tests/utils/test_quickbook.py. Results are written to benchmark-results.json and uploaded as a workflow artifact. By default the job compares against the committed baseline at .benchmarks/Linux-CPython-3.14-64bit/0001_baseline.json and fails when mean time regresses beyond the configured threshold.

Variable Where Purpose
BENCHMARK_COMPARE_FAIL Repository variable / workflow env (default mean:30%) Passed to pytest --benchmark-compare-fail
BENCHMARK_COMPARE_ENABLED Repository variable / workflow env (default true) Set to false to skip comparison (record-only mode)

Refresh baseline after an intentional parser performance change. Capture on ubuntu-latest (GitHub Actions) — the committed baseline must match CI hardware (local VMs/desktops are often ~2× faster and will cause false regressions). Download the benchmark-* artifact from a green run, or on a GitHub-hosted runner:

uv run --group dev pytest -m benchmark --benchmark-only \
  -k "not peak_memory" \
  --benchmark-save=baseline tests/utils/test_quickbook.py
git add .benchmarks/Linux-CPython-3.14-64bit/0001_baseline.json

Peak-memory bounds are checked separately (test_parse_1mb_peak_memory); they are not part of the timing baseline compare.

If CI Python version changes, the .benchmarks/Linux-CPython-* directory name changes — regenerate and commit the new baseline path (update .gitignore exceptions if needed).

Other paths

Path Role
ci/apt-install Apt packages for Weblate-related CI jobs

Deploy environments and secrets

cd.yml selects the GitHub environment from the CI branch (workflow_run.head_branch):

Environment CI branch When deploy runs
staging develop After a successful CI run on a push to develop
production main After a successful CI run on a push to main (typically following promote-main.yml)

Both environments use the same secret names (configure different values per host):

Secret Purpose
SSH_HOST Deploy server hostname
SSH_USER SSH user
SSH_PRIVATE_KEY Private key for deploy
WEBLATE_PORT Host port for post-deploy /healthz/ poll
WEBLATE_URL_PREFIX URL prefix for health check (e.g. /weblate)
SSH_PORT Optional SSH port (default 22)

Server path: /opt/cppa-weblate-plugin with docker/docker-compose.cd.yml. Full procedure: docs/deployment-runbook.md.

Production promotion (repository secret)

promote-main.yml is separate from deploy: it ff-only merges develop into main and pushes with PROMOTE_PAT (classic or fine-grained PAT, Contents: write). Without a PAT, GitHub does not trigger CI or cd.yml on that push. Optional: required reviewers on the production environment only.

Weblate version pinning

Weblate is not bumped by Dependabot. A single logical release is pinned in two places:

Location Example Format
pyproject.toml Weblate[all]==2026.5 PyPI calver
docker/Dockerfile.weblate-plugin FROM weblate/weblate:2026.5.0.0 Docker fixed tag YEAR.MONTH.PATCH.BUILD

Mapping lives in scripts/weblate-version-map.sh. CI runs scripts/check-weblate-pin-sync.sh on every PR. weblate-pin-bump.yml opens a PR weekly (Monday 09:00 UTC) when a newer PyPI release has a matching Docker fixed tag.

Bump PR branch reconciliation

When the bump step changes pins, the Open pull request job uses branch weblate-pin/<pypi-version> and compares pyproject.toml, docker/Dockerfile.weblate-plugin, and uv.lock against the remote:

Outcome Condition Action
Open PR exists An open PR already targets the bump branch No-op (exit)
Remote branch matches bump files Remote branch exists and those three files match the local bump Open PR only (no commit or push)
Remote branch stale Remote branch missing or bump files differ Commit bump, push (force-with-lease if remote exists), then open PR