diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index 392a4dd..24bc8ba 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -25,6 +25,11 @@ jobs: runs-on: ubuntu-latest env: ACTIONLINT_VERSION: v1.7.12 + # Keep in step with the shellcheck-version/shellcheck-sha256 defaults in + # shell-ci.yml and workflow-lint.yml: this repository should not lint + # itself to a weaker standard than the one it ships to consumers. + SHELLCHECK_VERSION: v0.11.0 + SHELLCHECK_SHA256: 8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -44,5 +49,23 @@ jobs: if: steps.actionlint-cache.outputs.cache-hit != 'true' run: go install "github.com/rhysd/actionlint/cmd/actionlint@${ACTIONLINT_VERSION}" + - name: Install shellcheck + run: | + set -euo pipefail + # actionlint's embedded shellcheck pass otherwise falls back to the + # runner image's floating shellcheck, which is exactly what the + # workflow-lint reusable installs a pinned, verified one to avoid. + dir="$RUNNER_TEMP/shellcheck-bin" + tarball="$RUNNER_TEMP/shellcheck.tar.xz" + mkdir -p "$dir" + curl -sSfL -o "$tarball" \ + "https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" + printf '%s %s\n' "$SHELLCHECK_SHA256" "$tarball" | sha256sum -c - + tar -xJ -f "$tarball" -C "$dir" --strip-components=1 "shellcheck-${SHELLCHECK_VERSION}/shellcheck" + chmod +x "$dir/shellcheck" + echo "SHELLCHECK_BIN=$dir/shellcheck" >> "$GITHUB_ENV" + - name: Run actionlint - run: actionlint -color + env: + SHELLCHECK_BIN: ${{ env.SHELLCHECK_BIN }} + run: actionlint -color "-shellcheck=${SHELLCHECK_BIN}" diff --git a/.github/workflows/shell-ci.yml b/.github/workflows/shell-ci.yml index b71657b..d21d501 100644 --- a/.github/workflows/shell-ci.yml +++ b/.github/workflows/shell-ci.yml @@ -19,6 +19,10 @@ on: description: Exact shellcheck release tag to install from koalaman/shellcheck; bumped via .github releases type: string default: "v0.11.0" + shellcheck-sha256: + description: sha256 of that release's linux.x86_64 tarball; travels with shellcheck-version, so overriding one without the other fails the install + type: string + default: "8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198" test-command: description: Command running the repository's shell test suite (skipped when empty) type: string @@ -70,16 +74,22 @@ jobs: - name: Install shellcheck env: SHELLCHECK_VERSION: ${{ inputs.shellcheck-version }} + SHELLCHECK_SHA256: ${{ inputs.shellcheck-sha256 }} run: | set -euo pipefail - # Pinned by version, not whatever shellcheck the runner image - # happens to ship — the version pin is the control here; the - # tarball comes straight from koalaman/shellcheck's own GitHub - # release over HTTPS, so there is no separate checksum to embed. + # Pinned by version and by content. Every other tool here arrives + # through a registry that verifies what it hands over (Go's sumdb, + # crates.io, PyPI); this is a plain download, so the checksum is the + # only thing standing between us and whatever the transport returns. + # It has to land in a file first: piping curl into tar extracts the + # bytes before anything can check them. dir="$RUNNER_TEMP/shellcheck-bin" + tarball="$RUNNER_TEMP/shellcheck.tar.xz" mkdir -p "$dir" - curl -sSfL "https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" \ - | tar -xJ -C "$dir" --strip-components=1 "shellcheck-${SHELLCHECK_VERSION}/shellcheck" + curl -sSfL -o "$tarball" \ + "https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" + printf '%s %s\n' "$SHELLCHECK_SHA256" "$tarball" | sha256sum -c - + tar -xJ -f "$tarball" -C "$dir" --strip-components=1 "shellcheck-${SHELLCHECK_VERSION}/shellcheck" chmod +x "$dir/shellcheck" echo "$dir" >> "$GITHUB_PATH" diff --git a/.github/workflows/workflow-lint.yml b/.github/workflows/workflow-lint.yml index f7ae0e8..f5c4efe 100644 --- a/.github/workflows/workflow-lint.yml +++ b/.github/workflows/workflow-lint.yml @@ -22,6 +22,10 @@ on: description: Exact shellcheck release tag to install from koalaman/shellcheck for actionlint's embedded shellcheck pass; bumped via .github releases type: string default: "v0.11.0" + shellcheck-sha256: + description: sha256 of that release's linux.x86_64 tarball; travels with shellcheck-version, so overriding one without the other fails the install + type: string + default: "8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198" permissions: contents: read @@ -58,15 +62,20 @@ jobs: - name: Install shellcheck env: SHELLCHECK_VERSION: ${{ inputs.shellcheck-version }} + SHELLCHECK_SHA256: ${{ inputs.shellcheck-sha256 }} run: | set -euo pipefail - # Same pinned-download idiom as shell-ci.yml: fetch straight from - # koalaman/shellcheck's own release over HTTPS, pinned by tag rather - # than whatever the runner image happens to preinstall. + # Same verified-download idiom as shell-ci.yml: pinned by tag rather + # than whatever the runner image preinstalls, and checked against the + # release's sha256 before extraction, since a plain HTTPS fetch has no + # registry behind it vouching for what came back. dir="$RUNNER_TEMP/shellcheck-bin" + tarball="$RUNNER_TEMP/shellcheck.tar.xz" mkdir -p "$dir" - curl -sSfL "https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" \ - | tar -xJ -C "$dir" --strip-components=1 "shellcheck-${SHELLCHECK_VERSION}/shellcheck" + curl -sSfL -o "$tarball" \ + "https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" + printf '%s %s\n' "$SHELLCHECK_SHA256" "$tarball" | sha256sum -c - + tar -xJ -f "$tarball" -C "$dir" --strip-components=1 "shellcheck-${SHELLCHECK_VERSION}/shellcheck" chmod +x "$dir/shellcheck" echo "SHELLCHECK_BIN=$dir/shellcheck" >> "$GITHUB_ENV" diff --git a/.gitignore b/.gitignore index 6c89d15..0bef723 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ # OS .DS_Store Thumbs.db + +# Python — scripts/ holds the docs generator; running it leaves bytecode behind +__pycache__/ +*.py[cod] diff --git a/docs/reusables/README.md b/docs/reusables/README.md index 6112dc4..573bb70 100644 --- a/docs/reusables/README.md +++ b/docs/reusables/README.md @@ -25,8 +25,8 @@ which blocks every pull request until someone works out why. | [`rust-fuzz`](rust-fuzz.md) | 1 | 0 | 7 | | [`rust-supply-chain`](rust-supply-chain.md) | 1 | 0 | 5 | | [`schedule-freshness`](schedule-freshness.md) | 1 | 0 | 2 | -| [`shell-ci`](shell-ci.md) | 2 | 1 | 5 | -| [`workflow-lint`](workflow-lint.md) | 1 | 0 | 1 | +| [`shell-ci`](shell-ci.md) | 2 | 1 | 6 | +| [`workflow-lint`](workflow-lint.md) | 1 | 0 | 2 | *Conditional* checks only run when an input turns them on, so they emit no check name at all when it is left at its default. diff --git a/docs/reusables/shell-ci.md b/docs/reusables/shell-ci.md index a145ff0..689ab12 100644 --- a/docs/reusables/shell-ci.md +++ b/docs/reusables/shell-ci.md @@ -39,6 +39,7 @@ check is created. | `working-directory` | string | `.` | no | Directory to scan for shell scripts | | `severity` | string | `style` | no | Minimum shellcheck severity to report (style\|info\|warning\|error) | | `shellcheck-version` | string | `v0.11.0` | no | Exact shellcheck release tag to install from koalaman/shellcheck; bumped via .github releases | +| `shellcheck-sha256` | string | `8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198` | no | sha256 of that release's linux.x86_64 tarball; travels with shellcheck-version, so overriding one without the other fails the install | | `test-command` | string | — | no | Command running the repository's shell test suite (skipped when empty) | | `apt-packages` | string | — | no | Space-separated apt packages the test suite needs | diff --git a/docs/reusables/workflow-lint.md b/docs/reusables/workflow-lint.md index 14ef54c..d6c7e85 100644 --- a/docs/reusables/workflow-lint.md +++ b/docs/reusables/workflow-lint.md @@ -31,6 +31,7 @@ a required check whose name nothing emits blocks every pull request. | Input | Type | Default | Required | Description | |---|---|---|---|---| | `shellcheck-version` | string | `v0.11.0` | no | Exact shellcheck release tag to install from koalaman/shellcheck for actionlint's embedded shellcheck pass; bumped via .github releases | +| `shellcheck-sha256` | string | `8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198` | no | sha256 of that release's linux.x86_64 tarball; travels with shellcheck-version, so overriding one without the other fails the install | ---