From eca1c4bc3668d8cf369ef4abf2427ca20978e6c5 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Wed, 14 Oct 2026 10:57:07 +0300 Subject: [PATCH] ci: publish the dev container image to GitHub Packages --- .devcontainer/devcontainer.json | 5 +- .github/workflows/devcontainer-image.yml | 92 ++++++++++++++++++++++++ docs/dev-containers.md | 7 ++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/devcontainer-image.yml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index dbf02ce3..ff4ef266 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,9 @@ { "name": "Querya Desktop", - "build": { "dockerfile": "Dockerfile" }, + "build": { + "dockerfile": "Dockerfile", + "cacheFrom": "ghcr.io/queryahub/querya-devcontainer:latest" + }, "features": { "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {} }, diff --git a/.github/workflows/devcontainer-image.yml b/.github/workflows/devcontainer-image.yml new file mode 100644 index 00000000..c19e5de4 --- /dev/null +++ b/.github/workflows/devcontainer-image.yml @@ -0,0 +1,92 @@ +name: Dev container image + +# Publishes ghcr.io/queryahub/querya-devcontainer (GitHub Packages) so the dev +# container and Codespaces start from a prebuilt layer cache instead of +# rebuilding the Flutter + Linux desktop toolchain from scratch. +# +# Pull requests only build and smoke-test the image, they never push. +on: + push: + branches: [main, dev] + paths: + - .devcontainer/Dockerfile + - .github/workflows/devcontainer-image.yml + pull_request: + paths: + - .devcontainer/Dockerfile + - .github/workflows/devcontainer-image.yml + schedule: + - cron: "0 5 * * 1" # weekly: pick up base-image and apt security updates + workflow_dispatch: + +permissions: + contents: read + packages: write + +concurrency: + group: devcontainer-image-${{ github.ref }} + cancel-in-progress: true + +env: + IMAGE: ghcr.io/queryahub/querya-devcontainer + +jobs: + image: + name: Build and push querya-devcontainer + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Flutter version from the Dockerfile + id: flutter + run: | + v=$(sed -n 's#^FROM ghcr.io/cirruslabs/flutter:\(.*\)$#\1#p' .devcontainer/Dockerfile | head -n1) + test -n "$v" + echo "version=$v" >> "$GITHUB_OUTPUT" + + - uses: docker/setup-buildx-action@v3 + + - uses: docker/login-action@v3 + if: github.event_name != 'pull_request' + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build (loaded locally for the smoke test) + uses: docker/build-push-action@v6 + with: + context: .devcontainer + file: .devcontainer/Dockerfile + load: true + tags: querya-devcontainer:test + cache-from: type=gha + cache-to: type=gha,mode=max + labels: | + org.opencontainers.image.source=https://github.com/${{ github.repository }} + org.opencontainers.image.description=Querya Desktop dev container (Flutter ${{ steps.flutter.outputs.version }} + Linux desktop toolchain) + org.opencontainers.image.licenses=MIT + + - name: Smoke test + run: | + set -euo pipefail + docker run --rm querya-devcontainer:test flutter --version + docker run --rm querya-devcontainer:test docker --version + docker run --rm querya-devcontainer:test docker compose version + docker run --rm querya-devcontainer:test bash -c 'clang --version && cmake --version && ninja --version && pkg-config --exists gtk+-3.0 libsecret-1' + + - name: Push + if: github.event_name != 'pull_request' + uses: docker/build-push-action@v6 + with: + context: .devcontainer + file: .devcontainer/Dockerfile + push: true + cache-from: type=gha + tags: | + ${{ env.IMAGE }}:latest + ${{ env.IMAGE }}:flutter-${{ steps.flutter.outputs.version }} + labels: | + org.opencontainers.image.source=https://github.com/${{ github.repository }} + org.opencontainers.image.description=Querya Desktop dev container (Flutter ${{ steps.flutter.outputs.version }} + Linux desktop toolchain) + org.opencontainers.image.licenses=MIT diff --git a/docs/dev-containers.md b/docs/dev-containers.md index 30149442..423f8b6d 100644 --- a/docs/dev-containers.md +++ b/docs/dev-containers.md @@ -13,6 +13,13 @@ list of seeded data see the header of [`docker/docker-compose.yml`](../docker/do | [`.devcontainer/Dockerfile`](../.devcontainer/Dockerfile) | `ghcr.io/cirruslabs/flutter` plus the Linux desktop toolchain (clang, cmake, ninja, GTK 3, libsecret, SQLite headers, Xvfb) and the Docker CLI with the Compose plugin. `DISPLAY` is `:99`. | | [`docker/docker-compose.yml`](../docker/docker-compose.yml) | The database stack (project `querya-dev`): PostgreSQL 16, MySQL 8.4, Redis 7, MongoDB 7, ClickHouse 24.8 and a seeded SQLite file. | +The image is also published to GitHub Packages as +`ghcr.io/queryahub/querya-devcontainer` (`:latest` and `:flutter-`) by the +[Dev container image](../.github/workflows/devcontainer-image.yml) workflow, rebuilt when the +Dockerfile changes and weekly for security updates. `devcontainer.json` uses it as a layer +cache (`build.cacheFrom`), so the first build pulls the toolchain layers instead of compiling +them; if the package is unreachable the build simply falls back to building from the Dockerfile. + When the container is created it runs `flutter config --enable-linux-desktop` and `flutter pub get`; every time it starts it tries `docker compose -f docker/docker-compose.yml up -d` and prints a hint if Docker