fix CI: skip readonly tests as root, manual rustup for containers

- Add skip_if_root() to 8 permission-based tests (root bypasses
  filesystem permissions in Docker containers)
- Replace dtolnay/rust-toolchain with manual rustup install via sh
  for container-based jobs (opensuse lacks bash, which the composite
  action requires)
- Keep dtolnay/rust-toolchain for non-container ubuntu jobs
This commit is contained in:
Marco Allegretti 2026-02-22 20:03:42 +01:00
parent fd7313a318
commit cc67d70211
2 changed files with 31 additions and 5 deletions

View file

@ -64,8 +64,15 @@ jobs:
run: dnf install -y gcc make curl
- name: Install build deps (openSUSE)
if: matrix.os == 'opensuse'
run: zypper install -y gcc make curl gzip tar xz bash
run: zypper install -y gcc make curl gzip tar xz
- name: Install Rust (container)
if: matrix.container != ''
shell: sh
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain $RUST_TOOLCHAIN --profile minimal
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- uses: dtolnay/rust-toolchain@stable
if: matrix.container == ''
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
- uses: Swatinem/rust-cache@v2
@ -136,15 +143,17 @@ jobs:
setup: "dnf install -y gcc make curl fuse-overlayfs fuse3 crun"
- os: opensuse
container: opensuse/tumbleweed:latest
setup: "zypper install -y gcc make curl fuse-overlayfs gzip tar xz bash crun"
setup: "zypper install -y gcc make curl fuse-overlayfs gzip tar xz crun"
container: ${{ matrix.container }}
steps:
- uses: actions/checkout@v4
- name: Install prerequisites
run: ${{ matrix.setup }}
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
- name: Install Rust
shell: sh
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain $RUST_TOOLCHAIN --profile minimal
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- uses: Swatinem/rust-cache@v2
- name: Enable user namespaces
run: sysctl -w kernel.unprivileged_userns_clone=1 || true

View file

@ -8,6 +8,15 @@ use std::path::Path;
use std::sync::{Arc, Barrier};
use std::thread;
/// Skip test if running as root — root bypasses filesystem permission checks,
/// so read-only directory tests are meaningless in containers running as uid 0.
fn skip_if_root() -> bool {
#[allow(unsafe_code)]
unsafe {
libc::getuid() == 0
}
}
fn write_manifest(dir: &Path, content: &str) -> std::path::PathBuf {
let path = dir.join("karapace.toml");
fs::write(&path, content).unwrap();
@ -1370,6 +1379,7 @@ fn gc_is_idempotent_after_partial_run() {
// M6.2: Object read fails gracefully on permission denied
#[test]
fn object_get_fails_on_permission_denied() {
if skip_if_root() { return; }
let store = tempfile::tempdir().unwrap();
let layout = StoreLayout::new(store.path());
layout.initialize().unwrap();
@ -1391,6 +1401,7 @@ fn object_get_fails_on_permission_denied() {
// M6.2: Metadata write fails gracefully on read-only store
#[test]
fn metadata_put_fails_on_read_only_dir() {
if skip_if_root() { return; }
let store = tempfile::tempdir().unwrap();
let layout = StoreLayout::new(store.path());
layout.initialize().unwrap();
@ -1594,6 +1605,7 @@ fn stale_running_marker_cleaned_on_engine_new() {
#[test]
fn build_on_readonly_objects_dir_returns_error() {
if skip_if_root() { return; }
let store = tempfile::tempdir().unwrap();
let project = tempfile::tempdir().unwrap();
@ -1618,6 +1630,7 @@ fn build_on_readonly_objects_dir_returns_error() {
#[test]
fn build_on_readonly_metadata_dir_returns_error() {
if skip_if_root() { return; }
let store = tempfile::tempdir().unwrap();
let project = tempfile::tempdir().unwrap();
@ -1640,6 +1653,7 @@ fn build_on_readonly_metadata_dir_returns_error() {
#[test]
fn commit_on_readonly_layers_dir_returns_error() {
if skip_if_root() { return; }
let store = tempfile::tempdir().unwrap();
let project = tempfile::tempdir().unwrap();
let engine = Engine::new(store.path());
@ -1678,6 +1692,7 @@ fn commit_on_readonly_layers_dir_returns_error() {
#[test]
fn write_failure_never_panics() {
if skip_if_root() { return; }
let store = tempfile::tempdir().unwrap();
let layout = StoreLayout::new(store.path());
layout.initialize().unwrap();
@ -2099,6 +2114,7 @@ backend = "mock"
#[test]
fn wal_write_fails_on_readonly_dir() {
if skip_if_root() { return; }
let store = tempfile::tempdir().unwrap();
let layout = StoreLayout::new(store.path());
layout.initialize().unwrap();
@ -2122,6 +2138,7 @@ fn wal_write_fails_on_readonly_dir() {
#[test]
fn build_fails_cleanly_when_wal_dir_is_readonly() {
if skip_if_root() { return; }
let store = tempfile::tempdir().unwrap();
let project = tempfile::tempdir().unwrap();