123 lines
4.6 KiB
Markdown
123 lines
4.6 KiB
Markdown
# CI and supply-chain release gates
|
|
|
|
GeoIntel uses the same release gates in Gitea Actions and GitHub Actions:
|
|
|
|
- `.gitea/workflows/release-gates.yml`
|
|
- `.github/workflows/release-gates.yml`
|
|
|
|
Gitea is the operational source-control platform. The GitHub workflow is kept
|
|
equivalent so a mirror or external review does not receive a weaker gate.
|
|
|
|
## Runner requirements
|
|
|
|
The `ubuntu-latest` runner must provide:
|
|
|
|
- outbound HTTPS access to PyPI, npm, Docker Hub and vulnerability databases;
|
|
- Python 3.11 and Node 20 through the official setup actions;
|
|
- Bash and Docker with Compose v2;
|
|
- permission to build images and mount `/var/run/docker.sock`;
|
|
- sufficient disk for the all-in-one GIS image and scanner databases.
|
|
|
|
The container job builds the GIS release variant only. PyTorch and
|
|
Ultralytics remain in the optional `ai` extra and in the explicit AI image
|
|
variant; CI does not silently make them base dependencies.
|
|
|
|
## Quality gate
|
|
|
|
The quality job installs:
|
|
|
|
```bash
|
|
python -m pip install --require-hashes -r backend/requirements-ci.lock
|
|
python -m pip install --no-deps -e backend
|
|
cd frontend && npm ci
|
|
```
|
|
|
|
It then validates the lock policy and runs the complete readiness script. The
|
|
readiness script covers backend compile/tests, contract audits, Alembic
|
|
single-head, frontend typecheck/build and release-script syntax. CI also
|
|
renders offline migration SQL and resolved Compose configuration as retained
|
|
evidence.
|
|
|
|
## Reproducible Python lock
|
|
|
|
`backend/requirements-runtime.lock` and `backend/requirements-ci.lock` are
|
|
generated in a digest-pinned Linux Python 3.11 container. The runtime lock
|
|
contains base and GIS packages used by the release image. The CI lock adds
|
|
developer/test dependencies. Both use package hashes and deliberately exclude
|
|
the optional AI dependency group.
|
|
|
|
Regenerate after changing relevant `pyproject.toml` dependencies:
|
|
|
|
```bash
|
|
bash scripts/generate_python_lock.sh
|
|
python scripts/verify_python_lock.py
|
|
```
|
|
|
|
The all-in-one frontend build uses `npm ci`; the non-AI runtime installs the
|
|
hashed runtime lock. The optional AI image additionally uses explicit
|
|
PyTorch, torchvision and Ultralytics build-argument versions.
|
|
|
|
Do not hand-edit dependency versions or hashes in either generated lock.
|
|
`verify_python_lock.py` rejects a stale input fingerprint, another Python
|
|
generation version, unhashed packages, missing direct dependencies and AI
|
|
packages leaking into the standard CI environment.
|
|
|
|
## Vulnerability policy
|
|
|
|
The dependency job:
|
|
|
|
- fails on any non-excepted vulnerability reported by `pip-audit` for the
|
|
complete exact lock without platform-specific re-resolution;
|
|
- fails when `npm audit --audit-level=high` finds a high or critical frontend
|
|
dependency vulnerability;
|
|
- publishes both unfiltered and policy-filtered Python JSON reports plus the
|
|
npm JSON report, including on failure.
|
|
|
|
The only current Python/container exceptions are the Starlette 2026 advisories recorded
|
|
in `security/pip-audit-exceptions.json`. FastAPI 0.139.2 still constrains
|
|
Starlette below 0.53 while patched releases begin at 1.x. GeoIntel applies
|
|
request-target, form-content, route-class and Linux-runtime compensating
|
|
controls. The exception file has a mandatory review date; readiness and CI
|
|
fail automatically after it expires. New advisories are never auto-ignored.
|
|
The all-in-one image replaces the Go-based base-image `gosu` helper with a
|
|
small `setpriv` exec wrapper and upgrades packaged setuptools/wheel metadata;
|
|
these scanner findings are fixed rather than excepted.
|
|
|
|
The container job builds a non-AI all-in-one image and uses digest-pinned
|
|
scanner images:
|
|
|
|
- Syft 1.44.0 generates an SPDX JSON SBOM;
|
|
- Trivy 0.70.0 generates a complete JSON vulnerability report;
|
|
- fixed high or critical image vulnerabilities fail the gate;
|
|
- unfixed findings remain in the full report and require explicit release
|
|
review, but do not make a rebuild impossible when no patched package exists.
|
|
|
|
Run these controls on a Docker-enabled workstation:
|
|
|
|
```bash
|
|
docker build \
|
|
-f deploy/unraid/Dockerfile.all-in-one \
|
|
--build-arg GEOINTEL_INSTALL_AI=false \
|
|
--build-arg GEOINTEL_BUILD_SHA=local \
|
|
--build-arg GEOINTEL_BUILD_TIME=local \
|
|
-t geointel-ci:local .
|
|
bash scripts/generate_container_sbom.sh geointel-ci:local
|
|
bash scripts/scan_container_image.sh geointel-ci:local
|
|
```
|
|
|
|
Outputs are written below ignored `artifacts/`; scanner cache is written below
|
|
ignored `.cache/trivy/`.
|
|
|
|
## Published evidence
|
|
|
|
Every workflow run retains:
|
|
|
|
- offline Alembic upgrade SQL;
|
|
- resolved Docker Compose configuration;
|
|
- pip-audit and npm-audit JSON;
|
|
- image inspection metadata;
|
|
- SPDX JSON SBOM;
|
|
- complete Trivy JSON report.
|
|
|
|
No secret or plaintext database credential belongs in these artefacts.
|