From 349fc5675fd207b5a31049aea5704a8c6d84f0d6 Mon Sep 17 00:00:00 2001 From: Robear Selwans Date: Sat, 2 May 2026 17:51:57 +0300 Subject: [PATCH] Add Evol testbed CI image --- .dockerignore | 5 + .gitea/workflows/build-ci-image.yml | 37 ++ .gitea/workflows/build.yml | 34 ++ .gitignore | 13 + ci/.dockerignore | 5 + ci/Dockerfile | 118 ++++++ ci/README.md | 106 +++++ ci/USE_CI_IMAGE.md | 615 ++++++++++++++++++++++++++++ 8 files changed, 933 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitea/workflows/build-ci-image.yml create mode 100644 .gitea/workflows/build.yml create mode 100644 .gitignore create mode 100644 ci/.dockerignore create mode 100644 ci/Dockerfile create mode 100644 ci/README.md create mode 100644 ci/USE_CI_IMAGE.md diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cd67d99 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.git +build +.cache +.venv +subprojects/packagecache diff --git a/.gitea/workflows/build-ci-image.yml b/.gitea/workflows/build-ci-image.yml new file mode 100644 index 0000000..d5333a5 --- /dev/null +++ b/.gitea/workflows/build-ci-image.yml @@ -0,0 +1,37 @@ +name: build-ci-image + +on: + push: + paths: + - ci/Dockerfile + - .dockerignore + - .gitea/workflows/build-ci-image.yml + workflow_dispatch: + +jobs: + image: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Log in to container registry + run: | + echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "${{ vars.REGISTRY_HOST }}" \ + -u "${{ secrets.REGISTRY_USERNAME }}" \ + --password-stdin + + - name: Build CI image + run: | + docker build \ + --build-arg BASE_IMAGE=catthehacker/ubuntu:act-latest \ + --build-arg LLVM_VERSION=22 \ + --build-arg MESON_VERSION=latest \ + -t "${{ vars.REGISTRY_IMAGE }}:latest" \ + -t "${{ vars.REGISTRY_IMAGE }}:clang22" \ + -f ci/Dockerfile . + + - name: Push CI image + run: | + docker push "${{ vars.REGISTRY_IMAGE }}:latest" + docker push "${{ vars.REGISTRY_IMAGE }}:clang22" diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..7d1b5eb --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,34 @@ +name: build + +on: + push: + pull_request: + +jobs: + linux: + runs-on: ubuntu-latest + + # Set vars.CI_IMAGE to the same value as vars.REGISTRY_IMAGE, or replace this + # line with your full image path, e.g. git.neosisyphus.com/evol3d/evol-testbed:clang22 + container: + image: ${{ vars.CI_IMAGE }}:clang22 + + steps: + - uses: actions/checkout@v4 + + - name: Check CI toolchain + run: | + clang --version + clang++ --version + meson --version + ninja --version + python3 --version + vulkaninfo --summary || true + + - name: Configure + run: | + meson setup build + + - name: Build + run: | + meson compile -C build diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7fa59dd --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Local/build artifacts +build/ +.cache/ +.venv/ + +# This repo is only for the CI image/testbed setup. +evol-sandbox/ +test.c + +# OS/editor noise +.DS_Store +*.swp +*.swo diff --git a/ci/.dockerignore b/ci/.dockerignore new file mode 100644 index 0000000..cd67d99 --- /dev/null +++ b/ci/.dockerignore @@ -0,0 +1,5 @@ +.git +build +.cache +.venv +subprojects/packagecache diff --git a/ci/Dockerfile b/ci/Dockerfile new file mode 100644 index 0000000..6b80031 --- /dev/null +++ b/ci/Dockerfile @@ -0,0 +1,118 @@ +# Gitea Actions CI image for C/C++ + Vulkan projects. +# This extends the Ubuntu image commonly used by Gitea/act_runner so JS actions +# such as actions/checkout keep working. +# +# Build: +# docker build -t evol-testbed:latest -f ci/Dockerfile . + +ARG BASE_IMAGE=catthehacker/ubuntu:act-latest +FROM ${BASE_IMAGE} + +ARG LLVM_VERSION=22 +ARG MESON_VERSION=latest +ARG USE_LUNARG_VULKAN=false +ARG LUNARG_SDK_VERSION=1.4.309.0 + +ENV DEBIAN_FRONTEND=noninteractive +ENV CC=clang +ENV CXX=clang++ +ENV AR=llvm-ar +ENV RANLIB=llvm-ranlib +ENV NM=llvm-nm +ENV STRIP=llvm-strip + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# Base compiler/build/Python/Vulkan packages from Ubuntu. +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + gnupg \ + lsb-release \ + wget \ + xz-utils \ + git \ + build-essential \ + pkg-config \ + software-properties-common \ + python3 \ + python3-pip \ + python3-venv \ + ninja-build \ + libvulkan-dev \ + vulkan-tools \ + vulkan-validationlayers \ + glslang-tools \ + spirv-tools \ + spirv-headers; \ + rm -rf /var/lib/apt/lists/* + +# LLVM/Clang from apt.llvm.org. +RUN set -eux; \ + codename="$(. /etc/os-release && echo "${VERSION_CODENAME}")"; \ + curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key \ + | gpg --dearmor -o /usr/share/keyrings/llvm-snapshot.gpg; \ + echo "deb [signed-by=/usr/share/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-${LLVM_VERSION} main" \ + > "/etc/apt/sources.list.d/llvm-${LLVM_VERSION}.list"; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + "clang-${LLVM_VERSION}" \ + "clang-tools-${LLVM_VERSION}" \ + "clang-format-${LLVM_VERSION}" \ + "clang-tidy-${LLVM_VERSION}" \ + "lld-${LLVM_VERSION}" \ + "lldb-${LLVM_VERSION}" \ + "llvm-${LLVM_VERSION}" \ + "llvm-${LLVM_VERSION}-dev" \ + "llvm-${LLVM_VERSION}-tools"; \ + rm -rf /var/lib/apt/lists/* + +# Optional LunarG Vulkan SDK repo. Disabled by default because Ubuntu distro +# Vulkan packages are more stable for CI and usually enough for building/testing. +RUN set -eux; \ + if [ "${USE_LUNARG_VULKAN}" = "true" ]; then \ + codename="$(. /etc/os-release && echo "${VERSION_CODENAME}")"; \ + curl -fsSL https://packages.lunarg.com/lunarg-signing-key-pub.asc \ + | gpg --dearmor -o /usr/share/keyrings/lunarg.gpg; \ + echo "deb [signed-by=/usr/share/keyrings/lunarg.gpg] https://packages.lunarg.com/vulkan/${LUNARG_SDK_VERSION}/ubuntu ${codename} main" \ + > /etc/apt/sources.list.d/lunarg-vulkan-sdk.list; \ + apt-get update; \ + apt-get install -y --no-install-recommends vulkan-sdk; \ + rm -rf /var/lib/apt/lists/*; \ + fi + +# Make LLVM_VERSION the default clang toolchain. +RUN set -eux; \ + update-alternatives --install /usr/bin/clang clang "/usr/bin/clang-${LLVM_VERSION}" 100; \ + update-alternatives --install /usr/bin/clang++ clang++ "/usr/bin/clang++-${LLVM_VERSION}" 100; \ + update-alternatives --install /usr/bin/clang-cpp clang-cpp "/usr/bin/clang-cpp-${LLVM_VERSION}" 100; \ + update-alternatives --install /usr/bin/lld lld "/usr/bin/lld-${LLVM_VERSION}" 100; \ + update-alternatives --install /usr/bin/lldb lldb "/usr/bin/lldb-${LLVM_VERSION}" 100; \ + update-alternatives --install /usr/bin/llvm-ar llvm-ar "/usr/bin/llvm-ar-${LLVM_VERSION}" 100; \ + update-alternatives --install /usr/bin/llvm-ranlib llvm-ranlib "/usr/bin/llvm-ranlib-${LLVM_VERSION}" 100; \ + update-alternatives --install /usr/bin/llvm-nm llvm-nm "/usr/bin/llvm-nm-${LLVM_VERSION}" 100; \ + update-alternatives --install /usr/bin/llvm-strip llvm-strip "/usr/bin/llvm-strip-${LLVM_VERSION}" 100 + +# Meson in an isolated venv avoids Debian/Ubuntu PEP 668 externally-managed pip errors. +RUN set -eux; \ + python3 -m venv /opt/meson-venv; \ + /opt/meson-venv/bin/python -m pip install --upgrade pip setuptools wheel; \ + if [ "${MESON_VERSION}" = "latest" ]; then \ + /opt/meson-venv/bin/python -m pip install --upgrade meson; \ + else \ + /opt/meson-venv/bin/python -m pip install --upgrade "meson==${MESON_VERSION}"; \ + fi; \ + ln -sf /opt/meson-venv/bin/meson /usr/local/bin/meson + +# Verify installed tools at image build time. +RUN set -eux; \ + python3 --version; \ + clang --version; \ + clang++ --version; \ + meson --version; \ + ninja --version; \ + vulkaninfo --summary || true + +CMD ["bash"] diff --git a/ci/README.md b/ci/README.md new file mode 100644 index 0000000..590c1a4 --- /dev/null +++ b/ci/README.md @@ -0,0 +1,106 @@ +# Gitea Actions CI image + +This image extends Gitea/act's Ubuntu runner image: + +```text +catthehacker/ubuntu:act-latest +``` + +It includes: + +- Clang/LLVM 22 +- Meson +- Ninja +- Python 3 + pip + venv +- Vulkan development packages/tools +- Git/build-essential/pkg-config +- Node/runtime pieces inherited from the act Ubuntu image, so JavaScript actions like `actions/checkout` keep working + +## Files prepared + +```text +ci/Dockerfile +.dockerignore +.gitea/workflows/build-ci-image.yml +.gitea/workflows/build.yml +``` + +## Required Gitea variables/secrets + +In your repository or organization settings, add these **Actions variables**: + +```text +REGISTRY_HOST=git.neosisyphus.com +REGISTRY_IMAGE=git.neosisyphus.com/evol3d/evol-testbed +CI_IMAGE=git.neosisyphus.com/evol3d/evol-testbed +``` + +Add these **Actions secrets**: + +```text +REGISTRY_USERNAME=your-gitea-username +REGISTRY_PASSWORD=your-gitea-token-or-password +``` + +The token/password needs permission to publish packages/container images. + +## Build manually + +```bash +docker build -t evol-testbed:latest -f ci/Dockerfile . +``` + +Test: + +```bash +docker run --rm -it evol-testbed:latest bash -lc ' + clang --version && + meson --version && + ninja --version && + python3 --version && + vulkaninfo --summary || true +' +``` + +Tag and push: + +```bash +docker login git.neosisyphus.com + +docker tag evol-testbed:latest git.neosisyphus.com/evol3d/evol-testbed:latest +docker tag evol-testbed:latest git.neosisyphus.com/evol3d/evol-testbed:clang22 + +docker push git.neosisyphus.com/evol3d/evol-testbed:latest +docker push git.neosisyphus.com/evol3d/evol-testbed:clang22 +``` + +## Build automatically in Gitea Actions + +After setting the variables/secrets above, run: + +```text +.gitea/workflows/build-ci-image.yml +``` + +It builds and pushes: + +```text +${REGISTRY_IMAGE}:latest +${REGISTRY_IMAGE}:clang22 +``` + +## Use in normal builds + +`.gitea/workflows/build.yml` is already prepared to use: + +```yaml +container: + image: ${{ vars.CI_IMAGE }}:clang22 +``` + +If expressions do not work in `container.image` on your Gitea version, replace it with the literal image path: + +```yaml +container: + image: git.neosisyphus.com/evol3d/evol-testbed:clang22 +``` diff --git a/ci/USE_CI_IMAGE.md b/ci/USE_CI_IMAGE.md new file mode 100644 index 0000000..35e71af --- /dev/null +++ b/ci/USE_CI_IMAGE.md @@ -0,0 +1,615 @@ +# Using the Clang 22 + Vulkan Gitea Actions CI Image + +This guide explains how to build, publish, and use the prepared Docker image for Gitea Actions. + +The prepared files are: + +```text +ci/Dockerfile +ci/README.md +ci/USE_CI_IMAGE.md +.dockerignore +.gitea/workflows/build-ci-image.yml +.gitea/workflows/build.yml +``` + +The image extends: + +```text +catthehacker/ubuntu:act-latest +``` + +It includes: + +- Clang/LLVM 22 +- `clang-format-22` +- `clang-tidy-22` +- `lld-22` +- `lldb-22` +- Meson +- Ninja +- Python 3 / pip / venv +- Vulkan development packages/tools +- `build-essential` +- `pkg-config` +- Git +- Gitea/act-compatible tooling inherited from the base image + +--- + +## 1. Decide your image name + +Pick a container image path in your Gitea registry. + +Example Gitea host: + +```text +git.neosisyphus.com +``` + +Organization: + +```text +evol3d +``` + +Image path: + +```text +git.neosisyphus.com/evol3d/evol-testbed +``` + +The pushed tags will be: + +```text +git.neosisyphus.com/evol3d/evol-testbed:latest +git.neosisyphus.com/evol3d/evol-testbed:clang22 +``` + +--- + +## 2. Commit the prepared files + +From the repository root: + +```bash +git add ci/Dockerfile ci/README.md ci/USE_CI_IMAGE.md .dockerignore .gitea/workflows/build-ci-image.yml .gitea/workflows/build.yml +git commit -m "Add reusable Clang 22 Vulkan CI image" +git push +``` + +--- + +## 3. Create a Gitea access token + +In the Gitea web UI: + +1. Open your user menu. +2. Go to **Settings**. +3. Go to **Applications**. +4. Create a new access token. +5. Give it package/container registry write permissions. + +Depending on your Gitea version, the permission may be named one of: + +```text +package +packages +write:package +write:packages +``` + +Copy the token. It will be used as the registry password. + +--- + +## 4. Add Gitea Actions variables + +In your repository: + +1. Go to **Settings**. +2. Go to **Actions**. +3. Go to **Variables**. +4. Add these variables: + +```text +REGISTRY_HOST=git.neosisyphus.com +REGISTRY_IMAGE=git.neosisyphus.com/evol3d/evol-testbed +CI_IMAGE=git.neosisyphus.com/evol3d/evol-testbed +``` + +Use your actual values. + +### `REGISTRY_HOST` + +Only the hostname: + +```text +git.neosisyphus.com +``` + +Do not include `https://`. + +Correct: + +```text +git.neosisyphus.com +``` + +Wrong: + +```text +https://git.neosisyphus.com +``` + +### `REGISTRY_IMAGE` + +The full image path without a tag: + +```text +git.neosisyphus.com/evol3d/evol-testbed +``` + +### `CI_IMAGE` + +Usually the same as `REGISTRY_IMAGE`: + +```text +git.neosisyphus.com/evol3d/evol-testbed +``` + +This is used by the normal build workflow. + +--- + +## 5. Add Gitea Actions secrets + +In your repository: + +1. Go to **Settings**. +2. Go to **Actions**. +3. Go to **Secrets**. +4. Add: + +```text +REGISTRY_USERNAME +REGISTRY_PASSWORD +``` + +Example: + +```text +REGISTRY_USERNAME=myusername +REGISTRY_PASSWORD= +``` + +Use your Gitea username for `REGISTRY_USERNAME`. + +Use the token from step 3 for `REGISTRY_PASSWORD`. + +--- + +## 6. Check the image build workflow + +The image build workflow is: + +```text +.gitea/workflows/build-ci-image.yml +``` + +It logs into your registry, builds the image, and pushes two tags: + +```text +latest +clang22 +``` + +The important commands are: + +```yaml +- name: Build CI image + run: | + docker build \ + --build-arg BASE_IMAGE=catthehacker/ubuntu:act-latest \ + --build-arg LLVM_VERSION=22 \ + --build-arg MESON_VERSION=latest \ + -t "${{ vars.REGISTRY_IMAGE }}:latest" \ + -t "${{ vars.REGISTRY_IMAGE }}:clang22" \ + -f ci/Dockerfile . + +- name: Push CI image + run: | + docker push "${{ vars.REGISTRY_IMAGE }}:latest" + docker push "${{ vars.REGISTRY_IMAGE }}:clang22" +``` + +--- + +## 7. Make sure your runner can build Docker images + +The image-building workflow needs Docker. + +On the runner host, check: + +```bash +docker version +``` + +If that works, the host has Docker. + +Your Gitea runner still needs permission to access Docker. + +### Option A: `act_runner` runs directly on the host + +If your runner runs directly on the machine, make sure the runner user can use Docker. + +Check the runner user, then add it to the Docker group if needed: + +```bash +sudo usermod -aG docker +sudo systemctl restart act_runner +``` + +Test as that user: + +```bash +docker ps +``` + +### Option B: `act_runner` runs inside Docker + +If `act_runner` itself runs inside a container, it needs the host Docker socket mounted: + +```bash +-v /var/run/docker.sock:/var/run/docker.sock +``` + +Example: + +```bash +docker run -d \ + --name gitea-act-runner \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v /opt/act-runner/config.yaml:/config.yaml \ + -v /opt/act-runner/data:/data \ + gitea/act_runner:latest +``` + +Without the socket mount, the workflow cannot run `docker build`. + +--- + +## 8. Run the image build workflow + +There are two ways. + +### Method 1: push changes + +The workflow triggers when these files change: + +```text +ci/Dockerfile +.dockerignore +.gitea/workflows/build-ci-image.yml +``` + +So this is enough: + +```bash +git push +``` + +### Method 2: manual workflow dispatch + +If your Gitea version supports `workflow_dispatch`: + +1. Go to your repository. +2. Open **Actions**. +3. Select **build-ci-image**. +4. Click **Run workflow**. + +--- + +## 9. Confirm the image was pushed + +In Gitea: + +1. Open the repository or organization. +2. Go to **Packages**. +3. Look for: + +```text +evol-testbed +``` + +Confirm these tags exist: + +```text +latest +clang22 +``` + +--- + +## 10. Use the image in your normal build workflow + +The prepared normal workflow is: + +```text +.gitea/workflows/build.yml +``` + +It uses: + +```yaml +container: + image: ${{ vars.CI_IMAGE }}:clang22 +``` + +If you set: + +```text +CI_IMAGE=git.neosisyphus.com/evol3d/evol-testbed +``` + +then the workflow uses: + +```text +git.neosisyphus.com/evol3d/evol-testbed:clang22 +``` + +The key workflow shape is: + +```yaml +name: build + +on: + push: + pull_request: + +jobs: + linux: + runs-on: ubuntu-latest + + container: + image: ${{ vars.CI_IMAGE }}:clang22 + + steps: + - uses: actions/checkout@v4 + + - name: Check CI toolchain + run: | + clang --version + clang++ --version + meson --version + ninja --version + python3 --version + vulkaninfo --summary || true + + - name: Configure + run: | + meson setup build + + - name: Build + run: | + meson compile -C build +``` + +Commit and push: + +```bash +git add .gitea/workflows/build.yml +git commit -m "Use Clang 22 Vulkan CI image" +git push +``` + +--- + +## 11. If `vars.CI_IMAGE` does not work in `container.image` + +Some Gitea/act versions may not expand variables in `container.image`. + +If the build fails because the image name is invalid, replace this: + +```yaml +container: + image: ${{ vars.CI_IMAGE }}:clang22 +``` + +with the literal image name: + +```yaml +container: + image: git.neosisyphus.com/evol3d/evol-testbed:clang22 +``` + +Then commit and push: + +```bash +git add .gitea/workflows/build.yml +git commit -m "Use literal CI image path" +git push +``` + +--- + +## 12. If the image is private + +Your runner must be able to pull it. + +Log in on the runner host: + +```bash +docker login git.neosisyphus.com +``` + +Use your Gitea username and token. + +If `act_runner` runs as a system service, log in as the same user that runs `act_runner`, or configure Docker credentials for that user. + +Then restart the runner: + +```bash +sudo systemctl restart act_runner +``` + +If your runner itself is Dockerized, make sure Docker credentials are available to the runner setup. + +--- + +## 13. Test the image manually on the runner + +On the runner host: + +```bash +docker pull git.neosisyphus.com/evol3d/evol-testbed:clang22 +``` + +Run it: + +```bash +docker run --rm -it git.neosisyphus.com/evol3d/evol-testbed:clang22 bash +``` + +Inside the container: + +```bash +clang --version +clang++ --version +meson --version +ninja --version +python3 --version +vulkaninfo --summary +``` + +Expected results: + +- `clang` should be version 22. +- `meson` should print a version. +- `ninja` should print a version. +- `vulkaninfo --summary` may fail if the CI machine has no GPU/display/runtime Vulkan driver. That is usually okay for compile-only CI as long as Vulkan headers/tools are installed. + +Exit: + +```bash +exit +``` + +--- + +## 14. Use it in other projects + +Once the image exists, any project can use it: + +```yaml +name: build + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + container: + image: git.neosisyphus.com/evol3d/evol-testbed:clang22 + + steps: + - uses: actions/checkout@v4 + + - run: | + meson setup build + meson compile -C build +``` + +No more installing LLVM/Vulkan/Meson every CI run. + +--- + +## 15. Updating the image later + +Edit: + +```text +ci/Dockerfile +``` + +Then: + +```bash +git add ci/Dockerfile +git commit -m "Update CI image" +git push +``` + +The image workflow will rebuild and push: + +```text +latest +clang22 +``` + +Your normal builds will use the updated image next time they run. + +--- + +## 16. Recommended: version image tags + +Instead of only using: + +```text +clang22 +``` + +consider immutable tags: + +```text +clang22-v1 +clang22-v2 +clang22-2026-05 +``` + +Example build command tag: + +```yaml +-t "${{ vars.REGISTRY_IMAGE }}:clang22-v1" +``` + +Then use: + +```yaml +container: + image: git.neosisyphus.com/evol3d/evol-testbed:clang22-v1 +``` + +This avoids surprise breakage when `clang22` or `latest` changes. + +--- + +## 17. Quick checklist + +```text +1. Commit ci/Dockerfile and workflows. +2. Create Gitea token with package/container write access. +3. Add Actions variables: + - REGISTRY_HOST + - REGISTRY_IMAGE + - CI_IMAGE +4. Add Actions secrets: + - REGISTRY_USERNAME + - REGISTRY_PASSWORD +5. Make sure the runner can run docker build. +6. Run build-ci-image workflow. +7. Confirm image appears in Gitea Packages. +8. Use image in .gitea/workflows/build.yml. +9. Push normal project code. +10. Build should run inside the prebuilt Clang/Vulkan image. +``` + +The most important final workflow line is: + +```yaml +container: + image: git.neosisyphus.com/evol3d/evol-testbed:clang22 +```