Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .github/actions/repo-gate/repo_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ def check_eol_coverage(root: Path, files: list[str]) -> list[str]:
ACTION_FILE = re.compile(r"^\.github/actions/(?:.+/)?action\.ya?ml$")
# A GitHub expression is not shell, so shellcheck would read its braces as syntax.
EXPRESSION_START = "${{"
SHELLCHECK_IMAGE = "koalaman/shellcheck:stable"
SHELLCHECK_IMAGE = "mirror.gcr.io/koalaman/shellcheck:stable"
SHELLCHECK_TIMEOUT = 300
SCHEMA_TIMEOUT = 300
YAML_TIMEOUT = 60
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/validate-task.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ jobs:
uses: raven-actions/actionlint@3d39aea434753780c3b3d4a1a31c854b4dbf49d7 # v2.2.0

- name: Check EditorConfig step
run: docker run --rm --pull=always -v "$PWD":/check --workdir /check mstruebing/editorconfig-checker:latest
run: docker run --rm --pull=always -v "$PWD":/check --workdir /check ghcr.io/editorconfig-checker/editorconfig-checker:latest

# The file list comes from git rather than a glob, and the docker run is skipped rather than invoked on an empty argument list.
# That is how a repo with no shell scripts stays clean instead of failing on a linter's own no-file usage error.
Expand Down Expand Up @@ -226,8 +226,8 @@ jobs:
fi
done
if [ "${#scripts[@]}" -gt 0 ]; then
docker run --rm --pull=always -v "$PWD":/mnt --workdir /mnt koalaman/shellcheck:stable -- "${scripts[@]}"
docker run --rm --pull=always -v "$PWD":/mnt --workdir /mnt mvdan/shfmt:latest -d -- "${scripts[@]}"
docker run --rm --pull=always -v "$PWD":/mnt --workdir /mnt mirror.gcr.io/koalaman/shellcheck:stable -- "${scripts[@]}"
docker run --rm --pull=always -v "$PWD":/mnt --workdir /mnt mirror.gcr.io/mvdan/shfmt:latest -d -- "${scripts[@]}"
else
echo "no shell scripts are tracked"
fi
Expand Down
2 changes: 1 addition & 1 deletion host-setup/linux/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ Two of those are guards rather than previews. `--release --dry-run` on a Proxmox

`--repo` adds the repository's `install.linux` entries to the report or action. Only `apt` package names are accepted. The script does not execute the declaration's `remedy` text. Reading the JSON needs `jq`, which the ordinary fleet install provides.

The scripts are checked by `shellcheck` and `shfmt`, which run in CI over every `.sh` file `git ls-files` returns, plus a tracked, extension-less file whose shebang names bash or sh. A local run uses the same `koalaman/shellcheck:stable` and `mvdan/shfmt:latest` containers. [`tests/test_bootstrap.py`][test-bootstrap] asserts that every tool the spec requires on Linux is one `install-tools.sh` can provide, or a recorded exception. It also asserts each script here is tracked executable, so a fresh checkout can run it.
CI checks the scripts with `shellcheck` and `shfmt`. It runs both over every `.sh` file `git ls-files` returns, plus a tracked, extension-less file whose shebang names bash or sh. A local run uses the same `mirror.gcr.io/koalaman/shellcheck:stable` and `mirror.gcr.io/mvdan/shfmt:latest` containers. [`tests/test_bootstrap.py`][test-bootstrap] asserts that every tool the spec requires on Linux is one `install-tools.sh` can provide, or a recorded exception. It also asserts each script here is tracked executable, so a fresh checkout can run it.

<!-- Repo -->

Expand Down
2 changes: 1 addition & 1 deletion scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Deterministic checks:
- `sha-pin`: every external action or reusable-workflow `uses:` reference is a 40-hex commit SHA, with the documented `dotnet/nbgv@master` exception. References under the scanned repository's owner are also resolved through GitHub. References under another owner are shape-checked only. Local (`./`) and self-repository (`$/`) references name no ref, so they take no pin, and a quoted one is recognized once its quotes are stripped. They resolve differently, though. A `$/` reference and a job-level `./` reusable-workflow call resolve at the calling workflow file's commit, while a `./` action reference resolves against whatever the job checked out, which is the caller's tree where a reusable workflow called from another repository checks out its caller. A reference starting with a bare `.github/` is reported, since GitHub reads it as `owner/repo` rather than as a path.
- `eol`: every path pinned LF in [`.gitattributes`][gitattributes] has the matching [`.editorconfig`][editorconfig] override the line-ending rule requires, with EditorConfig brace syntax expanded. One direction only: an `.editorconfig` LF glob with no git pin is legitimate, since `.editorconfig` governs what the editor writes where git enforces a class it must not guess at.
- `eol-coverage`: the same pins read against the tree instead. A tracked file opening `#!` that git does not resolve to `eol=lf` is an interpreter line a CRLF checkout breaks, and a pin matching no tracked file is dead unless its block is marked `forward-declared`.
- `composite-actions`: every tracked `action.yml` or `action.yaml` under `.github/actions/`, at any depth, is shellchecked and schema-checked, because actionlint reads workflows only. Each non-empty `run:` body of a bash, sh, or unset-shell step goes to shellcheck. Every `${{ }}` expression is replaced by a placeholder first. A finding names the action file and the step. A pwsh or python step is skipped. The file set goes to `check-jsonschema`'s `vendor.github-actions` builtin through `uvx check-jsonschema@latest`, or `pipx run` where `uvx` is absent. Shellcheck runs from the `koalaman/shellcheck:stable` image, so the check needs Docker. It reads the action through PyYAML, in process where it is importable and through `uvx --with pyyaml` otherwise. Each half reports its own missing tool. Bodies run at warning severity without SC2154, so this is weaker than shellcheck over a `.sh` file. A tree with no action file is skipped with a note.
- `composite-actions`: every tracked `action.yml` or `action.yaml` under `.github/actions/`, at any depth, is shellchecked and schema-checked, because actionlint reads workflows only. Each non-empty `run:` body of a bash, sh, or unset-shell step goes to shellcheck. Every `${{ }}` expression is replaced by a placeholder first. A finding names the action file and the step. A pwsh or python step is skipped. The file set goes to `check-jsonschema`'s `vendor.github-actions` builtin through `uvx check-jsonschema@latest`, or `pipx run` where `uvx` is absent. Shellcheck runs from the `mirror.gcr.io/koalaman/shellcheck:stable` image, so the check needs Docker. It reads the action through PyYAML, in process where it is importable and through `uvx --with pyyaml` otherwise. Each half reports its own missing tool. Bodies run at warning severity without SC2154, so this is weaker than shellcheck over a `.sh` file. A tree with no action file is skipped with a note.

```sh
python3 scripts/repo_gate.py
Expand Down
17 changes: 14 additions & 3 deletions scripts/docker_lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@ class Linter:
NODE_MODULES_EXCLUDE = ":(glob,exclude)**/node_modules/**"

LINTERS = (
Linter("editorconfig-checker", "mstruebing/editorconfig-checker:latest", (), "/check"),
Linter(
"editorconfig-checker",
"ghcr.io/editorconfig-checker/editorconfig-checker:latest",
(),
"/check",
),
Linter(
"actionlint",
"rhysd/actionlint:latest",
Expand All @@ -62,10 +67,16 @@ class Linter:
"/workdir",
arguments=("--no-progress",),
),
Linter("shellcheck", "koalaman/shellcheck:stable", ("*.sh",), "/mnt", discover_shebang=True),
Linter(
"shellcheck",
"mirror.gcr.io/koalaman/shellcheck:stable",
("*.sh",),
"/mnt",
discover_shebang=True,
),
Linter(
"shfmt",
"mvdan/shfmt:latest",
"mirror.gcr.io/mvdan/shfmt:latest",
("*.sh",),
"/mnt",
arguments=("-d",),
Expand Down
Loading