Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 35 additions & 15 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,27 @@ updates:
prefix: "chore(ci)"

# --- Python --------------------------------------------------------------
# Root: the CI dependency set for the required green-set job.
- package-ecosystem: pip
directory: "/"
schedule:
interval: monthly
open-pull-requests-limit: 3
groups:
ci-python:
patterns: ["*"]
commit-message:
prefix: "chore(deps)"

# ARF: the application dependency set, including the ML stack.
# ONE entry covering every requirements location, not one per directory.
#
# Two entries (`/` and `/ARF`) produced two PRs that both edited
# ARF/requirements.txt -- #51 and #49 -- so they were guaranteed to conflict,
# and whichever merged second would need a manual rebase for no reason. The
# root entry already reaches ARF/requirements.txt on its own; `directories`
# adds the pwnies file that only the /ARF entry was picking up.
#
# One group means one PR per cycle across the whole Python surface, which is
# also what makes the green-set gate meaningful: the CI set and the app set
# move together or not at all.
- package-ecosystem: pip
directory: "/ARF"
directories:
- "/"
- "/ARF"
- "/ARF/pwnies"
schedule:
interval: monthly
open-pull-requests-limit: 3
groups:
arf-python:
python:
patterns: ["*"]
Comment thread
kalisam marked this conversation as resolved.
Resolved
commit-message:
prefix: "chore(deps)"
Expand Down Expand Up @@ -102,5 +103,24 @@ updates:
- dependency-name: "hdi"
- dependency-name: "hdk"
- dependency-name: "holochain_serialized_bytes"
# getrandom is NOT an ordinary dependency of the zomes. Each zome declares
# `getrandom = { version = "0.3", features = ["wasm_js"] }` purely to turn
# on the wasm backend of the getrandom that hdi/hdk already pull in. It is
# a feature-enabling shim, and it only works while it resolves to the SAME
# version hdi requires.
#
# PR #46 bumped it to 0.4 on its own. hdi 0.7.1 still needs 0.3.4, so the
# two now coexisted as separate crates, `wasm_js` applied only to 0.4.3,
# and 0.3.4 was left with no wasm backend:
#
# error[E0425]: cannot find function `inner_u32` in module `backends`
# --> getrandom-0.3.4/src/lib.rs
#
# Verified by `cargo check --workspace --target wasm32-unknown-unknown`:
# clean on origin/main, broken on that PR. Native `cargo check` passes on
# both, which is why it looks harmless.
#
# It moves when the Holochain line moves, not before.
- dependency-name: "getrandom"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
commit-message:
prefix: "chore(deps)"
103 changes: 97 additions & 6 deletions .github/workflows/rust-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,20 @@ on:
- "**/Cargo.lock"
- "rustfmt.toml"
- ".github/workflows/rust-ci.yml"
# Deliberately NOT path-filtered, for the same reason python-ci.yml is not --
# see the comment on its `pull_request` trigger.
#
# GitHub leaves a required check PENDING, not passing, when its workflow is
# skipped by path filtering. `fmt` and `wasm-check` are meant to be required,
# so a filter here would hang every PR that happens to touch no Rust. Six of
# the seven PRs open when this was written match zero Rust paths, so that is
# measured, not hypothetical.
#
# I made this exact mistake here after documenting it one file over. The jobs
# below therefore always RUN and always report; what they skip is the
# expensive work, decided per-PR by the `changes` job.
pull_request:
branches: [ "main" ]
paths:
- "**/*.rs"
- "**/Cargo.toml"
- "**/Cargo.lock"
- "rustfmt.toml"
- ".github/workflows/rust-ci.yml"
merge_group:
types: [checks_requested]
schedule:
Expand Down Expand Up @@ -68,22 +74,107 @@ env:
CARGO_WORKSPACE: ARF

jobs:
# Decides whether the Rust work is worth doing on this ref, without deciding
# whether the CHECKS report -- those always do.
changes:
name: Detect Rust changes
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
rust: ${{ steps.detect.outputs.rust }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Detect
id: detect
run: |
set -euo pipefail
if [ "${{ github.event_name }}" != "pull_request" ]; then
# push, schedule, merge_group, manual: always do the work.
echo "rust=true" >> "$GITHUB_OUTPUT"
Comment thread
kalisam marked this conversation as resolved.
Resolved
exit 0
fi
base="origin/${{ github.base_ref }}"
git fetch --no-tags --depth=0 origin "${{ github.base_ref }}" >/dev/null 2>&1 || true
changed=$(git diff --name-only "$base"...HEAD)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
echo "changed files:"; echo "$changed" | sed 's/^/ /'
if echo "$changed" | grep -qE '\.rs$|(^|/)Cargo\.(toml|lock)$|(^|/)rustfmt\.toml$|\.github/workflows/rust-ci\.yml$'; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include workspace configuration in Rust change detection

For a PR that changes only ARF/.cargo/config.toml or ARF/rust-toolchain.toml, this predicate reports rust=false, so both required checks follow their no-op success paths. This is especially risky for .cargo/config.toml: its target-specific rustflags select the getrandom WASM backend, so altering or removing them can cause the exact compilation failure this gate is intended to catch while Compile check (wasm32) remains green. Include these existing workspace control files in the detection predicate.

Useful? React with 👍 / 👎.

Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
echo "rust=true" >> "$GITHUB_OUTPUT"
else
echo "rust=false" >> "$GITHUB_OUTPUT"
fi

fmt:
name: Format (cargo fmt --check)
runs-on: ubuntu-latest
timeout-minutes: 10
needs: changes
steps:
- uses: actions/checkout@v4

- name: Set up Rust toolchain (stable + rustfmt)
if: needs.changes.outputs.rust == 'true'
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # `stable` branch head, 2026-08-21
with:
components: rustfmt

- name: Cargo fmt (check only)
if: needs.changes.outputs.rust == 'true'
working-directory: ${{ env.CARGO_WORKSPACE }}
run: cargo fmt --all -- --check

- name: No Rust changes
if: needs.changes.outputs.rust != 'true'
run: echo "No Rust files changed; nothing to format-check. Reporting success."

wasm-check:
name: Compile check (wasm32)
Comment on lines +180 to +181

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Run the required WASM check for every pull request

When Compile check (wasm32) is registered as a required check—which is necessary for this job to act as the advertised merge gate—the workflow's pull_request trigger still filters to Rust-related paths at lines 33–40. GitHub will not create the required check for npm-, Python-, or documentation-only PRs, leaving those PRs pending and unable to merge; this exact failure mode is already documented in python-ci.yml lines 34–42. Run the workflow on every pull request and conditionally skip the expensive work while still producing the required status.

Useful? React with 👍 / 👎.

runs-on: ubuntu-latest
timeout-minutes: 30
needs: changes

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Propagate change-detector failures to the WASM gate

When changes fails—for example because its explicit base-ref verification, checkout, or diff fails—GitHub Actions skips jobs that need the failed job unless they use an always() condition. Consequently, wasm-check never reaches its fallback step and is reported as skipped; skipped required checks do not block merging, so a Rust PR can bypass the advertised compile gate precisely when detection cannot decide. Run the required job with always() and fail it when needs.changes.result is not success (and apply the same protection to fmt), or make the detector itself a required check.

Useful? React with 👍 / 👎.

steps:
- uses: actions/checkout@v4

- name: Cache cargo registry + build
if: needs.changes.outputs.rust == 'true'
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
ARF/target
key: ${{ runner.os }}-cargo-wasm-${{ hashFiles('ARF/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-wasm-

- name: Set up Rust toolchain (stable + wasm32)
if: needs.changes.outputs.rust == 'true'
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # `stable` branch head, 2026-08-21
with:
targets: wasm32-unknown-unknown

# NOT part of the `clippy`/`test` hold. Those are held because the full
# Holochain build and test surface is not expected to pass yet. This is a
# type-check of the zomes against the target they actually ship to, and it
# is the only thing that can catch a dependency bump breaking the wasm
# backend.
#
# It exists because it was needed: dependabot PR #46 bumped getrandom
# 0.3 -> 0.4 and every check on that PR passed -- green set, CodeQL,
# semgrep, cargo fmt -- while `cargo check --target wasm32-unknown-unknown`
# failed outright. `cargo fmt` does not compile, and clippy and test are
# held, so nothing in CI could see it. Native `cargo check` passes too, so
# the target matters.
- name: Cargo check (wasm32)
if: needs.changes.outputs.rust == 'true'
working-directory: ${{ env.CARGO_WORKSPACE }}
run: cargo check --workspace --target wasm32-unknown-unknown

- name: No Rust changes
if: needs.changes.outputs.rust != 'true'
run: echo "No Rust files changed; nothing to compile-check. Reporting success."

clippy:
name: Lint (cargo clippy) [HELD -- manual only]
if: github.event_name == 'workflow_dispatch'
Expand Down
Loading