Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c93f3f3
build(devcontainer): add development container setup
kadykov Oct 27, 2025
c2ee361
Merge branch 'darktable-org:master' into devcontainer
kadykov Nov 8, 2025
196a090
Merge branch 'darktable-org:master' into devcontainer
kadykov Jan 9, 2026
1908f7f
Merge branch 'darktable-org:master' into devcontainer
kadykov Mar 11, 2026
8582a3b
Remove apt cache in the container
kadykov Mar 13, 2026
505cf46
Merge branch 'darktable-org:master' into devcontainer
kadykov May 14, 2026
fe0fbbd
Merge branch 'darktable-org:master' into devcontainer
kadykov Jul 15, 2026
9dc1426
Merge branch 'darktable-org:master' into devcontainer
kadykov Aug 15, 2026
3dc0a80
Add devcontainer-lock.json for common-utils feature configuration
kadykov Aug 15, 2026
4eca62a
Add additional dependencies for image processing and tools in Dockerfile
kadykov Aug 15, 2026
f6d62f3
Align development container with CI environment by updating base imag…
kadykov Aug 15, 2026
a9019c5
Update README to clarify devcontainer purpose and prerequisites, enha…
kadykov Aug 15, 2026
a9123e5
Remove clang-format extension from VSCode settings in devcontainer co…
kadykov Aug 16, 2026
9ae2189
Rewrite dev container README, reference container-based build environ…
kadykov Aug 16, 2026
5eef79e
Enhance README with Docker and Podman installation instructions for c…
kadykov Aug 16, 2026
cf55266
Refactor CI Docker setup: remove Dockerfile, update devcontainer to u…
kadykov Aug 18, 2026
93cc54d
Merge branch 'master' into ci-docker-build-environment
kadykov Aug 21, 2026
87fc0c8
Refactor CI Linux workflow to build from Dockerfile and use GHCH as c…
kadykov Aug 21, 2026
547ba6f
Revert for using images from GHCR, add publish-image job in CI workflow
kadykov Aug 21, 2026
a64930a
Refactor CI Docker workflow: remove legacy Dockerfile, add test-image…
kadykov Aug 23, 2026
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
139 changes: 0 additions & 139 deletions .ci/Dockerfile

This file was deleted.

56 changes: 30 additions & 26 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,24 @@ See the [Podman installation guide](https://podman.io/docs/installation).
No IDE, no extra tooling — just build and run the container directly.

```bash
# Build the image once (from the repository root)
docker build -t darktable-dev -f .devcontainer/Dockerfile .
# Pull the pre-built CI image
docker pull ghcr.io/darktable-org/darktable-build:latest

# Verify the build compiles (same environment as CI)
# Verify the build compiles cleanly (same environment as CI)
docker run --rm --user "$(id -u):$(id -g)" \
-v "$PWD":/workspace -w /workspace \
darktable-dev \
ghcr.io/darktable-org/darktable-build:latest \
bash -lc './build.sh --prefix /tmp/dt --build-type Release'

# Build an AppImage for GUI testing on the host
docker run --rm --user "$(id -u):$(id -g)" \
-v "$PWD":/workspace -w /workspace \
-e APPIMAGE_EXTRACT_AND_RUN=1 \
darktable-dev \
ghcr.io/darktable-org/darktable-build:latest \
bash -lc './tools/appimage-build-script.sh'
```

The AppImage appears in `build/Darktable-*.AppImage` and can be run on the host.
The AppImage appears in `build/Darktable-*.AppImage` and can be run directly on the host.

> Replace `docker` with `podman` if you use Podman.

Expand Down Expand Up @@ -95,10 +95,12 @@ Then:
# Start the container
devcontainer up --workspace-folder .

# Open a shell
# Open a shell inside it
devcontainer exec --workspace-folder . bash
```

Then build as usual (see [Building](#building)).

> **VS Code and JetBrains bundle their own devcontainer implementation** — you
> only need to install the CLI separately when using other editors or working
> purely in a terminal.
Expand Down Expand Up @@ -150,31 +152,32 @@ Using `--configdir` avoids touching your production darktable configuration.
cd build && ctest
```

## CI environment and pre-built images
## CI environment

The [Dockerfile](Dockerfile) is the single source of truth for the build
environment. Inspect it for the exact base image, compiler versions, and
package list.
environment. The `.github/workflows/build-docker.yml` workflow implements a
**build → test → push** sequence: it builds a candidate image from the
Dockerfile, runs a smoke-test build of darktable inside it, and only pushes
to GHCR if the build succeeds. Linux CI jobs always pull the last tested
`:latest` image.

### Pre-built images on GHCR

`.github/workflows/build-docker.yml` automatically builds the image and
publishes it to the GitHub Container Registry (GHCR) whenever the `Dockerfile`
changes on the `master` branch. The pre-built image is available at:
The `:latest` tag on `ghcr.io/darktable-org/darktable-build` is updated
whenever `.devcontainer/Dockerfile` changes on `master`, after the candidate
image passes a smoke-test build of darktable. Each release is also tagged
`YYYY-MM-DD-SHORTSHA` for pinned auditing.

```
ghcr.io/darktable-org/darktable-build:latest
```
`workflow_dispatch` on `build-docker.yml` lets maintainers trigger a manual
rebuild — useful when the upstream `ubuntu:26.04` base image gains security
patches without any change to the Dockerfile.

Using the pre-built image skips the local build step:
### Customising the build environment

```bash
docker pull ghcr.io/darktable-org/darktable-build:latest
docker run --rm --user "$(id -u):$(id -g)" \
-v "$PWD":/workspace -w /workspace \
ghcr.io/darktable-org/darktable-build:latest \
bash -lc './build.sh --prefix /tmp/dt --build-type Release'
```
To add or remove packages, edit `.devcontainer/Dockerfile` and submit it as a
normal PR. When the change merges to `master`, `build-docker.yml` runs
automatically, builds and smoke-tests the new image, and pushes it to GHCR
only if the build succeeds.

## Troubleshooting

Expand All @@ -200,7 +203,7 @@ Always set `APPIMAGE_EXTRACT_AND_RUN=1` — FUSE is not available inside contain
git submodule update --init --recursive
```

### Git says the repository has dubious ownership inside the container
### Git says the mounted repository has dubious ownership inside the container

Pass `--user "$(id -u):$(id -g)"` to `docker run` (as shown in the examples
above), or mark the path as safe inside the container:
Expand Down Expand Up @@ -228,5 +231,6 @@ CLI: `devcontainer up --workspace-folder . --remove-existing-container`
├── devcontainer.json # IDE/tooling configuration
└── README.md # This file
.github/workflows/
└── build-docker.yml # Publishes the image to GHCR on Dockerfile changes
├── ci.yml # Linux jobs run against the published :latest image
└── build-docker.yml # Build → test → push :latest (on Dockerfile changes or workflow_dispatch)
```
5 changes: 1 addition & 4 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
{
"name": "Darktable Development",
"build": {
"dockerfile": "Dockerfile",
"context": ".."
},
"image": "ghcr.io/darktable-org/darktable-build:latest",
"runArgs": [
"--cap-add=SYS_PTRACE",
"--security-opt=seccomp=unconfined"
Expand Down
53 changes: 53 additions & 0 deletions .github/scripts/test-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env bash
# Run all Linux CI matrix configurations against a candidate Docker image.
# Used by build-docker.yml; can also be called locally to validate a new image.
# Usage: test-image.sh <image> <src-dir>
set -euo pipefail

IMAGE="${1:?Usage: $0 <image> <src-dir>}"
SRC_DIR="${2:?Usage: $0 <image> <src-dir>}"

run_config() {
local name="$1"; shift
local build_dir="${SRC_DIR}/build/${name}"
local install_dir="${SRC_DIR}/install/${name}"
mkdir -p "${build_dir}" "${install_dir}"
printf '\n=== Testing configuration: %s ===\n\n' "${name}"
docker run --rm \
--tmpfs /tmp:exec \
-v "${SRC_DIR}:${SRC_DIR}" \
-e SRC_DIR="${SRC_DIR}" \
-e BUILD_DIR="${build_dir}" \
-e INSTALL_PREFIX="${install_dir}" \
-e GENERATOR=Ninja \
"$@" \
"${IMAGE}" \
"${SRC_DIR}/.ci/ci-script.sh"
}

# Mirror all Linux matrix configurations from .github/workflows/ci.yml
run_config GNU16_Release \
-e CC=gcc-16 -e CXX=g++-16 \
-e CMAKE_BUILD_TYPE=Release \
-e TARGET=skiptest \
-e ECO="-DDONT_USE_INTERNAL_LIBRAW=ON"

run_config LLVM22_Release \
-e CC=clang-22 -e CXX=clang++-22 \
-e CMAKE_BUILD_TYPE=Release \
-e TARGET=skiptest \
-e ECO="-DDONT_USE_INTERNAL_LIBRAW=ON"

run_config GNU16_Debug \
-e CC=gcc-16 -e CXX=g++-16 \
-e CMAKE_BUILD_TYPE=Debug \
-e TARGET=skiptest \
-e ECO="-DDONT_USE_INTERNAL_LIBRAW=OFF"

run_config GNU16_Release_tests \
-e CC=gcc-16 -e CXX=g++-16 \
-e CMAKE_BUILD_TYPE=Release \
-e TARGET=build \
-e ECO="-DDONT_USE_INTERNAL_LIBRAW=ON"

printf '\n=== All configurations passed ===\n'
57 changes: 46 additions & 11 deletions .github/workflows/build-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,66 @@ on:
- '.devcontainer/Dockerfile'
workflow_dispatch:

permissions:
contents: read
packages: write

jobs:
build-and-push:
build-test-push:
name: Build, test and push CI Docker image
if: github.repository == 'darktable-org/darktable' || github.event_name == 'workflow_dispatch'
name: Build and push darktable-build Docker image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v7
with:
submodules: false
fetch-depth: 1

- name: Get build submodules
run: |
git submodule init
git config submodule.src/tests/integration.update none
git submodule update

- name: Log in to GitHub Container Registry
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push Docker image
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build candidate image
uses: docker/build-push-action@v6
with:
context: .
file: .devcontainer/Dockerfile
load: true
push: false
tags: darktable-build:candidate
cache-from: type=registry,ref=ghcr.io/darktable-org/darktable-build:latest

- name: Run CI matrix checks with candidate image
run: .github/scripts/test-image.sh darktable-build:candidate "$GITHUB_WORKSPACE"

- name: Compute image tags
id: tags
run: |
SHORT_SHA=$(echo "$GITHUB_SHA" | cut -c1-8)
{
echo 'tags<<EOF'
echo "ghcr.io/darktable-org/darktable-build:latest"
echo "ghcr.io/darktable-org/darktable-build:$(date -u +%Y-%m-%d)-${SHORT_SHA}"
echo 'EOF'
} >> "$GITHUB_OUTPUT"

- name: Push tested image to GHCR
uses: docker/build-push-action@v6
with:
context: .
file: .devcontainer/Dockerfile
push: true
tags: |
ghcr.io/darktable-org/darktable-build:latest
ghcr.io/darktable-org/darktable-build:${{ github.sha }}
tags: ${{ steps.tags.outputs.tags }}
cache-from: type=registry,ref=ghcr.io/darktable-org/darktable-build:latest
cache-to: type=inline
Loading
Loading