Merge pull request 'feat(ci): add persistent pre-baked Docker builder images' (#21) from feat/persistent-ci-builders into master
Reviewed-on: #21
This commit is contained in:
commit
bff11dc847
24
.docker/Dockerfile.linux-amd64
Normal file
24
.docker/Dockerfile.linux-amd64
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Pre-baked builder for Linux amd64 Tauri releases.
|
||||||
|
# All system dependencies are installed once here; CI jobs skip apt-get entirely.
|
||||||
|
# Rebuild when: Rust toolchain version changes, webkit2gtk/gtk major version changes,
|
||||||
|
# or Node.js major version changes. Tag format: rust<VER>-node<VER>
|
||||||
|
FROM rust:1.88-slim
|
||||||
|
|
||||||
|
RUN apt-get update -qq \
|
||||||
|
&& apt-get install -y -qq --no-install-recommends \
|
||||||
|
libwebkit2gtk-4.1-dev \
|
||||||
|
libssl-dev \
|
||||||
|
libgtk-3-dev \
|
||||||
|
libayatana-appindicator3-dev \
|
||||||
|
librsvg2-dev \
|
||||||
|
patchelf \
|
||||||
|
pkg-config \
|
||||||
|
curl \
|
||||||
|
perl \
|
||||||
|
jq \
|
||||||
|
git \
|
||||||
|
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
||||||
|
&& apt-get install -y --no-install-recommends nodejs \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN rustup target add x86_64-unknown-linux-gnu
|
||||||
45
.docker/Dockerfile.linux-arm64
Normal file
45
.docker/Dockerfile.linux-arm64
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Pre-baked cross-compiler for Linux arm64 Tauri releases (runs on Linux amd64).
|
||||||
|
# Bakes in: amd64 cross-toolchain, arm64 multiarch dev libs, Node.js, and Rust.
|
||||||
|
# This image takes ~15 min to build but is only rebuilt when deps change.
|
||||||
|
# Rebuild when: Rust toolchain version, webkit2gtk/gtk major version, or Node.js changes.
|
||||||
|
# Tag format: rust<VER>-node<VER>
|
||||||
|
FROM ubuntu:22.04
|
||||||
|
|
||||||
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# Step 1: amd64 host tools and cross-compiler
|
||||||
|
RUN apt-get update -qq \
|
||||||
|
&& apt-get install -y -qq --no-install-recommends \
|
||||||
|
curl git gcc g++ make patchelf pkg-config perl jq \
|
||||||
|
gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Step 2: Enable arm64 multiarch. Ubuntu uses ports.ubuntu.com for arm64 to avoid
|
||||||
|
# binary-all index conflicts with the amd64 archive.ubuntu.com mirror.
|
||||||
|
RUN dpkg --add-architecture arm64 \
|
||||||
|
&& sed -i 's|^deb http://archive.ubuntu.com|deb [arch=amd64] http://archive.ubuntu.com|g' /etc/apt/sources.list \
|
||||||
|
&& sed -i 's|^deb http://security.ubuntu.com|deb [arch=amd64] http://security.ubuntu.com|g' /etc/apt/sources.list \
|
||||||
|
&& printf '%s\n' \
|
||||||
|
'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiverse' \
|
||||||
|
'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiverse' \
|
||||||
|
'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted universe multiverse' \
|
||||||
|
> /etc/apt/sources.list.d/arm64-ports.list \
|
||||||
|
&& apt-get update -qq \
|
||||||
|
&& apt-get install -y -qq --no-install-recommends \
|
||||||
|
libwebkit2gtk-4.1-dev:arm64 \
|
||||||
|
libssl-dev:arm64 \
|
||||||
|
libgtk-3-dev:arm64 \
|
||||||
|
librsvg2-dev:arm64 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Step 3: Node.js 22
|
||||||
|
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
||||||
|
&& apt-get install -y --no-install-recommends nodejs \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Step 4: Rust 1.88 with arm64 cross-compilation target
|
||||||
|
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \
|
||||||
|
--default-toolchain 1.88.0 --profile minimal --no-modify-path \
|
||||||
|
&& /root/.cargo/bin/rustup target add aarch64-unknown-linux-gnu
|
||||||
|
|
||||||
|
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||||
20
.docker/Dockerfile.windows-cross
Normal file
20
.docker/Dockerfile.windows-cross
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Pre-baked cross-compiler for Windows amd64 Tauri releases (runs on Linux amd64).
|
||||||
|
# All MinGW and Node.js dependencies are installed once here; CI jobs skip apt-get entirely.
|
||||||
|
# Rebuild when: Rust toolchain version changes or Node.js major version changes.
|
||||||
|
# Tag format: rust<VER>-node<VER>
|
||||||
|
FROM rust:1.88-slim
|
||||||
|
|
||||||
|
RUN apt-get update -qq \
|
||||||
|
&& apt-get install -y -qq --no-install-recommends \
|
||||||
|
mingw-w64 \
|
||||||
|
curl \
|
||||||
|
nsis \
|
||||||
|
perl \
|
||||||
|
make \
|
||||||
|
jq \
|
||||||
|
git \
|
||||||
|
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
||||||
|
&& apt-get install -y --no-install-recommends nodejs \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN rustup target add x86_64-pc-windows-gnu
|
||||||
107
.gitea/workflows/build-images.yml
Normal file
107
.gitea/workflows/build-images.yml
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
name: Build CI Docker Images
|
||||||
|
|
||||||
|
# Rebuilds the pre-baked builder images and pushes them to the local Gitea
|
||||||
|
# container registry (172.0.0.29:3000).
|
||||||
|
#
|
||||||
|
# WHEN TO RUN:
|
||||||
|
# - Automatically: whenever a Dockerfile under .docker/ changes on master.
|
||||||
|
# - Manually: via workflow_dispatch (e.g. first-time setup, forced rebuild).
|
||||||
|
#
|
||||||
|
# ONE-TIME SERVER PREREQUISITE (run once on 172.0.0.29 before first use):
|
||||||
|
# echo '{"insecure-registries":["172.0.0.29:3000"]}' \
|
||||||
|
# | sudo tee /etc/docker/daemon.json
|
||||||
|
# sudo systemctl restart docker
|
||||||
|
#
|
||||||
|
# Images produced:
|
||||||
|
# 172.0.0.29:3000/sarman/trcaa-linux-amd64:rust1.88-node22
|
||||||
|
# 172.0.0.29:3000/sarman/trcaa-windows-cross:rust1.88-node22
|
||||||
|
# 172.0.0.29:3000/sarman/trcaa-linux-arm64:rust1.88-node22
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths:
|
||||||
|
- '.docker/**'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: build-ci-images
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: 172.0.0.29:3000
|
||||||
|
REGISTRY_USER: sarman
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linux-amd64:
|
||||||
|
runs-on: linux-amd64
|
||||||
|
container:
|
||||||
|
image: docker:24-cli
|
||||||
|
options: -v /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
run: |
|
||||||
|
apk add --no-cache git
|
||||||
|
git init
|
||||||
|
git remote add origin http://172.0.0.29:3000/sarman/tftsr-devops_investigation.git
|
||||||
|
git fetch --depth=1 origin "$GITHUB_SHA"
|
||||||
|
git checkout FETCH_HEAD
|
||||||
|
- name: Build and push linux-amd64 builder
|
||||||
|
env:
|
||||||
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
run: |
|
||||||
|
echo "$RELEASE_TOKEN" | docker login $REGISTRY -u $REGISTRY_USER --password-stdin
|
||||||
|
docker build \
|
||||||
|
-t $REGISTRY/$REGISTRY_USER/trcaa-linux-amd64:rust1.88-node22 \
|
||||||
|
-f .docker/Dockerfile.linux-amd64 .
|
||||||
|
docker push $REGISTRY/$REGISTRY_USER/trcaa-linux-amd64:rust1.88-node22
|
||||||
|
echo "✓ Pushed $REGISTRY/$REGISTRY_USER/trcaa-linux-amd64:rust1.88-node22"
|
||||||
|
|
||||||
|
windows-cross:
|
||||||
|
runs-on: linux-amd64
|
||||||
|
container:
|
||||||
|
image: docker:24-cli
|
||||||
|
options: -v /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
run: |
|
||||||
|
apk add --no-cache git
|
||||||
|
git init
|
||||||
|
git remote add origin http://172.0.0.29:3000/sarman/tftsr-devops_investigation.git
|
||||||
|
git fetch --depth=1 origin "$GITHUB_SHA"
|
||||||
|
git checkout FETCH_HEAD
|
||||||
|
- name: Build and push windows-cross builder
|
||||||
|
env:
|
||||||
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
run: |
|
||||||
|
echo "$RELEASE_TOKEN" | docker login $REGISTRY -u $REGISTRY_USER --password-stdin
|
||||||
|
docker build \
|
||||||
|
-t $REGISTRY/$REGISTRY_USER/trcaa-windows-cross:rust1.88-node22 \
|
||||||
|
-f .docker/Dockerfile.windows-cross .
|
||||||
|
docker push $REGISTRY/$REGISTRY_USER/trcaa-windows-cross:rust1.88-node22
|
||||||
|
echo "✓ Pushed $REGISTRY/$REGISTRY_USER/trcaa-windows-cross:rust1.88-node22"
|
||||||
|
|
||||||
|
linux-arm64:
|
||||||
|
runs-on: linux-amd64
|
||||||
|
container:
|
||||||
|
image: docker:24-cli
|
||||||
|
options: -v /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
run: |
|
||||||
|
apk add --no-cache git
|
||||||
|
git init
|
||||||
|
git remote add origin http://172.0.0.29:3000/sarman/tftsr-devops_investigation.git
|
||||||
|
git fetch --depth=1 origin "$GITHUB_SHA"
|
||||||
|
git checkout FETCH_HEAD
|
||||||
|
- name: Build and push linux-arm64 builder
|
||||||
|
env:
|
||||||
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
run: |
|
||||||
|
echo "$RELEASE_TOKEN" | docker login $REGISTRY -u $REGISTRY_USER --password-stdin
|
||||||
|
docker build \
|
||||||
|
-t $REGISTRY/$REGISTRY_USER/trcaa-linux-arm64:rust1.88-node22 \
|
||||||
|
-f .docker/Dockerfile.linux-arm64 .
|
||||||
|
docker push $REGISTRY/$REGISTRY_USER/trcaa-linux-arm64:rust1.88-node22
|
||||||
|
echo "✓ Pushed $REGISTRY/$REGISTRY_USER/trcaa-linux-arm64:rust1.88-node22"
|
||||||
142
tests/unit/ciDockerBuilders.test.ts
Normal file
142
tests/unit/ciDockerBuilders.test.ts
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
const root = process.cwd();
|
||||||
|
|
||||||
|
const readFile = (rel: string) => readFileSync(path.resolve(root, rel), "utf-8");
|
||||||
|
|
||||||
|
// ─── Dockerfiles ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("Dockerfile.linux-amd64", () => {
|
||||||
|
const df = readFile(".docker/Dockerfile.linux-amd64");
|
||||||
|
|
||||||
|
it("is based on the pinned Rust 1.88 slim image", () => {
|
||||||
|
expect(df).toContain("FROM rust:1.88-slim");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs webkit2gtk 4.1 dev package", () => {
|
||||||
|
expect(df).toContain("libwebkit2gtk-4.1-dev");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs Node.js 22 via NodeSource", () => {
|
||||||
|
expect(df).toContain("nodesource.com/setup_22.x");
|
||||||
|
expect(df).toContain("nodejs");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("pre-adds the x86_64 Linux Rust target", () => {
|
||||||
|
expect(df).toContain("rustup target add x86_64-unknown-linux-gnu");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("cleans apt lists to keep image lean", () => {
|
||||||
|
expect(df).toContain("rm -rf /var/lib/apt/lists/*");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Dockerfile.windows-cross", () => {
|
||||||
|
const df = readFile(".docker/Dockerfile.windows-cross");
|
||||||
|
|
||||||
|
it("is based on the pinned Rust 1.88 slim image", () => {
|
||||||
|
expect(df).toContain("FROM rust:1.88-slim");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs mingw-w64 cross-compiler", () => {
|
||||||
|
expect(df).toContain("mingw-w64");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs nsis for Windows installer bundling", () => {
|
||||||
|
expect(df).toContain("nsis");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs Node.js 22 via NodeSource", () => {
|
||||||
|
expect(df).toContain("nodesource.com/setup_22.x");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("pre-adds the Windows GNU Rust target", () => {
|
||||||
|
expect(df).toContain("rustup target add x86_64-pc-windows-gnu");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("cleans apt lists to keep image lean", () => {
|
||||||
|
expect(df).toContain("rm -rf /var/lib/apt/lists/*");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Dockerfile.linux-arm64", () => {
|
||||||
|
const df = readFile(".docker/Dockerfile.linux-arm64");
|
||||||
|
|
||||||
|
it("is based on Ubuntu 22.04 (Jammy)", () => {
|
||||||
|
expect(df).toContain("FROM ubuntu:22.04");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs aarch64 cross-compiler", () => {
|
||||||
|
expect(df).toContain("gcc-aarch64-linux-gnu");
|
||||||
|
expect(df).toContain("g++-aarch64-linux-gnu");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sets up arm64 multiarch via ports.ubuntu.com", () => {
|
||||||
|
expect(df).toContain("dpkg --add-architecture arm64");
|
||||||
|
expect(df).toContain("ports.ubuntu.com/ubuntu-ports");
|
||||||
|
expect(df).toContain("jammy");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs arm64 webkit2gtk dev package", () => {
|
||||||
|
expect(df).toContain("libwebkit2gtk-4.1-dev:arm64");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs Rust 1.88 with arm64 cross-compilation target", () => {
|
||||||
|
expect(df).toContain("--default-toolchain 1.88.0");
|
||||||
|
expect(df).toContain("rustup target add aarch64-unknown-linux-gnu");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds cargo to PATH via ENV", () => {
|
||||||
|
expect(df).toContain('ENV PATH="/root/.cargo/bin:${PATH}"');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("installs Node.js 22 via NodeSource", () => {
|
||||||
|
expect(df).toContain("nodesource.com/setup_22.x");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── build-images.yml workflow ───────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe("build-images.yml workflow", () => {
|
||||||
|
const wf = readFile(".gitea/workflows/build-images.yml");
|
||||||
|
|
||||||
|
it("triggers on changes to .docker/ files on master", () => {
|
||||||
|
expect(wf).toContain("- master");
|
||||||
|
expect(wf).toContain("- '.docker/**'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("supports manual workflow_dispatch trigger", () => {
|
||||||
|
expect(wf).toContain("workflow_dispatch:");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("mounts the host Docker socket for image builds", () => {
|
||||||
|
expect(wf).toContain("-v /var/run/docker.sock:/var/run/docker.sock");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("authenticates to the local Gitea registry before pushing", () => {
|
||||||
|
expect(wf).toContain("docker login");
|
||||||
|
expect(wf).toContain("--password-stdin");
|
||||||
|
expect(wf).toContain("172.0.0.29:3000");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("builds and pushes all three platform images", () => {
|
||||||
|
expect(wf).toContain("trcaa-linux-amd64:rust1.88-node22");
|
||||||
|
expect(wf).toContain("trcaa-windows-cross:rust1.88-node22");
|
||||||
|
expect(wf).toContain("trcaa-linux-arm64:rust1.88-node22");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses docker:24-cli image for build jobs", () => {
|
||||||
|
expect(wf).toContain("docker:24-cli");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("runs all three build jobs on linux-amd64 runner", () => {
|
||||||
|
const matches = wf.match(/runs-on: linux-amd64/g) ?? [];
|
||||||
|
expect(matches.length).toBeGreaterThanOrEqual(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses RELEASE_TOKEN secret for registry auth", () => {
|
||||||
|
expect(wf).toContain("secrets.RELEASE_TOKEN");
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user