diff --git a/.taskfiles/_internal.Taskfile.yml b/.taskfiles/_internal.Taskfile.yml index 0f5ff8f..ff70665 100644 --- a/.taskfiles/_internal.Taskfile.yml +++ b/.taskfiles/_internal.Taskfile.yml @@ -42,14 +42,19 @@ tasks: cmds: - cmd: | {{if ne .VER "latest"}} - {{.CMD}} | grep -F "{{.VER}}" + version="{{.VER}}" + normalized="${version#v}" + output="$({{.CMD}})" + printf '%s\n' "${output}" | grep -F "${version}" >/dev/null || printf '%s\n' "${output}" | grep -F "${normalized}" >/dev/null {{end}} platforms: [linux, darwin] - cmd: | {{if ne .VER "latest"}} {{.PWSH}} ' - $match = (& {{.CMD}}) | Select-String -Pattern "{{.VER}}" -SimpleMatch - if (-not $match) { exit 1 } + $version = "{{.VER}}" + $normalized = $version -replace "^v", "" + $output = (& {{.CMD}}) | Out-String + if (-not $output.Contains($version) -and -not $output.Contains($normalized)) { exit 1 } ' {{end}} platforms: [windows] diff --git a/.taskfiles/azure.Taskfile.yml b/.taskfiles/azure.Taskfile.yml index ed14395..246c1a6 100644 --- a/.taskfiles/azure.Taskfile.yml +++ b/.taskfiles/azure.Taskfile.yml @@ -6,9 +6,9 @@ version: "3" vars: AZURE_VERSION: map: - az: latest - azd: latest - bicep: latest + az: 2.86.0 + azd: 1.25.2 + bicep: 0.43.8 AZURE_INSTALLER_SHA: map: azd: 0340065907dee7ca71cd68ed132033cabb38cbce # 2025-03-27 Azure/azure-dev cli/installer/install-azd.sh diff --git a/.taskfiles/github.Taskfile.yml b/.taskfiles/github.Taskfile.yml index 26eaa11..2a8afa2 100644 --- a/.taskfiles/github.Taskfile.yml +++ b/.taskfiles/github.Taskfile.yml @@ -6,11 +6,11 @@ version: "3" vars: GITHUB_VERSION: map: - actionlint: latest - act: latest - pinact: latest - ghalint: latest - gh: latest + actionlint: 1.7.12 + act: 0.2.88 + pinact: 4.0.0 + ghalint: 1.5.6 + gh: 2.92.0 GITHUB_INSTALLER_SHA: map: actionlint: 62c50a97a146fe36a8951a2a365158c4a4795ba8 # v1.7.11 rhysd/actionlint scripts/download-actionlint.bash diff --git a/.taskfiles/golang.Taskfile.yml b/.taskfiles/golang.Taskfile.yml index a0cb612..df5e415 100644 --- a/.taskfiles/golang.Taskfile.yml +++ b/.taskfiles/golang.Taskfile.yml @@ -6,17 +6,17 @@ version: "3" vars: GO_VERSION: map: - dlv: latest - gopls: latest - deadcode: latest - golangciLint: latest - gotestsum: latest - govulncheck: latest - goimports: latest - gofumpt: latest - goTestCoverage: latest - gocoverCobertura: latest - goreleaser: latest + dlv: v1.26.3 + gopls: v0.22.0 + deadcode: v0.45.0 + golangciLint: 2.12.2 + gotestsum: v1.13.0 + govulncheck: v1.3.0 + goimports: v0.45.0 + gofumpt: v0.10.0 + goTestCoverage: v2.18.8 + gocoverCobertura: v1.5.0 + goreleaser: 2.16.0 GO_INSTALLER_SHA: map: golangciLint: 35b2189782a6a059489289257e6523550167cb64 # 2026-05-01 golangci/golangci-lint install.sh diff --git a/.taskfiles/javascript.Taskfile.yml b/.taskfiles/javascript.Taskfile.yml index 8576fec..79643ac 100644 --- a/.taskfiles/javascript.Taskfile.yml +++ b/.taskfiles/javascript.Taskfile.yml @@ -6,7 +6,8 @@ version: "3" vars: JAVASCRIPT_VERSION: map: - prettier: latest + prettier: 3.8.3 + prettierPluginMultilineArrays: 4.1.8 tasks: # * Install Prettier @@ -18,7 +19,7 @@ tasks: APP: prettier@{{.JAVASCRIPT_VERSION.prettier}} - task: :internal:_install:npm vars: - APP: prettier-plugin-multiline-arrays + APP: prettier-plugin-multiline-arrays@{{.JAVASCRIPT_VERSION.prettierPluginMultilineArrays}} OPTS: --no-save # * Tools diff --git a/.taskfiles/markdown.Taskfile.yml b/.taskfiles/markdown.Taskfile.yml index c1499f4..8b827fc 100644 --- a/.taskfiles/markdown.Taskfile.yml +++ b/.taskfiles/markdown.Taskfile.yml @@ -6,8 +6,8 @@ version: "3" vars: MARKDOWN_VERSION: map: - markdownlintCli2: latest - markdownTableFormatter: latest + markdownlintCli2: 0.22.1 + markdownTableFormatter: 1.7.0 tasks: # * Install markdownlint-cli2 @@ -46,7 +46,7 @@ tasks: preconditions: - sh: task internal:command -- markdownlint-cli2 msg: "❌ Error: markdownlint-cli2 is not installed. Please run 'task md:install:markdownlint-cli2'" - - sh: task internal:command:version -- "markdownlint-cli2 --help" "{{.MARKDOWN_VERSION.markdownlintCli2}}" + - sh: task internal:command:version -- "markdownlint-cli2 --version" "{{.MARKDOWN_VERSION.markdownlintCli2}}" msg: "❌ Version Mismatch: You are not using {{.MARKDOWN_VERSION.markdownlintCli2}} version. Please run 'task md:install:markdownlint-cli2'" sources: - "**/*.md" diff --git a/.taskfiles/runtime.Taskfile.yml b/.taskfiles/runtime.Taskfile.yml index cc0607b..3493712 100644 --- a/.taskfiles/runtime.Taskfile.yml +++ b/.taskfiles/runtime.Taskfile.yml @@ -6,13 +6,19 @@ version: "3" vars: RUNTIME_VERSION: map: - uv: latest - fnm: latest - pwsh: latest - golang: latest + uv: 0.11.16 + fnm: 1.39.0 + pwsh: 7.6.2 + golang: 1.26.3 RUNTIME_INSTALLER_SHA: map: fnm: bfb186034978b1ddaf87501eb1633bdc42a5c0a6 # 2026-03-09 Schniz/fnm .ci/install.sh + RUNTIME_SHA256: + map: + pwshLinuxX64: 6cbcfbf20e376aa62ffd91c973493c41a7a52ddfd5a5db3ff9bc12f0d0fe9292 + pwshLinuxArm64: a8d4e386dfafda385d0604045eed03ce6f3a843d45fc8f0b9588b836ca17cdb8 + pwshOsxX64: 3ce51ba39fd3c816212866ea461d582d69c5c9c3d35a1fd6cd789d23803758a2 + pwshOsxArm64: 4b10e8a8e3dba067cf68c09bd92ee137ccac00b7c05ed31a0ae136309ef107b6 PYTHON_VERSION: sh: | [ -f .python-version ] && cat .python-version || echo "3.14" @@ -85,10 +91,10 @@ tasks: desc: pwsh setup cmds: - cmd: | - sudo ./scripts/setup_pwsh.sh "{{.RUNTIME_VERSION.pwsh}}" + sudo env PWSH_SHA256_LINUX_X64="{{.RUNTIME_SHA256.pwshLinuxX64}}" PWSH_SHA256_LINUX_ARM64="{{.RUNTIME_SHA256.pwshLinuxArm64}}" ./scripts/setup_pwsh.sh "{{.RUNTIME_VERSION.pwsh}}" platforms: [linux] - cmd: | - ./scripts/setup_pwsh.sh "{{.RUNTIME_VERSION.pwsh}}" + PWSH_SHA256_OSX_X64="{{.RUNTIME_SHA256.pwshOsxX64}}" PWSH_SHA256_OSX_ARM64="{{.RUNTIME_SHA256.pwshOsxArm64}}" ./scripts/setup_pwsh.sh "{{.RUNTIME_VERSION.pwsh}}" platforms: [darwin] - task: :internal:_install:winget vars: diff --git a/.taskfiles/scripts/install_actionlint.sh b/.taskfiles/scripts/install_actionlint.sh index ea72dc7..9bd0ec3 100755 --- a/.taskfiles/scripts/install_actionlint.sh +++ b/.taskfiles/scripts/install_actionlint.sh @@ -69,11 +69,11 @@ if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then exit 0 fi -# Normalize VERSION: empty/whitespace -> "latest", numeric -> add "v" prefix +# Normalize VERSION: empty/whitespace -> "latest", optional release tag -> upstream script version if [[ -z "${VERSION//[[:space:]]/}" ]]; then VERSION="latest" -elif [[ "${VERSION}" != "latest" && "${VERSION}" =~ ^[0-9] ]]; then - VERSION="v${VERSION}" +elif [[ "${VERSION}" != "latest" ]]; then + VERSION="${VERSION#v}" fi # Determine install directory diff --git a/.taskfiles/scripts/install_gh.sh b/.taskfiles/scripts/install_gh.sh index 5b2e4ee..a7c9121 100755 --- a/.taskfiles/scripts/install_gh.sh +++ b/.taskfiles/scripts/install_gh.sh @@ -65,6 +65,8 @@ fi # Normalize VERSION: empty/whitespace -> "latest" if [[ -z "${VERSION//[[:space:]]/}" ]]; then VERSION="latest" +elif [[ "${VERSION}" != "latest" ]]; then + VERSION="${VERSION#v}" fi # Main execution diff --git a/.taskfiles/scripts/install_opentofu.sh b/.taskfiles/scripts/install_opentofu.sh index 8f92876..d0d9342 100755 --- a/.taskfiles/scripts/install_opentofu.sh +++ b/.taskfiles/scripts/install_opentofu.sh @@ -67,11 +67,11 @@ if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then exit 0 fi -# Normalize VERSION: empty/whitespace -> "latest", numeric -> add "v" prefix +# Normalize VERSION: empty/whitespace -> "latest", optional release tag -> upstream script version if [[ -z "${VERSION//[[:space:]]/}" ]]; then VERSION="latest" -elif [[ "${VERSION}" != "latest" && "${VERSION}" =~ ^[0-9] ]]; then - VERSION="v${VERSION}" +elif [[ "${VERSION}" != "latest" ]]; then + VERSION="${VERSION#v}" fi # Determine install directory diff --git a/.taskfiles/scripts/setup_pwsh.sh b/.taskfiles/scripts/setup_pwsh.sh index 7f856d7..dc733ff 100755 --- a/.taskfiles/scripts/setup_pwsh.sh +++ b/.taskfiles/scripts/setup_pwsh.sh @@ -11,6 +11,7 @@ readonly PACKAGES_DEB="packages-microsoft-prod.deb" VERSION="${1:-${VERSION:-latest}}" tempFile="" +tempDir="" log() { echo "-> $*" >&2 @@ -29,6 +30,10 @@ Positional arguments: Environment variables: VERSION Desired version (default: latest) + PWSH_SHA256_LINUX_X64 Expected SHA256 for pinned linux-x64 archive + PWSH_SHA256_LINUX_ARM64 Expected SHA256 for pinned linux-arm64 archive + PWSH_SHA256_OSX_X64 Expected SHA256 for pinned osx-x64 archive + PWSH_SHA256_OSX_ARM64 Expected SHA256 for pinned osx-arm64 archive Notes: - Linux: installs PowerShell from packages.microsoft.com (preferred method in official docs). Must be run with sudo/root. @@ -44,6 +49,9 @@ cleanup() { if [[ -n "${tempFile}" && -f "${tempFile}" ]]; then rm -f "${tempFile}" fi + if [[ -n "${tempDir}" && -d "${tempDir}" ]]; then + rm -rf "${tempDir}" + fi } trap cleanup EXIT INT TERM @@ -53,6 +61,24 @@ check_sudo() { fi } +verify_sha256() { + local filePath="$1" + local expectedSha="$2" + local actualSha + + [[ -n "${expectedSha}" ]] || die "Missing expected SHA256 for pinned PowerShell archive" + + if command -v sha256sum >/dev/null 2>&1; then + actualSha="$(sha256sum "${filePath}" | awk '{print $1}')" + elif command -v shasum >/dev/null 2>&1; then + actualSha="$(shasum -a 256 "${filePath}" | awk '{print $1}')" + else + die "Missing required dependency: sha256sum or shasum" + fi + + [[ "${actualSha}" == "${expectedSha}" ]] || die "SHA256 mismatch for ${filePath}" +} + # Show help if requested if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then usage @@ -65,20 +91,52 @@ if [[ -z "${VERSION//[[:space:]]/}" ]]; then fi os="$(uname -s | tr '[:upper:]' '[:lower:]')" +version="${VERSION#v}" if [[ "${os}" == "darwin" ]]; then - log "Installing ${TOOL_NAME} (${VERSION}) using Homebrew" - - command -v brew >/dev/null 2>&1 || die "brew is not installed. Install it from https://brew.sh/" - - if [[ "${VERSION}" != "latest" ]]; then - log "Note: version pinning isn't supported by this Homebrew installer path; installing latest stable." + if [[ "${VERSION}" == "latest" ]]; then + log "Installing ${TOOL_NAME} (${VERSION}) using Homebrew" + command -v brew >/dev/null 2>&1 || die "brew is not installed. Install it from https://brew.sh/" + brew install --cask powershell || die "Failed to install PowerShell via Homebrew" + log "✓ Successfully installed ${TOOL_NAME}" + pwsh --version >/dev/null 2>&1 || die "Installed binary failed to run" + exit 0 fi - brew install --cask powershell || die "Failed to install PowerShell via Homebrew" + log "Installing ${TOOL_NAME} (${version}) from pinned release archive" + + for dep in curl tar; do + command -v "${dep}" >/dev/null 2>&1 || die "Missing required dependency: ${dep}" + done + + arch="$(uname -m)" + case "${arch}" in + x86_64 | amd64) + asset_arch="x64" + expectedSha="${PWSH_SHA256_OSX_X64:-}" + ;; + arm64 | aarch64) + asset_arch="arm64" + expectedSha="${PWSH_SHA256_OSX_ARM64:-}" + ;; + *) die "Unsupported architecture: ${arch}" ;; + esac + + tempDir="$(mktemp -d)" || die "Failed to create temporary directory" + installDir="${HOME}/.local/powershell/${version}" + binDir="${HOME}/.local/bin" + archivePath="${tempDir}/powershell.tar.gz" + downloadUrl="https://github.com/PowerShell/PowerShell/releases/download/v${version}/powershell-${version}-osx-${asset_arch}.tar.gz" + + mkdir -p "${installDir}" "${binDir}" || die "Failed to create install directories" + curl -fsSL "${downloadUrl}" -o "${archivePath}" || die "Failed to download PowerShell ${version}" + verify_sha256 "${archivePath}" "${expectedSha}" + tar -xzf "${archivePath}" -C "${installDir}" || die "Failed to extract PowerShell ${version}" + chmod +x "${installDir}/pwsh" || die "Failed to make pwsh executable" + ln -sf "${installDir}/pwsh" "${binDir}/pwsh" || die "Failed to link pwsh" log "✓ Successfully installed ${TOOL_NAME}" - pwsh --version >/dev/null 2>&1 || die "Installed binary failed to run" + "${binDir}/pwsh" --version >/dev/null 2>&1 || die "Installed binary failed to run" exit 0 fi @@ -86,14 +144,15 @@ if [[ "${os}" != "linux" ]]; then die "Unsupported OS: ${os}" fi -# Check for ARM64 architecture - PowerShell apt packages are not available for ARM64 arch="$(uname -m)" -if [[ "${arch}" == "aarch64" || "${arch}" == "arm64" ]]; then + +if [[ "${VERSION}" == "latest" && ("${arch}" == "aarch64" || "${arch}" == "arm64") ]]; then log "⚠ PowerShell is not available via apt for ARM64 architecture." log "Installing PowerShell via .NET global tool instead..." # Install .NET SDK if not present if ! command -v dotnet >/dev/null 2>&1; then + check_sudo log "Installing .NET SDK..." apt-get update apt-get install -y dotnet-sdk-8.0 || die "Failed to install .NET SDK" @@ -116,7 +175,38 @@ fi check_sudo if [[ "${VERSION}" != "latest" ]]; then - die "This installer uses the Microsoft package repository method and installs the latest available version. For specific versions, use the official direct-download method." + for dep in curl tar; do + command -v "${dep}" >/dev/null 2>&1 || die "Missing required dependency: ${dep}" + done + + case "${arch}" in + x86_64 | amd64) + asset_arch="x64" + expectedSha="${PWSH_SHA256_LINUX_X64:-}" + ;; + arm64 | aarch64) + asset_arch="arm64" + expectedSha="${PWSH_SHA256_LINUX_ARM64:-}" + ;; + *) die "Unsupported architecture: ${arch}" ;; + esac + + tempDir="$(mktemp -d)" || die "Failed to create temporary directory" + installDir="/opt/microsoft/powershell/${version}" + archivePath="${tempDir}/powershell.tar.gz" + downloadUrl="https://github.com/PowerShell/PowerShell/releases/download/v${version}/powershell-${version}-linux-${asset_arch}.tar.gz" + + log "Installing ${TOOL_NAME} (${version}) from pinned release archive" + mkdir -p "${installDir}" || die "Failed to create install directory ${installDir}" + curl -fsSL "${downloadUrl}" -o "${archivePath}" || die "Failed to download PowerShell ${version}" + verify_sha256 "${archivePath}" "${expectedSha}" + tar -xzf "${archivePath}" -C "${installDir}" || die "Failed to extract PowerShell ${version}" + chmod +x "${installDir}/pwsh" || die "Failed to make pwsh executable" + ln -sf "${installDir}/pwsh" /usr/bin/pwsh || die "Failed to link pwsh" + + log "✓ Successfully installed ${TOOL_NAME}" + "${TOOL_NAME}" -Version >/dev/null 2>&1 || die "Installed binary failed to run" + exit 0 fi log "Installing ${TOOL_NAME} (${VERSION}) via Microsoft package repository" diff --git a/.taskfiles/shell.Taskfile.yml b/.taskfiles/shell.Taskfile.yml index c1f7a95..d055fc8 100644 --- a/.taskfiles/shell.Taskfile.yml +++ b/.taskfiles/shell.Taskfile.yml @@ -6,8 +6,8 @@ version: "3" vars: SHELL_VERSION: map: - shellcheck: latest - shfmt: latest + shellcheck: 0.11.0 + shfmt: 3.13.1 tasks: # * Install shellcheck diff --git a/.taskfiles/terraform.Taskfile.yml b/.taskfiles/terraform.Taskfile.yml index b448af6..6d40569 100644 --- a/.taskfiles/terraform.Taskfile.yml +++ b/.taskfiles/terraform.Taskfile.yml @@ -6,8 +6,8 @@ version: "3" vars: TERRAFORM_VERSION: map: - terraform: latest - opentofu: latest + terraform: 1.15.4 + opentofu: 1.12.1 TERRAFORM_INSTALLER_SHA: map: opentofu: c4f7de951e69f7c11b04e2e97b72b1e4e447e5bc # 2024-12-26 opentofu/get.opentofu.org static/install-opentofu.sh diff --git a/.taskfiles/yaml.Taskfile.yml b/.taskfiles/yaml.Taskfile.yml index cd6c983..d678972 100644 --- a/.taskfiles/yaml.Taskfile.yml +++ b/.taskfiles/yaml.Taskfile.yml @@ -6,7 +6,7 @@ version: "3" vars: YAML_VERSION: map: - yamllint: latest + yamllint: 1.38.0 tasks: # * Install YAMLlint