Skip to content

chore(shellcheck): add yarn shellcheck script and CI workflow#3300

Draft
kriskowal wants to merge 2 commits into
masterfrom
kriskowal-shellcheck-ci
Draft

chore(shellcheck): add yarn shellcheck script and CI workflow#3300
kriskowal wants to merge 2 commits into
masterfrom
kriskowal-shellcheck-ci

Conversation

@kriskowal

Copy link
Copy Markdown
Member

Description

Adds a yarn shellcheck gate that lint-checks every tracked shell script in the repository, and brings the existing scripts into compliance with it.

The wrapper (scripts/shellcheck.sh) enumerates git ls-files '*.sh' and runs shellcheck -S warning over the result, forwarding any extra arguments to the underlying checker. The file list is streamed to shellcheck through a git blob (git hash-object -w --stdin, then git cat-file blob) rather than an argument vector or shell variable, so the gate stays clear of ARG_MAX on hosts with many tracked scripts. It exits 0 when the list is empty, so a fork or branch with no shell scripts stays green.

A companion CI workflow runs the gate on push to master and on any pull request whose diff touches a .sh file; the workflow's path filter means a pull request that changes no shell scripts does not trigger it at all. shellcheck ships preinstalled on the ubuntu-latest runner, so the workflow needs no install step.

The remainder of the change fixes the warnings shellcheck reports at -S warning across the scripts that already exist in the tree, so the gate is green from the first run. The fixes are mechanical and do not change runtime behavior: missing shebangs, || exit on cd invocations whose failure should abort, whitespace-safe iteration over find output, read -r, and unambiguous CDPATH=''.

Security Considerations

The workflow runs with contents: read and persist-credentials: false, and pins its actions to commit SHAs in keeping with the repository's existing posture. The gate executes shellcheck over the repository's own tracked scripts and grants no new authority to those scripts.

Scaling Considerations

The workflow only runs when a pull request's diff includes a shell script, so it adds no CI time to the common case. When it does run, it is a single shellcheck pass over a small file set.

Documentation Considerations

None. The yarn shellcheck script is self-describing and the workflow is internal to CI.

Testing Considerations

The gate is its own test: it passes against the current tree because this change also fixes the pre-existing warnings. New shell scripts (or edits to existing ones) that introduce a warning at -S warning will fail the gate in CI.

Compatibility Considerations

No usage patterns change. The script edits preserve existing behavior; the new gate is additive.

Upgrade Considerations

None. This affects developer tooling and CI only, with no runtime or on-chain impact.

kriskowal added 2 commits June 7, 2026 19:43
Address every finding shellcheck emits at -S warning over the
repository's tracked shell scripts. The changes are mechanical and
do not alter runtime behavior:

- Add missing `#!/bin/sh` / `#!/bin/bash` shebangs (SC2148).
- Append `|| exit` to bare `cd` invocations whose failure should
  abort (SC2164).
- Convert `for X in $(find ...)` to `while read; do ...; done < <(find ...)`
  so filenames with whitespace survive (SC2044).
- Convert `find ... | xargs` to `find ... -print0 | xargs -0` for
  the same reason (SC2038).
- Replace `CDPATH=` with `CDPATH=''` so the assignment is
  unambiguous (SC1007).
- Drop an unused `DIR=$(dirname ...)` assignment (SC2034).
- Add `-r` to `read` calls so backslashes round-trip through the
  pipe.

These prepare the tree for the `yarn shellcheck` gate that lands in
the same PR.
Adds a deterministic lint gate over every tracked .sh file in the
repository.

- `scripts/shellcheck.sh` enumerates `git ls-files '*.sh'` and runs
  `shellcheck -S warning` over the list, forwarding any extra args
  to the underlying checker. The file list is streamed through a git
  blob (`git hash-object -w --stdin` then `git cat-file blob $HASH`)
  rather than an argument vector or shell variable, keeping clear of
  ARG_MAX limits on hosts with many tracked .sh files. Exits 0 when
  the list is empty so forks or branches that have not yet adopted a
  shell script stay green.
- `yarn shellcheck` wires the wrapper into the root `package.json`
  scripts table.
- `.github/workflows/shellcheck.yml` runs the gate on push to
  master and on any pull_request that touches a `.sh` file (the
  workflow's `paths:` filter). A pull request that touches no shell
  scripts does not trigger the workflow at all.

shellcheck ships preinstalled on `ubuntu-latest` runners so no
additional dependency or apt install is needed. Action pins follow
the project's existing zizmor-pedantic posture; the workflow scope
grants `contents: read` and the job runs with
`persist-credentials: false`.
@changeset-bot

changeset-bot Bot commented Jun 8, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: a26f747

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

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