Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
docs: document docker build and release flow
- document that the reusable build workflow validates images without pushing
- clarify the required dist/ wheel prerequisite for local Docker builds
- add a source-image existence check before release tag promotion
- explain the main-branch GHCR publication flow and semver promotion order
- align contributor docs with the actual Docker release behavior
  • Loading branch information
amimas committed Sep 26, 2026
commit e05c758e94a53d577bafa64d3ab60f5967df5bb6
6 changes: 6 additions & 0 deletions .github/workflows/_releases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,12 @@ jobs:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Verify source image exists before promotion
run: |
set -euo pipefail
SOURCE=ghcr.io/gitlabform/gitlabform:sha-${{ needs.prep-release.outputs.head_sha }}
echo "Checking source image: ${SOURCE}"
docker buildx imagetools inspect "$SOURCE" >/dev/null
- name: Promote image to release tags
run: |
set -euo pipefail
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ jobs:
platform: linux/arm64
tag_suffix: arm64
tarball: docker-image-arm64.tar
# PRs and branch validation must confirm the image is healthy without exposing
# registry credentials to the build job. The actual GHCR publication happens in
# the release workflow after a successful main-branch run.
steps:
- name: Checkout repository
uses: actions/checkout@v7
Expand Down
10 changes: 10 additions & 0 deletions dev/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
def build(extra_args: list[str] | None = None):
"""Builds the GitLabForm Docker image from a prebuilt wheel in dist/.

The Dockerfile installs the packaged wheel rather than building from the source tree,
so the local prerequisite is always: `uv run package build` before `uv run docker build`.

Local development usually builds for the host architecture only (for example, `docker buildx build`
with no explicit `--platform` override). CI uses the same toolkit commands but passes explicit
`--platform` values for multi-arch validation; the reusable build workflow validates each target
architecture without pushing registry credentials. This keeps the CLI surface consistent across
local development and GitHub Actions while the actual GHCR publication remains in the release
workflow.

Args:
extra_args: Arguments for the docker build command (e.g., --image, --tag, --push, --output).
"""
Expand Down
8 changes: 7 additions & 1 deletion docs/contrib/local_development.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,18 @@ uv run glf-dev package verify

### Docker Images

The Docker image is the recommended way to run GitLabForm in CI/CD environments. To build the image locally using our multi-stage `Dockerfile`:
The Docker image is the recommended way to run GitLabForm in CI/CD environments.

Before building a container image, make sure the Python wheel exists in `dist/`:

```bash
uv run glf-dev package build
uv run glf-dev docker build
```

This requirement is intentional: the `Dockerfile` installs the packaged wheel, instead of rebuilding from the source code again. The `uv run docker build` command is the same local and CI entry point, but the GitHub Actions workflow passes explicit `--platform` values for multi-arch validation while local development typically targets the host architecture only.


You can customize the image name and tag via arguments:

```bash
Expand Down
21 changes: 15 additions & 6 deletions docs/contrib/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,21 @@ We try to follow the [PEP 440](https://peps.python.org/pep-0440/) versioning sch

Executing `tbump` will create a commit containing version updates to necessary files (i.e. `tbump.toml`, `pyproject.toml`), create a new tag from for the new version from the current `ref` in `main` branch, and finally push the commits and tag to remote.

Following the above steps when a new tag is created, GitHub Action workflow will do following:
When the version tag is created, the release workflow will do the following:

- Create a docker image containing new version of gitlabform and publish to [github's package registry under gitlabform](https://github.com/gitlabform/gitlabform/pkgs/container/gitlabform).
- Upload new version of gitlabform to [pypi package registry under gitlabform](https://pypi.org/project/gitlabform/).
- A corresponding [GitHub release](https://github.com/gitlabform/gitlabform/releases) will be created that references the new tag.
- validate that the upstream Main workflow passed for the same commit and that the tag points to that commit
- upload the new version of gitlabform to [PyPI](https://pypi.org/project/gitlabform/)
- create the corresponding [GitHub release](https://github.com/gitlabform/gitlabform/releases) that references the new tag
- promote the already published SHA-tagged Docker image to release tags such as `vX.Y.Z`, `vX.Y`, and `vX` using `docker buildx imagetools create`

The release workflow also verifies that the commit on `main` passed the build and quality. It will trigger a release workflow that will proceed only if a corresponding version tag exists in GitHub and main branch workflow on that commit passed. The release workflow can also be triggered manually, which will require 2 inputs: a release version tag and main branch workflow's run id from corresponding commit.
The immutable `sha-<full-sha>` and `sha-<short-sha>` Docker tags are created earlier, as part of the successful main-branch publication flow, and are not created as part of the version-tag release procedure itself.

3. Edit the release in GitHub and copy the changelog entry into its description.
The release workflow can also be triggered manually, in which case it requires a release version tag and the corresponding main workflow run id.

4. Edit the release in GitHub and copy the changelog entry into its description.

## Docker publication model

The Docker image is built and verified by the reusable `build.yml` workflow, and the resulting artifacts are then published by the release pipeline.

This avoids rebuilding the image during the final release step and keeps PR validation free of registry credentials. The image that gets promoted to the semver tags is always the already published `sha-<head_sha>` image from the successful main-branch publication flow.
40 changes: 40 additions & 0 deletions docs/contrib/workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,46 @@ us by GitLab's customer success team.
These tests are run in an GitHub Environment, requiring approval from a maintainer, and the licenses assigned to this
project's maintainers are stored as GitHub Repository Secrets to prevent misuse.

## Docker build and release flow

The GitHub Actions workflows are intentionally split into two concerns:

- the reusable build workflow validates the project and Docker image, but does not push anything to a registry
- the release workflow publishes the verified main-branch image to GHCR and then promotes it to versioned release tags

This separation keeps PR validation credential-free while still allowing the repository to publish a verified container image from the main branch.

### Build workflow

The reusable `build.yml` workflow is called from both PR and main branch flows. It always performs the same validation steps:

- build the Python package and verify its output
- build the Docker image from the packaged wheel in `dist/`
- verify that the image runs successfully
- upload the resulting Docker image archives as workflow artifacts

For PR validation, the workflow builds and verifies the Docker image for both amd64 and arm64 targets but stops before any registry push. The job only exercises local Docker validation and never requires GHCR write permissions.

For the main branch, the build workflow still validates the image without pushing, but it uploads the same Docker image archives for later publication by the release workflow.

### Release workflow

The release workflow is triggered after a successful run of the main branch workflow and can also be triggered manually for a specific tag. It performs two different publication steps:

1. `publish-to-ghcr-main`:
- downloads the archived images generated by `build.yml`
- loads the amd64 and arm64 images into Docker
- pushes the immutable `sha-<full-sha>` and `sha-<short-sha>` tags to GHCR
- creates the corresponding multi-arch manifests
- updates `latest` to the newest successful main-branch build

2. `publish-to-ghcr-release`:
- runs only when a valid semver tag exists for the commit
- verifies that the source image `ghcr.io/gitlabform/gitlabform:sha-<head_sha>` exists
- promotes that image to version tags such as `vX.Y.Z`, `vX.Y`, and `vX` with `docker buildx imagetools create`

This ensures that the release tag always points to a previously built, verified image instead of rebuilding from source at release time.

## Pipeline Trigger
We use `pull_request_target` as the event to trigger PR pipelines on Forks- which has a downside that we can't test
pipeline changes submitted from forks until merged into main, but allows us to pass License Secrets to Forks more easily.
Expand Down