From 500d36ecc98947f747419bdae6ec92bfd3b8e25f Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Fri, 23 Oct 2026 13:22:34 +0100 Subject: [PATCH 1/7] CCM-24467: Implement Mise and Prek --- .github/actions/lint-terraform/action.yaml | 3 +-- docs/github-actions/lint-terraform.md | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/actions/lint-terraform/action.yaml b/.github/actions/lint-terraform/action.yaml index 71c61134..85bb9d94 100644 --- a/.github/actions/lint-terraform/action.yaml +++ b/.github/actions/lint-terraform/action.yaml @@ -10,8 +10,7 @@ runs: - name: "Install Terraform binary" shell: bash run: | - asdf plugin add terraform || true - asdf install terraform || true + MISE_LOCKED=1 mise install terraform - name: "Check Terraform format" shell: bash run: | diff --git a/docs/github-actions/lint-terraform.md b/docs/github-actions/lint-terraform.md index bb98340d..a860937b 100644 --- a/docs/github-actions/lint-terraform.md +++ b/docs/github-actions/lint-terraform.md @@ -23,12 +23,16 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Setup mise + uses: jdx/mise-action@v4 + - name: Lint Terraform uses: NHSDigital/nhs-notify-shared-modules/.github/actions/lint-terraform@v1.0.0 ``` ### Details +- Requires: `mise` on the runner's `PATH` and Terraform pinned in the repository's `mise.toml` and `mise.lock` - Tool: `terraform fmt` - Checks: Terraform code formatting - Validates: HCL syntax and style From e96da267cf3bfafad48a72b92ba293713d8dd3bc Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Fri, 23 Oct 2026 14:39:41 +0100 Subject: [PATCH 2/7] CCM-24467: Implement Mise and Prek --- .tool-versions => .docker-versions | 17 +- .github/workflows/cicd-1-pull-request.yaml | 8 +- .github/workflows/cicd-3-deploy.yaml | 8 +- .github/workflows/release_created.yaml | 4 +- .github/workflows/stage-1-commit.yaml | 9 +- docs/github-actions/setup.md | 2 +- docs/pre-commit-hooks.md | 4 +- mise.lock | 421 ++++++++++++++++++ mise.toml | 20 + .../config/.repository-template-sync-merge | 2 +- scripts/config/check-todos-ignore.conf | 2 +- scripts/devcontainer/postcreatecommand.sh | 43 +- scripts/docker/docker.lib.sh | 12 +- scripts/docker/docker.mk | 2 +- ...ol-versions.test => .docker-versions.test} | 0 scripts/docker/tests/Dockerfile | 2 +- scripts/docker/tests/docker.test.sh | 2 +- scripts/init.mk | 20 +- scripts/maintenance/merge.js | 2 +- scripts/terraform/terraform.mk | 2 +- 20 files changed, 520 insertions(+), 62 deletions(-) rename .tool-versions => .docker-versions (85%) create mode 100644 mise.lock create mode 100644 mise.toml rename scripts/docker/tests/{.tool-versions.test => .docker-versions.test} (100%) diff --git a/.tool-versions b/.docker-versions similarity index 85% rename from .tool-versions rename to .docker-versions index 5f4a288c..e96deb6e 100644 --- a/.tool-versions +++ b/.docker-versions @@ -1,20 +1,5 @@ -act 0.2.64 -gitleaks 8.24.0 -jq 1.6 -nodejs 22.15.1 -pre-commit 3.6.0 -pnpm 11.15.1 -terraform 1.10.1 -terraform-docs 0.24.0 -trivy 0.69.2 -vale 3.6.0 -python 3.13.5 -ruby 3.2.0 +# Docker image versions, read by scripts/docker/docker.lib.sh. CLI tool versions are pinned in mise.toml. -# ============================================================================== -# The section below is reserved for Docker image versions. - -# TODO: Move this section - consider using a different file for the repository template dependencies. # docker/ghcr.io/anchore/grype v0.104.3@sha256:d340f4f8b3b7e6e72a6c9c0152f25402ed8a2d7375dba1dfce4e53115242feb6 # SEE: https://github.com/anchore/grype/pkgs/container/grype # docker/ghcr.io/anchore/syft v1.39.0@sha256:6f13bb010923c33fb197047c8f88888e77071bd32596b3f605d62a133e493ce4 # SEE: https://github.com/anchore/syft/pkgs/container/syft # docker/ghcr.io/gitleaks/gitleaks:v8.24.0@sha256:b8e9bf46893c2f20e10bfb4b2e783adaef519dea981b01ca6221ac325e836040 # SEE: https://github.com/gitleaks/gitleaks/pkgs/container/gitleaks diff --git a/.github/workflows/cicd-1-pull-request.yaml b/.github/workflows/cicd-1-pull-request.yaml index 935f109e..a78be2cb 100644 --- a/.github/workflows/cicd-1-pull-request.yaml +++ b/.github/workflows/cicd-1-pull-request.yaml @@ -53,10 +53,10 @@ jobs: echo "build_datetime=$datetime" >> $GITHUB_OUTPUT echo "build_timestamp=$(date --date=$datetime -u +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT echo "build_epoch=$(date --date=$datetime -u +'%s')" >> $GITHUB_OUTPUT - echo "nodejs_version=$(grep "^nodejs\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT - echo "pnpm_version=$(grep "^pnpm\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT - echo "python_version=$(grep "^python\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT - echo "terraform_version=$(grep "^terraform\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT + echo "nodejs_version=$(grep -E '^node\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT + echo "pnpm_version=$(grep -E '^pnpm\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT + echo "python_version=$(grep -E '^python\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT + echo "terraform_version=$(grep -E '^terraform\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT echo "version=$(echo $version)" >> $GITHUB_OUTPUT echo "is_version_prerelease=$(if [[ $version == *-* ]]; then echo "true"; else echo "false"; fi)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/cicd-3-deploy.yaml b/.github/workflows/cicd-3-deploy.yaml index c5fb55ba..4b68aad8 100644 --- a/.github/workflows/cicd-3-deploy.yaml +++ b/.github/workflows/cicd-3-deploy.yaml @@ -46,10 +46,10 @@ jobs: echo "build_datetime=$datetime" >> $GITHUB_OUTPUT echo "build_timestamp=$(date --date=$datetime -u +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT echo "build_epoch=$(date --date=$datetime -u +'%s')" >> $GITHUB_OUTPUT - echo "nodejs_version=$(grep "^nodejs\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT - echo "pnpm_version=$(grep "^pnpm\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT - echo "python_version=$(grep "^python\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT - echo "terraform_version=$(grep "^terraform\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT + echo "nodejs_version=$(grep -E '^node\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT + echo "pnpm_version=$(grep -E '^pnpm\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT + echo "python_version=$(grep -E '^python\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT + echo "terraform_version=$(grep -E '^terraform\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT echo "version=$(head -n 1 .version 2> /dev/null || echo unknown)" >> $GITHUB_OUTPUT # echo "tag=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT - name: "List variables" diff --git a/.github/workflows/release_created.yaml b/.github/workflows/release_created.yaml index a6df2b62..e84d36cc 100644 --- a/.github/workflows/release_created.yaml +++ b/.github/workflows/release_created.yaml @@ -34,8 +34,8 @@ jobs: - name: "Set CI/CD variables" id: variables run: | - echo "nodejs_version=$(grep "^nodejs\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT - echo "pnpm_version=$(grep "^pnpm\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT + echo "nodejs_version=$(grep -E '^node\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT + echo "pnpm_version=$(grep -E '^pnpm\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT deploy-main: name: Package and Publish Terraform Modules to GitHub Releases assets runs-on: ubuntu-latest diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml index e8689292..68c85c00 100644 --- a/.github/workflows/stage-1-commit.yaml +++ b/.github/workflows/stage-1-commit.yaml @@ -156,8 +156,13 @@ jobs: steps: - name: "Checkout code" uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: "Setup ASDF" - uses: asdf-vm/actions/setup@b7bcd026f18772e44fe1026d729e1611cc435d47 # v4.0.1 + - name: "Setup mise" + uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4.3.0 + with: + install: true + cache: true + env: + MISE_LOCKED: "1" - name: "Lint Terraform" uses: ./.github/actions/lint-terraform count-lines-of-code: diff --git a/docs/github-actions/setup.md b/docs/github-actions/setup.md index 8b160c51..32d865e6 100644 --- a/docs/github-actions/setup.md +++ b/docs/github-actions/setup.md @@ -39,7 +39,7 @@ jobs: ### What Gets Installed -- asdf/mise tools from `.tool-versions` +- mise tools from `mise.toml`, verified against `mise.lock` - Ruby gems via Bundler - Node packages via npm/pnpm - Python packages via pip diff --git a/docs/pre-commit-hooks.md b/docs/pre-commit-hooks.md index 0a946769..54ae526d 100644 --- a/docs/pre-commit-hooks.md +++ b/docs/pre-commit-hooks.md @@ -131,7 +131,7 @@ Runs the same SBOM and Grype dependency scan used in CI and prints the markdown Run it manually when needed: ```bash -pre-commit run --config scripts/config/pre-commit.yaml --hook-stage manual scan-dependencies +prek run --config scripts/config/pre-commit.yaml --hook-stage manual scan-dependencies ``` ## Setup in Your Repository @@ -154,7 +154,7 @@ repos: Then install: ```bash -pre-commit install +prek install ``` ## Notes diff --git a/mise.lock b/mise.lock new file mode 100644 index 00000000..d0035e86 --- /dev/null +++ b/mise.lock @@ -0,0 +1,421 @@ +# @generated - this file is auto-generated by `mise lock` https://mise.jdx.dev/dev-tools/mise-lock.html + +lockfile_version = 3 + +[[tools.act]] +version = "0.2.64" +backend = "aqua:nektos/act" +specifiers = ["0.2.64"] + +[tools.act."platforms.linux-arm64"] +checksum = "sha256:b1f8540efcb97943374344c03566cbd7f07b074a4bb572a740f144c6f26697b4" +url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901806" + +[tools.act."platforms.linux-arm64-musl"] +checksum = "sha256:b1f8540efcb97943374344c03566cbd7f07b074a4bb572a740f144c6f26697b4" +url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901806" + +[tools.act."platforms.linux-x64"] +checksum = "sha256:78af3327620fed8b736794803a638e730083e2f25caa52aa0108d2fb9670a0ad" +url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Linux_x86_64.tar.gz" +url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901803" + +[tools.act."platforms.linux-x64-musl"] +checksum = "sha256:78af3327620fed8b736794803a638e730083e2f25caa52aa0108d2fb9670a0ad" +url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Linux_x86_64.tar.gz" +url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901803" + +[tools.act."platforms.macos-arm64"] +checksum = "sha256:8a0232ba98b883d23b45ce1085fbc77140e1ce0eb5244cc8ed8c52d208917bf5" +url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Darwin_arm64.tar.gz" +url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901814" + +[tools.act."platforms.macos-x64"] +checksum = "sha256:efb8fca836115294644f857c83d65e0cd2098e371e0925f32e837f3231e87d39" +url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Darwin_x86_64.tar.gz" +url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901804" + +[tools.act."platforms.windows-x64"] +checksum = "sha256:c04de9fd6f6dd651c638b199c15b16e64981696c9ba9b465545faba340b6bef4" +url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Windows_x86_64.zip" +url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901807" + +[[tools.gitleaks]] +version = "8.24.0" +backend = "aqua:gitleaks/gitleaks" +specifiers = ["8.24.0"] + +[tools.gitleaks."platforms.linux-arm64"] +checksum = "sha256:3755cc9b81f2466ad308f722a064ca04df27f59d551396183efe07978fef8fcb" +url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829270" + +[tools.gitleaks."platforms.linux-arm64-musl"] +checksum = "sha256:3755cc9b81f2466ad308f722a064ca04df27f59d551396183efe07978fef8fcb" +url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829270" + +[tools.gitleaks."platforms.linux-x64"] +checksum = "sha256:cb49b7de5ee986510fe8666ca0273a6cc15eb82571f2f14832c9e8920751f3a4" +url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_linux_x64.tar.gz" +url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829275" + +[tools.gitleaks."platforms.linux-x64-musl"] +checksum = "sha256:cb49b7de5ee986510fe8666ca0273a6cc15eb82571f2f14832c9e8920751f3a4" +url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_linux_x64.tar.gz" +url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829275" + +[tools.gitleaks."platforms.macos-arm64"] +checksum = "sha256:a3d281867df087ded8c2f9afd35d61ff923a25e64caa127b720991ee433d763b" +url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_darwin_arm64.tar.gz" +url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829277" + +[tools.gitleaks."platforms.macos-x64"] +checksum = "sha256:bd9ed3294c086f10dcc5fc25de57d44ba940c19c1a5a3d5f1cfeb10b9dff005e" +url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_darwin_x64.tar.gz" +url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829271" + +[tools.gitleaks."platforms.windows-x64"] +checksum = "sha256:dab91070b01feec49bd157375085c93a16fe85e13b3bff6916aaaa0a3b3b5fac" +url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_windows_x64.zip" +url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829282" + +[[tools.jq]] +version = "1.6" +backend = "aqua:jqlang/jq" +specifiers = ["1.6"] + +[tools.jq."platforms.linux-x64"] +url = "https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux64" +url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/9521005" + +[tools.jq."platforms.linux-x64-musl"] +url = "https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux64" +url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/9521005" + +[tools.jq."platforms.macos-arm64"] +url = "https://github.com/jqlang/jq/releases/download/jq-1.6/jq-osx-amd64" +url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/9521006" + +[tools.jq."platforms.macos-x64"] +url = "https://github.com/jqlang/jq/releases/download/jq-1.6/jq-osx-amd64" +url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/9521006" + +[tools.jq."platforms.windows-x64"] +url = "https://github.com/jqlang/jq/releases/download/jq-1.6/jq-win64.exe" +url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/9521008" + +[[tools.node]] +version = "22.15.1" +backend = "core:node" +specifiers = ["22.15.1"] + +[tools.node."platforms.linux-arm64"] +checksum = "sha256:eb3f232b83dfe83397b98395ec77a973e888e8959c978b3e4eeb551b8845b74f" +url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1-linux-arm64.tar.gz" + +[tools.node."platforms.linux-arm64-musl"] +checksum = "sha256:38aea029f8818f7783f273fbc70dcf930f9ef54bdd49c5f90c0152caec7a57be" +url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1.tar.gz" +install = "source" + +[tools.node."platforms.linux-x64"] +checksum = "sha256:f4b8eec683708acb1a2a73c7182ba2de5466a5dd5f705934a0830903df28821c" +url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1-linux-x64.tar.gz" + +[tools.node."platforms.linux-x64-musl"] +checksum = "sha256:408fee9895ac6ba4a1893c7be66aba5cb2c995b4c15d5fa09fabbe4f44497fbd" +url = "https://unofficial-builds.nodejs.org/download/release/v22.15.1/node-v22.15.1-linux-x64-musl.tar.gz" + +[tools.node."platforms.macos-arm64"] +checksum = "sha256:d2689b86b17e1b51e76f801ffe2d9acca4225e76eda4b843c3d8438d4a7cd6fe" +url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1-darwin-arm64.tar.gz" + +[tools.node."platforms.macos-x64"] +checksum = "sha256:1c722d0dd6d3f60e8b0be014ea01b8a59f5088f4419197a1b37544854d61cc6f" +url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1-darwin-x64.tar.gz" + +[tools.node."platforms.windows-x64"] +checksum = "sha256:7c7997d6ef2efd9525a54b033fc0be6f22549a5905f5da6573a41e61a436a1b5" +url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1-win-x64.zip" + +[[tools.pnpm]] +version = "11.15.1" +backend = "aqua:pnpm/pnpm" +specifiers = ["11.15.1"] + +[tools.pnpm."platforms.linux-arm64"] +checksum = "sha256:361e385867146972d0635a41a1871cb44c9c23f65acce78a5f1ca1d44ac0afcd" +url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-linux-arm64.tar.gz" +url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780455" +provenance = "github-attestations" + +[tools.pnpm."platforms.linux-arm64-musl"] +checksum = "sha256:5e293db656ee6a54387945572e06f08245140a7427c8e67b821d56471f373b77" +url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-linux-arm64-musl.tar.gz" +url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780459" +provenance = "github-attestations" + +[tools.pnpm."platforms.linux-x64"] +checksum = "sha256:0c1373b6390f6b89ff8b896d3647c9826577ddc49173a2f732da69b36569f9e0" +url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-linux-x64.tar.gz" +url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780457" +provenance = "github-attestations" + +[tools.pnpm."platforms.linux-x64-musl"] +checksum = "sha256:593039435b88cb4e15c60c18ba032a1ae6a28159287199f20aacc44ad553a094" +url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-linux-x64-musl.tar.gz" +url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780453" +provenance = "github-attestations" + +[tools.pnpm."platforms.macos-arm64"] +checksum = "sha256:4ff53ecc9de8df115d4efef60eab77f91be4f8237cdaca078351a22e707d1849" +url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-darwin-arm64.tar.gz" +url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780456" +provenance = "github-attestations" + +[tools.pnpm."platforms.windows-x64"] +checksum = "sha256:e9179d727211d5556e969fccfa36f828392892c54728a711c9da1cc3093f7900" +url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-win32-x64.zip" +url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780452" +provenance = "github-attestations" + +[[tools.prek]] +version = "0.5.7" +backend = "aqua:j178/prek" +specifiers = ["0.5.7"] + +[tools.prek."platforms.linux-arm64"] +checksum = "sha256:98bdb31002ca42b61f4f6c746b2de351aee4e1f29c95f8dec8ec3b9a62929c1e" +url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929498" +provenance = "github-attestations" + +[tools.prek."platforms.linux-arm64-musl"] +checksum = "sha256:022ddbaef649d83ab7e0cfde13400612b896b04cce338623205525560d47bcf6" +url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929502" +provenance = "github-attestations" + +[tools.prek."platforms.linux-x64"] +checksum = "sha256:e238e5a6b4e384e8d18f33d3c3b1a329be0e1237f77ac6e021e641ddd3a2bab6" +url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929556" +provenance = "github-attestations" + +[tools.prek."platforms.linux-x64-musl"] +checksum = "sha256:25d6a0316125127aed3ad7010128884d7e7243c4ac06f084218b98dc20020ca9" +url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929599" +provenance = "github-attestations" + +[tools.prek."platforms.macos-arm64"] +checksum = "sha256:800c5b9c8239045bbdf4201957dd4175135e216e838c40a6ec1904ff18ebaf2c" +url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-aarch64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929480" +provenance = "github-attestations" + +[tools.prek."platforms.macos-x64"] +checksum = "sha256:12b65c6685fc44ff9130c0bf5dcb01be69c0c81d9a0709553fd369c3b2010815" +url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-apple-darwin.tar.gz" +url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929524" +provenance = "github-attestations" + +[tools.prek."platforms.windows-x64"] +checksum = "sha256:50ccc606e19965585807c0a8be99da82eb4237c7c9df2539e5a83704d1f16a36" +url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-pc-windows-msvc.zip" +url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929530" +provenance = "github-attestations" + +[[tools.python]] +version = "3.13.5" +backend = "core:python" +specifiers = ["3.13.5"] + +[tools.python."platforms.linux-arm64"] +checksum = "sha256:65412f4d99966ab9e0218211c1408497b5ecd2a40e1bd12183a37937c25cce4e" +url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-aarch64-unknown-linux-gnu-install_only_stripped.tar.gz" +provenance = "github-attestations" + +[tools.python."platforms.linux-x64"] +checksum = "sha256:f7ac16748be2674ec14df532a3e48d0c6f215017b537f14ca3feb837dbe86292" +url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz" +provenance = "github-attestations" + +[tools.python."platforms.linux-x64-musl"] +checksum = "sha256:8ba1a81e371263b668667ca66234c0422dfff212005a5fb0ced0dbc5011be942" +url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-x86_64-unknown-linux-musl-install_only_stripped.tar.gz" +provenance = "github-attestations" + +[tools.python."platforms.macos-arm64"] +checksum = "sha256:a2c25baa13d271b730744d7e8684d7db54a003dfeeb5ae3b0ae86af7d81d44ae" +url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-aarch64-apple-darwin-install_only_stripped.tar.gz" +provenance = "github-attestations" + +[tools.python."platforms.macos-x64"] +checksum = "sha256:c198610998092c42650600ef250be388ba27ab307ade4d8684c27af9a0b5569a" +url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-x86_64-apple-darwin-install_only_stripped.tar.gz" +provenance = "github-attestations" + +[tools.python."platforms.windows-x64"] +checksum = "sha256:4d88fdda4a59e0d6d45953c37c2fcb4e114dd5a2d41cb5b24b75b42ab8328ff8" +url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-x86_64-pc-windows-msvc-install_only_stripped.tar.gz" +provenance = "github-attestations" + +[[tools.ruby]] +version = "3.2.0" +backend = "core:ruby" +specifiers = ["3.2.0"] + +[tools.ruby.options] +compile = "false" +precompiled_url = "jdx/ruby" +ruby_build_repo = "https://github.com/rbenv/ruby-build.git" +ruby_install = "false" + +[tools.ruby."platforms.linux-arm64"] +checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" +url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" + +[tools.ruby."platforms.linux-arm64-musl"] +checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" +url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" + +[tools.ruby."platforms.linux-x64"] +checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" +url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" + +[tools.ruby."platforms.linux-x64-musl"] +checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" +url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" + +[tools.ruby."platforms.macos-arm64"] +checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" +url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" + +[tools.ruby."platforms.macos-x64"] +checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" +url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" + +[[tools.ruby]] +version = "3.2.0" +backend = "core:ruby" +specifiers = ["3.2.0"] + +[tools.ruby."platforms.windows-x64"] +url = "https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-3.2.0-1/rubyinstaller-3.2.0-1-x64.7z" + +[[tools.terraform]] +version = "1.10.1" +backend = "aqua:hashicorp/terraform" +specifiers = ["1.10.1"] + +[tools.terraform."platforms.linux-arm64"] +checksum = "sha256:6375a763b7784e47b4314e939a8c15f357db718d932e82825d87392abb5d1e09" +url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_linux_arm64.zip" + +[tools.terraform."platforms.linux-arm64-musl"] +checksum = "sha256:6375a763b7784e47b4314e939a8c15f357db718d932e82825d87392abb5d1e09" +url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_linux_arm64.zip" + +[tools.terraform."platforms.linux-x64"] +checksum = "sha256:d49d4d08ed092a8dec335f1fe3e127d1a285f160557323dd5a84ddc0c8472e1a" +url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_linux_amd64.zip" + +[tools.terraform."platforms.linux-x64-musl"] +checksum = "sha256:d49d4d08ed092a8dec335f1fe3e127d1a285f160557323dd5a84ddc0c8472e1a" +url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_linux_amd64.zip" + +[tools.terraform."platforms.macos-arm64"] +checksum = "sha256:bae8bef4e19a404427a25e1ddc35eeff4ed9afb675c33e2988dfd47f1543ad3b" +url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_darwin_arm64.zip" + +[tools.terraform."platforms.macos-x64"] +checksum = "sha256:9e3e0127c7dbef8a34773820736acbb312a0727149a3b5df07b73f0cf859c261" +url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_darwin_amd64.zip" + +[tools.terraform."platforms.windows-x64"] +checksum = "sha256:c73ff963038d151360928101ba7e228dffbd362f9706499438ba590db3b7ec2e" +url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_windows_amd64.zip" + +[[tools.terraform-docs]] +version = "0.24.0" +backend = "aqua:terraform-docs/terraform-docs" +specifiers = ["0.24.0"] + +[tools.terraform-docs."platforms.linux-arm64"] +checksum = "sha256:d12bd7b73c1fc9c64efc79f8157dd713dabd559f1ecf3cfc0f42e32279a155fd" +url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-linux-arm64.tar.gz" +url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956212" + +[tools.terraform-docs."platforms.linux-arm64-musl"] +checksum = "sha256:d12bd7b73c1fc9c64efc79f8157dd713dabd559f1ecf3cfc0f42e32279a155fd" +url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-linux-arm64.tar.gz" +url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956212" + +[tools.terraform-docs."platforms.linux-x64"] +checksum = "sha256:9005daf969de0b50134493a2c00078b49f5f5b39d021cda7c89bf4d4f3d776d3" +url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-linux-amd64.tar.gz" +url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956208" + +[tools.terraform-docs."platforms.linux-x64-musl"] +checksum = "sha256:9005daf969de0b50134493a2c00078b49f5f5b39d021cda7c89bf4d4f3d776d3" +url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-linux-amd64.tar.gz" +url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956208" + +[tools.terraform-docs."platforms.macos-arm64"] +checksum = "sha256:f6b114f4b032f3f9202ab6c23bfd28c3c8e68aeeb8a8f12fc118bf2073081d71" +url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-darwin-arm64.tar.gz" +url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956237" + +[tools.terraform-docs."platforms.macos-x64"] +checksum = "sha256:3c3f7f18f908457fd1209cbe341418f7f6bae78c08126cfbe8de0d1b06aa8781" +url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-darwin-amd64.tar.gz" +url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956256" + +[tools.terraform-docs."platforms.windows-x64"] +checksum = "sha256:afc02cbdf63726d3e5fb26a077ca1f24acd4820d7e44c21b03a3e030f9266490" +url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-windows-amd64.zip" +url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956245" + +[[tools.vale]] +version = "3.6.0" +backend = "aqua:vale-cli/vale" +specifiers = ["3.6.0"] + +[tools.vale."platforms.linux-arm64"] +checksum = "sha256:45295ab07fd99c87a9cac20dce5d230d7b63ffec1394b38c8d5d4496347a069b" +url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_Linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588938" + +[tools.vale."platforms.linux-arm64-musl"] +checksum = "sha256:45295ab07fd99c87a9cac20dce5d230d7b63ffec1394b38c8d5d4496347a069b" +url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_Linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588938" + +[tools.vale."platforms.linux-x64"] +checksum = "sha256:d27cd03f920202a7be5bba3fd9e784a22fe8b33f838911853588ce3ce594a25d" +url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_Linux_64-bit.tar.gz" +url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588941" + +[tools.vale."platforms.linux-x64-musl"] +checksum = "sha256:d27cd03f920202a7be5bba3fd9e784a22fe8b33f838911853588ce3ce594a25d" +url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_Linux_64-bit.tar.gz" +url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588941" + +[tools.vale."platforms.macos-arm64"] +checksum = "sha256:df71e5fcbefca9413479737fa946e105249ec73e2a328ef1784e5558d92414b0" +url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_macOS_arm64.tar.gz" +url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588939" + +[tools.vale."platforms.macos-x64"] +checksum = "sha256:4d1df61fc3b1e4109bd965b478dad6cb8998e2ca7836100b936c16c331c8c9f2" +url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_macOS_64-bit.tar.gz" +url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588940" + +[tools.vale."platforms.windows-x64"] +checksum = "sha256:6b205cd9ee4df016d42287cd0b2b8f234acb45900fc371cda97a5c49bc69b350" +url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_Windows_64-bit.zip" +url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588942" diff --git a/mise.toml b/mise.toml new file mode 100644 index 00000000..299ddf89 --- /dev/null +++ b/mise.toml @@ -0,0 +1,20 @@ +[settings] +# Record checksums and download URLs in mise.lock; verified on every install +lockfile = true +# Refuse remote code execution paths such as asdf/vfox plugins +disable_backends = ["asdf", "vfox"] +# Ignore releases newer than this when resolving versions, giving time for compromised releases to be yanked +minimum_release_age = "7d" + +[tools] +act = "0.2.64" +gitleaks = "8.24.0" +jq = "1.6" +node = "22.15.1" +pnpm = "11.15.1" +prek = "0.5.7" +python = "3.13.5" +ruby = "3.2.0" +terraform = "1.10.1" +terraform-docs = "0.24.0" +vale = "3.6.0" diff --git a/scripts/config/.repository-template-sync-merge b/scripts/config/.repository-template-sync-merge index 8b5774fd..e9d3d415 100644 --- a/scripts/config/.repository-template-sync-merge +++ b/scripts/config/.repository-template-sync-merge @@ -3,7 +3,7 @@ scripts/config/.repository-template-sync-ignore scripts/config/.repository-template-sync-merge scripts/config/vale/vale.ini -.tool-versions +mise.toml .gitignore scripts/config/vale/styles/config/vocabularies/words/accept.txt scripts/config/vale/styles/config/vocabularies/words/reject.txt diff --git a/scripts/config/check-todos-ignore.conf b/scripts/config/check-todos-ignore.conf index 4a655ca6..5dc93430 100644 --- a/scripts/config/check-todos-ignore.conf +++ b/scripts/config/check-todos-ignore.conf @@ -4,7 +4,7 @@ .devcontainer/devcontainer.json .github/workflows/stage-1-commit.yaml .pre-commit-hooks.yaml -.tool-versions +mise.toml .vscode/extensions.json infrastructure/terraform/bin/terraform.sh Makefile diff --git a/scripts/devcontainer/postcreatecommand.sh b/scripts/devcontainer/postcreatecommand.sh index aefabaf3..0daa560f 100755 --- a/scripts/devcontainer/postcreatecommand.sh +++ b/scripts/devcontainer/postcreatecommand.sh @@ -1,15 +1,44 @@ #!/bin/bash -rm -Rf ~/.asdf -git clone https://github.com/asdf-vm/asdf.git ~/.asdf; -chmod +x ~/.asdf/asdf.sh; -echo '. $HOME/.asdf/asdf.sh' >> ~/.zshrc -echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.zshrc +set -euo pipefail -source ~/.zshrc +# Pinned release verified by checksum, instead of piping an install script to a shell +mise_version="v2026.10.17" -echo 'asdf setup complete' +case "$(uname -m)" in + x86_64) + arch="x64" + sha256="17565e268c5542d8ce944321e17af81e0b741b65af4aa7e8e010ee77376a4aa3" + ;; + aarch64 | arm64) + arch="arm64" + sha256="cac510e51793ad45e65fe92305bdbe4309c9c60b5907badbc7eba111738ab08f" + ;; + *) + echo "Unsupported architecture: $(uname -m)" >&2 + exit 1 + ;; +esac +archive="mise-${mise_version}-linux-${arch}.tar.gz" +tmp_dir="$(mktemp -d)" +trap 'rm -rf "${tmp_dir}"' EXIT + +curl -fsSL --proto '=https' --tlsv1.2 \ + --output "${tmp_dir}/${archive}" \ + "https://github.com/jdx/mise/releases/download/${mise_version}/${archive}" +echo "${sha256} ${tmp_dir}/${archive}" | sha256sum --check --status + +mkdir -p ~/.local/bin +tar -xzf "${tmp_dir}/${archive}" -C "${tmp_dir}" +install -m 0755 "${tmp_dir}/mise/bin/mise" ~/.local/bin/mise + +echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc + +echo 'mise setup complete' + +# Shims put mise-managed tools on PATH for this non-interactive script +export PATH="${HOME}/.local/bin:${HOME}/.local/share/mise/shims:${PATH}" make config jekyll --version && cd docs && bundle install diff --git a/scripts/docker/docker.lib.sh b/scripts/docker/docker.lib.sh index 18787105..f3801afb 100644 --- a/scripts/docker/docker.lib.sh +++ b/scripts/docker/docker.lib.sh @@ -13,7 +13,7 @@ set -euo pipefail # Arguments (provided as environment variables): # DOCKER_IMAGE=ghcr.io/org/repo # Docker image name # DOCKER_TITLE="My Docker image" # Docker image title -# TOOL_VERSIONS=$project_dir/.tool-versions # Path to the tool versions file +# TOOL_VERSIONS=$project_dir/.docker-versions # Path to the Docker image versions file # ============================================================================== # Functions to be used with custom images. @@ -144,7 +144,7 @@ function version-create-effective-file() { # ============================================================================== # Functions to be used with external images. -# Retrieve the Docker image version from the '.tool-versions' file and pull the +# Retrieve the Docker image version from the '.docker-versions' file and pull the # image if required. This function is to be used in conjunction with the # external images and it prevents Docker from downloading an image each time it # is used, since the digest is not stored locally for compressed images. To @@ -157,15 +157,15 @@ function version-create-effective-file() { function docker-get-image-version-and-pull() { # E.g. for the given entry "# docker/ghcr.io/org/image 1.2.3@sha256:hash" in - # the '.tool-versions' file, the following variables will be set to: + # the '.docker-versions' file, the following variables will be set to: # name="ghcr.io/org/image" # version="1.2.3@sha256:hash" # tag="1.2.3" # digest="sha256:hash" - # Get the image full version from the '.tool-versions' file, + # Get the image full version from the '.docker-versions' file, # match it by name and version regex, if given. - local versions_file="${TOOL_VERSIONS:=$(git rev-parse --show-toplevel)/.tool-versions}" + local versions_file="${TOOL_VERSIONS:=$(git rev-parse --show-toplevel)/.docker-versions}" local version="latest" if [ -f "$versions_file" ]; then line=$(grep "docker/${name} " "$versions_file" | sed "s/^#\s*//; s/\s*#.*$//" | grep "${match_version:-".*"}") @@ -218,7 +218,7 @@ function _create-effective-dockerfile() { function _replace-image-latest-by-specific-version() { local dir=${dir:-$PWD} - local versions_file="${TOOL_VERSIONS:=$(git rev-parse --show-toplevel)/.tool-versions}" + local versions_file="${TOOL_VERSIONS:=$(git rev-parse --show-toplevel)/.docker-versions}" local dockerfile="${dir}/Dockerfile.effective" local build_datetime=${BUILD_DATETIME:-$(date -u +'%Y-%m-%dT%H:%M:%S%z')} diff --git a/scripts/docker/docker.mk b/scripts/docker/docker.mk index a31ad9db..42540f39 100644 --- a/scripts/docker/docker.mk +++ b/scripts/docker/docker.mk @@ -45,7 +45,7 @@ docker-example-build: # Build Docker example @ExamplesAndTests cd scripts/docker/examples/python DOCKER_IMAGE=repository-template/docker-example-python DOCKER_TITLE="Repository Template Docker Python Example" - TOOL_VERSIONS="$(shell git rev-parse --show-toplevel)/scripts/docker/examples/python/.tool-versions.example" + TOOL_VERSIONS="$(shell git rev-parse --show-toplevel)/scripts/docker/examples/python/.docker-versions.example" docker-build docker-example-lint: # Lint Docker example @ExamplesAndTests diff --git a/scripts/docker/tests/.tool-versions.test b/scripts/docker/tests/.docker-versions.test similarity index 100% rename from scripts/docker/tests/.tool-versions.test rename to scripts/docker/tests/.docker-versions.test diff --git a/scripts/docker/tests/Dockerfile b/scripts/docker/tests/Dockerfile index b5ea5606..b2d62606 100644 --- a/scripts/docker/tests/Dockerfile +++ b/scripts/docker/tests/Dockerfile @@ -1,3 +1,3 @@ -# `*:latest` will be replaced with a corresponding version stored in the '.tool-versions' file +# `*:latest` will be replaced with a corresponding version stored in the '.docker-versions' file # hadolint ignore=DL3007 FROM python:latest diff --git a/scripts/docker/tests/docker.test.sh b/scripts/docker/tests/docker.test.sh index 8f487b8f..b64c3cf0 100755 --- a/scripts/docker/tests/docker.test.sh +++ b/scripts/docker/tests/docker.test.sh @@ -74,7 +74,7 @@ function test-docker-build() { function test-docker-image-from-signature() { # Arrange - TOOL_VERSIONS="$(git rev-parse --show-toplevel)/scripts/docker/tests/.tool-versions.test" + TOOL_VERSIONS="$(git rev-parse --show-toplevel)/scripts/docker/tests/.docker-versions.test" cp Dockerfile Dockerfile.effective # Act _replace-image-latest-by-specific-version diff --git a/scripts/init.mk b/scripts/init.mk index b3d70139..32de8311 100644 --- a/scripts/init.mk +++ b/scripts/init.mk @@ -30,31 +30,29 @@ shellscript-lint-all: # Lint all shell scripts in this project, do not fail on e done githooks-config: # Trigger Git hooks on commit that are defined in this repository @Configuration - make _install-dependency name="pre-commit" - pre-commit install \ + make _install-dependency name="prek" + prek install \ + --force \ --config scripts/config/pre-commit.yaml \ --install-hooks githooks-run: # Run git hooks configured in this repository @Operations - pre-commit run \ + prek run \ --config scripts/config/pre-commit.yaml \ --all-files githooks-dependencies: # Run git hook for manually scanning depdencies - pre-commit run \ + prek run \ --config scripts/config/pre-commit.yaml \ --hook-stage manual scan-dependencies \ --all-files -_install-dependency: # Install asdf dependency - mandatory: name=[listed in the '.tool-versions' file]; optional: version=[if not listed] +_install-dependency: # Install a tool pinned in 'mise.toml', verified against 'mise.lock' - mandatory: name=[listed in the 'mise.toml' file] echo ${name} - asdf plugin add ${name} ||: - asdf install ${name} $(or ${version},) + MISE_LOCKED=1 mise install ${name} -_install-dependencies: # Install all the dependencies listed in .tool-versions - for plugin in $$(grep ^[a-z] .tool-versions | sed 's/[[:space:]].*//'); do - $(MAKE) _install-dependency name=$${plugin}; \ - done +_install-dependencies: # Install all the dependencies listed in mise.toml + MISE_LOCKED=1 mise install clean:: # Remove all generated and temporary files (common) @Operations rm -rf \ diff --git a/scripts/maintenance/merge.js b/scripts/maintenance/merge.js index 8f5bd6cc..c6cae6ff 100644 --- a/scripts/maintenance/merge.js +++ b/scripts/maintenance/merge.js @@ -2,7 +2,7 @@ * Script to merge all added lines from source to target. * Modified lines will be left intact. * - * This is intended for updating config files like .tool-versions and .gitignore + * This is intended for updating config files like mise.toml and .gitignore * where the first token on the line remains the same * * Usage: diff --git a/scripts/terraform/terraform.mk b/scripts/terraform/terraform.mk index 5e59be7b..4dd03925 100644 --- a/scripts/terraform/terraform.mk +++ b/scripts/terraform/terraform.mk @@ -72,7 +72,7 @@ clean:: # Remove Terraform build artifacts and cache @Operations # ============================================================================== # Installation -terraform-install: # Install Terraform using asdf @Installation +terraform-install: # Install Terraform using mise @Installation # Example: make terraform-install make _install-dependency name="terraform" From c1569f72cf2dd6bda28e900f07ec9a671080d40e Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Fri, 23 Oct 2026 15:50:56 +0100 Subject: [PATCH 3/7] CCM-24467: Implement Mise and Prek --- docs/github-actions.md | 3 - docs/github-actions/trivy-iac.md | 44 --------- docs/github-actions/trivy-package.md | 42 -------- docs/github-actions/trivy.md | 40 -------- .../aws-backup-source/iam_role_backup.tf | 1 - .../modules/kms/data_iam_kms_admin_policy.tf | 1 - .../modules/kms/data_iam_kms_user_policy.tf | 1 - .../data_iam_policy_document_put_logs.tf | 1 - .../terraform/modules/s3bucket/s3_bucket.tf | 1 - scripts/config/trivy.yaml | 6 -- .../config/vocabularies/words/accept.txt | 1 - scripts/terraform/terraform.mk | 5 - scripts/terraform/trivy.sh | 96 ------------------- 13 files changed, 242 deletions(-) delete mode 100644 docs/github-actions/trivy-iac.md delete mode 100644 docs/github-actions/trivy-package.md delete mode 100644 docs/github-actions/trivy.md delete mode 100644 scripts/config/trivy.yaml delete mode 100755 scripts/terraform/trivy.sh diff --git a/docs/github-actions.md b/docs/github-actions.md index baee8e8f..5ce3f824 100644 --- a/docs/github-actions.md +++ b/docs/github-actions.md @@ -26,9 +26,6 @@ This repository provides reusable composite actions for NHS Notify projects. - [Scan Secrets](github-actions/scan-secrets.html) - Scans Git history for secrets - [Setup](github-actions/setup.html) - Installs dependencies and runs make config - [Sync Template Repo](github-actions/sync-template-repo.html) - Syncs repository template changes -- [Trivy](github-actions/trivy.html) - General Trivy security scanner -- [Trivy IaC](github-actions/trivy-iac.html) - Scans Terraform IaC with Trivy -- [Trivy Package](github-actions/trivy-package.html) - Scans packages with Trivy ## Usage diff --git a/docs/github-actions/trivy-iac.md b/docs/github-actions/trivy-iac.md deleted file mode 100644 index d304f059..00000000 --- a/docs/github-actions/trivy-iac.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -layout: default -title: Trivy IaC -parent: GitHub Actions -grand_parent: Home -nav_order: 15 ---- - -## Trivy IaC - -Scans Terraform Infrastructure as Code using Trivy. - -### Description - -This composite action scans Terraform code for security misconfigurations and compliance issues. - -### Usage - -```yaml -jobs: - scan-iac: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Scan Terraform IaC - uses: NHSDigital/nhs-notify-shared-modules/.github/actions/trivy-iac@v1.0.0 -``` - -### Details - -- Tool: Trivy IaC scanner -- Targets: Terraform (.tf) files -- Checks: Security misconfigurations -- Standards: AWS security best practices -- Reports: Terraform-specific vulnerabilities - -### What It Detects - -- Insecure resource configurations -- Missing encryption settings -- Public access misconfigurations -- IAM permission issues -- Non-compliant security group rules diff --git a/docs/github-actions/trivy-package.md b/docs/github-actions/trivy-package.md deleted file mode 100644 index 76025ebb..00000000 --- a/docs/github-actions/trivy-package.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -layout: default -title: Trivy Package -parent: GitHub Actions -grand_parent: Home -nav_order: 16 ---- - -## Trivy Package - -Scans project packages and dependencies using Trivy. - -### Description - -This composite action scans package dependencies for known vulnerabilities using Trivy. - -### Usage - -```yaml -jobs: - scan-packages: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Scan packages - uses: NHSDigital/nhs-notify-shared-modules/.github/actions/trivy-package@v1.0.0 -``` - -### Details - -- Tool: Trivy package scanner -- Targets: Package manifest files -- Scans: npm, Ruby gems, Python packages -- Checks: Known CVEs and vulnerabilities -- Reports: Dependency security issues - -### Package Types Scanned - -- Node.js: `package.json`, `package-lock.json` -- Ruby: `Gemfile`, `Gemfile.lock` -- Python: `requirements.txt`, `Pipfile` diff --git a/docs/github-actions/trivy.md b/docs/github-actions/trivy.md deleted file mode 100644 index bda9c94a..00000000 --- a/docs/github-actions/trivy.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -layout: default -title: Trivy -parent: GitHub Actions -grand_parent: Home -nav_order: 14 ---- - -## Trivy - -General Trivy security scanner. - -### Description - -This composite action runs Trivy security scanner for vulnerability detection. - -### Usage - -```yaml -jobs: - security-scan: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Run Trivy scan - uses: NHSDigital/nhs-notify-shared-modules/.github/actions/trivy@v1.0.0 -``` - -### Details - -- Tool: Trivy security scanner -- Scans: Multiple security aspects -- Detects: Vulnerabilities, misconfigurations, secrets -- Reports: Security findings - -### Related Actions - -- [Trivy IaC](trivy-iac.html) - Infrastructure as Code scanning -- [Trivy Package](trivy-package.html) - Package dependency scanning diff --git a/infrastructure/terraform/modules/aws-backup-source/iam_role_backup.tf b/infrastructure/terraform/modules/aws-backup-source/iam_role_backup.tf index fe8d00ab..bac7c1d2 100644 --- a/infrastructure/terraform/modules/aws-backup-source/iam_role_backup.tf +++ b/infrastructure/terraform/modules/aws-backup-source/iam_role_backup.tf @@ -56,7 +56,6 @@ data "aws_iam_policy_document" "backup_additional" { "backup:TagResource", ] - #trivy:ignore:aws-iam-no-policy-wildcards resources = [ "*", ] diff --git a/infrastructure/terraform/modules/kms/data_iam_kms_admin_policy.tf b/infrastructure/terraform/modules/kms/data_iam_kms_admin_policy.tf index c363415b..25d4fb31 100644 --- a/infrastructure/terraform/modules/kms/data_iam_kms_admin_policy.tf +++ b/infrastructure/terraform/modules/kms/data_iam_kms_admin_policy.tf @@ -1,4 +1,3 @@ -#trivy:ignore:aws-iam-no-policy-wildcards data "aws_iam_policy_document" "admin" { policy_id = "${local.csi}-admin" diff --git a/infrastructure/terraform/modules/kms/data_iam_kms_user_policy.tf b/infrastructure/terraform/modules/kms/data_iam_kms_user_policy.tf index 64f51d92..99a63f9b 100644 --- a/infrastructure/terraform/modules/kms/data_iam_kms_user_policy.tf +++ b/infrastructure/terraform/modules/kms/data_iam_kms_user_policy.tf @@ -1,4 +1,3 @@ -#trivy:ignore:aws-iam-no-policy-wildcards data "aws_iam_policy_document" "user" { policy_id = "${local.csi}-user" diff --git a/infrastructure/terraform/modules/lambda/data_iam_policy_document_put_logs.tf b/infrastructure/terraform/modules/lambda/data_iam_policy_document_put_logs.tf index 978ddf72..2f171260 100644 --- a/infrastructure/terraform/modules/lambda/data_iam_policy_document_put_logs.tf +++ b/infrastructure/terraform/modules/lambda/data_iam_policy_document_put_logs.tf @@ -8,7 +8,6 @@ data "aws_iam_policy_document" "put_logs" { "logs:PutLogEvents", ] - #trivy:ignore:aws-iam-no-policy-wildcards resources = flatten([[ "${aws_cloudwatch_log_group.main.arn}:*", ], var.lambda_at_edge ? [ diff --git a/infrastructure/terraform/modules/s3bucket/s3_bucket.tf b/infrastructure/terraform/modules/s3bucket/s3_bucket.tf index f640081a..5f88ad2d 100644 --- a/infrastructure/terraform/modules/s3bucket/s3_bucket.tf +++ b/infrastructure/terraform/modules/s3bucket/s3_bucket.tf @@ -1,4 +1,3 @@ -#trivy:ignore:aws-s3-enable-bucket-logging Logging is a depricated attribute, use aws_s3_bucket_logging resource resource "aws_s3_bucket" "main" { bucket = local.csi_global force_destroy = var.force_destroy diff --git a/scripts/config/trivy.yaml b/scripts/config/trivy.yaml deleted file mode 100644 index a4eff466..00000000 --- a/scripts/config/trivy.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -severity: MEDIUM # Minimum reported findings -exit-code: 1 # When issues are found -scan: - skip-files: - - "**/.terraform/**/*" diff --git a/scripts/config/vale/styles/config/vocabularies/words/accept.txt b/scripts/config/vale/styles/config/vocabularies/words/accept.txt index 2cc7e525..d311cc4d 100644 --- a/scripts/config/vale/styles/config/vocabularies/words/accept.txt +++ b/scripts/config/vale/styles/config/vocabularies/words/accept.txt @@ -37,6 +37,5 @@ simplifiable sublicense Syft toolchain -Trivy Trufflehog [Tt]erraform diff --git a/scripts/terraform/terraform.mk b/scripts/terraform/terraform.mk index 4dd03925..7b01244f 100644 --- a/scripts/terraform/terraform.mk +++ b/scripts/terraform/terraform.mk @@ -44,10 +44,6 @@ terraform-validate-all: # Validate all Terraform modules @Quality fi; \ done -terraform-sec: # Run Trivy IaC security scanning on Terraform modules @Quality - # Example: make terraform-sec - ./scripts/terraform/trivy-scan.sh --mode iac infrastructure/terraform/modules - terraform-docs: # Generate Terraform module documentation - optional: module=[specific module, or all if omitted] @Quality # Example: make terraform-docs module=mymodule # Example: make terraform-docs (generates for all modules) @@ -84,6 +80,5 @@ ${VERBOSE}.SILENT: \ terraform-fmt \ terraform-fmt-check \ terraform-install \ - terraform-sec \ terraform-validate \ terraform-validate-all diff --git a/scripts/terraform/trivy.sh b/scripts/terraform/trivy.sh deleted file mode 100755 index 93caabd8..00000000 --- a/scripts/terraform/trivy.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env bash - -# WARNING: Please DO NOT edit this file! It is maintained in the Repository Template (https://github.com/NHSDigital/nhs-notify-repository-template). Raise a PR instead. - -set -euo pipefail - -# TFSec command wrapper. It will run the command natively if TFSec is -# installed, otherwise it will run it in a Docker container. -# Run tfsec for security checks on Terraform code. -# -# Usage: -# $ ./trivy.sh [directory] -# ============================================================================== - -function main() { - - cd "$(git rev-parse --show-toplevel)" - - local dir_to_scan=${1:-.} - - if command -v trivy > /dev/null 2>&1 && ! is-arg-true "${FORCE_USE_DOCKER:-false}"; then - # shellcheck disable=SC2154 - run-trivy-natively "$dir_to_scan" - else - run-trivy-in-docker "$dir_to_scan" - fi -} - -# Run trivy on the specified directory. -# Arguments: -# $1 - Directory to scan -function run-trivy-natively() { - - local dir_to_scan="$1" - - echo "Trivy found locally, running natively" - - echo "Running Trivy on directory: $dir_to_scan" - trivy config \ - --config scripts/config/trivy.yaml \ - --tf-exclude-downloaded-modules \ - "${dir_to_scan}" - - check-trivy-status -} - -# Check the exit status of tfsec. -function check-trivy-status() { - - if [ $? -eq 0 ]; then - echo "Trivy completed successfully." - else - echo "Trivy found issues." - exit 1 - fi -} - -function run-trivy-in-docker() { - - # shellcheck disable=SC1091 - source ./scripts/docker/docker.lib.sh - local dir_to_scan="$1" - - # shellcheck disable=SC2155 - local image=$(name=aquasec/trivy docker-get-image-version-and-pull) - # shellcheck disable=SC2086 - echo "Trivy not found locally, running in Docker Container" - echo "Running Trivy on directory: $dir_to_scan" - docker run --rm --platform linux/amd64 \ - --volume "$PWD":/workdir \ - --workdir /workdir \ - "$image" \ - config \ - --config scripts/config/trivy.yaml \ - --tf-exclude-downloaded-modules \ - "${dir_to_scan}" - check-trivy-status -} -# ============================================================================== - -function is-arg-true() { - - if [[ "$1" =~ ^(true|yes|y|on|1|TRUE|YES|Y|ON)$ ]]; then - return 0 - else - return 1 - fi -} - -# ============================================================================== - -is-arg-true "${VERBOSE:-false}" && set -x - -main "$@" - -exit 0 From a745604044c03a8de5d932a9471e84e442896f4e Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Mon, 26 Oct 2026 09:59:21 +0000 Subject: [PATCH 4/7] CCM-24467: Implement Mise and Prek --- .github/actions/lint-terraform/action.yaml | 16 ++++- docs/github-actions/lint-terraform.md | 2 +- scripts/docker/docker.lib.sh | 71 ++++++++++++++++++---- scripts/docker/tests/docker.test.sh | 36 +++++++++++ 4 files changed, 111 insertions(+), 14 deletions(-) diff --git a/.github/actions/lint-terraform/action.yaml b/.github/actions/lint-terraform/action.yaml index 85bb9d94..722740ca 100644 --- a/.github/actions/lint-terraform/action.yaml +++ b/.github/actions/lint-terraform/action.yaml @@ -10,7 +10,21 @@ runs: - name: "Install Terraform binary" shell: bash run: | - MISE_LOCKED=1 mise install terraform + if command -v mise >/dev/null 2>&1 && [[ -f mise.toml ]]; then + MISE_LOCKED=1 mise install terraform + elif command -v asdf >/dev/null 2>&1; then + if ! asdf plugin list | grep -qx terraform; then + asdf plugin add terraform + fi + asdf install terraform + elif ! command -v terraform >/dev/null 2>&1; then + echo "Terraform is unavailable: configure mise or asdf, or provide terraform on PATH." >&2 + exit 1 + fi + command -v terraform >/dev/null 2>&1 || { + echo "Terraform installation failed; terraform is not on PATH." >&2 + exit 1 + } - name: "Check Terraform format" shell: bash run: | diff --git a/docs/github-actions/lint-terraform.md b/docs/github-actions/lint-terraform.md index a860937b..78e022b0 100644 --- a/docs/github-actions/lint-terraform.md +++ b/docs/github-actions/lint-terraform.md @@ -32,7 +32,7 @@ jobs: ### Details -- Requires: `mise` on the runner's `PATH` and Terraform pinned in the repository's `mise.toml` and `mise.lock` +- Uses mise and the repository's `mise.lock` when available; falls back to the legacy version manager for repositories not yet migrated - Tool: `terraform fmt` - Checks: Terraform code formatting - Validates: HCL syntax and style diff --git a/scripts/docker/docker.lib.sh b/scripts/docker/docker.lib.sh index f3801afb..1681fc69 100644 --- a/scripts/docker/docker.lib.sh +++ b/scripts/docker/docker.lib.sh @@ -13,7 +13,7 @@ set -euo pipefail # Arguments (provided as environment variables): # DOCKER_IMAGE=ghcr.io/org/repo # Docker image name # DOCKER_TITLE="My Docker image" # Docker image title -# TOOL_VERSIONS=$project_dir/.docker-versions # Path to the Docker image versions file +# TOOL_VERSIONS=$project_dir/.docker-versions # Optional override for image versions # ============================================================================== # Functions to be used with custom images. @@ -144,8 +144,8 @@ function version-create-effective-file() { # ============================================================================== # Functions to be used with external images. -# Retrieve the Docker image version from the '.docker-versions' file and pull the -# image if required. This function is to be used in conjunction with the +# Retrieve the Docker image version from '.docker-versions', falling back to +# '.tool-versions' during migration, then pull the image if required. Use with the # external images and it prevents Docker from downloading an image each time it # is used, since the digest is not stored locally for compressed images. To # optimise, the solution is to pull the image using its digest and then tag it, @@ -163,14 +163,28 @@ function docker-get-image-version-and-pull() { # tag="1.2.3" # digest="sha256:hash" - # Get the image full version from the '.docker-versions' file, - # match it by name and version regex, if given. - local versions_file="${TOOL_VERSIONS:=$(git rev-parse --show-toplevel)/.docker-versions}" local version="latest" - if [ -f "$versions_file" ]; then - line=$(grep "docker/${name} " "$versions_file" | sed "s/^#\s*//; s/\s*#.*$//" | grep "${match_version:-".*"}") - [ -n "$line" ] && version=$(echo "$line" | awk '{print $2}') + local repository_root + local versions_file + local resolved_version + local -a versions_files + repository_root=$(git rev-parse --show-toplevel) + if [ -n "${TOOL_VERSIONS:-}" ]; then + case "$TOOL_VERSIONS" in + *.docker-versions*) versions_files=("$TOOL_VERSIONS" "${TOOL_VERSIONS/.docker-versions/.tool-versions}") ;; + *.tool-versions*) versions_files=("${TOOL_VERSIONS/.tool-versions/.docker-versions}" "$TOOL_VERSIONS") ;; + *) versions_files=("$TOOL_VERSIONS") ;; + esac + else + versions_files=("$repository_root/.docker-versions" "$repository_root/.tool-versions") fi + for versions_file in "${versions_files[@]}"; do + resolved_version=$(_docker-image-version-from-file "$versions_file" "$name" "${match_version:-.*}") || true + if [ -n "$resolved_version" ]; then + version="$resolved_version" + break + fi + done # Split the image version into two, tag name and digest sha256. local tag="$(echo "$version" | sed 's/@.*$//')" @@ -218,13 +232,33 @@ function _create-effective-dockerfile() { function _replace-image-latest-by-specific-version() { local dir=${dir:-$PWD} - local versions_file="${TOOL_VERSIONS:=$(git rev-parse --show-toplevel)/.docker-versions}" + local repository_root + local versions_file + local -a versions_files local dockerfile="${dir}/Dockerfile.effective" local build_datetime=${BUILD_DATETIME:-$(date -u +'%Y-%m-%dT%H:%M:%S%z')} - if [ -f "$versions_file" ]; then + repository_root=$(git rev-parse --show-toplevel) + if [ -n "${TOOL_VERSIONS:-}" ]; then + case "$TOOL_VERSIONS" in + *.docker-versions*) versions_files=("$TOOL_VERSIONS" "${TOOL_VERSIONS/.docker-versions/.tool-versions}") ;; + *.tool-versions*) versions_files=("${TOOL_VERSIONS/.tool-versions/.docker-versions}" "$TOOL_VERSIONS") ;; + *) versions_files=("$TOOL_VERSIONS") ;; + esac + else + versions_files=("$repository_root/.docker-versions" "$repository_root/.tool-versions") + fi + if [ "${#versions_files[@]}" -gt 0 ]; then # First, list the entries specific for Docker to take precedence, then the rest but exclude comments - content=$(grep " docker/" "$versions_file"; grep -v " docker/" "$versions_file" ||: | grep -v "^#") + content="" + for versions_file in "${versions_files[@]}"; do + if [ -f "$versions_file" ]; then + content+=$(grep " docker/" "$versions_file" || true) + content+=$'\n' + content+=$(grep -v " docker/" "$versions_file" | grep -v "^#" || true) + content+=$'\n' + fi + done echo "$content" | while IFS= read -r line; do [ -z "$line" ] && continue line=$(echo "$line" | sed "s/^#\s*//; s/\s*#.*$//" | sed "s;docker/;;") @@ -252,6 +286,19 @@ function _replace-image-latest-by-specific-version() { sed -Ei "/# hadolint ignore=DL3007$/d" "${dir}/Dockerfile.effective" } +function _docker-image-version-from-file() { + + local versions_file="$1" + local image_name="$2" + local match_version="$3" + local line + + [ -f "$versions_file" ] || return 1 + line=$(grep "docker/${image_name} " "$versions_file" | sed "s/^#\\s*//; s/\\s*#.*$//" | grep "$match_version" || true) + [ -n "$line" ] || return 1 + echo "$line" | awk '{print $2}' +} + # Append metadata to the end of Dockerfile. # Arguments (provided as environment variables): # dir=[path to the image directory where the Dockerfile is located, default is '.'] diff --git a/scripts/docker/tests/docker.test.sh b/scripts/docker/tests/docker.test.sh index b64c3cf0..bbdb6486 100755 --- a/scripts/docker/tests/docker.test.sh +++ b/scripts/docker/tests/docker.test.sh @@ -28,6 +28,7 @@ function main() { tests=( \ test-docker-build \ test-docker-image-from-signature \ + test-docker-legacy-tool-versions \ test-docker-version-file \ test-docker-test \ test-docker-run \ @@ -82,6 +83,41 @@ function test-docker-image-from-signature() { grep -q "FROM python:.*-alpine.*@sha256:.*" Dockerfile.effective && return 0 || return 1 } +function test-docker-legacy-tool-versions() { + + local legacy_root + legacy_root=$(mktemp -d) + git -C "$legacy_root" init -q || return 1 + git -C "$legacy_root" -c user.name=test -c user.email=test@example.com commit --allow-empty -qm test || return 1 + cp Dockerfile "$legacy_root/Dockerfile" + cp .docker-versions.test "$legacy_root/.tool-versions" + cp Dockerfile "$legacy_root/Dockerfile.effective" + + ( + cd "$legacy_root" || exit 1 + unset TOOL_VERSIONS + _replace-image-latest-by-specific-version + grep -q "FROM python:.*-alpine.*@sha256:.*" Dockerfile.effective || exit 1 + cp Dockerfile Dockerfile.effective + TOOL_VERSIONS="$legacy_root/.docker-versions" _replace-image-latest-by-specific-version + grep -q "FROM python:.*-alpine.*@sha256:.*" Dockerfile.effective || exit 1 + printf '%s\n' '# docker/python 9.9-alpine@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' > .docker-versions + cp Dockerfile Dockerfile.effective + _replace-image-latest-by-specific-version + grep -q "FROM python:9.9-alpine@sha256:aaaaaaaa" Dockerfile.effective || exit 1 + docker() { + case "$1" in + images) return 0 ;; + pull | tag) return 0 ;; + esac + } + name="python" docker-get-image-version-and-pull | grep -q "python:9\\.9-alpine@sha256:" + ) + local result=$? + rm -rf "$legacy_root" + return "$result" +} + function test-docker-version-file() { # Arrange From 5f3143e7d5e3a79bbe58421ee2d5f82a1dfd467b Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Mon, 26 Oct 2026 10:28:54 +0000 Subject: [PATCH 5/7] CCM-24467: Implement Mise and Prek --- .github/workflows/stage-1-commit.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml index 68c85c00..defce7b0 100644 --- a/.github/workflows/stage-1-commit.yaml +++ b/.github/workflows/stage-1-commit.yaml @@ -159,7 +159,7 @@ jobs: - name: "Setup mise" uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4.3.0 with: - install: true + install: false cache: true env: MISE_LOCKED: "1" From 6caf1013d00bfa9c9afb11d60de4760e68bcd813 Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Mon, 26 Oct 2026 13:24:14 +0000 Subject: [PATCH 6/7] CCM-24467: Implement Mise and Prek --- .github/workflows/cicd-1-pull-request.yaml | 8 +- .github/workflows/cicd-3-deploy.yaml | 8 +- .github/workflows/release_created.yaml | 4 +- .github/workflows/stage-1-commit.yaml | 9 +- .docker-versions => .tool-versions | 17 +- docs/github-actions.md | 3 + docs/github-actions/lint-terraform.md | 5 +- docs/github-actions/setup.md | 2 +- docs/github-actions/trivy-iac.md | 44 ++ docs/github-actions/trivy-package.md | 42 ++ docs/github-actions/trivy.md | 40 ++ docs/pre-commit-hooks.md | 4 +- .../aws-backup-source/iam_role_backup.tf | 1 + .../modules/kms/data_iam_kms_admin_policy.tf | 1 + .../modules/kms/data_iam_kms_user_policy.tf | 1 + .../data_iam_policy_document_put_logs.tf | 1 + .../terraform/modules/s3bucket/s3_bucket.tf | 1 + mise.lock | 421 ------------------ mise.toml | 20 - .../config/.repository-template-sync-merge | 2 +- scripts/config/check-todos-ignore.conf | 2 +- scripts/config/trivy.yaml | 6 + .../config/vocabularies/words/accept.txt | 1 + scripts/devcontainer/postcreatecommand.sh | 43 +- scripts/docker/docker.mk | 2 +- scripts/docker/tests/.tool-versions.test | 2 + scripts/docker/tests/Dockerfile | 2 +- scripts/docker/tests/docker.test.sh | 2 +- scripts/init.mk | 20 +- scripts/maintenance/merge.js | 2 +- scripts/terraform/terraform.mk | 7 +- scripts/terraform/trivy.sh | 96 ++++ 32 files changed, 303 insertions(+), 516 deletions(-) rename .docker-versions => .tool-versions (85%) create mode 100644 docs/github-actions/trivy-iac.md create mode 100644 docs/github-actions/trivy-package.md create mode 100644 docs/github-actions/trivy.md delete mode 100644 mise.lock delete mode 100644 mise.toml create mode 100644 scripts/config/trivy.yaml create mode 100644 scripts/docker/tests/.tool-versions.test create mode 100755 scripts/terraform/trivy.sh diff --git a/.github/workflows/cicd-1-pull-request.yaml b/.github/workflows/cicd-1-pull-request.yaml index a78be2cb..935f109e 100644 --- a/.github/workflows/cicd-1-pull-request.yaml +++ b/.github/workflows/cicd-1-pull-request.yaml @@ -53,10 +53,10 @@ jobs: echo "build_datetime=$datetime" >> $GITHUB_OUTPUT echo "build_timestamp=$(date --date=$datetime -u +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT echo "build_epoch=$(date --date=$datetime -u +'%s')" >> $GITHUB_OUTPUT - echo "nodejs_version=$(grep -E '^node\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT - echo "pnpm_version=$(grep -E '^pnpm\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT - echo "python_version=$(grep -E '^python\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT - echo "terraform_version=$(grep -E '^terraform\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT + echo "nodejs_version=$(grep "^nodejs\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT + echo "pnpm_version=$(grep "^pnpm\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT + echo "python_version=$(grep "^python\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT + echo "terraform_version=$(grep "^terraform\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT echo "version=$(echo $version)" >> $GITHUB_OUTPUT echo "is_version_prerelease=$(if [[ $version == *-* ]]; then echo "true"; else echo "false"; fi)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/cicd-3-deploy.yaml b/.github/workflows/cicd-3-deploy.yaml index 4b68aad8..c5fb55ba 100644 --- a/.github/workflows/cicd-3-deploy.yaml +++ b/.github/workflows/cicd-3-deploy.yaml @@ -46,10 +46,10 @@ jobs: echo "build_datetime=$datetime" >> $GITHUB_OUTPUT echo "build_timestamp=$(date --date=$datetime -u +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT echo "build_epoch=$(date --date=$datetime -u +'%s')" >> $GITHUB_OUTPUT - echo "nodejs_version=$(grep -E '^node\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT - echo "pnpm_version=$(grep -E '^pnpm\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT - echo "python_version=$(grep -E '^python\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT - echo "terraform_version=$(grep -E '^terraform\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT + echo "nodejs_version=$(grep "^nodejs\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT + echo "pnpm_version=$(grep "^pnpm\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT + echo "python_version=$(grep "^python\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT + echo "terraform_version=$(grep "^terraform\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT echo "version=$(head -n 1 .version 2> /dev/null || echo unknown)" >> $GITHUB_OUTPUT # echo "tag=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT - name: "List variables" diff --git a/.github/workflows/release_created.yaml b/.github/workflows/release_created.yaml index e84d36cc..a6df2b62 100644 --- a/.github/workflows/release_created.yaml +++ b/.github/workflows/release_created.yaml @@ -34,8 +34,8 @@ jobs: - name: "Set CI/CD variables" id: variables run: | - echo "nodejs_version=$(grep -E '^node\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT - echo "pnpm_version=$(grep -E '^pnpm\s*=' mise.toml | cut -d'"' -f2)" >> $GITHUB_OUTPUT + echo "nodejs_version=$(grep "^nodejs\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT + echo "pnpm_version=$(grep "^pnpm\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT deploy-main: name: Package and Publish Terraform Modules to GitHub Releases assets runs-on: ubuntu-latest diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml index defce7b0..e8689292 100644 --- a/.github/workflows/stage-1-commit.yaml +++ b/.github/workflows/stage-1-commit.yaml @@ -156,13 +156,8 @@ jobs: steps: - name: "Checkout code" uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: "Setup mise" - uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4.3.0 - with: - install: false - cache: true - env: - MISE_LOCKED: "1" + - name: "Setup ASDF" + uses: asdf-vm/actions/setup@b7bcd026f18772e44fe1026d729e1611cc435d47 # v4.0.1 - name: "Lint Terraform" uses: ./.github/actions/lint-terraform count-lines-of-code: diff --git a/.docker-versions b/.tool-versions similarity index 85% rename from .docker-versions rename to .tool-versions index e96deb6e..5f4a288c 100644 --- a/.docker-versions +++ b/.tool-versions @@ -1,5 +1,20 @@ -# Docker image versions, read by scripts/docker/docker.lib.sh. CLI tool versions are pinned in mise.toml. +act 0.2.64 +gitleaks 8.24.0 +jq 1.6 +nodejs 22.15.1 +pre-commit 3.6.0 +pnpm 11.15.1 +terraform 1.10.1 +terraform-docs 0.24.0 +trivy 0.69.2 +vale 3.6.0 +python 3.13.5 +ruby 3.2.0 +# ============================================================================== +# The section below is reserved for Docker image versions. + +# TODO: Move this section - consider using a different file for the repository template dependencies. # docker/ghcr.io/anchore/grype v0.104.3@sha256:d340f4f8b3b7e6e72a6c9c0152f25402ed8a2d7375dba1dfce4e53115242feb6 # SEE: https://github.com/anchore/grype/pkgs/container/grype # docker/ghcr.io/anchore/syft v1.39.0@sha256:6f13bb010923c33fb197047c8f88888e77071bd32596b3f605d62a133e493ce4 # SEE: https://github.com/anchore/syft/pkgs/container/syft # docker/ghcr.io/gitleaks/gitleaks:v8.24.0@sha256:b8e9bf46893c2f20e10bfb4b2e783adaef519dea981b01ca6221ac325e836040 # SEE: https://github.com/gitleaks/gitleaks/pkgs/container/gitleaks diff --git a/docs/github-actions.md b/docs/github-actions.md index 5ce3f824..baee8e8f 100644 --- a/docs/github-actions.md +++ b/docs/github-actions.md @@ -26,6 +26,9 @@ This repository provides reusable composite actions for NHS Notify projects. - [Scan Secrets](github-actions/scan-secrets.html) - Scans Git history for secrets - [Setup](github-actions/setup.html) - Installs dependencies and runs make config - [Sync Template Repo](github-actions/sync-template-repo.html) - Syncs repository template changes +- [Trivy](github-actions/trivy.html) - General Trivy security scanner +- [Trivy IaC](github-actions/trivy-iac.html) - Scans Terraform IaC with Trivy +- [Trivy Package](github-actions/trivy-package.html) - Scans packages with Trivy ## Usage diff --git a/docs/github-actions/lint-terraform.md b/docs/github-actions/lint-terraform.md index 78e022b0..99715902 100644 --- a/docs/github-actions/lint-terraform.md +++ b/docs/github-actions/lint-terraform.md @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup mise - uses: jdx/mise-action@v4 + uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4.3.0 - name: Lint Terraform uses: NHSDigital/nhs-notify-shared-modules/.github/actions/lint-terraform@v1.0.0 @@ -32,7 +32,8 @@ jobs: ### Details -- Uses mise and the repository's `mise.lock` when available; falls back to the legacy version manager for repositories not yet migrated +- The caller must set up a version manager before this action. For migrated repositories, set up mise as shown above. Legacy repositories should retain their existing version-manager setup. +- Installs Terraform from `mise.lock` when the checkout has `mise.toml`; otherwise installs it using the legacy version manager and `.tool-versions`. If neither manager is available, Terraform must already be on `PATH`. - Tool: `terraform fmt` - Checks: Terraform code formatting - Validates: HCL syntax and style diff --git a/docs/github-actions/setup.md b/docs/github-actions/setup.md index 32d865e6..8b160c51 100644 --- a/docs/github-actions/setup.md +++ b/docs/github-actions/setup.md @@ -39,7 +39,7 @@ jobs: ### What Gets Installed -- mise tools from `mise.toml`, verified against `mise.lock` +- asdf/mise tools from `.tool-versions` - Ruby gems via Bundler - Node packages via npm/pnpm - Python packages via pip diff --git a/docs/github-actions/trivy-iac.md b/docs/github-actions/trivy-iac.md new file mode 100644 index 00000000..d304f059 --- /dev/null +++ b/docs/github-actions/trivy-iac.md @@ -0,0 +1,44 @@ +--- +layout: default +title: Trivy IaC +parent: GitHub Actions +grand_parent: Home +nav_order: 15 +--- + +## Trivy IaC + +Scans Terraform Infrastructure as Code using Trivy. + +### Description + +This composite action scans Terraform code for security misconfigurations and compliance issues. + +### Usage + +```yaml +jobs: + scan-iac: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Scan Terraform IaC + uses: NHSDigital/nhs-notify-shared-modules/.github/actions/trivy-iac@v1.0.0 +``` + +### Details + +- Tool: Trivy IaC scanner +- Targets: Terraform (.tf) files +- Checks: Security misconfigurations +- Standards: AWS security best practices +- Reports: Terraform-specific vulnerabilities + +### What It Detects + +- Insecure resource configurations +- Missing encryption settings +- Public access misconfigurations +- IAM permission issues +- Non-compliant security group rules diff --git a/docs/github-actions/trivy-package.md b/docs/github-actions/trivy-package.md new file mode 100644 index 00000000..76025ebb --- /dev/null +++ b/docs/github-actions/trivy-package.md @@ -0,0 +1,42 @@ +--- +layout: default +title: Trivy Package +parent: GitHub Actions +grand_parent: Home +nav_order: 16 +--- + +## Trivy Package + +Scans project packages and dependencies using Trivy. + +### Description + +This composite action scans package dependencies for known vulnerabilities using Trivy. + +### Usage + +```yaml +jobs: + scan-packages: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Scan packages + uses: NHSDigital/nhs-notify-shared-modules/.github/actions/trivy-package@v1.0.0 +``` + +### Details + +- Tool: Trivy package scanner +- Targets: Package manifest files +- Scans: npm, Ruby gems, Python packages +- Checks: Known CVEs and vulnerabilities +- Reports: Dependency security issues + +### Package Types Scanned + +- Node.js: `package.json`, `package-lock.json` +- Ruby: `Gemfile`, `Gemfile.lock` +- Python: `requirements.txt`, `Pipfile` diff --git a/docs/github-actions/trivy.md b/docs/github-actions/trivy.md new file mode 100644 index 00000000..bda9c94a --- /dev/null +++ b/docs/github-actions/trivy.md @@ -0,0 +1,40 @@ +--- +layout: default +title: Trivy +parent: GitHub Actions +grand_parent: Home +nav_order: 14 +--- + +## Trivy + +General Trivy security scanner. + +### Description + +This composite action runs Trivy security scanner for vulnerability detection. + +### Usage + +```yaml +jobs: + security-scan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run Trivy scan + uses: NHSDigital/nhs-notify-shared-modules/.github/actions/trivy@v1.0.0 +``` + +### Details + +- Tool: Trivy security scanner +- Scans: Multiple security aspects +- Detects: Vulnerabilities, misconfigurations, secrets +- Reports: Security findings + +### Related Actions + +- [Trivy IaC](trivy-iac.html) - Infrastructure as Code scanning +- [Trivy Package](trivy-package.html) - Package dependency scanning diff --git a/docs/pre-commit-hooks.md b/docs/pre-commit-hooks.md index 54ae526d..0a946769 100644 --- a/docs/pre-commit-hooks.md +++ b/docs/pre-commit-hooks.md @@ -131,7 +131,7 @@ Runs the same SBOM and Grype dependency scan used in CI and prints the markdown Run it manually when needed: ```bash -prek run --config scripts/config/pre-commit.yaml --hook-stage manual scan-dependencies +pre-commit run --config scripts/config/pre-commit.yaml --hook-stage manual scan-dependencies ``` ## Setup in Your Repository @@ -154,7 +154,7 @@ repos: Then install: ```bash -prek install +pre-commit install ``` ## Notes diff --git a/infrastructure/terraform/modules/aws-backup-source/iam_role_backup.tf b/infrastructure/terraform/modules/aws-backup-source/iam_role_backup.tf index bac7c1d2..fe8d00ab 100644 --- a/infrastructure/terraform/modules/aws-backup-source/iam_role_backup.tf +++ b/infrastructure/terraform/modules/aws-backup-source/iam_role_backup.tf @@ -56,6 +56,7 @@ data "aws_iam_policy_document" "backup_additional" { "backup:TagResource", ] + #trivy:ignore:aws-iam-no-policy-wildcards resources = [ "*", ] diff --git a/infrastructure/terraform/modules/kms/data_iam_kms_admin_policy.tf b/infrastructure/terraform/modules/kms/data_iam_kms_admin_policy.tf index 25d4fb31..c363415b 100644 --- a/infrastructure/terraform/modules/kms/data_iam_kms_admin_policy.tf +++ b/infrastructure/terraform/modules/kms/data_iam_kms_admin_policy.tf @@ -1,3 +1,4 @@ +#trivy:ignore:aws-iam-no-policy-wildcards data "aws_iam_policy_document" "admin" { policy_id = "${local.csi}-admin" diff --git a/infrastructure/terraform/modules/kms/data_iam_kms_user_policy.tf b/infrastructure/terraform/modules/kms/data_iam_kms_user_policy.tf index 99a63f9b..64f51d92 100644 --- a/infrastructure/terraform/modules/kms/data_iam_kms_user_policy.tf +++ b/infrastructure/terraform/modules/kms/data_iam_kms_user_policy.tf @@ -1,3 +1,4 @@ +#trivy:ignore:aws-iam-no-policy-wildcards data "aws_iam_policy_document" "user" { policy_id = "${local.csi}-user" diff --git a/infrastructure/terraform/modules/lambda/data_iam_policy_document_put_logs.tf b/infrastructure/terraform/modules/lambda/data_iam_policy_document_put_logs.tf index 2f171260..978ddf72 100644 --- a/infrastructure/terraform/modules/lambda/data_iam_policy_document_put_logs.tf +++ b/infrastructure/terraform/modules/lambda/data_iam_policy_document_put_logs.tf @@ -8,6 +8,7 @@ data "aws_iam_policy_document" "put_logs" { "logs:PutLogEvents", ] + #trivy:ignore:aws-iam-no-policy-wildcards resources = flatten([[ "${aws_cloudwatch_log_group.main.arn}:*", ], var.lambda_at_edge ? [ diff --git a/infrastructure/terraform/modules/s3bucket/s3_bucket.tf b/infrastructure/terraform/modules/s3bucket/s3_bucket.tf index 5f88ad2d..f640081a 100644 --- a/infrastructure/terraform/modules/s3bucket/s3_bucket.tf +++ b/infrastructure/terraform/modules/s3bucket/s3_bucket.tf @@ -1,3 +1,4 @@ +#trivy:ignore:aws-s3-enable-bucket-logging Logging is a depricated attribute, use aws_s3_bucket_logging resource resource "aws_s3_bucket" "main" { bucket = local.csi_global force_destroy = var.force_destroy diff --git a/mise.lock b/mise.lock deleted file mode 100644 index d0035e86..00000000 --- a/mise.lock +++ /dev/null @@ -1,421 +0,0 @@ -# @generated - this file is auto-generated by `mise lock` https://mise.jdx.dev/dev-tools/mise-lock.html - -lockfile_version = 3 - -[[tools.act]] -version = "0.2.64" -backend = "aqua:nektos/act" -specifiers = ["0.2.64"] - -[tools.act."platforms.linux-arm64"] -checksum = "sha256:b1f8540efcb97943374344c03566cbd7f07b074a4bb572a740f144c6f26697b4" -url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901806" - -[tools.act."platforms.linux-arm64-musl"] -checksum = "sha256:b1f8540efcb97943374344c03566cbd7f07b074a4bb572a740f144c6f26697b4" -url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901806" - -[tools.act."platforms.linux-x64"] -checksum = "sha256:78af3327620fed8b736794803a638e730083e2f25caa52aa0108d2fb9670a0ad" -url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Linux_x86_64.tar.gz" -url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901803" - -[tools.act."platforms.linux-x64-musl"] -checksum = "sha256:78af3327620fed8b736794803a638e730083e2f25caa52aa0108d2fb9670a0ad" -url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Linux_x86_64.tar.gz" -url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901803" - -[tools.act."platforms.macos-arm64"] -checksum = "sha256:8a0232ba98b883d23b45ce1085fbc77140e1ce0eb5244cc8ed8c52d208917bf5" -url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Darwin_arm64.tar.gz" -url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901814" - -[tools.act."platforms.macos-x64"] -checksum = "sha256:efb8fca836115294644f857c83d65e0cd2098e371e0925f32e837f3231e87d39" -url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Darwin_x86_64.tar.gz" -url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901804" - -[tools.act."platforms.windows-x64"] -checksum = "sha256:c04de9fd6f6dd651c638b199c15b16e64981696c9ba9b465545faba340b6bef4" -url = "https://github.com/nektos/act/releases/download/v0.2.64/act_Windows_x86_64.zip" -url_api = "https://api.github.com/repos/nektos/act/releases/assets/176901807" - -[[tools.gitleaks]] -version = "8.24.0" -backend = "aqua:gitleaks/gitleaks" -specifiers = ["8.24.0"] - -[tools.gitleaks."platforms.linux-arm64"] -checksum = "sha256:3755cc9b81f2466ad308f722a064ca04df27f59d551396183efe07978fef8fcb" -url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829270" - -[tools.gitleaks."platforms.linux-arm64-musl"] -checksum = "sha256:3755cc9b81f2466ad308f722a064ca04df27f59d551396183efe07978fef8fcb" -url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829270" - -[tools.gitleaks."platforms.linux-x64"] -checksum = "sha256:cb49b7de5ee986510fe8666ca0273a6cc15eb82571f2f14832c9e8920751f3a4" -url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_linux_x64.tar.gz" -url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829275" - -[tools.gitleaks."platforms.linux-x64-musl"] -checksum = "sha256:cb49b7de5ee986510fe8666ca0273a6cc15eb82571f2f14832c9e8920751f3a4" -url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_linux_x64.tar.gz" -url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829275" - -[tools.gitleaks."platforms.macos-arm64"] -checksum = "sha256:a3d281867df087ded8c2f9afd35d61ff923a25e64caa127b720991ee433d763b" -url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_darwin_arm64.tar.gz" -url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829277" - -[tools.gitleaks."platforms.macos-x64"] -checksum = "sha256:bd9ed3294c086f10dcc5fc25de57d44ba940c19c1a5a3d5f1cfeb10b9dff005e" -url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_darwin_x64.tar.gz" -url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829271" - -[tools.gitleaks."platforms.windows-x64"] -checksum = "sha256:dab91070b01feec49bd157375085c93a16fe85e13b3bff6916aaaa0a3b3b5fac" -url = "https://github.com/gitleaks/gitleaks/releases/download/v8.24.0/gitleaks_8.24.0_windows_x64.zip" -url_api = "https://api.github.com/repos/gitleaks/gitleaks/releases/assets/230829282" - -[[tools.jq]] -version = "1.6" -backend = "aqua:jqlang/jq" -specifiers = ["1.6"] - -[tools.jq."platforms.linux-x64"] -url = "https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux64" -url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/9521005" - -[tools.jq."platforms.linux-x64-musl"] -url = "https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux64" -url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/9521005" - -[tools.jq."platforms.macos-arm64"] -url = "https://github.com/jqlang/jq/releases/download/jq-1.6/jq-osx-amd64" -url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/9521006" - -[tools.jq."platforms.macos-x64"] -url = "https://github.com/jqlang/jq/releases/download/jq-1.6/jq-osx-amd64" -url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/9521006" - -[tools.jq."platforms.windows-x64"] -url = "https://github.com/jqlang/jq/releases/download/jq-1.6/jq-win64.exe" -url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/9521008" - -[[tools.node]] -version = "22.15.1" -backend = "core:node" -specifiers = ["22.15.1"] - -[tools.node."platforms.linux-arm64"] -checksum = "sha256:eb3f232b83dfe83397b98395ec77a973e888e8959c978b3e4eeb551b8845b74f" -url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1-linux-arm64.tar.gz" - -[tools.node."platforms.linux-arm64-musl"] -checksum = "sha256:38aea029f8818f7783f273fbc70dcf930f9ef54bdd49c5f90c0152caec7a57be" -url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1.tar.gz" -install = "source" - -[tools.node."platforms.linux-x64"] -checksum = "sha256:f4b8eec683708acb1a2a73c7182ba2de5466a5dd5f705934a0830903df28821c" -url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1-linux-x64.tar.gz" - -[tools.node."platforms.linux-x64-musl"] -checksum = "sha256:408fee9895ac6ba4a1893c7be66aba5cb2c995b4c15d5fa09fabbe4f44497fbd" -url = "https://unofficial-builds.nodejs.org/download/release/v22.15.1/node-v22.15.1-linux-x64-musl.tar.gz" - -[tools.node."platforms.macos-arm64"] -checksum = "sha256:d2689b86b17e1b51e76f801ffe2d9acca4225e76eda4b843c3d8438d4a7cd6fe" -url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1-darwin-arm64.tar.gz" - -[tools.node."platforms.macos-x64"] -checksum = "sha256:1c722d0dd6d3f60e8b0be014ea01b8a59f5088f4419197a1b37544854d61cc6f" -url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1-darwin-x64.tar.gz" - -[tools.node."platforms.windows-x64"] -checksum = "sha256:7c7997d6ef2efd9525a54b033fc0be6f22549a5905f5da6573a41e61a436a1b5" -url = "https://nodejs.org/dist/v22.15.1/node-v22.15.1-win-x64.zip" - -[[tools.pnpm]] -version = "11.15.1" -backend = "aqua:pnpm/pnpm" -specifiers = ["11.15.1"] - -[tools.pnpm."platforms.linux-arm64"] -checksum = "sha256:361e385867146972d0635a41a1871cb44c9c23f65acce78a5f1ca1d44ac0afcd" -url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-linux-arm64.tar.gz" -url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780455" -provenance = "github-attestations" - -[tools.pnpm."platforms.linux-arm64-musl"] -checksum = "sha256:5e293db656ee6a54387945572e06f08245140a7427c8e67b821d56471f373b77" -url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-linux-arm64-musl.tar.gz" -url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780459" -provenance = "github-attestations" - -[tools.pnpm."platforms.linux-x64"] -checksum = "sha256:0c1373b6390f6b89ff8b896d3647c9826577ddc49173a2f732da69b36569f9e0" -url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-linux-x64.tar.gz" -url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780457" -provenance = "github-attestations" - -[tools.pnpm."platforms.linux-x64-musl"] -checksum = "sha256:593039435b88cb4e15c60c18ba032a1ae6a28159287199f20aacc44ad553a094" -url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-linux-x64-musl.tar.gz" -url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780453" -provenance = "github-attestations" - -[tools.pnpm."platforms.macos-arm64"] -checksum = "sha256:4ff53ecc9de8df115d4efef60eab77f91be4f8237cdaca078351a22e707d1849" -url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-darwin-arm64.tar.gz" -url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780456" -provenance = "github-attestations" - -[tools.pnpm."platforms.windows-x64"] -checksum = "sha256:e9179d727211d5556e969fccfa36f828392892c54728a711c9da1cc3093f7900" -url = "https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-win32-x64.zip" -url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/482780452" -provenance = "github-attestations" - -[[tools.prek]] -version = "0.5.7" -backend = "aqua:j178/prek" -specifiers = ["0.5.7"] - -[tools.prek."platforms.linux-arm64"] -checksum = "sha256:98bdb31002ca42b61f4f6c746b2de351aee4e1f29c95f8dec8ec3b9a62929c1e" -url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-aarch64-unknown-linux-gnu.tar.gz" -url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929498" -provenance = "github-attestations" - -[tools.prek."platforms.linux-arm64-musl"] -checksum = "sha256:022ddbaef649d83ab7e0cfde13400612b896b04cce338623205525560d47bcf6" -url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-aarch64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929502" -provenance = "github-attestations" - -[tools.prek."platforms.linux-x64"] -checksum = "sha256:e238e5a6b4e384e8d18f33d3c3b1a329be0e1237f77ac6e021e641ddd3a2bab6" -url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-unknown-linux-gnu.tar.gz" -url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929556" -provenance = "github-attestations" - -[tools.prek."platforms.linux-x64-musl"] -checksum = "sha256:25d6a0316125127aed3ad7010128884d7e7243c4ac06f084218b98dc20020ca9" -url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-unknown-linux-musl.tar.gz" -url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929599" -provenance = "github-attestations" - -[tools.prek."platforms.macos-arm64"] -checksum = "sha256:800c5b9c8239045bbdf4201957dd4175135e216e838c40a6ec1904ff18ebaf2c" -url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-aarch64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929480" -provenance = "github-attestations" - -[tools.prek."platforms.macos-x64"] -checksum = "sha256:12b65c6685fc44ff9130c0bf5dcb01be69c0c81d9a0709553fd369c3b2010815" -url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-apple-darwin.tar.gz" -url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929524" -provenance = "github-attestations" - -[tools.prek."platforms.windows-x64"] -checksum = "sha256:50ccc606e19965585807c0a8be99da82eb4237c7c9df2539e5a83704d1f16a36" -url = "https://github.com/j178/prek/releases/download/v0.5.7/prek-x86_64-pc-windows-msvc.zip" -url_api = "https://api.github.com/repos/j178/prek/releases/assets/660929530" -provenance = "github-attestations" - -[[tools.python]] -version = "3.13.5" -backend = "core:python" -specifiers = ["3.13.5"] - -[tools.python."platforms.linux-arm64"] -checksum = "sha256:65412f4d99966ab9e0218211c1408497b5ecd2a40e1bd12183a37937c25cce4e" -url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-aarch64-unknown-linux-gnu-install_only_stripped.tar.gz" -provenance = "github-attestations" - -[tools.python."platforms.linux-x64"] -checksum = "sha256:f7ac16748be2674ec14df532a3e48d0c6f215017b537f14ca3feb837dbe86292" -url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz" -provenance = "github-attestations" - -[tools.python."platforms.linux-x64-musl"] -checksum = "sha256:8ba1a81e371263b668667ca66234c0422dfff212005a5fb0ced0dbc5011be942" -url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-x86_64-unknown-linux-musl-install_only_stripped.tar.gz" -provenance = "github-attestations" - -[tools.python."platforms.macos-arm64"] -checksum = "sha256:a2c25baa13d271b730744d7e8684d7db54a003dfeeb5ae3b0ae86af7d81d44ae" -url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-aarch64-apple-darwin-install_only_stripped.tar.gz" -provenance = "github-attestations" - -[tools.python."platforms.macos-x64"] -checksum = "sha256:c198610998092c42650600ef250be388ba27ab307ade4d8684c27af9a0b5569a" -url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-x86_64-apple-darwin-install_only_stripped.tar.gz" -provenance = "github-attestations" - -[tools.python."platforms.windows-x64"] -checksum = "sha256:4d88fdda4a59e0d6d45953c37c2fcb4e114dd5a2d41cb5b24b75b42ab8328ff8" -url = "https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-x86_64-pc-windows-msvc-install_only_stripped.tar.gz" -provenance = "github-attestations" - -[[tools.ruby]] -version = "3.2.0" -backend = "core:ruby" -specifiers = ["3.2.0"] - -[tools.ruby.options] -compile = "false" -precompiled_url = "jdx/ruby" -ruby_build_repo = "https://github.com/rbenv/ruby-build.git" -ruby_install = "false" - -[tools.ruby."platforms.linux-arm64"] -checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" -url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" - -[tools.ruby."platforms.linux-arm64-musl"] -checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" -url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" - -[tools.ruby."platforms.linux-x64"] -checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" -url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" - -[tools.ruby."platforms.linux-x64-musl"] -checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" -url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" - -[tools.ruby."platforms.macos-arm64"] -checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" -url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" - -[tools.ruby."platforms.macos-x64"] -checksum = "sha256:daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272" -url = "https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz" - -[[tools.ruby]] -version = "3.2.0" -backend = "core:ruby" -specifiers = ["3.2.0"] - -[tools.ruby."platforms.windows-x64"] -url = "https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-3.2.0-1/rubyinstaller-3.2.0-1-x64.7z" - -[[tools.terraform]] -version = "1.10.1" -backend = "aqua:hashicorp/terraform" -specifiers = ["1.10.1"] - -[tools.terraform."platforms.linux-arm64"] -checksum = "sha256:6375a763b7784e47b4314e939a8c15f357db718d932e82825d87392abb5d1e09" -url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_linux_arm64.zip" - -[tools.terraform."platforms.linux-arm64-musl"] -checksum = "sha256:6375a763b7784e47b4314e939a8c15f357db718d932e82825d87392abb5d1e09" -url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_linux_arm64.zip" - -[tools.terraform."platforms.linux-x64"] -checksum = "sha256:d49d4d08ed092a8dec335f1fe3e127d1a285f160557323dd5a84ddc0c8472e1a" -url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_linux_amd64.zip" - -[tools.terraform."platforms.linux-x64-musl"] -checksum = "sha256:d49d4d08ed092a8dec335f1fe3e127d1a285f160557323dd5a84ddc0c8472e1a" -url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_linux_amd64.zip" - -[tools.terraform."platforms.macos-arm64"] -checksum = "sha256:bae8bef4e19a404427a25e1ddc35eeff4ed9afb675c33e2988dfd47f1543ad3b" -url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_darwin_arm64.zip" - -[tools.terraform."platforms.macos-x64"] -checksum = "sha256:9e3e0127c7dbef8a34773820736acbb312a0727149a3b5df07b73f0cf859c261" -url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_darwin_amd64.zip" - -[tools.terraform."platforms.windows-x64"] -checksum = "sha256:c73ff963038d151360928101ba7e228dffbd362f9706499438ba590db3b7ec2e" -url = "https://releases.hashicorp.com/terraform/1.10.1/terraform_1.10.1_windows_amd64.zip" - -[[tools.terraform-docs]] -version = "0.24.0" -backend = "aqua:terraform-docs/terraform-docs" -specifiers = ["0.24.0"] - -[tools.terraform-docs."platforms.linux-arm64"] -checksum = "sha256:d12bd7b73c1fc9c64efc79f8157dd713dabd559f1ecf3cfc0f42e32279a155fd" -url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-linux-arm64.tar.gz" -url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956212" - -[tools.terraform-docs."platforms.linux-arm64-musl"] -checksum = "sha256:d12bd7b73c1fc9c64efc79f8157dd713dabd559f1ecf3cfc0f42e32279a155fd" -url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-linux-arm64.tar.gz" -url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956212" - -[tools.terraform-docs."platforms.linux-x64"] -checksum = "sha256:9005daf969de0b50134493a2c00078b49f5f5b39d021cda7c89bf4d4f3d776d3" -url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-linux-amd64.tar.gz" -url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956208" - -[tools.terraform-docs."platforms.linux-x64-musl"] -checksum = "sha256:9005daf969de0b50134493a2c00078b49f5f5b39d021cda7c89bf4d4f3d776d3" -url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-linux-amd64.tar.gz" -url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956208" - -[tools.terraform-docs."platforms.macos-arm64"] -checksum = "sha256:f6b114f4b032f3f9202ab6c23bfd28c3c8e68aeeb8a8f12fc118bf2073081d71" -url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-darwin-arm64.tar.gz" -url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956237" - -[tools.terraform-docs."platforms.macos-x64"] -checksum = "sha256:3c3f7f18f908457fd1209cbe341418f7f6bae78c08126cfbe8de0d1b06aa8781" -url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-darwin-amd64.tar.gz" -url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956256" - -[tools.terraform-docs."platforms.windows-x64"] -checksum = "sha256:afc02cbdf63726d3e5fb26a077ca1f24acd4820d7e44c21b03a3e030f9266490" -url = "https://github.com/terraform-docs/terraform-docs/releases/download/v0.24.0/terraform-docs-v0.24.0-windows-amd64.zip" -url_api = "https://api.github.com/repos/terraform-docs/terraform-docs/releases/assets/416956245" - -[[tools.vale]] -version = "3.6.0" -backend = "aqua:vale-cli/vale" -specifiers = ["3.6.0"] - -[tools.vale."platforms.linux-arm64"] -checksum = "sha256:45295ab07fd99c87a9cac20dce5d230d7b63ffec1394b38c8d5d4496347a069b" -url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_Linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588938" - -[tools.vale."platforms.linux-arm64-musl"] -checksum = "sha256:45295ab07fd99c87a9cac20dce5d230d7b63ffec1394b38c8d5d4496347a069b" -url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_Linux_arm64.tar.gz" -url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588938" - -[tools.vale."platforms.linux-x64"] -checksum = "sha256:d27cd03f920202a7be5bba3fd9e784a22fe8b33f838911853588ce3ce594a25d" -url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_Linux_64-bit.tar.gz" -url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588941" - -[tools.vale."platforms.linux-x64-musl"] -checksum = "sha256:d27cd03f920202a7be5bba3fd9e784a22fe8b33f838911853588ce3ce594a25d" -url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_Linux_64-bit.tar.gz" -url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588941" - -[tools.vale."platforms.macos-arm64"] -checksum = "sha256:df71e5fcbefca9413479737fa946e105249ec73e2a328ef1784e5558d92414b0" -url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_macOS_arm64.tar.gz" -url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588939" - -[tools.vale."platforms.macos-x64"] -checksum = "sha256:4d1df61fc3b1e4109bd965b478dad6cb8998e2ca7836100b936c16c331c8c9f2" -url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_macOS_64-bit.tar.gz" -url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588940" - -[tools.vale."platforms.windows-x64"] -checksum = "sha256:6b205cd9ee4df016d42287cd0b2b8f234acb45900fc371cda97a5c49bc69b350" -url = "https://github.com/vale-cli/vale/releases/download/v3.6.0/vale_3.6.0_Windows_64-bit.zip" -url_api = "https://api.github.com/repos/vale-cli/vale/releases/assets/174588942" diff --git a/mise.toml b/mise.toml deleted file mode 100644 index 299ddf89..00000000 --- a/mise.toml +++ /dev/null @@ -1,20 +0,0 @@ -[settings] -# Record checksums and download URLs in mise.lock; verified on every install -lockfile = true -# Refuse remote code execution paths such as asdf/vfox plugins -disable_backends = ["asdf", "vfox"] -# Ignore releases newer than this when resolving versions, giving time for compromised releases to be yanked -minimum_release_age = "7d" - -[tools] -act = "0.2.64" -gitleaks = "8.24.0" -jq = "1.6" -node = "22.15.1" -pnpm = "11.15.1" -prek = "0.5.7" -python = "3.13.5" -ruby = "3.2.0" -terraform = "1.10.1" -terraform-docs = "0.24.0" -vale = "3.6.0" diff --git a/scripts/config/.repository-template-sync-merge b/scripts/config/.repository-template-sync-merge index e9d3d415..8b5774fd 100644 --- a/scripts/config/.repository-template-sync-merge +++ b/scripts/config/.repository-template-sync-merge @@ -3,7 +3,7 @@ scripts/config/.repository-template-sync-ignore scripts/config/.repository-template-sync-merge scripts/config/vale/vale.ini -mise.toml +.tool-versions .gitignore scripts/config/vale/styles/config/vocabularies/words/accept.txt scripts/config/vale/styles/config/vocabularies/words/reject.txt diff --git a/scripts/config/check-todos-ignore.conf b/scripts/config/check-todos-ignore.conf index 5dc93430..4a655ca6 100644 --- a/scripts/config/check-todos-ignore.conf +++ b/scripts/config/check-todos-ignore.conf @@ -4,7 +4,7 @@ .devcontainer/devcontainer.json .github/workflows/stage-1-commit.yaml .pre-commit-hooks.yaml -mise.toml +.tool-versions .vscode/extensions.json infrastructure/terraform/bin/terraform.sh Makefile diff --git a/scripts/config/trivy.yaml b/scripts/config/trivy.yaml new file mode 100644 index 00000000..a4eff466 --- /dev/null +++ b/scripts/config/trivy.yaml @@ -0,0 +1,6 @@ +--- +severity: MEDIUM # Minimum reported findings +exit-code: 1 # When issues are found +scan: + skip-files: + - "**/.terraform/**/*" diff --git a/scripts/config/vale/styles/config/vocabularies/words/accept.txt b/scripts/config/vale/styles/config/vocabularies/words/accept.txt index d311cc4d..2cc7e525 100644 --- a/scripts/config/vale/styles/config/vocabularies/words/accept.txt +++ b/scripts/config/vale/styles/config/vocabularies/words/accept.txt @@ -37,5 +37,6 @@ simplifiable sublicense Syft toolchain +Trivy Trufflehog [Tt]erraform diff --git a/scripts/devcontainer/postcreatecommand.sh b/scripts/devcontainer/postcreatecommand.sh index 0daa560f..aefabaf3 100755 --- a/scripts/devcontainer/postcreatecommand.sh +++ b/scripts/devcontainer/postcreatecommand.sh @@ -1,44 +1,15 @@ #!/bin/bash -set -euo pipefail +rm -Rf ~/.asdf +git clone https://github.com/asdf-vm/asdf.git ~/.asdf; +chmod +x ~/.asdf/asdf.sh; +echo '. $HOME/.asdf/asdf.sh' >> ~/.zshrc +echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.zshrc -# Pinned release verified by checksum, instead of piping an install script to a shell -mise_version="v2026.10.17" +source ~/.zshrc -case "$(uname -m)" in - x86_64) - arch="x64" - sha256="17565e268c5542d8ce944321e17af81e0b741b65af4aa7e8e010ee77376a4aa3" - ;; - aarch64 | arm64) - arch="arm64" - sha256="cac510e51793ad45e65fe92305bdbe4309c9c60b5907badbc7eba111738ab08f" - ;; - *) - echo "Unsupported architecture: $(uname -m)" >&2 - exit 1 - ;; -esac +echo 'asdf setup complete' -archive="mise-${mise_version}-linux-${arch}.tar.gz" -tmp_dir="$(mktemp -d)" -trap 'rm -rf "${tmp_dir}"' EXIT - -curl -fsSL --proto '=https' --tlsv1.2 \ - --output "${tmp_dir}/${archive}" \ - "https://github.com/jdx/mise/releases/download/${mise_version}/${archive}" -echo "${sha256} ${tmp_dir}/${archive}" | sha256sum --check --status - -mkdir -p ~/.local/bin -tar -xzf "${tmp_dir}/${archive}" -C "${tmp_dir}" -install -m 0755 "${tmp_dir}/mise/bin/mise" ~/.local/bin/mise - -echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc - -echo 'mise setup complete' - -# Shims put mise-managed tools on PATH for this non-interactive script -export PATH="${HOME}/.local/bin:${HOME}/.local/share/mise/shims:${PATH}" make config jekyll --version && cd docs && bundle install diff --git a/scripts/docker/docker.mk b/scripts/docker/docker.mk index 42540f39..a31ad9db 100644 --- a/scripts/docker/docker.mk +++ b/scripts/docker/docker.mk @@ -45,7 +45,7 @@ docker-example-build: # Build Docker example @ExamplesAndTests cd scripts/docker/examples/python DOCKER_IMAGE=repository-template/docker-example-python DOCKER_TITLE="Repository Template Docker Python Example" - TOOL_VERSIONS="$(shell git rev-parse --show-toplevel)/scripts/docker/examples/python/.docker-versions.example" + TOOL_VERSIONS="$(shell git rev-parse --show-toplevel)/scripts/docker/examples/python/.tool-versions.example" docker-build docker-example-lint: # Lint Docker example @ExamplesAndTests diff --git a/scripts/docker/tests/.tool-versions.test b/scripts/docker/tests/.tool-versions.test new file mode 100644 index 00000000..92093116 --- /dev/null +++ b/scripts/docker/tests/.tool-versions.test @@ -0,0 +1,2 @@ +# python, SEE: https://hub.docker.com/_/python/tags +# docker/python 3.11.4-alpine3.18@sha256:0135ae6442d1269379860b361760ad2cf6ab7c403d21935a8015b48d5bf78a86 diff --git a/scripts/docker/tests/Dockerfile b/scripts/docker/tests/Dockerfile index b2d62606..b5ea5606 100644 --- a/scripts/docker/tests/Dockerfile +++ b/scripts/docker/tests/Dockerfile @@ -1,3 +1,3 @@ -# `*:latest` will be replaced with a corresponding version stored in the '.docker-versions' file +# `*:latest` will be replaced with a corresponding version stored in the '.tool-versions' file # hadolint ignore=DL3007 FROM python:latest diff --git a/scripts/docker/tests/docker.test.sh b/scripts/docker/tests/docker.test.sh index bbdb6486..595b9ec4 100755 --- a/scripts/docker/tests/docker.test.sh +++ b/scripts/docker/tests/docker.test.sh @@ -1,5 +1,5 @@ #!/bin/bash -# shellcheck disable=SC1091,SC2034,SC2317 +# shellcheck disable=SC1091,SC2034,SC2317,SC2329 # WARNING: Please DO NOT edit this file! It is maintained in the Repository Template (https://github.com/nhs-england-tools/repository-template). Raise a PR instead. diff --git a/scripts/init.mk b/scripts/init.mk index 32de8311..b3d70139 100644 --- a/scripts/init.mk +++ b/scripts/init.mk @@ -30,29 +30,31 @@ shellscript-lint-all: # Lint all shell scripts in this project, do not fail on e done githooks-config: # Trigger Git hooks on commit that are defined in this repository @Configuration - make _install-dependency name="prek" - prek install \ - --force \ + make _install-dependency name="pre-commit" + pre-commit install \ --config scripts/config/pre-commit.yaml \ --install-hooks githooks-run: # Run git hooks configured in this repository @Operations - prek run \ + pre-commit run \ --config scripts/config/pre-commit.yaml \ --all-files githooks-dependencies: # Run git hook for manually scanning depdencies - prek run \ + pre-commit run \ --config scripts/config/pre-commit.yaml \ --hook-stage manual scan-dependencies \ --all-files -_install-dependency: # Install a tool pinned in 'mise.toml', verified against 'mise.lock' - mandatory: name=[listed in the 'mise.toml' file] +_install-dependency: # Install asdf dependency - mandatory: name=[listed in the '.tool-versions' file]; optional: version=[if not listed] echo ${name} - MISE_LOCKED=1 mise install ${name} + asdf plugin add ${name} ||: + asdf install ${name} $(or ${version},) -_install-dependencies: # Install all the dependencies listed in mise.toml - MISE_LOCKED=1 mise install +_install-dependencies: # Install all the dependencies listed in .tool-versions + for plugin in $$(grep ^[a-z] .tool-versions | sed 's/[[:space:]].*//'); do + $(MAKE) _install-dependency name=$${plugin}; \ + done clean:: # Remove all generated and temporary files (common) @Operations rm -rf \ diff --git a/scripts/maintenance/merge.js b/scripts/maintenance/merge.js index c6cae6ff..8f5bd6cc 100644 --- a/scripts/maintenance/merge.js +++ b/scripts/maintenance/merge.js @@ -2,7 +2,7 @@ * Script to merge all added lines from source to target. * Modified lines will be left intact. * - * This is intended for updating config files like mise.toml and .gitignore + * This is intended for updating config files like .tool-versions and .gitignore * where the first token on the line remains the same * * Usage: diff --git a/scripts/terraform/terraform.mk b/scripts/terraform/terraform.mk index 7b01244f..5e59be7b 100644 --- a/scripts/terraform/terraform.mk +++ b/scripts/terraform/terraform.mk @@ -44,6 +44,10 @@ terraform-validate-all: # Validate all Terraform modules @Quality fi; \ done +terraform-sec: # Run Trivy IaC security scanning on Terraform modules @Quality + # Example: make terraform-sec + ./scripts/terraform/trivy-scan.sh --mode iac infrastructure/terraform/modules + terraform-docs: # Generate Terraform module documentation - optional: module=[specific module, or all if omitted] @Quality # Example: make terraform-docs module=mymodule # Example: make terraform-docs (generates for all modules) @@ -68,7 +72,7 @@ clean:: # Remove Terraform build artifacts and cache @Operations # ============================================================================== # Installation -terraform-install: # Install Terraform using mise @Installation +terraform-install: # Install Terraform using asdf @Installation # Example: make terraform-install make _install-dependency name="terraform" @@ -80,5 +84,6 @@ ${VERBOSE}.SILENT: \ terraform-fmt \ terraform-fmt-check \ terraform-install \ + terraform-sec \ terraform-validate \ terraform-validate-all diff --git a/scripts/terraform/trivy.sh b/scripts/terraform/trivy.sh new file mode 100755 index 00000000..93caabd8 --- /dev/null +++ b/scripts/terraform/trivy.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +# WARNING: Please DO NOT edit this file! It is maintained in the Repository Template (https://github.com/NHSDigital/nhs-notify-repository-template). Raise a PR instead. + +set -euo pipefail + +# TFSec command wrapper. It will run the command natively if TFSec is +# installed, otherwise it will run it in a Docker container. +# Run tfsec for security checks on Terraform code. +# +# Usage: +# $ ./trivy.sh [directory] +# ============================================================================== + +function main() { + + cd "$(git rev-parse --show-toplevel)" + + local dir_to_scan=${1:-.} + + if command -v trivy > /dev/null 2>&1 && ! is-arg-true "${FORCE_USE_DOCKER:-false}"; then + # shellcheck disable=SC2154 + run-trivy-natively "$dir_to_scan" + else + run-trivy-in-docker "$dir_to_scan" + fi +} + +# Run trivy on the specified directory. +# Arguments: +# $1 - Directory to scan +function run-trivy-natively() { + + local dir_to_scan="$1" + + echo "Trivy found locally, running natively" + + echo "Running Trivy on directory: $dir_to_scan" + trivy config \ + --config scripts/config/trivy.yaml \ + --tf-exclude-downloaded-modules \ + "${dir_to_scan}" + + check-trivy-status +} + +# Check the exit status of tfsec. +function check-trivy-status() { + + if [ $? -eq 0 ]; then + echo "Trivy completed successfully." + else + echo "Trivy found issues." + exit 1 + fi +} + +function run-trivy-in-docker() { + + # shellcheck disable=SC1091 + source ./scripts/docker/docker.lib.sh + local dir_to_scan="$1" + + # shellcheck disable=SC2155 + local image=$(name=aquasec/trivy docker-get-image-version-and-pull) + # shellcheck disable=SC2086 + echo "Trivy not found locally, running in Docker Container" + echo "Running Trivy on directory: $dir_to_scan" + docker run --rm --platform linux/amd64 \ + --volume "$PWD":/workdir \ + --workdir /workdir \ + "$image" \ + config \ + --config scripts/config/trivy.yaml \ + --tf-exclude-downloaded-modules \ + "${dir_to_scan}" + check-trivy-status +} +# ============================================================================== + +function is-arg-true() { + + if [[ "$1" =~ ^(true|yes|y|on|1|TRUE|YES|Y|ON)$ ]]; then + return 0 + else + return 1 + fi +} + +# ============================================================================== + +is-arg-true "${VERBOSE:-false}" && set -x + +main "$@" + +exit 0 From 235ab33304059485e1e535ab46a39197db3f72bb Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Wed, 28 Oct 2026 11:52:30 +0000 Subject: [PATCH 7/7] CCM-24467: Mise Compatibility --- .github/actions/lint-terraform/action.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/lint-terraform/action.yaml b/.github/actions/lint-terraform/action.yaml index 722740ca..17cf2b8c 100644 --- a/.github/actions/lint-terraform/action.yaml +++ b/.github/actions/lint-terraform/action.yaml @@ -12,6 +12,7 @@ runs: run: | if command -v mise >/dev/null 2>&1 && [[ -f mise.toml ]]; then MISE_LOCKED=1 mise install terraform + # TODO: CCM-25293 Remove asdf compatibility. elif command -v asdf >/dev/null 2>&1; then if ! asdf plugin list | grep -qx terraform; then asdf plugin add terraform