diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 28af6800..561baf34 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -141,6 +141,8 @@ jobs: run: dotnet fsi scripts/unpinnedDotnetPackageVersions.fsx - name: Check there are no unpinned nuget package reference versions in F# scripts run: dotnet fsi scripts/unpinnedNugetPackageReferenceVersions.fsx + - name: Check there are no unpinned versions in `dotnet tool install` commands + run: dotnet fsi scripts/unpinnedDotnetToolInstallVersions.fsx - name: Check if gitPush1by1 was used if: github.event_name == 'pull_request' run: dotnet fsi scripts/detectNotUsingGitPush1by1.fsx diff --git a/ReadMe.md b/ReadMe.md index 35503052..58593c9a 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -13,6 +13,7 @@ This is a repository that contains several useful things that other `nblockchain * [Use of `-latest` suffix in `runs-on:` GitHubCI tags](scripts/unpinnedGitHubActionsImageVersions.fsx). * [Use of asterisk (*) in `PackageReference` items of .NET projects](scripts/unpinnedDotnetPackageVersions.fsx). * [Missing the version number in `#r "nuget: ` refs of F# scripts](scripts/unpinnedNugetPackageReferenceVersions.fsx). + * [Missing the `--version` flag in `dotnet tool install foo` invocations](scripts/unpinnedDotnetToolInstallVersions.fsx). All in all, this is mainly documentation, and some tooling to detect bad practices. @@ -21,5 +22,3 @@ More things to come: - Detect old versions of FSharpLint and fantomas/fantomless being used. - Detect old versions of .editorconfig or Directory.Build.props being used. - Detect non-verbose flags (e.g. `dotnet build -c Debug` instead of `dotnet build --configuration Debug`) being used in scripts or YML CI files (there are exceptions, e.g. `env -S`). -- Detect unpinned versions, such as: - * Missing the `--version` flag in `dotnet tool install foo` invocations. diff --git a/scripts/unpinnedDotnetToolInstallVersions.fsx b/scripts/unpinnedDotnetToolInstallVersions.fsx new file mode 100644 index 00000000..0d99b0f4 --- /dev/null +++ b/scripts/unpinnedDotnetToolInstallVersions.fsx @@ -0,0 +1,20 @@ +#!/usr/bin/env -S dotnet fsi + +open System +open System.IO + +#load "../src/FileConventions/Library.fs" +#load "../src/FileConventions/Helpers.fs" + +let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo + +let invalidFiles = + Helpers.GetInvalidFiles + rootDir + "*.yml" + FileConventions.DetectUnpinnedDotnetToolInstallVersions + +let message = + "Please define the package version number in the `dotnet tool install` commands." + +Helpers.AssertNoInvalidFiles invalidFiles message diff --git a/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedDotnetToolInstallVersion.yml b/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedDotnetToolInstallVersion.yml new file mode 100644 index 00000000..bc3f93f6 --- /dev/null +++ b/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedDotnetToolInstallVersion.yml @@ -0,0 +1,17 @@ +name: CI + +on: [push, pull_request] + +jobs: + build: + name: Build + runs-on: ubuntu-22.04 + container: + image: "ubuntu:22.04" + steps: + - name: Install fantomless-tool + run: | + dotnet tool install fantomless-tool + - name: Print "Hello World!" + run: echo "Hello World" + diff --git a/src/FileConventions.Test/FileConventions.Test.fs b/src/FileConventions.Test/FileConventions.Test.fs index ec5198f1..f4d1682e 100644 --- a/src/FileConventions.Test/FileConventions.Test.fs +++ b/src/FileConventions.Test/FileConventions.Test.fs @@ -123,6 +123,22 @@ let DetectUnpinnedVersionsInGitHubCI2() = Assert.That(DetectUnpinnedVersionsInGitHubCI fileInfo, Is.EqualTo false) +[] +let DetectUnpinnedDotnetToolInstallVersions1() = + let fileInfo = + (FileInfo( + Path.Combine( + dummyFilesDirectory.FullName, + "DummyCIWithUnpinnedDotnetToolInstallVersion.yml" + ) + )) + + Assert.That( + DetectUnpinnedDotnetToolInstallVersions fileInfo, + Is.EqualTo true + ) + + [] let DetectAsteriskInPackageReferenceItems1() = let fileInfo = diff --git a/src/FileConventions/Library.fs b/src/FileConventions/Library.fs index 18524405..5f5bab98 100644 --- a/src/FileConventions/Library.fs +++ b/src/FileConventions/Library.fs @@ -49,6 +49,24 @@ let DetectUnpinnedVersionsInGitHubCI(fileInfo: FileInfo) = latestTagInRunsOnRegex.IsMatch fileText +let DetectUnpinnedDotnetToolInstallVersions(fileInfo: FileInfo) = + assert (fileInfo.FullName.EndsWith(".yml")) + + let fileLines = File.ReadLines fileInfo.FullName + + let dotnetToolInstallRegex = + Regex("dotnet\\s+tool\\s+install\\s+", RegexOptions.Compiled) + + let unpinnedDotnetToolInstallVersions = + fileLines + |> Seq.filter(fun line -> dotnetToolInstallRegex.IsMatch line) + |> Seq.filter(fun line -> + not(line.Contains("--version")) && not(line.Contains("-v")) + ) + |> (fun unpinnedVersions -> Seq.length unpinnedVersions > 0) + + unpinnedDotnetToolInstallVersions + let DetectAsteriskInPackageReferenceItems(fileInfo: FileInfo) = assert (fileInfo.FullName.EndsWith "proj") use streamReader = new StreamReader(fileInfo.FullName)