Skip to content

ci: lint shell, workflows, TOML, Nix, and justfiles via nix devShell#1519

Merged
kixelated merged 3 commits into
mainfrom
claude/laughing-bhaskara-56089f
May 27, 2026
Merged

ci: lint shell, workflows, TOML, Nix, and justfiles via nix devShell#1519
kixelated merged 3 commits into
mainfrom
claude/laughing-bhaskara-56089f

Conversation

@kixelated
Copy link
Copy Markdown
Collaborator

@kixelated kixelated commented May 27, 2026

Summary

Wires a suite of linters / formatters into the existing just check / just ci pipeline, closing the major unlinted surfaces in the repo:

Tool Targets Where
shellcheck + shfmt 19 shell scripts (.github/scripts, go/, kt/, swift/, infra/{apt,rpm}, rs/{libmoq,moq-ffi,moq-gst,scripts}, demo/throttle/enable) inline in root justfile
actionlint .github/workflows/*.yml new .github/justfile module (mod gh '.github')
taplo every TOML in-tree (Cargo, deny, pyproject, relay configs, …) inline in root justfile, configured by new .taplo.toml
nixfmt (RFC-style) flake.nix, nix/overlay.nix, nix/modules/moq-relay.nix inline in root justfile
just --fmt --unstable every justfile in-tree (17 total) inline in root justfile

All tools come from nixpkgs via a single lintDeps group in flake.nix, so nix develop provides them automatically and just ci can require them. just check / just fix guard each tool with command -v so they skip silently when missing, keeping the inner loop usable outside Nix.

What's in the diff

Tooling

  • flake.nixlintDeps = [ shellcheck shfmt actionlint taplo nixfmt-rfc-style ], added to the devShell packages.
  • .github/justfile (new)check (silent skip) and ci (required) recipes for actionlint.
  • .taplo.toml (new)indent_string = " ", column_width = 150, align_comments = false, plus an exclude array for node_modules, target, dist, .venv.
  • justfile — registers mod gh '.github'; inlines guarded calls to all the new tools in check / fix (matching the existing bun remark pattern) and unguarded calls in the always-run block of ci.
  • .editorconfig[*.sh] + [demo/throttle/enable] blocks lock in 4-space indent + switch_case_indent for shfmt; [{node_modules,target,dist,.venv}/**] ignore = true so shfmt's recursive walk skips vendored / build output.
  • rs/justfilecargo sort --workspace --check --no-format and matching fix, so cargo-sort owns dep ordering and taplo owns whitespace. Without this they fought over quinn = { ..., features = [...] } in rs/moq-native/Cargo.toml.

Format-pass fallout (folded in)

All mechanical:

  • Shell: 19 scripts reformatted by shfmt --write. Mechanical: case bodies with ;-separated statements expanded onto multiple lines; \ line continuations removed where | already implies continuation.
  • Just: 11 justfiles re-indented from tabs to 4 spaces by just --fmt.
  • Nix: flake.nix (with pkgs; [...] blocks expanded to a let-style), plus light reflows in nix/overlay.nix and nix/modules/moq-relay.nix.
  • TOML: one long features array in rs/moq-native/Cargo.toml collapsed inline (now under column_width = 150) and one was rewrapped multi-line.

Real findings addressed (not just formatting)

  • shellcheck flagged a dead SCRIPT_DIR assignment in swift/scripts/publish.sh — removed.
  • actionlint (which runs an embedded shellcheck on run: blocks) flagged six lines across six workflows:
    • docker.yml — quoted "$GITHUB_OUTPUT" and added a targeted # shellcheck disable=SC2046 on the intentional word-splitting printf ... * of digests.
    • release-brew.yml — refactored three consecutive echo "k=v" >> "$GITHUB_OUTPUT" lines into a single {...} >> "$GITHUB_OUTPUT" block (SC2129).
    • moq-cli.yml, moq-gst.yml, moq-relay.yml, moq-token-cli.yml — added # shellcheck disable=SC2016 on the envsubst '$VAR1 $VAR2 ...' calls (single-quoting the varlist is the correct invocation).

Reviewer notes

  • The total diff looks large but is dominated by mechanical format-pass output (shell scripts + justfiles + nix + one Cargo.toml). The actual logic / config additions are concentrated in flake.nix, justfile, .taplo.toml, .editorconfig, and .github/justfile.
  • The command -v guard pattern is documented in code comments so future tools can follow the same "optional locally, required in ci" convention.
  • I deferred hadolint (1 Dockerfile, 44 lines) — out of scope per discussion.

Test plan

  • nix develop --command just check passes locally.
  • nix develop --command just fix is idempotent on the post-pass tree.
  • command -v guards exit 0 silently when a tool is missing from $PATH.
  • check.yml workflow goes green on this PR.

(Written by Claude)

Wires three new linters into the existing just check / just ci pipeline:

- shellcheck + shfmt over all 19 shell scripts (.github/scripts, go/,
  kt/, swift/, infra/{apt,rpm}, rs/{libmoq,moq-ffi,moq-gst,scripts},
  demo/throttle/enable).
- actionlint over .github/workflows/*.yml, exposed via the new
  .github/justfile module so it parallels the per-area justfile pattern.

Tools come from nixpkgs via a new lintDeps group in flake.nix. The local
just check / just fix recipes guard each tool with `command -v` so they
skip silently when not on $PATH; just ci requires them (it always runs
inside `nix develop`).

.editorconfig gains a [*.sh] block locking in 4-space indent and
switch_case_indent so shfmt is deterministic across machines, plus
`ignore = true` for node_modules/target/dist/.venv so shfmt's recursive
walk doesn't pick up vendored files.

Fallout from the initial pass:
- shfmt reformatted all 19 scripts (mechanical: case bodies expanded
  onto multiple lines, line-continuation `\` removed where `|` already
  implies continuation).
- shellcheck found one real issue: dropped unused SCRIPT_DIR assignment
  in swift/scripts/publish.sh.
- actionlint (via embedded shellcheck) flagged six workflow lines:
  quoted $GITHUB_OUTPUT in docker.yml, refactored consecutive >>
  redirects in release-brew.yml into a single `{...} >>` block, and
  added targeted SC2016 disables for the four nfpm `envsubst` calls
  (single-quoting the varlist is the correct invocation).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f311ebd5-43b1-4afb-b6dd-f1c682867469

📥 Commits

Reviewing files that changed from the base of the PR and between 091badd and 64e0e95.

📒 Files selected for processing (2)
  • demo/boy/justfile
  • demo/pub/justfile
🚧 Files skipped from review as they are similar to previous changes (1)
  • demo/boy/justfile

Walkthrough

This PR adds editor and Taplo formatter configs, introduces a .github/justfile and lintDeps in flake.nix, inserts ShellCheck suppressions and grouped output writes in several GitHub workflows, and refactors many shell/build/package scripts and justfiles across Go, Kotlin, Rust, Swift, and infra for consistent CLI parsing, redirection, and explicit preflight/error guards while preserving existing behavior.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a suite of linters and formatters (shell, workflows, TOML, Nix, justfiles) integrated via the nix devShell.
Description check ✅ Passed The description comprehensively explains the changes, tools added, configuration details, format-pass mechanical changes, and real findings addressed, directly relating to the changeset.
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
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/laughing-bhaskara-56089f

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Extends the lintDeps group in flake.nix with:

- taplo for TOML formatting (Cargo.toml, deny.toml, pyproject.toml,
  relay configs, etc.). Configured via .taplo.toml to match the existing
  4-space indent, with column_width = 150 to avoid fighting cargo-sort
  on long dep lines. exclude rules keep taplo out of node_modules,
  target/, dist/, and .venv/.
- nixfmt (RFC-style) for flake.nix, nix/overlay.nix, and the relay
  NixOS module. Used through `nix develop` -- the `formatter` field in
  flake.nix (pkgs.nixfmt-tree) handles `nix fmt` independently and is
  unchanged.
- just --fmt --unstable for every justfile in the repo. The flag is
  still marked unstable upstream but the formatter is stable enough to
  enforce; it normalizes tabs to 4-space indent across the 17 justfiles.

The same conditional pattern applies: just check / just fix guard each
new tool with `command -v` so local runs without `nix develop` skip
silently, while just ci runs them unconditionally.

rs/justfile passes --no-format to `cargo sort` so cargo-sort owns
dependency ordering and taplo owns whitespace/wrapping. Without this
they fought over `quinn = { ..., features = [...] }`.

Format-pass fallout, all mechanical:
- 11 justfiles indent-converted (tabs -> 4 spaces) and minor recipe
  formatting from just --fmt.
- flake.nix and the two nix/ files reformatted by nixfmt (mostly
  `with pkgs; [...]` expanded to a let-style with separate lines).
- rs/moq-native/Cargo.toml: one long features array stayed inline (now
  under column_width = 150) and one was rewrapped multi-line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@kixelated kixelated changed the title ci: add shellcheck, shfmt, and actionlint via nix devShell ci: lint shell, workflows, TOML, Nix, and justfiles via nix devShell May 27, 2026
@kixelated kixelated enabled auto-merge (squash) May 27, 2026 23:04
Copy link
Copy Markdown
Contributor

@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: 3

🤖 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 `@demo/boy/justfile`:
- Around line 76-80: The for-loop over "{{ dir }}"/* can iterate the literal "*"
when the directory is empty; add a guard before calling basename and running the
upload command in the loop (the block starting with for file in "{{ dir }}"/*;
do) — e.g., skip iteration unless the globbed path exists/is a regular file
(test with [ -e "$file" ] or [ -f "$file" ]), so only run key=$(basename
"$file") and bun wrangler r2 object put "rom-moq-dev/$key" --file "$file"
--remote for real files.

In `@demo/pub/justfile`:
- Around line 238-240: The download step writes to media/{{ name }}.mp4 but
doesn’t ensure the media directory exists; update the `@if` block in the Justfile
so it creates the directory (e.g., mkdir -p media) before running curl.
Specifically, modify the conditional around the media/{{ name }}.mp4 check in
the Justfile so that when the file is missing you first run a directory-creation
command, then curl the URL to media/{{ name }}.mp4.
- Around line 29-33: The loop over "{{ dir }}"/* can expand to a literal glob
when the directory is empty, causing failing uploads; modify the loop around the
variable "$file" (and the key=$(basename "$file") / bun wrangler r2 object put
invocation) to skip non-existent matches by adding a file-exists guard—either
enable nullglob behavior before iterating or add an if test inside the loop
(e.g., check that "$file" exists and is a regular file and continue if not) so
the upload command only runs for real files.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4d4c2738-8496-46d3-aa43-21622eb3bd28

📥 Commits

Reviewing files that changed from the base of the PR and between 3c21a47 and 091badd.

📒 Files selected for processing (22)
  • .github/justfile
  • .taplo.toml
  • demo/boy/justfile
  • demo/justfile
  • demo/pub/justfile
  • demo/relay/justfile
  • demo/sub/justfile
  • demo/web/justfile
  • flake.nix
  • go/justfile
  • infra/apt/justfile
  • infra/justfile
  • infra/rpm/justfile
  • js/justfile
  • justfile
  • kt/justfile
  • nix/modules/moq-relay.nix
  • nix/overlay.nix
  • py/justfile
  • rs/justfile
  • rs/moq-native/Cargo.toml
  • swift/justfile
✅ Files skipped from review due to trivial changes (10)
  • demo/relay/justfile
  • infra/justfile
  • .github/justfile
  • nix/modules/moq-relay.nix
  • .taplo.toml
  • nix/overlay.nix
  • rs/moq-native/Cargo.toml
  • demo/web/justfile
  • swift/justfile
  • py/justfile
🚧 Files skipped from review as they are similar to previous changes (1)
  • flake.nix

Comment thread demo/boy/justfile
Comment thread demo/pub/justfile
Comment thread demo/pub/justfile
CodeRabbit flagged three pre-existing demo justfile bugs while reviewing
the lint-tooling PR (they were in the diff only because just --fmt
reformatted those files). Small enough to fix in the same PR:

- demo/boy/justfile sync: `for file in "$dir"/*` iterates the literal
  glob when the dir is empty, causing a failing wrangler upload. Skip
  non-existent paths with `[ -e "$file" ] || continue`.
- demo/pub/justfile sync: same fix.
- demo/pub/justfile download: `curl -o media/X.mp4` fails on first run
  if media/ doesn't exist. `mkdir -p media` before downloading.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@kixelated kixelated merged commit 51e1d61 into main May 27, 2026
37 of 38 checks passed
@kixelated kixelated deleted the claude/laughing-bhaskara-56089f branch May 27, 2026 23:24
@moq-bot moq-bot Bot mentioned this pull request May 27, 2026
kixelated added a commit that referenced this pull request May 29, 2026
The repo-wide nixfmt check (top-level justfile, line 50) started failing
on every PR because this file drifted from the formatter's expected
shape since #1519 wired nixfmt into CI. Run nixfmt over it: 73 lines
reflowed, no semantic changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@moq-bot moq-bot Bot mentioned this pull request May 30, 2026
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