refactor: migrate to gitea actions
This commit is contained in:
11 files changed
+480
-7
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
.git
|
||||||
|
.gitea
|
||||||
|
Jenkinsfile
|
||||||
|
README.md
|
||||||
|
**/__pycache__
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
name: Build OpenWrt Rust SDK images
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
targets:
|
||||||
|
description: 'Comma-separated targets, or all'
|
||||||
|
default: 'x86/64,mediatek/filogic,octeon/generic'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
publish:
|
||||||
|
description: 'Publish the original Docker Hub tags (requires approval)'
|
||||||
|
default: false
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
matrix:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
matrix: ${{ steps.resolve.outputs.matrix }}
|
||||||
|
steps:
|
||||||
|
- uses: builtin:checkout
|
||||||
|
- name: Resolve targets and OpenWrt versions
|
||||||
|
id: resolve
|
||||||
|
env:
|
||||||
|
TARGETS: ${{ inputs.targets }}
|
||||||
|
run: python3 ci/matrix.py
|
||||||
|
|
||||||
|
build:
|
||||||
|
needs: matrix
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 360
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
max-parallel: 1
|
||||||
|
matrix: ${{ fromJSON(needs.matrix.outputs.matrix) }}
|
||||||
|
env:
|
||||||
|
SAFE_TARGET: ${{ matrix.target }}
|
||||||
|
VERSION: ${{ matrix.version }}
|
||||||
|
steps:
|
||||||
|
- uses: builtin:checkout
|
||||||
|
- name: Prepare persistent cache and bounded builder
|
||||||
|
run: sh ci/setup-builder.sh
|
||||||
|
- name: Build SDK image
|
||||||
|
run: |
|
||||||
|
docker buildx build --builder openwrt-sdk-rust --load --progress plain \
|
||||||
|
--network host --allow network.host \
|
||||||
|
--no-cache-filter configured,sdk \
|
||||||
|
--build-arg SAFE_TARGET="$SAFE_TARGET" \
|
||||||
|
--build-arg VERSION="$VERSION" \
|
||||||
|
--build-arg JOBS=8 \
|
||||||
|
--build-arg SCCACHE_REDIS_ENDPOINT=redis://127.0.0.1:6379 \
|
||||||
|
--tag "lochnair/openwrt-sdk-rust:${SAFE_TARGET}-${VERSION}" .
|
||||||
|
- name: Verify SDK image
|
||||||
|
run: |
|
||||||
|
docker run --rm "lochnair/openwrt-sdk-rust:${SAFE_TARGET}-${VERSION}" sh -ec '
|
||||||
|
sccache --version
|
||||||
|
grep -qx "CONFIG_RUST_SCCACHE=y" .config
|
||||||
|
rustc=$(find staging_dir -type f -path "*/host/bin/rustc")
|
||||||
|
test -x "$rustc"
|
||||||
|
"$rustc" -vV
|
||||||
|
"$(dirname "$rustc")/cargo" --version
|
||||||
|
'
|
||||||
|
sh ci/verify-cache.sh "lochnair/openwrt-sdk-rust:${SAFE_TARGET}-${VERSION}"
|
||||||
|
- name: Publish Docker Hub tag
|
||||||
|
if: inputs.publish == true
|
||||||
|
env:
|
||||||
|
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
DOCKER_CONFIG=$(mktemp -d)
|
||||||
|
export DOCKER_CONFIG
|
||||||
|
trap 'rm -rf "$DOCKER_CONFIG"' EXIT
|
||||||
|
printf '%s' "$DOCKERHUB_TOKEN" | docker login --username "$DOCKERHUB_USERNAME" --password-stdin
|
||||||
|
docker push "lochnair/openwrt-sdk-rust:${SAFE_TARGET}-${VERSION}"
|
||||||
+28
-6
@@ -1,13 +1,35 @@
|
|||||||
ARG SAFE_TARGET
|
ARG SAFE_TARGET
|
||||||
ARG VERSION
|
ARG VERSION
|
||||||
|
|
||||||
FROM ghcr.io/openwrt/sdk:${SAFE_TARGET}-${VERSION}
|
FROM ghcr.io/openwrt/sdk:${SAFE_TARGET}-${VERSION} AS tooling
|
||||||
|
|
||||||
|
# The SDK runs on amd64 even when compiling for another OpenWrt target.
|
||||||
|
USER root
|
||||||
|
RUN curl -fsSL https://github.com/mozilla/sccache/releases/download/v0.18.0/sccache-v0.18.0-x86_64-unknown-linux-musl.tar.gz -o /tmp/sccache.tar.gz && \
|
||||||
|
echo '45f1447fbe231e3037bde351ef70677dd212216c8d62ae7ca409fecc4d6acc89 /tmp/sccache.tar.gz' | sha256sum -c - && \
|
||||||
|
tar -xzf /tmp/sccache.tar.gz -C /tmp && \
|
||||||
|
install -m 0755 /tmp/sccache-v0.18.0-x86_64-unknown-linux-musl/sccache /usr/local/bin/sccache && \
|
||||||
|
rm -rf /tmp/sccache.tar.gz /tmp/sccache-v0.18.0-x86_64-unknown-linux-musl
|
||||||
|
USER buildbot
|
||||||
|
|
||||||
|
FROM tooling AS configured
|
||||||
|
ARG SAFE_TARGET
|
||||||
|
ARG VERSION
|
||||||
|
ENV SCCACHE_REDIS_KEY_PREFIX=openwrt-rust:${SAFE_TARGET}-${VERSION}: \
|
||||||
|
CARGO_INCREMENTAL=0
|
||||||
|
COPY --chmod=0755 ci/build-rust.sh /usr/local/bin/build-rust
|
||||||
RUN ./scripts/feeds update packages && \
|
RUN ./scripts/feeds update packages && \
|
||||||
./scripts/feeds install rust && \
|
./scripts/feeds install rust && \
|
||||||
|
printf '\nCONFIG_RUST_SCCACHE=y\n' >> .config && \
|
||||||
make defconfig && \
|
make defconfig && \
|
||||||
sed -i 's/--set=llvm.download-ci-llvm=true/--set=llvm.download-ci-llvm=false/g' feeds/packages/lang/rust/Makefile; \
|
grep -qx 'CONFIG_RUST_SCCACHE=y' .config && \
|
||||||
{ make package/rust/host/compile -j$(nproc) || \
|
sed -i 's/--set=llvm.download-ci-llvm=true/--set=llvm.download-ci-llvm=false/g' feeds/packages/lang/rust/Makefile && \
|
||||||
make package/rust/host/compile -j1 V=sc; } && \
|
sed -i '/--set=llvm.download-ci-llvm=false/a\ --set=build.ccache=sccache \\' feeds/packages/lang/rust/Makefile && \
|
||||||
rm -rf build_dir/host/rustc-*/rustc-*/build \
|
sed -i '/^define Host\/Compile/i RUST_BUILD_JOBS ?= 8' feeds/packages/lang/rust/Makefile && \
|
||||||
dl/rustc-*.tar.*
|
sed -i 's/--build-dir /--jobs=$(RUST_BUILD_JOBS) --build-dir /' feeds/packages/lang/rust/Makefile
|
||||||
|
|
||||||
|
FROM configured AS sdk
|
||||||
|
ARG JOBS=8
|
||||||
|
# A non-secret endpoint on the runner; do not persist it in the published image.
|
||||||
|
ARG SCCACHE_REDIS_ENDPOINT
|
||||||
|
RUN build-rust
|
||||||
@@ -1 +1,128 @@
|
|||||||
# openwrt-sdk-rust
|
# openwrt-sdk-rust
|
||||||
|
|
||||||
|
Builds the OpenWrt SDK with its Rust host toolchain installed. Gitea Actions
|
||||||
|
resolves `stable_version` and `oldstable_version` from OpenWrt's `.versions.json`.
|
||||||
|
The default targets remain `x86/64,mediatek/filogic,octeon/generic`; dispatch with
|
||||||
|
`targets=all` to use upstream `dump-target-info.pl`, or supply a comma-separated
|
||||||
|
list. Images still use `ghcr.io/openwrt/sdk:<target-with-dashes>-<version>` and
|
||||||
|
publish to `lochnair/openwrt-sdk-rust:<target-with-dashes>-<version>` on Docker Hub.
|
||||||
|
No `latest` tag or additional registry is introduced.
|
||||||
|
|
||||||
|
## Runner setup and cutover
|
||||||
|
|
||||||
|
The workflow uses `ubuntu-latest` on the existing TheBeast runner, currently
|
||||||
|
the only runner. Its job image and access to the persistent Docker daemon were
|
||||||
|
verified; no additional runner, label, capacity change, or restart is required.
|
||||||
|
`builtin:checkout` uses the existing Runner 5 checkout support.
|
||||||
|
|
||||||
|
Enable repository Actions and set `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN`
|
||||||
|
secrets with push permission to `lochnair/openwrt-sdk-rust`. Jenkins' credential
|
||||||
|
ID is not reusable in Gitea. The workflow is manually dispatched, matching the
|
||||||
|
parameterized Jenkins job; there are no PR, push, or scheduled publication
|
||||||
|
triggers. `publish=false` is the safe validation default. Dispatch
|
||||||
|
`publish=true` only after publication is approved. Login uses a temporary job
|
||||||
|
directory, and each successfully built and checked image is pushed under its
|
||||||
|
original tag. Before any push, `ci/verify-cache.sh` uses the installed SDK rustc
|
||||||
|
in two disposable containers and requires a Redis miss followed by a hit.
|
||||||
|
|
||||||
|
Run a non-publishing dispatch for the default six combinations, then an
|
||||||
|
approved publishing dispatch. Check the pulled image's Rust/Cargo installation
|
||||||
|
and downstream package build before disabling the old Jenkins job and deleting
|
||||||
|
`Jenkinsfile`. Do not retire Jenkins before this acceptance run. No Jenkins
|
||||||
|
plugins or credentials are used by the new workflow.
|
||||||
|
|
||||||
|
## Persistent compilation cache
|
||||||
|
|
||||||
|
`ci/setup-builder.sh` provisions one Redis service and one reusable BuildKit
|
||||||
|
builder on that daemon. Redis uses the named volume `openwrt-rust-sccache`, AOF
|
||||||
|
persistence (`appendfsync everysec`), a 6 GiB LRU cache, an 8 GiB memory limit,
|
||||||
|
and one CPU. Jobs and build containers can disappear without losing it. A
|
||||||
|
machine crash can lose up to the most recent second of cache writes; eviction
|
||||||
|
or lost entries cause recompilation. Do not run `docker compose down -v` or
|
||||||
|
prune this volume. BuildKit's layer cache is separate and may be garbage
|
||||||
|
collected without clearing sccache.
|
||||||
|
|
||||||
|
The cache joins the existing `gitea-runner-jobs` network and exposes port 6379
|
||||||
|
only on loopback. BuildKit uses host networking to reach it; package containers
|
||||||
|
use its Docker DNS name. This is a trusted-runner cache: do not attach untrusted
|
||||||
|
PR containers or public networks to it. No password or endpoint is baked into
|
||||||
|
published SDK images. Consumers outside this runner can use their own Redis
|
||||||
|
endpoint. Each target/OpenWrt version has its own key prefix; sccache also
|
||||||
|
hashes Rust compiler version and shared libraries, compilation arguments
|
||||||
|
(including target and flags), source and dependency contents. Different Rust
|
||||||
|
versions/toolchains therefore miss rather than reuse incompatible objects.
|
||||||
|
|
||||||
|
The shared BuildKit worker executes one build step at a time, even across
|
||||||
|
simultaneous dispatches. It is limited to eight CPUs and 20 GiB RAM with no
|
||||||
|
swap. Make and Rust bootstrap both receive eight jobs; the original `-j1 V=sc`
|
||||||
|
diagnostic retry also reduces bootstrap/Ninja to one job. Rust
|
||||||
|
build-directory/archive cleanup remains. BuildKit
|
||||||
|
layer storage has a 50 GiB GC budget. Matrix jobs also run one at a time and
|
||||||
|
stop scheduling on a failure, as Jenkins' sequential stage loop did.
|
||||||
|
|
||||||
|
OpenWrt integration was inspected in the SDK's pinned packages feed:
|
||||||
|
|
||||||
|
- `rust-values.mk` **unexports `RUSTC_WRAPPER`**. Setting it in the workflow
|
||||||
|
alone does not enable caching. `CONFIG_RUST_SCCACHE=y` makes OpenWrt inject
|
||||||
|
`CARGO_INCREMENTAL=0`, `RUSTC_WRAPPER=sccache`, and `SCCACHE_DIR` into host
|
||||||
|
and package Cargo invocations. The Dockerfile enables and checks that option.
|
||||||
|
- The base SDK has no sccache binary. We install the pinned 0.18.0 amd64-musl
|
||||||
|
release and verify its SHA-256 before using it.
|
||||||
|
- Rust bootstrap wraps rustc itself. We also set `build.ccache=sccache` in
|
||||||
|
its configure arguments so stage-zero compilation and LLVM use sccache,
|
||||||
|
retaining `llvm.download-ci-llvm=false`. The inherited wrapper is forwarded
|
||||||
|
by bootstrap through `RUSTC_WRAPPER_REAL` where applicable.
|
||||||
|
- sccache is a compiler cache, not a Cargo target-directory cache. Linked
|
||||||
|
binaries, proc macros, some bootstrap work and incremental compilation are
|
||||||
|
not cacheable. SDK bootstrap and downstream dependencies can share storage
|
||||||
|
without necessarily sharing every compiled object. Every actual SDK build
|
||||||
|
prints statistics on success or failure; configured/compile layers are
|
||||||
|
rebuilt so stale Docker layer hits do not hide those statistics.
|
||||||
|
|
||||||
|
Sources: [OpenWrt Rust configuration](https://github.com/openwrt/packages/blob/openwrt-24.10/lang/rust/rust-values.mk),
|
||||||
|
[Rust bootstrap](https://github.com/rust-lang/rust/blob/1.90.0/src/bootstrap/src/core/build_steps/compile.rs),
|
||||||
|
[sccache Redis](https://github.com/mozilla/sccache/blob/v0.18.0/docs/Redis.md),
|
||||||
|
[Rust cache limitations](https://github.com/mozilla/sccache/blob/v0.18.0/docs/Rust.md).
|
||||||
|
|
||||||
|
## Downstream OpenWrt packages
|
||||||
|
|
||||||
|
Use the same persistent daemon and target/version image. For example, after
|
||||||
|
installing the `sqm-autorate-rust` feed/package in the SDK:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker run --rm --network gitea-runner-jobs --cpus 8 \
|
||||||
|
--memory 20g --memory-swap 20g \
|
||||||
|
-e SCCACHE_REDIS_ENDPOINT=redis://openwrt-rust-cache:6379 \
|
||||||
|
lochnair/openwrt-sdk-rust:x86-64-24.10.8 sh -ec '
|
||||||
|
# Install/update the downstream feed here before defconfig.
|
||||||
|
make defconfig
|
||||||
|
grep -qx "CONFIG_RUST_SCCACHE=y" .config
|
||||||
|
sccache --start-server
|
||||||
|
trap "sccache --show-stats; sccache --stop-server" EXIT
|
||||||
|
sccache --zero-stats
|
||||||
|
make package/sqm-autorate-rust/compile -j8 V=sc
|
||||||
|
'
|
||||||
|
```
|
||||||
|
|
||||||
|
Keep the image's cache prefix and enable `CONFIG_RUST_SCCACHE` after any
|
||||||
|
downstream configuration replacement. Cache statistics belong to the current
|
||||||
|
container's sccache server; `--zero-stats` does not erase cached objects.
|
||||||
|
`sqm-autorate-rust` currently uses cross-rs to publish static binaries, not an
|
||||||
|
OpenWrt SDK package workflow; that unrelated pipeline is unchanged. The package
|
||||||
|
Makefile in `openwrt-feeds` already uses OpenWrt's `rust-package.mk`, so an SDK
|
||||||
|
package job can use this cache without patching the package.
|
||||||
|
|
||||||
|
For a local SDK build on the prepared runner:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sh ci/setup-builder.sh
|
||||||
|
docker buildx build --builder openwrt-sdk-rust --load --progress plain \
|
||||||
|
--network host --allow network.host --no-cache-filter configured,sdk \
|
||||||
|
--build-arg SAFE_TARGET=x86-64 --build-arg VERSION=24.10.8 \
|
||||||
|
--build-arg JOBS=8 \
|
||||||
|
--build-arg SCCACHE_REDIS_ENDPOINT=redis://127.0.0.1:6379 \
|
||||||
|
-t lochnair/openwrt-sdk-rust:x86-64-24.10.8 .
|
||||||
|
```
|
||||||
|
|
||||||
|
See [validation results](ci/VALIDATION.md) for the checks performed and the
|
||||||
|
remaining cutover acceptance.
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# Migration validation — 2026-10-10
|
||||||
|
|
||||||
|
Inspected the original Jenkinsfile, Dockerfile, downstream `sqm-autorate-rust`
|
||||||
|
workflows and package Makefile, Terraform runner definition, and live TheBeast
|
||||||
|
runner configuration before changing the repository.
|
||||||
|
|
||||||
|
## Passed
|
||||||
|
|
||||||
|
- YAML parsing; TOML parsing; `sh -n`; ShellCheck; `git diff --check`.
|
||||||
|
- actionlint 1.7.12, excluding only its unsupported `builtin:checkout` action
|
||||||
|
syntax. The workflow uses the existing `ubuntu-latest` label. Gitea's documentation and the
|
||||||
|
existing downstream workflow confirm built-in checkout support.
|
||||||
|
- Default matrix resolves six entries for stable 25.12.5 and oldstable 24.10.8.
|
||||||
|
`targets=all` ran upstream target discovery inside the actual job image and
|
||||||
|
resolved 194 entries. Empty/invalid targets fail. Every default base-image
|
||||||
|
tag was read successfully from GHCR.
|
||||||
|
- Docker Compose configuration accepted; Redis healthy with its named volume,
|
||||||
|
AOF enabled and successful AOF writes. Service and bounded builder were
|
||||||
|
provisioned on TheBeast without changing the runner configuration.
|
||||||
|
- Builder inspected: eight-CPU quota, 20 GiB memory/swap limit, one BuildKit
|
||||||
|
worker step, 50 GiB layer GC budget. A second disposable job container with
|
||||||
|
fresh Docker client configuration reused the existing daemon and builder.
|
||||||
|
- Dockerfile build checks completed. Two expected advisory warnings: mandatory
|
||||||
|
base-image arguments have no defaults, and Docker's secret-name heuristic
|
||||||
|
mistakes the public `SCCACHE_REDIS_KEY_PREFIX` for a secret.
|
||||||
|
- `configured` Dockerfile stage built for x86/64 on both OpenWrt releases.
|
||||||
|
Pinned feeds select Rust 1.94.0 on 25.12.5 and 1.90.0 on 24.10.8. Both retain
|
||||||
|
`CONFIG_RUST_SCCACHE=y` through defconfig and contain the explicit bootstrap
|
||||||
|
`build.ccache=sccache` setting with LLVM CI downloads disabled.
|
||||||
|
- Actual OpenWrt make-variable expansion injects sccache into host and package
|
||||||
|
compilation, despite unexporting an inherited wrapper.
|
||||||
|
- Real Cargo library compilation in Docker BuildKit: one Redis miss. A fresh
|
||||||
|
runtime container using the Docker-network endpoint: one hit, zero misses.
|
||||||
|
- Recreated the newly provisioned Redis container using the same named volume;
|
||||||
|
a fresh compiler container still recorded one hit, zero misses. No existing
|
||||||
|
infrastructure containers were restarted.
|
||||||
|
- Same source/cache namespace with GNU versus musl target: first musl build
|
||||||
|
missed; repetition hit. Rust 1.90.0 versus 1.91.0: first 1.91 build missed;
|
||||||
|
repetition hit. All probes reported zero cache read/write errors.
|
||||||
|
- A disposable OpenWrt package used the real `Build/Compile/Cargo` helper,
|
||||||
|
SDK GCC/musl linker, OpenWrt LTO/optimization flags and a local Rust library
|
||||||
|
dependency. It built successfully in two separate containers: one dependency
|
||||||
|
miss, then one hit. The linked executable correctly remained non-cacheable.
|
||||||
|
This used a prebuilt Rust 1.90 toolchain for the probe, not a freshly compiled
|
||||||
|
SDK toolchain; it is not a full SDK/source-bootstrap acceptance result.
|
||||||
|
- Retained `ci/verify-cache.sh` passed its separate-container miss/hit checks
|
||||||
|
against that prebuilt validation toolchain. Its original hardcoded SDK rustc
|
||||||
|
path was later corrected after the live mediatek/filogic build exposed the
|
||||||
|
target-specific staging layout; see the follow-up below.
|
||||||
|
- Publication configuration checked: original Docker Hub namespace/tag format,
|
||||||
|
verification before push, explicit publish input, temporary credential
|
||||||
|
directory, no automatic publication trigger. No registry login or push was
|
||||||
|
attempted.
|
||||||
|
|
||||||
|
## Remaining acceptance
|
||||||
|
|
||||||
|
1. Enable repository Actions and configure the two Docker Hub secrets. No
|
||||||
|
runner configuration changes are required.
|
||||||
|
2. Complete a non-publishing Gitea dispatch for the full default matrix.
|
||||||
|
The mediatek/filogic 24.10.8 job completed Rust source bootstrap and image
|
||||||
|
export; its corrected verification passed on the built image. Acceptance
|
||||||
|
for the other combinations remains pending.
|
||||||
|
3. With explicit publication approval, run the publishing dispatch, pull the
|
||||||
|
resulting tags and build the downstream OpenWrt package with the new image.
|
||||||
|
Actual Docker Hub authorization and publication remain unverified.
|
||||||
|
4. After acceptance, disable the old Jenkins job and remove `Jenkinsfile`.
|
||||||
|
It is deliberately retained until the replacement passes these checks.
|
||||||
|
|
||||||
|
Remote test logs and disposable probe sources are under
|
||||||
|
`/tmp/openwrt-sdk-rust-migration` in TheBeast's `gitea-runner` instance. The
|
||||||
|
Redis volume/service and BuildKit builder remain available for the replacement
|
||||||
|
pipeline; no cache volume or existing infrastructure was deleted.
|
||||||
|
|
||||||
|
## Follow-up: mediatek/filogic 24.10.8 verification
|
||||||
|
|
||||||
|
The supplied job 1602 log shows full SDK compilation and image export completed
|
||||||
|
successfully. Verification failed with exit 127 because it assumed
|
||||||
|
`staging_dir/host/bin/rustc`. Inspection of that exact built image reproduced
|
||||||
|
the failure and located Rust/Cargo in
|
||||||
|
`staging_dir/target-aarch64_cortex-a53_musl/host/bin` instead. Both the workflow
|
||||||
|
and retained cache probe now resolve the unique executable compiler from the
|
||||||
|
SDK staging tree, rather than assuming a shared host directory.
|
||||||
|
|
||||||
|
Reran the corrected verification on that image: Rust 1.90.0 and Cargo 1.90.0
|
||||||
|
execute successfully. The retained cache probe reports one Redis miss in its
|
||||||
|
first container and one hit in a fresh second container, with zero cache
|
||||||
|
read/write errors. ShellCheck, actionlint (excluding only Gitea's built-in
|
||||||
|
checkout syntax), and `git diff --check` pass. No rebuild or publication was
|
||||||
|
performed for this fix.
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
: "${SCCACHE_REDIS_ENDPOINT:?Set the persistent sccache Redis endpoint}"
|
||||||
|
: "${JOBS:=8}"
|
||||||
|
case "$JOBS" in ''|*[!0-9]*|0) echo 'JOBS must be a positive integer' >&2; exit 1 ;; esac
|
||||||
|
|
||||||
|
sccache --start-server
|
||||||
|
trap 'sccache --show-stats; sccache --stop-server' EXIT
|
||||||
|
sccache --zero-stats
|
||||||
|
# Bootstrap/Ninja does not inherit Make's job count. Bound both explicitly.
|
||||||
|
make package/rust/host/compile -j"$JOBS" RUST_BUILD_JOBS="$JOBS" || \
|
||||||
|
make package/rust/host/compile -j1 RUST_BUILD_JOBS=1 V=sc
|
||||||
|
rm -rf build_dir/host/rustc-*/rustc-*/build dl/rustc-*.tar.*
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Shared by all SDK jobs on this daemon, including simultaneous dispatches.
|
||||||
|
[worker.oci]
|
||||||
|
max-parallelism = 1
|
||||||
|
gc = true
|
||||||
|
reservedSpace = "10GB"
|
||||||
|
maxUsedSpace = "50GB"
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
services:
|
||||||
|
cache:
|
||||||
|
image: redis:7.4.6-alpine
|
||||||
|
container_name: openwrt-rust-cache
|
||||||
|
restart: unless-stopped
|
||||||
|
command:
|
||||||
|
- redis-server
|
||||||
|
- --appendonly
|
||||||
|
- 'yes'
|
||||||
|
- --appendfsync
|
||||||
|
- everysec
|
||||||
|
- --maxmemory
|
||||||
|
- 6gb
|
||||||
|
- --maxmemory-policy
|
||||||
|
- allkeys-lru
|
||||||
|
- --save
|
||||||
|
- ''
|
||||||
|
mem_limit: 8g
|
||||||
|
memswap_limit: 8g
|
||||||
|
cpus: 1
|
||||||
|
ports:
|
||||||
|
- '127.0.0.1:6379:6379'
|
||||||
|
volumes:
|
||||||
|
- cache:/data
|
||||||
|
networks:
|
||||||
|
- jobs
|
||||||
|
healthcheck:
|
||||||
|
test: ['CMD', 'redis-cli', 'ping']
|
||||||
|
interval: 5s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 12
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
cache:
|
||||||
|
name: openwrt-rust-sccache
|
||||||
|
|
||||||
|
networks:
|
||||||
|
jobs:
|
||||||
|
external: true
|
||||||
|
name: gitea-runner-jobs
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Resolve the same stable/oldstable x target matrix as Jenkins."""
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
|
||||||
|
def resolve(versions, targets):
|
||||||
|
versions = [versions[k] for k in ("stable_version", "oldstable_version") if versions.get(k)]
|
||||||
|
if not versions:
|
||||||
|
raise ValueError("OpenWrt returned no stable or oldstable version")
|
||||||
|
targets = [t.strip() for t in targets.split(",") if t.strip()]
|
||||||
|
if not targets:
|
||||||
|
raise ValueError("No targets selected")
|
||||||
|
for target in targets:
|
||||||
|
if not re.fullmatch(r"[a-z0-9_+-]+/[a-z0-9_+-]+", target):
|
||||||
|
raise ValueError(f"Invalid target: {target!r}")
|
||||||
|
for version in versions:
|
||||||
|
if not re.fullmatch(r"[a-zA-Z0-9_.-]+", version):
|
||||||
|
raise ValueError(f"Invalid version: {version!r}")
|
||||||
|
return {"include": [{"target": t.replace("/", "-"), "version": v}
|
||||||
|
for v in versions for t in dict.fromkeys(targets)]}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
with urllib.request.urlopen("https://downloads.openwrt.org/.versions.json", timeout=60) as response:
|
||||||
|
versions = json.load(response)
|
||||||
|
targets = os.environ.get("TARGETS", "x86/64,mediatek/filogic,octeon/generic")
|
||||||
|
if targets.strip() == "all":
|
||||||
|
with tempfile.TemporaryDirectory(prefix="openwrt-targets-") as source:
|
||||||
|
subprocess.run(["git", "clone", "--depth", "1", "https://github.com/openwrt/openwrt.git", source], check=True)
|
||||||
|
output = subprocess.check_output(["perl", "scripts/dump-target-info.pl", "targets"], cwd=source, text=True)
|
||||||
|
targets = ",".join(line.split()[0] for line in output.splitlines() if line.strip())
|
||||||
|
matrix = json.dumps(resolve(versions, targets), separators=(",", ":"))
|
||||||
|
print(matrix)
|
||||||
|
with open(os.environ["GITHUB_OUTPUT"], "a") as output:
|
||||||
|
output.write(f"matrix={matrix}\n")
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
docker compose -p openwrt-rust -f ci/cache.compose.yml up -d --wait
|
||||||
|
if ! docker buildx inspect openwrt-sdk-rust >/dev/null 2>&1; then
|
||||||
|
docker buildx create --name openwrt-sdk-rust --driver docker-container \
|
||||||
|
--driver-opt network=host,memory=20g,memory-swap=20g,cpu-period=100000,cpu-quota=800000 \
|
||||||
|
--buildkitd-config ci/buildkitd.toml \
|
||||||
|
--buildkitd-flags '--allow-insecure-entitlement network.host' || \
|
||||||
|
docker buildx inspect openwrt-sdk-rust
|
||||||
|
fi
|
||||||
|
docker buildx inspect openwrt-sdk-rust --bootstrap
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Compile in two disposable containers: the second must read the first's cache.
|
||||||
|
set -eu
|
||||||
|
image=${1:?Usage: verify-cache.sh IMAGE}
|
||||||
|
nonce=$(mktemp -d)
|
||||||
|
trap 'rmdir "$nonce"' EXIT
|
||||||
|
prefix="validation:${image##*:}:$(basename "$nonce"):"
|
||||||
|
for expected in miss hit; do
|
||||||
|
docker run --rm -i --network gitea-runner-jobs --cpus 2 \
|
||||||
|
--memory 2g --memory-swap 2g \
|
||||||
|
-e SCCACHE_REDIS_ENDPOINT=redis://openwrt-rust-cache:6379 \
|
||||||
|
-e SCCACHE_REDIS_KEY_PREFIX="$prefix" -e EXPECTED="$expected" \
|
||||||
|
"$image" sh -es <<'PROBE'
|
||||||
|
rustc=$(find /builder/staging_dir -type f -path '*/host/bin/rustc')
|
||||||
|
test -x "$rustc"
|
||||||
|
mkdir /tmp/sccache-probe
|
||||||
|
cd /tmp/sccache-probe
|
||||||
|
printf 'pub fn probe(n: u64) -> u64 { n.wrapping_mul(17) }\n' > probe.rs
|
||||||
|
sccache --start-server
|
||||||
|
trap 'sccache --stop-server' EXIT
|
||||||
|
sccache --zero-stats
|
||||||
|
sccache "$rustc" --crate-name ci_sccache_probe \
|
||||||
|
--crate-type rlib --emit link,dep-info --out-dir . probe.rs
|
||||||
|
sccache --show-stats
|
||||||
|
sccache --show-stats --stats-format json > stats.json
|
||||||
|
python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
data = json.load(open("stats.json"))
|
||||||
|
assert data["cache_location"].startswith("redis,"), data
|
||||||
|
stats = data["stats"]
|
||||||
|
field = "cache_hits" if os.environ["EXPECTED"] == "hit" else "cache_misses"
|
||||||
|
assert sum(stats[field]["counts"].values()) == 1, data
|
||||||
|
assert stats["cache_read_errors"] == stats["cache_write_errors"] == 0, data
|
||||||
|
print("Verified persistent cache", os.environ["EXPECTED"])
|
||||||
|
PY
|
||||||
|
PROBE
|
||||||
|
done
|
||||||
Reference in new issue
Block a user