Skip to content

Release workflow

Tagged releases are reproducible and GitLab-native. The workflow creates GitLab release metadata and downloadable job artifacts, but it does not publish packages to PyPI or another package registry.

Version source

The canonical package version is stored in both:

  • pyproject.toml under tool.poetry.version
  • gitlab_project_audit.__version__

These values must match before a release tag is accepted.

Tag format

Release tags use:

vMAJOR.MINOR.PATCH

For example:

v0.2.0

A tag is rejected when:

  • it does not use the expected v... form
  • it does not match tool.poetry.version
  • tool.poetry.version and gitlab_project_audit.__version__ differ

Manual release procedure

  1. Update pyproject.toml and src/gitlab_project_audit/__init__.py to the same version.
  2. Run the local quality suite.
  3. Merge the version change to main.
  4. Create the matching tag on the exact commit:
git checkout main
git pull
git tag v0.2.0
git push origin v0.2.0
  1. The tag pipeline validates the tag/version before package artifacts are trusted.
  2. package-build creates the wheel and source distribution.
  3. release-artifacts verifies the artifact names, calculates SHA-256 checksums, and writes:
  4. release-meta/SHA256SUMS
  5. release-meta/RELEASE-MANIFEST.json
  6. release-meta/RELEASE-NOTES.md
  7. create-gitlab-release creates the GitLab release for the same tag and commit.

The GitLab release includes links to:

  • the complete release-artifacts archive
  • SHA256SUMS
  • RELEASE-MANIFEST.json

The manifest binds the release tag and Git commit SHA to the exact distribution artifact hashes.

Credentials

No PyPI token or package-registry publishing credential is required.

GitLab release creation runs inside the tagged pipeline and uses the GitLab CI job context.

Local validation

You can validate a prospective tag without creating a release:

PYTHONPATH=src python -m gitlab_project_audit.release_workflow validate --tag v0.2.0

After building distributions locally:

poetry build

PYTHONPATH=src python -m gitlab_project_audit.release_workflow prepare \
  --tag v0.2.0 \
  --commit "$(git rev-parse HEAD)" \
  --dist-dir dist \
  --output-dir release-meta

OCI container image

The repository also builds the CLI as an OCI image.

The image uses:

  • pinned python:3.12.12-slim-bookworm builder and runtime stages
  • a wheel built from the repository source
  • non-root runtime user 10001:10001
  • OCI version, revision, source, and licence labels
  • gitlab-project-audit as the image entrypoint

Build locally

VERSION="$(python - <<'PY'
import tomllib
from pathlib import Path
print(tomllib.loads(Path("pyproject.toml").read_text())["tool"]["poetry"]["version"])
PY
)"

docker build \
  --build-arg VERSION="$VERSION" \
  --build-arg VCS_REF="$(git rev-parse HEAD)" \
  -t "gitlab-project-audit:$VERSION" \
  .

Smoke-test the CLI:

docker run --rm "gitlab-project-audit:$VERSION" --help

Merge-request pipeline

Merge requests build the Dockerfile with BuildKit and export an OCI tar artifact. The image jobs use BuildKit's standard image, so they need a runner with privileged = true in its config.toml. Rootless BuildKit is no alternative on an unprivileged runner: it needs user namespaces, which Docker's default seccomp profile blocks.

gitlab-project-audit.oci.tar

The merge-request job does not authenticate to the Container Registry and does not push an image.

Release-tag publishing

Validated release tags publish exactly one immutable image reference:

$CI_REGISTRY_IMAGE:$CI_COMMIT_TAG

For example, tag v0.2.0 publishes:

registry.gitlab.com/DiogoRibeiro7/gitlab-project-audit:v0.2.0

The container job verifies again that $CI_COMMIT_TAG == v$PACKAGE_VERSION and depends on the existing release-validate job.

GitLab's built-in per-job registry credentials CI_REGISTRY_USER and CI_REGISTRY_PASSWORD are used. No personal access token is required.

Latest-tag policy

The project intentionally does not publish :latest.

Release tags are immutable/versioned and consumers should pin the exact release they intend to run. If a moving tag is introduced later, that will require an explicit policy change.

CI component release coupling

The reusable component in templates/audit.yml is versioned by the same Git tag as the package and OCI image.

A consumer that includes:

.../audit@v0.2.0

runs:

registry.gitlab.com/DiogoRibeiro7/gitlab-project-audit:v0.2.0

No separate component version is maintained.