Skip to content

build: reuse built wheel in container image and publish image every main build - #1437

Open
amimas wants to merge 15 commits into
mainfrom
refactor-container-build-release
Open

amimas wants to merge 15 commits into
mainfrom
refactor-container-build-release

Conversation

@amimas

@amimas amimas commented Sep 27, 2026 •

Copy link
Copy Markdown
Collaborator

This PR refactors the container build and release process.

Currently the CI process does not have any steps for building the container image. It only gets built after changes are merged into main branch. Even then, the container image is created by rebuilding the python package/wheel.

This PR introduces following changes regarding how container image is built:

  • The Dockerfile does not build the python package - it consumes a pre-built package. This makes both pypi release and container image using the same artifact created in build step
  • The CI now includes an additional step for running the container build process including validating that the python package in the container is working - does not publish the container image. The image is saved as pipeline artifact by the build step and downloaded by the verify step and loaded into docker and then run the container.

Building on those, updated when container image is published. Every merge to main branch will publish docker image using 2 non-versioned tags. One tag is sha-<short-commit-hash> and another for sha-<full-commit-hash>. This way, features/fixes are readily available for anyone to test without needing to wait for a release to happen in gitlabform. Also added main tag point to these commit based tags. This tag will auto update on every merge to main branch.

All other release process stays same as before. The gitlabform version can be a bit confusing from the commit based or non-versioned tags. Wanted to limit the amount of changes being introduced in this PR. So, didn't look into this as currently version numbers are hard coded in pyproject.toml and tbump.toml files. This is probably a different refactor for later.

Tested the change in my fork repo. The docker image tags can be seen here and an example of the release workflow run here.

- build the Docker image from the prebuilt wheel in dist/
- add a safety guard to fail early if the wheel is missing
- validate Docker images in CI without pushing from build.yml
- expose head_sha for release metadata tracking
- publish main-branch Docker images from the release workflow
- use artifact download + imagetools promotion instead of rebuild-on-release
- 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
Comment thread .github/workflows/_main.yml Outdated
Comment thread dev/main.py Outdated
@rickbrouwer

Copy link
Copy Markdown
Collaborator

Moving latest to every main commit changes what users get today. Could we keep latest for releases and use a separate tag like main for commit builds?

Comment thread dev/docker.py Outdated
@amimas

amimas commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator Author

Moving latest to every main commit changes what users get today. Could we keep latest for releases and use a separate tag like main for commit builds?

I debated about latest tag moving on every merge. I landed on this approach because using this tag is not the best practice/recommended anyway. That's why I was wondering if this needs to be marked as breaking change. But, using main for commit builds is not a bad idea. It still gives the same benefit and doesn't break what latest points to today.

Thanks for the suggestion. I'll look into updating it when I get a chance.

@amimas
amimas requested a deployment to Integrate Pull Request October 2, 2026 11:20 — with GitHub Actions Waiting
@amimas
amimas requested a deployment to Integrate Pull Request October 2, 2026 11:20 — with GitHub Actions Waiting
@amimas

amimas commented Oct 2, 2026

Copy link
Copy Markdown
Collaborator Author

Pushed some changes that now keeps the latest docker tags tied to the latest versioned tags. The main tag is added to the commit hash based tags.

Example: https://github.com/amimas/gitlabform/pkgs/container/gitlabform/versions

@rickbrouwer

rickbrouwer commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

I think the manual (workflow_dispatch) release silently skips Docker publication. publish-to-ghcr-release depends on publish-to-ghcr-main, which only runs on workflow_run, so the release ships to PyPI and GitHub with no image tags and no failure. I think the published images also lose all OCI labels now that nothing applies the metadata-action output, and the Dockerfile's wheel glob breaks (or silently ships stale code) as soon as dist/ holds more than one wheel locally.

Also there are some loose ends: commented-out code and duplicate logging in dev/docker.py, an advertised extra_args that is silently dropped, an error message pointing to a command that doesn't exist, and docs describing behaviour the workflow doesn't have (latest moving on main builds, vX.Y.Z tags).

Could you give the whole PR a cleanup pass with this in mind? I will re-review after that.

Ow, little note, one thing to decide explicitly. The release flow can no longer build an image itself, so if the main-branch run never pushed the sha image, a manual release can't recover. Is that intended?

@amimas

amimas commented Oct 3, 2026

Copy link
Copy Markdown
Collaborator Author

Really good observation @rickbrouwer. I think they are valid issues. I missed those! I'll look into those issues, soon I hope.

Ow, little note, one thing to decide explicitly. The release flow can no longer build an image itself, so if the main-branch run never pushed the sha image, a manual release can't recover. Is that intended?

You're right. I think we have to get the main branch workflow passing and then the manual release workflow should work (after the issue you found is fixed).

The main objective for the PR was that same artifact should be used everywhere. The python package gets built and verified in both PR and main branch build. Right now that same package gets published to pypi while Docker image rebuilds the package again. This is what I wanted to avoid. Basically build it once or reuse already built package. Publishing unreleased image (i.e. main or commit hash based tags) are just extra.

So, this does make the release flow dependent on main branch workflow completing successfully. We have flaky tests that sometimes fails the main branch workflow. That's going to be an issue and ideally they should be fixed.

At the same time, I've been thinking about our acceptance tests. I think they do have value and we're able to catch issues with GitLab's API change quickly. But the tests are growing and taking longer - some has sleep and retry logic. Right now I think acceptance tests takes about 30 minutes. I haven't thought it through yet, but maybe the acceptance tests needs to be slimmer and only test individual API calls instead of every possible scenario. For example: delete key and enforce key will both call the relevant APIs delete endpoint. So, we might not need to test every possible way that can happen in acceptance tests - instead use more unit tests? Basically unit test for whether the config is processed correctly and acceptance tests for validating resource creation/update/delete. Maybe there are better options.

Question: Should the docker image publish be dependent on pypi release? It's just a made up dependency that exists today - maybe just to make sure pypi release is successful. I considered whether docker build should install from pypi, but decided against it because that means in PR, we can't easily build and verify the docker image and I don't like the idea of different process between PR vs main branch workflow.

Please let me know if you have more suggestions or whether we/I should continue with this PR.

Thanks again for reviewing this, btw. Really appreciate it.

@rickbrouwer

Copy link
Copy Markdown
Collaborator

Basically build it once or reuse already built package. Publishing unreleased image (i.e. main or commit hash based tags) are just extra.

I am strongly in favor of building to 'main' in that case.

I haven't thought it through yet, but maybe the acceptance tests needs to be slimmer

I haven't yet closely examined whether we have any truly redundant or duplicate tests, but I am a proponent of comprehensive integration tests that provide thorough coverage. Admittedly, this can result in very long execution times. On another project where I work, we address this by using regex to select which tests to run; for instance, you can launch a test using /run-e2e badges to execute only the tests related to badges. This way, you get your output faster and avoid running unnecessary, time-consuming tests.

Should the docker image publish be dependent on pypi release?

I'd keep it. Since both now use the same wheel, the dependency is no longer technical, but it still guards release consistency. A PyPI version can never be re-uploaded, while Docker tags can be re-promoted at any time. If PyPI fails, a vX.Y.Z image would exist for a version that may never ship on PyPI. Promotion only retags, so the extra wait is negligible. Agree on not installing from PyPI: same artifact and same process in PR and main is the right call.

@rickbrouwer

Copy link
Copy Markdown
Collaborator

Please let me know if you have more suggestions or whether we/I should continue with this PR.

Oh right, I forgot to reply to this one.
Well, that's up to you :) For what it's worth, I'm not going to use main builds.
For me personally, that would also be the case if we were to start running nightlies or something similar.

This branch is waiting to be deployed

1 waiting deployment
Integrate Pull Request — e1f2c26b Waiting Oct 2, 2026 by amimas via Acceptance Tests / GitLab Ultimate #273
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants