Skip to content

CI: use pre-built Docker image for Linux build jobs - #21909

Closed
kadykov wants to merge 20 commits into
darktable-org:masterfrom
kadykov:ci-docker-build-environment
Closed

CI: use pre-built Docker image for Linux build jobs#21909
kadykov wants to merge 20 commits into
darktable-org:masterfrom
kadykov:ci-docker-build-environment

Conversation

@kadykov

@kadykov kadykov commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Follows up on #19597 (devcontainer configuration).

What this changes

Replaces the per-run apt-get install steps in the Linux CI jobs with a
pre-built Docker image hosted on GHCR. The image is built from
.devcontainer/Dockerfile, which was introduced in the prerequisite PR and
already mirrors the CI environment exactly.

Files changed:

  • .github/workflows/build-docker.yml — new workflow: builds and pushes the
    image to GHCR when .devcontainer/Dockerfile changes
  • .github/workflows/ci.yml — Linux job: use GHCR image, remove compiler
    and dependency install steps
  • .devcontainer/devcontainer.json — switch from local build to pulling the
    published GHCR image (faster for devcontainer users)
  • .ci/Dockerfile — removed (2016-era Jenkins artefact, superseded)

Why

  • Single source of truth: the Dockerfile is the only place that defines
    the Linux build environment. ci.yml and the devcontainer both consume it.
    No more risk of drift between them.
  • Faster CI feedback: the dependency install steps currently add several
    minutes to every Linux job. Pre-built images eliminate that overhead.
  • Easier onboarding: devcontainer.json now uses "image": instead of
    "build":, so opening the devcontainer is a docker pull rather than a
    full image build.

What does NOT change

  • Windows and macOS CI jobs — unchanged, containers are not applicable there
  • nightly.yml — the AppImage build deliberately targets ubuntu-22.04 for
    glibc compatibility and builds libs from source; it stays as-is
  • The CI matrix structure (compiler variants, build types, eco flags) —
    unchanged; compiler choice continues to be CC/CXX env vars

Image tagging strategy

Images are pushed as:

  • ghcr.io/darktable-org/darktable-build:latest — rolling, used by CI
  • ghcr.io/darktable-org/darktable-build:YYYY-MM-DD-SHORTSHA — pinned, for
    auditing

The build-docker workflow triggers on:

  • Push to master that modifies .devcontainer/Dockerfile
  • Manual workflow_dispatch

kadykov and others added 16 commits October 27, 2025 16:15
Add a complete devcontainer environment for building and testing darktable, including Dockerfile with all dependencies, configuration, and documentation. Also update .gitignore to exclude AppDir for AppImage builds.
Co-authored-by: Philipp Lutz <810285+da-phil@users.noreply.github.com>
…e to Ubuntu 26.04 and installing matching packages. Enhance README with compiler details and CI alignment information.
…ncing compatibility details for various IDEs.
…se pre-built image, and create GitHub Actions workflow for image build and publish
@kadykov

kadykov commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Action needed from a darktable-org organization admin: make the GHCR package public

The build-docker.yml workflow that was merged with #19597 successfully pushed the image:

ghcr.io/darktable-org/darktable-build:latest
ghcr.io/darktable-org/darktable-build:970e38b1c30bdfd71c27a2615b4098c52055f245

However, when a GitHub Actions workflow pushes a package to GHCR for an organization, it seems that it is created as private by default. The package is there — it's just invisible and inaccessible to anyone who isn't authenticated to the org:

aleksandr@bluefin ~> docker pull ghcr.io/darktable-org/darktable-build:latest
Error response from daemon: Head "https://ghcr.io/v2/darktable-org/darktable-build/manifests/latest": unauthorized

How to fix it:

An org admin needs to change the visibility once:

  1. Go to https://github.com/orgs/darktable-org/packages/container/darktable-build/settings
  2. Scroll to the Danger Zone section
  3. Click "Change visibility" → select Public → confirm

Alternatively, with the GitHub CLI and an org-admin token:

gh api --method PATCH /orgs/darktable-org/packages/container/darktable-build \
  -f visibility=public

Why this must happen before this PR can work:

  • The CI in this PR pulls ghcr.io/darktable-org/darktable-build:sha-<sha> (a per-commit image). Without the package being public, the runner cannot pull it.
  • Contributors and devcontainer users need docker pull ghcr.io/darktable-org/darktable-build:latest to work without any authentication.
    This is a one-time action. GitHub Actions workflows cannot set package visibility themselves — the packages:write scope only covers pushing images, not changing org-level visibility settings.

@kadykov
kadykov marked this pull request as ready for review August 21, 2026 17:17
Copilot AI lite review requested due to automatic review settings August 21, 2026 17:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR switches Linux GitHub Actions CI builds from installing dependencies on every run to using a pre-built Docker image published to GHCR, aligning CI and the devcontainer on a shared build environment definition.

Changes:

  • Update Linux CI job to run inside ghcr.io/darktable-org/darktable-build:latest, removing per-run apt-get install steps.
  • Add image publishing/build steps (including a publish-image job in ci.yml and a manual build-docker.yml workflow).
  • Update the devcontainer configuration and documentation to pull and use the published image.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
.github/workflows/ci.yml Linux job now uses a GHCR image; adds a publish-image job to build/push updated images.
.github/workflows/build-docker.yml Changes the image build workflow to be manual-only and adds tag computation + caching.
.devcontainer/README.md Updates docs to describe the new CI/devcontainer image flow and GHCR usage.
.devcontainer/devcontainer.json Switches devcontainer from building locally to consuming the published GHCR image.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/ci.yml Outdated
Comment on lines +45 to +47
permissions:
contents: read
packages: write
Comment on lines 3 to 6
on:
push:
branches:
- master
paths:
- '.devcontainer/Dockerfile'
# Manual trigger only — useful when the upstream ubuntu:26.04 base image
# updates without a Dockerfile change. Normal :latest updates happen via ci.yml.
workflow_dispatch:
Comment thread .devcontainer/README.md Outdated
Comment on lines +179 to +181
To add or remove packages, edit `.devcontainer/Dockerfile` and submit it as a
normal PR. CI will build from the updated Dockerfile automatically, so you can
verify the environment works before the change is merged.
Comment thread .github/workflows/ci.yml

Linux:
if: github.repository == 'darktable-org/darktable' || github.event_name == 'workflow_dispatch'
name: Linux_${{ matrix.distro }}_${{ matrix.compiler.compiler }}_${{ matrix.btype }}${{ matrix.name_suffix }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of matrix.distro we could keep the flexibility to test against docker images which are based on different distros, e.g. Ubuntu 26.04, Fedora 44, OpenSUSE 16 etc. (potential future work if we want to follow-up with that).

Comment thread .github/workflows/ci.yml Outdated
publish-image:
name: Publish CI Docker image
needs: Linux
if: (github.repository == 'darktable-org/darktable' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/master'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does github.event_name == 'workflow_dispatch') mean?
I'm just trying to understand when this action is even triggered. Could possibly be triggered manually, right?

@da-phil da-phil Aug 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean after .github/workflows/build-docker.yml finishes building the image?
I wonder why this action is part of the ci.yml file and not part of build-docker.yml as the final step after the docker image was built?
The step Compute image tags is also duplicated across both files.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this review the architecture has changed significantly. The publish-image job has been removed from ci.yml entirely. build-docker.yml now owns all image publishing and implements a build → smoke-test → push sequence. workflow_dispatch on that workflow lets a maintainer force a manual rebuild (e.g. to pick up Ubuntu security patches without changing the Dockerfile). ci.yml has no publishing step at all — it simply pulls :latest.

Comment thread .ci/Dockerfile Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging in master brought back the deprecated dockerfile.

Also, I don't think that syncing feature branches against master is done via merge commits in the darktable repo, we usually rebase against master.
It's also not nice to have merge commits in a feature branch commit history, when it gets merged back to master via a merge commit.

@da-phil

da-phil commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

@TurboGit I think #21909 (comment) was addressed to you

Action needed from a darktable-org organization admin: make the GHCR package public

… script, move image publishing to build-docker workflow
@kadykov

kadykov commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

@da-phil Thank you for the thorough review on this PR! I wanted to let you know that I've addressed all of the feedback, including the dirty git history, in a fresh PR #21972

A brief summary of what changed in response to the review:

Dirty git history / merge commit / .ci/Dockerfile reappearing

You were right on all counts. The original branch was based on an early draft made before #19597 merged, and I resolved the conflicts by merging master into the feature branch — which is not how darktable normally handles this, and it brought back the deleted .ci/Dockerfile as a side effect. The new PR starts from a clean checkout of current master and contains a single commit with only the relevant files.

packages: write at workflow level

Removed from ci.yml entirely — the publish-image job that needed it has been removed from ci.yml (see below).

build-docker.yml trigger / PR description mismatch

Both the workflow and the PR description are now consistent. The push trigger on .devcontainer/Dockerfile changes is restored. The workflow now implements a build→test→push sequence: it builds a candidate image, runs all four Linux CI matrix configurations against it using a new .github/scripts/test-image.sh helper, and only pushes to GHCR if every configuration passes. The workflow_dispatch trigger remains for manual rebuilds (e.g. picking up upstream Ubuntu security patches).

README "CI will verify Dockerfile changes before merge"

The README now correctly describes what actually happens: Dockerfile changes are picked up when they merge to master (triggering build-docker.yml), not during the PR itself.

publish-image in ci.yml / confusion about workflow_dispatch

You were right that it was confusing. The publish-image job has been removed from ci.yml entirely. Image publishing now belongs exclusively to build-docker.yml. ci.yml is back to its original simplicity — Linux jobs just pull :latest. The workflow_dispatch you asked about is on build-docker.yml, not ci.yml.

matrix.image / distro flexibility`

A great idea for future work. It's not in this PR to keep the scope focused, but the groundwork is there — adding an image: matrix dimension to ci.yml would be straightforward once :latest images for other distros are published.


I'll close this PR in favour of #21972. Thanks again for the careful review — it directly led to a significantly better architecture.

@kadykov kadykov closed this Aug 23, 2026
@TurboGit

TurboGit commented Aug 23, 2026

Copy link
Copy Markdown
Member

@kadykov : the GHCR package is now set to public.

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.

4 participants