diff --git a/.gitea/workflows/linux.yml b/.gitea/workflows/linux.yml new file mode 100644 index 0000000..49d35b0 --- /dev/null +++ b/.gitea/workflows/linux.yml @@ -0,0 +1,40 @@ +name: Sized Linux checks + +on: + push: + branches: [main, sizequeen-scan-hardening] + paths: ['Cargo.toml', 'Cargo.lock', 'src/**', 'tests/**', 'benches/**', 'scripts/**', '.gitea/workflows/**'] + pull_request: + branches: [main] + paths: ['Cargo.toml', 'Cargo.lock', 'src/**', 'tests/**', 'benches/**', 'scripts/**', '.gitea/workflows/**'] + workflow_dispatch: + +permissions: + contents: read + +jobs: + linux-amd64: + name: Linux AMD64 / Rust 1.88.0 + # Keep the existing shared runner limited to owner-triggered, same-repo code. + if: ${{ gitea.actor == 'gamertan' && (gitea.event_name != 'pull_request' || gitea.event.pull_request.head.repo.full_name == gitea.repository) }} + runs-on: himesan-node24 + timeout-minutes: 20 + container: + image: sha256:514512270649a85769c2b8ecfcc3a860d3a7da67c29b9b7b1cfe4c75de41d322 + options: >- + --user 65532:65532 + --tmpfs /tmp/sized-mount-test:rw,nosuid,nodev,noexec,size=16m,uid=65532,gid=65532,mode=0700 + --tmpfs /tmp/sized-mount-test/foreign:rw,nosuid,nodev,noexec,size=16m,uid=65532,gid=65532,mode=0700 + env: + CARGO_HOME: /tmp/sized-cargo + CARGO_BUILD_JOBS: '2' + SIZED_TEST_SOURCE: ${{ gitea.workspace }} + SIZED_TEST_MOUNT_ROOT: /tmp/sized-mount-test + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + persist-credentials: false + - name: Unprivileged Linux tests, real mount boundary, Clippy and release smoke + run: ./scripts/check-linux-container.sh + - name: Require an unchanged checkout + run: test -z "$(git status --porcelain=v1 --untracked-files=all)" diff --git a/README.md b/README.md index cedfbfc..fd00c94 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,13 @@ removed on exit. Docker retains the reusable check images/build cache. can select a different toolchain image for an explicit compatibility check. These are backend checks; desktop X11/Wayland acceptance belongs to SizeQueen. +Gitea's `Sized Linux checks` workflow runs the same checks natively on cliff-mads +for main/review-branch source changes and owner-triggered, same-repository PRs. +It uses a pinned Rust job image, UID 65532 and real tmpfs boundaries without +Docker access inside the job. Fork contributions can run the local script; +maintainers can bring reviewed changes onto a repository branch for CI. +See SHIPMENT for runner-image setup. Documentation-only pushes skip builds. + See [source review and release process](SHIPMENT.md) and the [live queue](TODO.md). ## License diff --git a/SHIPMENT.md b/SHIPMENT.md index fdd2646..450d073 100644 --- a/SHIPMENT.md +++ b/SHIPMENT.md @@ -23,9 +23,30 @@ in a separate PR so reviewers can distinguish behaviour changes from packaging. use the release steps below when explicitly authorized. Reconcile legacy GitLab download/package links before announcing a Gitea release. -Use the same Linux check script in Gitea CI when a Docker-capable runner is -configured. The current branch provides the local entry point; it does not -configure a runner or enable automatic publishing. +### Gitea Linux CI + +`.gitea/workflows/linux.yml` uses the existing `himesan-node24` label on +cliff-mads, overriding the job image with the pinned Sized Rust runtime. +The runner itself launches the two tmpfs mounts. Jobs have no Docker socket +and run `scripts/check-linux-container.sh` as UID 65532, using the checked-out +workspace as `SIZED_TEST_SOURCE`. Its tests, strict Clippy, formatting and +optimized-binary smoke test are the same as the local Docker workflow. + +The runtime contains Rust 1.88.0, rustfmt/Clippy and Node for the pinned checkout +action. On cliff-mads, rebuild it explicitly with: + +```bash +ssh cliff-mads 'docker build --platform linux/amd64 --tag local/gamertan-ci:sized-rust188 -' < scripts/gitea-linux.Dockerfile +ssh cliff-mads 'docker image inspect local/gamertan-ci:sized-rust188 --format "{{.Id}}"' +``` + +Review and update the workflow's image ID after an intentional rebuild; images +stay local to the runner host. No runner labels, global isolation settings or +publishing credentials are required. Repository Actions must be enabled. +Only owner-triggered, same-repository code runs on this shared homelab runner. +Source changes on main/the review branch and PRs to main trigger checks; +documentation-only pushes skip builds. Manual dispatch is also available. +This workflow does not publish or tag releases. ## 1. Versioning and Tagging diff --git a/TODO.md b/TODO.md index 918622a..876d328 100644 --- a/TODO.md +++ b/TODO.md @@ -19,6 +19,9 @@ Keep the existing CLI useful and preserve the GPL-3.0-only license. - [x] Commit the scanner hardening and Linux check tooling; push the existing `sizequeen-scan-hardening` review branch. Remote equality is verified. Open a PR when ready; release/tag/package publication remains separate. +- [ ] Enable repository Actions and run the same Linux checks on the existing + cliff-mads runner. Keep its container isolation and other jobs unchanged; + verify a real workflow result before treating CI as proven. ## Proposed next work @@ -36,6 +39,14 @@ authorized; see `SHIPMENT.md` for source review and the separate release process ## Resume note +Current CI checkpoint: repository Actions is enabled. The existing cliff-mads +runner is healthy (`gitea-runner v3.1.0`, native AMD64). The workflow reuses its +`himesan-node24` label and a separately built Rust/Node image; runner configuration, +other jobs and repository visibility are unchanged. The image bootstrap probe +verified UID 65532, workspace-volume ownership, Rust 1.88.0/Node 24.19.0 and +distinct tmpfs devices. Actual Gitea checkout/check execution is still pending; +do not call CI proven until the real workflow completes. + Linux validation and the requested remote review branch are complete. Scanner hardening is `8b177e2`; repeatable Linux checks and equivalent format interpolations are `988aad9`. Both implementation commits are pushed to diff --git a/scripts/check-linux-container.sh b/scripts/check-linux-container.sh index 2bedbf4..a8b3544 100755 --- a/scripts/check-linux-container.sh +++ b/scripts/check-linux-container.sh @@ -10,8 +10,9 @@ cargo --version # Only source inputs are copied. Cargo output and all fixtures disappear with # the container; the host checkout is read-only and no personal tree is scanned. check_root=$(mktemp -d /tmp/sized-check.XXXXXX) -cp /source/Cargo.toml /source/Cargo.lock "$check_root/" -cp -R /source/src /source/tests /source/benches "$check_root/" +source_root=${SIZED_TEST_SOURCE:-/source} +cp "$source_root/Cargo.toml" "$source_root/Cargo.lock" "$check_root/" +cp -R "$source_root/src" "$source_root/tests" "$source_root/benches" "$check_root/" cd "$check_root" cargo fmt --all -- --check cargo test --locked diff --git a/scripts/gitea-linux.Dockerfile b/scripts/gitea-linux.Dockerfile new file mode 100644 index 0000000..26572b9 --- /dev/null +++ b/scripts/gitea-linux.Dockerfile @@ -0,0 +1,10 @@ +# Node supports the pinned checkout action; application code remains Rust. +FROM node:24-bookworm@sha256:934240a162082fd8b8a2f90cd5114446443f1eba1c5378f6687167ca405e6584 AS node-runtime +FROM rust:1.88.0-bookworm@sha256:af306cfa71d987911a781c37b59d7d67d934f49684058f96cf72079c3626bfe0 +RUN rustup component add rustfmt clippy +COPY --from=node-runtime /usr/local/bin/node /usr/local/bin/node +# A new runner workspace volume inherits this ownership. No setuid step or +# Docker socket is needed in jobs, even with all capabilities dropped. +RUN mkdir -p /workspace && chown 65532:65532 /workspace +USER 65532:65532 +WORKDIR /workspace