Skip to content

ci: fix EXDEV error in fuzz-smoke rustup nightly install#113

Merged
27Bslash6 merged 9 commits into
mainfrom
fix/fuzz-rustup-exdev
May 16, 2026
Merged

ci: fix EXDEV error in fuzz-smoke rustup nightly install#113
27Bslash6 merged 9 commits into
mainfrom
fix/fuzz-rustup-exdev

Conversation

@27Bslash6
Copy link
Copy Markdown
Contributor

@27Bslash6 27Bslash6 commented May 15, 2026

Sets RUSTUP_HOME and CARGO_HOME to /tmp to avoid cross-device link errors on ephemeral runners. Same fix applied to cachekit-rs in 2026-03.

Summary by CodeRabbit

  • Chores
    • CI workflow set temporary Rust/Cargo dirs to avoid cross-device link errors on ephemeral runners.
    • Rust nightly toolchain pinned to a specific date for repeatable runs.
    • Fuzz test set reduced to a smaller, compatible subset of targets.
    • Fuzzing crate dependency switched to a version-pinned core package to align with upstream API.
    • CI test job now starts Redis via an explicit container run for test isolation.
    • Removed obsolete hardcoded fuzz summary step.

Review Change Stack

Set RUSTUP_HOME=/tmp/rustup and CARGO_HOME=/tmp/cargo so rustup temp
files and toolchains are on the same filesystem. Without this,
`rustup toolchain install nightly` fails with "Invalid cross-device
link (os error 18)" on ephemeral runners where /home/runner/.rustup
(hostPath cache volume) and /tmp (overlay) are different mounts.

Same fix applied to cachekit-rs CI in 2026-03.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 15, 2026

📝 Walkthrough

Walkthrough

Pins Rust nightly to nightly-2026-04-27 and sets RUSTUP_HOME/CARGO_HOME to /tmp in the fuzz-smoke workflow; updates the fuzz crate to depend on cachekit-core =0.1.1; reduces/adjusts FUZZ_TARGETS and the cargo fuzz invocation; and switches CI test job Redis startup to an explicit docker run that waits for PONG.

Changes

Fuzz workflow and crate changes

Layer / File(s) Summary
Ephemeral runner environment setup
.github/workflows/fuzz-smoke.yml
Workflow env overrides set RUSTUP_HOME and CARGO_HOME to /tmp/* to avoid EXDEV cross-device link errors on ephemeral runners.
Pinned nightly toolchain
.github/workflows/fuzz-smoke.yml
Installs and sets nightly-2026-04-27 as the default toolchain (replacing an unpinned nightly).
Fuzz crate dependency update
rust/fuzz/Cargo.toml
Replaces local cachekit-storage path dependency with a version-pinned cachekit-core package exposed as cachekit_storage; retains existing fuzz dependency features.
Fuzz targets and invocation
.github/workflows/fuzz-smoke.yml
Reduces FUZZ_TARGETS to a compatible subset and runs each target with cargo +nightly-2026-04-27 fuzz run ..., emitting target_count to GITHUB_OUTPUT.
CI test job Redis startup
.github/workflows/ci.yml
Replaces services-based Redis with an explicit docker run redis:7-alpine step and waits for redis-cli ping to return PONG before running tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

🐰 I hopped to /tmp paths, light and spry,
Pinned the night so builds won't fly,
Swapped a crate and trimmed the run,
Short fuzz hops now race the sun,
CI hums — a little rabbit's sigh.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is too brief and missing required template sections such as Motivation, Type of Change, Security Checklist, Documentation Validation, Testing, and Backward Compatibility. Complete the pull request description using the provided template, including sections for Motivation, Type of Change, and all Security and Testing checklists.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly addresses the main change: fixing EXDEV errors in the fuzz-smoke workflow by setting rustup environment variables, which is the primary objective of the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/fuzz-rustup-exdev

Comment @coderabbitai help to get the list of available commands and usage tips.

27Bslash6 added 2 commits May 15, 2026 21:52
cargo-fuzz 0.13.1 depends on rustix which uses internal
rustc_layout_scalar_valid_range_* attributes. Nightly 1.97.0
(2026-05-14+) reserved these attributes, breaking compilation.
Pin to last known-good nightly until cargo-fuzz ships a fix.
- rust/fuzz/Cargo.toml: depend on cachekit-core directly (the fuzz
  targets use its internal module paths, not the PyO3 wrapper's
  re-exports). The old cachekit-storage package name no longer exists.
- Reduce fuzz target list to 4 that compile against cachekit-core
  0.1.1. 9 targets have stale API calls (encrypt_aes_gcm etc.).
  Tracked in #114.
- Use pinned nightly toolchain name in cargo +nightly-2026-04-27.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/fuzz-smoke.yml (1)

115-115: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the target count to reflect the reduced set.

The message still says "14 targets" but the workflow now runs only 4 fuzz targets (per lines 57-62).

📊 Proposed fix
-            echo "Status: All fuzz targets passed (14 targets, 60s each)"
+            echo "Status: All fuzz targets passed (4 targets, 60s each)"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/fuzz-smoke.yml at line 115, The status echo still reports
"14 targets" but the workflow now runs only 4 fuzz targets; update the echo
statement that currently reads 'Status: All fuzz targets passed (14 targets, 60s
each)' to reflect the new count (e.g., '4 targets') so the message matches the
set defined in the fuzz target steps referenced around the fuzz target
declarations; ensure the time-per-target value remains correct if unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In @.github/workflows/fuzz-smoke.yml:
- Line 115: The status echo still reports "14 targets" but the workflow now runs
only 4 fuzz targets; update the echo statement that currently reads 'Status: All
fuzz targets passed (14 targets, 60s each)' to reflect the new count (e.g., '4
targets') so the message matches the set defined in the fuzz target steps
referenced around the fuzz target declarations; ensure the time-per-target value
remains correct if unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ef068be5-834c-4480-a640-c33c14abfccc

📥 Commits

Reviewing files that changed from the base of the PR and between 2cff09a and d9ffc0a.

📒 Files selected for processing (2)
  • .github/workflows/fuzz-smoke.yml
  • rust/fuzz/Cargo.toml

@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 72-77: The readiness loop using "until docker exec redis redis-cli
ping | grep -q PONG" is unbounded and can hang CI; modify the script that
follows "docker run -d --name redis -p 6379:6379 \ redis:7-alpine ..." to bound
the wait by replacing the raw until loop with a retry/timed loop (e.g., a
for/while loop with a MAX_ATTEMPTS or a timeout in seconds), break early on
success, and exit non‑zero with a clear error message if the ping never succeeds
(so the job fails fast instead of spinning indefinitely).

In @.github/workflows/fuzz-smoke.yml:
- Around line 36-40: The workflow pins a specific nightly via the rustup
commands ("rustup toolchain install nightly-2026-04-27" and "rustup default
nightly-2026-04-27") because cargo-fuzz 0.13.1 pulls in rustix which uses the
removed rustc_layout_scalar_valid_range_* attributes; monitor cargo-fuzz (and
rustix) releases for a version that removes or replaces that dependency and,
when available, drop the nightly pin by removing those rustup lines and
reverting to the project’s normal toolchain selection so the workflow no longer
depends on a time‑boxed nightly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9509c758-c18f-4001-8092-0428638f07e8

📥 Commits

Reviewing files that changed from the base of the PR and between d9ffc0a and a3b629e.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml
  • .github/workflows/fuzz-smoke.yml

Comment thread .github/workflows/ci.yml
Comment on lines +72 to +77
- name: Start Redis (no persistence)
run: |
docker run -d --name redis -p 6379:6379 \
redis:7-alpine redis-server --save "" --appendonly no
until docker exec redis redis-cli ping | grep -q PONG; do sleep 1; done

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

# First, let's check if the file exists and read the relevant section
if [ -f ".github/workflows/ci.yml" ]; then
  echo "=== File exists: .github/workflows/ci.yml ==="
  echo "=== Lines 70-80 ==="
  sed -n '70,80p' .github/workflows/ci.yml | cat -n
else
  echo "File not found. Searching for workflow files..."
  fd -e yml -e yaml | head -20
fi

Repository: cachekit-io/cachekit-py

Length of output: 638


🏁 Script executed:

# Let's examine the full workflow file to check for any timeout settings or other safeguards
echo "=== Full CI workflow (first 50 lines) ==="
head -50 .github/workflows/ci.yml | cat -n

echo ""
echo "=== Checking for timeout configurations ==="
grep -n "timeout" .github/workflows/ci.yml

echo ""
echo "=== Checking the full 'Start Redis' step context ==="
sed -n '70,85p' .github/workflows/ci.yml | cat -n

Repository: cachekit-io/cachekit-py

Length of output: 2418


🏁 Script executed:

# Let's find which job contains this Redis step and verify its timeout
echo "=== Looking for the job that contains the Redis step (around lines 55-80) ==="
sed -n '55,80p' .github/workflows/ci.yml | cat -n

echo ""
echo "=== Checking lines around line 60 for job definition ==="
sed -n '55,65p' .github/workflows/ci.yml | cat -n

Repository: cachekit-io/cachekit-py

Length of output: 1710


🏁 Script executed:

# Let's verify the suggested fix syntax is valid for the shell context
# GitHub Actions uses bash by default, so let's check if the syntax is correct
echo "=== Testing the proposed loop syntax ==="
cat << 'EOF' > /tmp/test_syntax.sh
#!/bin/bash
# This tests if the suggested syntax would work

# Simulate what the suggested fix would do
for i in {1..60}; do
  echo "Iteration $i"
  if [ $i -eq 3 ]; then
    echo "Would break here"
    break
  fi
  sleep 0.1
done

# The second part of the suggested fix
echo "After loop"
EOF

bash -n /tmp/test_syntax.sh && echo "✓ Syntax is valid" || echo "✗ Syntax error"

echo ""
echo "=== Examining the actual behavior of the current unbounded loop ==="
echo "If docker run fails OR Redis crashes, the 'until' loop will:"
echo "1. Keep running 'docker exec redis redis-cli ping' indefinitely"
echo "2. Fail at each iteration but continue"
echo "3. Not exit until the job timeout (15 minutes)"
echo "4. The actual error (container not running) gets hidden"

Repository: cachekit-io/cachekit-py

Length of output: 462


Bound the Redis readiness loop to prevent hang-on-failure.

The until loop on line 76 is unbounded. If the container fails to start or exits early, it will spin indefinitely until the 15-minute job timeout, obscuring the actual failure and wasting CI time across all test runs.

Suggested fix
    - name: Start Redis (no persistence)
      run: |
        docker run -d --name redis -p 6379:6379 \
          redis:7-alpine redis-server --save "" --appendonly no
-        until docker exec redis redis-cli ping | grep -q PONG; do sleep 1; done
+        for i in {1..60}; do
+          if docker exec redis redis-cli ping 2>/dev/null | grep -q PONG; then
+            break
+          fi
+          if ! docker ps --filter "name=^redis$" --filter "status=running" | grep -q redis; then
+            echo "Redis container is not running"
+            docker logs redis || true
+            exit 1
+          fi
+          sleep 1
+        done
+        docker exec redis redis-cli ping | grep -q PONG || { echo "Redis did not become ready in time"; docker logs redis || true; exit 1; }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Start Redis (no persistence)
run: |
docker run -d --name redis -p 6379:6379 \
redis:7-alpine redis-server --save "" --appendonly no
until docker exec redis redis-cli ping | grep -q PONG; do sleep 1; done
- name: Start Redis (no persistence)
run: |
docker run -d --name redis -p 6379:6379 \
redis:7-alpine redis-server --save "" --appendonly no
for i in {1..60}; do
if docker exec redis redis-cli ping 2>/dev/null | grep -q PONG; then
break
fi
if ! docker ps --filter "name=^redis$" --filter "status=running" | grep -q redis; then
echo "Redis container is not running"
docker logs redis || true
exit 1
fi
sleep 1
done
docker exec redis redis-cli ping | grep -q PONG || { echo "Redis did not become ready in time"; docker logs redis || true; exit 1; }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 72 - 77, The readiness loop using
"until docker exec redis redis-cli ping | grep -q PONG" is unbounded and can
hang CI; modify the script that follows "docker run -d --name redis -p 6379:6379
\ redis:7-alpine ..." to bound the wait by replacing the raw until loop with a
retry/timed loop (e.g., a for/while loop with a MAX_ATTEMPTS or a timeout in
seconds), break early on success, and exit non‑zero with a clear error message
if the ping never succeeds (so the job fails fast instead of spinning
indefinitely).

Comment on lines +36 to +40
run: |
# Pin nightly: cargo-fuzz 0.13.1 → rustix uses rustc_layout_scalar_valid_range_*
# attributes reserved after nightly-2026-04-27. Last known-good date.
rustup toolchain install nightly-2026-04-27
rustup default nightly-2026-04-27
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🌐 Web query:

Is Rust nightly-2026-04-27 currently available for download?

💡 Result:

Yes, the Rust nightly toolchain for 2026-04-27 is available [1]. You can install this specific version using the rustup toolchain manager by running the following command in your terminal: rustup toolchain install nightly-2026-04-27 This command instructs rustup to download and install the nightly compiler release corresponding to that specific date [2][3][4]. Once installed, you can use it by referencing the toolchain name directly (e.g., rustup run nightly-2026-04-27 cargo build) or by setting it as an override for a specific project directory [2][3]. Note that nightly toolchains are generated daily, and while a build exists for 2026-04-27 [1], it is possible for some nightly builds to be missing certain non-default components (such as clippy or rust-docs) depending on the build status for that day [5]. If you encounter issues with missing components, you can try using the --profile=minimal flag or check the build status via the rustup-components-history project [5].

Citations:


🌐 Web query:

Does cargo-fuzz 0.13.1 have a known issue with rustix and rustc_layout_scalar_valid_range attributes in Rust nightly builds after April 2026?

💡 Result:

Yes, cargo-fuzz 0.13.1 has a known issue with Rust nightly builds from May 2026 [1]. This issue arises because the Rust compiler removed support for the internal rustc_layout_scalar_valid_range_* attributes [2][3][4], which were previously used by dependencies like rustix [1]. As of May 2026, the Rust compiler has fully deprecated and removed these internal attributes in favor of new pattern types [2][3][5]. Because cargo-fuzz 0.13.1 relies on older versions of its dependencies (such as rustix) that still utilize these now-removed attributes, the crate fails to compile on recent nightly toolchains [1]. Users encountering this error are advised to check for updates to cargo-fuzz or its dependencies that have migrated away from these internal compiler attributes [1].

Citations:


Monitor for cargo-fuzz updates to resolve rustix compatibility and remove nightly pin.

The pinned nightly (2026-04-27) is ~19 days old. Rust nightlies are retained for ~90 days before expiring on distribution servers. Once this nightly expires, the workflow will fail. The pin exists because cargo-fuzz 0.13.1 depends on rustix, which uses the now-removed rustc_layout_scalar_valid_range_* internal compiler attributes. Track updates to cargo-fuzz that resolve this dependency issue, allowing migration away from a pinned nightly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/fuzz-smoke.yml around lines 36 - 40, The workflow pins a
specific nightly via the rustup commands ("rustup toolchain install
nightly-2026-04-27" and "rustup default nightly-2026-04-27") because cargo-fuzz
0.13.1 pulls in rustix which uses the removed rustc_layout_scalar_valid_range_*
attributes; monitor cargo-fuzz (and rustix) releases for a version that removes
or replaces that dependency and, when available, drop the nightly pin by
removing those rustup lines and reverting to the project’s normal toolchain
selection so the workflow no longer depends on a time‑boxed nightly.

@27Bslash6 27Bslash6 merged commit f51d3b1 into main May 16, 2026
33 checks passed
@27Bslash6 27Bslash6 deleted the fix/fuzz-rustup-exdev branch May 16, 2026 03:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant