Docker development, CI and demonstration images
One multi-stage Dockerfile builds the installed tool, runs Gentoo end-to-end tests and creates a demonstration image.
| Target | Purpose |
|---|---|
installed |
Gentoo stage3 + Portage repository + real app-eselect/eselect-version-manager installed through emerge |
e2e |
Runs the full Gentoo test suite, including separate synthetic fixture packages; never published |
demo |
Non-root shell with active user-local shims and two explicitly synthetic slotted fixture tools |
The demo image provides a genuine Portage installation of the version manager. The fixture-tool executable is a demonstration fixture, not an actual Go, Python or Node.js replacement. It installs no mocked dev-lang/go packages.
Run a published image
After the first GitHub release publishes the image to GHCR:
docker run --rm -it ghcr.io/arran4/eselect-version-manager:v0.1.0
Inside:
eselect version-manager list fixture
cd ~/projects/slot-1 && fixture-tool
cd ~/projects/slot-2 && fixture-tool
eselect version-manager resolve fixture
python3 --version
The two fixture projects use committed-style .eselect.conf files with VM_FIXTURE=":1" and VM_FIXTURE=":2". This shows that project-aware selection works without changing a global eselect symlink.
Run eselect version-manager resolve fixture from either project directory to inspect its selected slot. In the default /home/demo directory, no fixture version is selected; an attempted system resolution is expected to fail because the demonstration image does not install an unslotted system fixture-tool.
The image runs as an unprivileged demo user. GitHub Packages visibility may need to be set to public before anonymous pulls work.
Sync the latest companion overlay (opt-in)
The demo image installs the version manager from a pinned, CI-reviewed overlay checkout. Its interactive environment also preconfigures a separate, normal Gentoo Portage Git repository at /var/db/repos/eselect-version-manager-overlay, with dev-vcs/git available:
[eselect-version-manager-overlay]
location = /var/db/repos/eselect-version-manager-overlay
sync-type = git
sync-uri = https://github.com/arran4/eselect-version-manager-overlay.git
auto-sync = yes
masters = gentoo
The live repository has no initial checkout: a manual Portage sync obtains the latest branch from GitHub. From a root shell inside the running container:
emaint sync -r eselect-version-manager-overlay
Or from another terminal on the host, after naming your running container:
docker exec --user root <container-name> emaint sync -r eselect-version-manager-overlay
The normal demo user is deliberately unprivileged. Syncing changes available ebuild metadata, not installed packages; use emerge deliberately to upgrade a tool. The container is disposable, so this checkout does not persist unless a volume is mounted. auto-sync = yes also allows the overlay to participate in explicitly run emaint sync --auto or emerge --sync.
The CI and release workflows retain their pinned overlay checkout for reproducible validation; they never silently fetch a new overlay version as part of a passing test.
Build locally from the current checkout
The companion overlay must be checked out into ./overlay:
git clone https://github.com/arran4/eselect-version-manager-overlay.git overlay
docker build --target demo --build-arg VM_SOURCE=checkout -t eselect-vm-demo .
docker run --rm -it eselect-vm-demo
To execute full Gentoo integration tests locally:
docker build --target e2e --build-arg VM_SOURCE=checkout --progress=plain .
This builds and installs the current source through the real Portage ebuild, then executes the end-to-end suite.
CI and build cache
PR CI uses the e2e stage with Docker Buildx and the GitHub Actions cache (type=gha, mode=max). Cached immutable layers avoid re-copying the full Portage tree and reinstalling unchanged base dependencies on subsequent builds. When the application source changes, Portage package installation and E2E still run; no passing CI status is inferred from a different commit. Cache performance depends on available GitHub cache storage and source changes.
The Dockerfile pins the Gentoo stage3 and Portage image digests; update these deliberately.
Canonical release workflow
The single CI/CD workflow follows the repository-specific principles of the canonical GitHub Actions reference. The separate Pages workflow remains because Pages deployment has a different event and permission boundary.
From GitHub Actions → CI → Run workflow on main, choose release-patch, release-minor or release-major. For the first release, selecting release-patch without an override produces v0.1.0. Use release_version_override only for an intentionally different initial version; an initial release-minor or release-major requires an explicit override. The workflow will:
- Run Python validation and the real Gentoo container E2E against the selected commit.
- Refuse to release if
mainadvanced after testing, or the chosen tag already exists. - Push an immutable annotated
vX.Y.Ztag. - In the same workflow run, check out that tag and fetch its real GitHub archive through Portage; run the tagged archive E2E and demo image smoke tests.
- Push the verified
ghcr.io/arran4/eselect-version-manager:vX.Y.Zimage, then create the single GitHub Release.
External stable vX.Y.Z tag pushes use the same release gate. Recover a tag already created by a failed publisher without bumping or moving it: go to Actions → CI → Run workflow, select current main (not the old tag, which has the old release workflow), select mode=publish-tag, and enter the existing numeric version in release_version_override (for example, 0.1.0, without v). The workflow validates current main, checks out and builds the immutable tagged source archive with the reviewed companion overlay ebuild, and republishes only after tagged-source E2E and demo smoke tests pass. This recovery does not create another tag. Pre-release SemVer suffixes are not supported yet because they need an explicit Portage PV translation.
The Docker build uses an exact pinned companion overlay commit with the reviewed ebuild. When correcting a packaging defect, merge the overlay fix and update that pin in source CI before running publish-tag; no changes to the already-created source tag are necessary. The Docker build copies the reviewed 0.1.0 ebuild template to a temporary versioned ebuild inside the build context when required. This does not modify the companion overlay repository. Its independent release-update workflow detects published source releases and opens a separate, verified ebuild/Manifest PR.
No 9999 live ebuild is needed for this workflow: checkout builds already package the chosen source through the same ebuild, whereas release builds fetch the immutable tagged archive. Adding a live ebuild would be a separate opt-in capability, not a prerequisite.
The public image runs as an unprivileged demo user and contains synthetic fixture commands, not real slotted Go compilers. The GHCR package may need to be made public in package settings for anonymous pulls. No first release exists until the workflow actually succeeds.