From 283602ca3b82fbb7864b2d3304adde7c794bf941 Mon Sep 17 00:00:00 2001 From: realmarv Date: Tue, 23 May 2023 15:00:39 +0330 Subject: [PATCH 01/10] FileConventions.Test: add test Add test for DetectUnpinnedDotnetToolInstallVersions function. --- ...CIWithoutUnpinnedDotnetToolInstallVersion.yml | 16 ++++++++++++++++ src/FileConventions.Test/FileConventions.Test.fs | 15 +++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/FileConventions.Test/DummyFiles/DummyCIWithoutUnpinnedDotnetToolInstallVersion.yml diff --git a/src/FileConventions.Test/DummyFiles/DummyCIWithoutUnpinnedDotnetToolInstallVersion.yml b/src/FileConventions.Test/DummyFiles/DummyCIWithoutUnpinnedDotnetToolInstallVersion.yml new file mode 100644 index 000000000..10084073b --- /dev/null +++ b/src/FileConventions.Test/DummyFiles/DummyCIWithoutUnpinnedDotnetToolInstallVersion.yml @@ -0,0 +1,16 @@ +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 --version 4.8.999 + - 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 5e756b3ae..a80003f56 100644 --- a/src/FileConventions.Test/FileConventions.Test.fs +++ b/src/FileConventions.Test/FileConventions.Test.fs @@ -138,6 +138,21 @@ let DetectUnpinnedDotnetToolInstallVersions1() = Is.EqualTo true ) +[] +let DetectUnpinnedDotnetToolInstallVersions2() = + let fileInfo = + (FileInfo( + Path.Combine( + dummyFilesDirectory.FullName, + "DummyCIWithoutUnpinnedDotnetToolInstallVersion.yml" + ) + )) + + Assert.That( + DetectUnpinnedDotnetToolInstallVersions fileInfo, + Is.EqualTo false + ) + [] let DetectAsteriskInPackageReferenceItems1() = From 9909bdd0a8e8ac8f49378b2d3c369a0376f6f489 Mon Sep 17 00:00:00 2001 From: realmarv Date: Tue, 23 May 2023 15:03:57 +0330 Subject: [PATCH 02/10] FileConventions: remove extra parentheses --- src/FileConventions/Library.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FileConventions/Library.fs b/src/FileConventions/Library.fs index 9fc1f1e9a..78479e47f 100644 --- a/src/FileConventions/Library.fs +++ b/src/FileConventions/Library.fs @@ -49,7 +49,7 @@ let DetectUnpinnedVersionsInGitHubCI(fileInfo: FileInfo) = latestTagInRunsOnRegex.IsMatch fileText let DetectUnpinnedDotnetToolInstallVersions(fileInfo: FileInfo) = - assert (fileInfo.FullName.EndsWith(".yml")) + assert fileInfo.FullName.EndsWith ".yml" let fileLines = File.ReadLines fileInfo.FullName @@ -60,7 +60,7 @@ let DetectUnpinnedDotnetToolInstallVersions(fileInfo: FileInfo) = fileLines |> Seq.filter(fun line -> dotnetToolInstallRegex.IsMatch line) |> Seq.filter(fun line -> - not(line.Contains("--version")) && not(line.Contains("-v")) + not(line.Contains "--version") && not(line.Contains "-v") ) |> (fun unpinnedVersions -> Seq.length unpinnedVersions > 0) From f139e8b51d70a3001fbb458d99d275b80632a6a5 Mon Sep 17 00:00:00 2001 From: realmarv Date: Thu, 6 Jul 2023 12:39:50 +0330 Subject: [PATCH 03/10] FileConventions.Test: add failing test Add failing test for detecting unpinned version in npm package installations. --- ...mmyCIWithUnpinnedNpmPackageInstallVersion.yml | 11 +++++++++++ src/FileConventions.Test/FileConventions.Test.fs | 16 ++++++++++++++++ src/FileConventions/Library.fs | 4 ++++ 3 files changed, 31 insertions(+) create mode 100644 src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion.yml diff --git a/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion.yml b/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion.yml new file mode 100644 index 000000000..4f0e52c33 --- /dev/null +++ b/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion.yml @@ -0,0 +1,11 @@ +name: CI + +on: [push, pull_request] + +jobs: + file-conventions: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install prettier without specifying its version + run: npm install prettier diff --git a/src/FileConventions.Test/FileConventions.Test.fs b/src/FileConventions.Test/FileConventions.Test.fs index a80003f56..d558c8e92 100644 --- a/src/FileConventions.Test/FileConventions.Test.fs +++ b/src/FileConventions.Test/FileConventions.Test.fs @@ -154,6 +154,22 @@ let DetectUnpinnedDotnetToolInstallVersions2() = ) +[] +let DetectUnpinnedNpmPackageInstallVersions1() = + let fileInfo = + (FileInfo( + Path.Combine( + dummyFilesDirectory.FullName, + "DummyCIWithUnpinnedNpmPackageInstallVersion.yml" + ) + )) + + Assert.That( + DetectUnpinnedNpmPackageInstallVersions fileInfo, + Is.EqualTo true + ) + + [] let DetectAsteriskInPackageReferenceItems1() = let fileInfo = diff --git a/src/FileConventions/Library.fs b/src/FileConventions/Library.fs index 78479e47f..13aca0c2a 100644 --- a/src/FileConventions/Library.fs +++ b/src/FileConventions/Library.fs @@ -66,6 +66,10 @@ let DetectUnpinnedDotnetToolInstallVersions(fileInfo: FileInfo) = unpinnedDotnetToolInstallVersions +let DetectUnpinnedNpmPackageInstallVersions(fileInfo: FileInfo) = + printfn "File Path: %s" fileInfo.FullName + false + let DetectAsteriskInPackageReferenceItems(fileInfo: FileInfo) = assert (fileInfo.FullName.EndsWith "proj") From 5545a540f141b2496b8095cac4f37cf272d75b7c Mon Sep 17 00:00:00 2001 From: realmarv Date: Thu, 6 Jul 2023 12:56:59 +0330 Subject: [PATCH 04/10] FileConventions: implement the function Implement DetectUnpinnedNpmPackageInstallVersions function. --- src/FileConventions/Library.fs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/FileConventions/Library.fs b/src/FileConventions/Library.fs index 13aca0c2a..227e252df 100644 --- a/src/FileConventions/Library.fs +++ b/src/FileConventions/Library.fs @@ -67,8 +67,20 @@ let DetectUnpinnedDotnetToolInstallVersions(fileInfo: FileInfo) = unpinnedDotnetToolInstallVersions let DetectUnpinnedNpmPackageInstallVersions(fileInfo: FileInfo) = - printfn "File Path: %s" fileInfo.FullName - false + assert fileInfo.FullName.EndsWith ".yml" + + let fileLines = File.ReadLines fileInfo.FullName + + let npmPackageInstallRegex = + Regex("npm\\s+install\\s+", RegexOptions.Compiled) + + let unpinnedNpmPackageInstallVersions = + fileLines + |> Seq.filter(fun line -> npmPackageInstallRegex.IsMatch line) + |> Seq.filter(fun line -> not(line.Contains "@")) + |> (fun unpinnedVersions -> Seq.length unpinnedVersions > 0) + + unpinnedNpmPackageInstallVersions let DetectAsteriskInPackageReferenceItems(fileInfo: FileInfo) = assert (fileInfo.FullName.EndsWith "proj") From 6b83e51346bad2fe117a26c5e3e60aa7694522a1 Mon Sep 17 00:00:00 2001 From: realmarv Date: Thu, 6 Jul 2023 14:14:06 +0330 Subject: [PATCH 05/10] FileConventions.Test: add test Add another test for DetectUnpinnedNpmPackageInstallVersions. --- ...CIWithoutUnpinnedNpmPackageInstallVersion.yml | 11 +++++++++++ src/FileConventions.Test/FileConventions.Test.fs | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/FileConventions.Test/DummyFiles/DummyCIWithoutUnpinnedNpmPackageInstallVersion.yml diff --git a/src/FileConventions.Test/DummyFiles/DummyCIWithoutUnpinnedNpmPackageInstallVersion.yml b/src/FileConventions.Test/DummyFiles/DummyCIWithoutUnpinnedNpmPackageInstallVersion.yml new file mode 100644 index 000000000..080f74605 --- /dev/null +++ b/src/FileConventions.Test/DummyFiles/DummyCIWithoutUnpinnedNpmPackageInstallVersion.yml @@ -0,0 +1,11 @@ +name: CI + +on: [push, pull_request] + +jobs: + file-conventions: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install prettier with specifying its version + run: npm install prettier@2.8.3 diff --git a/src/FileConventions.Test/FileConventions.Test.fs b/src/FileConventions.Test/FileConventions.Test.fs index d558c8e92..24d891598 100644 --- a/src/FileConventions.Test/FileConventions.Test.fs +++ b/src/FileConventions.Test/FileConventions.Test.fs @@ -170,6 +170,22 @@ let DetectUnpinnedNpmPackageInstallVersions1() = ) +[] +let DetectUnpinnedNpmPackageInstallVersions2() = + let fileInfo = + (FileInfo( + Path.Combine( + dummyFilesDirectory.FullName, + "DummyCIWithoutUnpinnedNpmPackageInstallVersion.yml" + ) + )) + + Assert.That( + DetectUnpinnedNpmPackageInstallVersions fileInfo, + Is.EqualTo false + ) + + [] let DetectAsteriskInPackageReferenceItems1() = let fileInfo = From bd8be73762589ec39887e10c979783bd63115d05 Mon Sep 17 00:00:00 2001 From: realmarv Date: Thu, 6 Jul 2023 14:20:56 +0330 Subject: [PATCH 06/10] scripts/unpinnedNpmPackageInstallVersions.fsx: add Add unpinnedNpmPackageInstallVersions.fsx script and specify package versions in npm install commands in GitHubCI. --- .github/workflows/CI.yml | 12 ++++++----- scripts/unpinnedNpmPackageInstallVersions.fsx | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 scripts/unpinnedNpmPackageInstallVersions.fsx diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d49047e90..7682f8ba6 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -77,7 +77,7 @@ jobs: sudo apt install --yes --no-install-recommends npm curl # need to update nodejs because with ubuntu's default nodejs version we would get this error: # error @jest/core@29.4.1: The engine "node" is incompatible with this module. Expected version "^14.15.0 || ^16.10.0 || >=18.0.0". Got "12.22.9" - sudo npm install --global n + sudo npm install --global n@9.1.0 sudo n lts - name: Print versions run: | @@ -86,12 +86,12 @@ jobs: npm --version - name: Install yarn run: | - npm install --global yarn + npm install --global yarn@1.22.19 yarn add --dev jest typescript ts-jest @types/jest - name: Install commitlint run: | - npm install conventional-changelog-conventionalcommits - npm install commitlint@latest + npm install conventional-changelog-conventionalcommits@6.1.0 + npm install commitlint@17.6.6 - name: Print versions run: | git --version @@ -130,7 +130,7 @@ jobs: # at wrapSafe (internal/modules/cjs/loader.js:915:16) # ... # ``` - sudo npm install --global n + sudo npm install --global n@9.1.0 sudo n lts - uses: actions/checkout@v2 with: @@ -179,6 +179,8 @@ jobs: 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 there are no unpinned versions in `npm install` commands + run: dotnet fsi scripts/unpinnedNpmPackageInstallVersions.fsx - name: Check commits 1 by 1 if: github.event_name == 'pull_request' run: dotnet fsi scripts/checkCommits1by1.fsx diff --git a/scripts/unpinnedNpmPackageInstallVersions.fsx b/scripts/unpinnedNpmPackageInstallVersions.fsx new file mode 100644 index 000000000..d1969334b --- /dev/null +++ b/scripts/unpinnedNpmPackageInstallVersions.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.DetectUnpinnedNpmPackageInstallVersions + +let message = + "Please define the package version number in the `npm install` commands." + +Helpers.AssertNoInvalidFiles invalidFiles message From fadc5dc5785f1e09098f9030a0fdfd05f1b308e8 Mon Sep 17 00:00:00 2001 From: realmarv Date: Thu, 6 Jul 2023 14:29:20 +0330 Subject: [PATCH 07/10] FileConventions.Test: add failing test Add failing test for DetectUnpinnedNpmPackageInstallVersions function. --- ...IWithUnpinnedNpmPackageInstallVersion1.yml} | 0 ...CIWithUnpinnedNpmPackageInstallVersion2.yml | 11 +++++++++++ .../FileConventions.Test.fs | 18 +++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) rename src/FileConventions.Test/DummyFiles/{DummyCIWithUnpinnedNpmPackageInstallVersion.yml => DummyCIWithUnpinnedNpmPackageInstallVersion1.yml} (100%) create mode 100644 src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion2.yml diff --git a/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion.yml b/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion1.yml similarity index 100% rename from src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion.yml rename to src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion1.yml diff --git a/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion2.yml b/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion2.yml new file mode 100644 index 000000000..a05bab538 --- /dev/null +++ b/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion2.yml @@ -0,0 +1,11 @@ +name: CI + +on: [push, pull_request] + +jobs: + file-conventions: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install an npm package without specifying its version + run: sudo npm install --save-dev @prettier/plugin-xml diff --git a/src/FileConventions.Test/FileConventions.Test.fs b/src/FileConventions.Test/FileConventions.Test.fs index 24d891598..67ba593b9 100644 --- a/src/FileConventions.Test/FileConventions.Test.fs +++ b/src/FileConventions.Test/FileConventions.Test.fs @@ -160,7 +160,7 @@ let DetectUnpinnedNpmPackageInstallVersions1() = (FileInfo( Path.Combine( dummyFilesDirectory.FullName, - "DummyCIWithUnpinnedNpmPackageInstallVersion.yml" + "DummyCIWithUnpinnedNpmPackageInstallVersion1.yml" ) )) @@ -186,6 +186,22 @@ let DetectUnpinnedNpmPackageInstallVersions2() = ) +[] +let DetectUnpinnedNpmPackageInstallVersions3() = + let fileInfo = + (FileInfo( + Path.Combine( + dummyFilesDirectory.FullName, + "DummyCIWithUnpinnedNpmPackageInstallVersion2.yml" + ) + )) + + Assert.That( + DetectUnpinnedNpmPackageInstallVersions fileInfo, + Is.EqualTo true + ) + + [] let DetectAsteriskInPackageReferenceItems1() = let fileInfo = From a35680666d86c9ba786c56471ad42cf3be6c12e7 Mon Sep 17 00:00:00 2001 From: realmarv Date: Thu, 6 Jul 2023 14:37:49 +0330 Subject: [PATCH 08/10] FileConventions: fix the function Fix DetectUnpinnedNpmPackageInstallVersions function. --- src/FileConventions/Library.fs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/FileConventions/Library.fs b/src/FileConventions/Library.fs index 227e252df..aab372311 100644 --- a/src/FileConventions/Library.fs +++ b/src/FileConventions/Library.fs @@ -74,10 +74,15 @@ let DetectUnpinnedNpmPackageInstallVersions(fileInfo: FileInfo) = let npmPackageInstallRegex = Regex("npm\\s+install\\s+", RegexOptions.Compiled) + let npmPackageVersionRegex = + Regex("@\\d+\\.\\d+\\.\\d+", RegexOptions.Compiled) + let unpinnedNpmPackageInstallVersions = fileLines - |> Seq.filter(fun line -> npmPackageInstallRegex.IsMatch line) - |> Seq.filter(fun line -> not(line.Contains "@")) + |> Seq.filter(fun line -> + npmPackageInstallRegex.IsMatch line + && npmPackageVersionRegex.IsMatch line |> not + ) |> (fun unpinnedVersions -> Seq.length unpinnedVersions > 0) unpinnedNpmPackageInstallVersions From 145dd13007a5739f3d267c6fb3a5b818eaaaff55 Mon Sep 17 00:00:00 2001 From: realmarv Date: Thu, 6 Jul 2023 15:03:04 +0330 Subject: [PATCH 09/10] FileConventions: add another failing test Add failing test for DetectUnpinnedNpmPackageInstallVersions function. --- ...myCIWithUnpinnedNpmPackageInstallVersion3.yml | 11 +++++++++++ src/FileConventions.Test/FileConventions.Test.fs | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion3.yml diff --git a/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion3.yml b/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion3.yml new file mode 100644 index 000000000..87ed0e981 --- /dev/null +++ b/src/FileConventions.Test/DummyFiles/DummyCIWithUnpinnedNpmPackageInstallVersion3.yml @@ -0,0 +1,11 @@ +name: CI + +on: [push, pull_request] + +jobs: + file-conventions: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install two npm packages, one with version and the other one without version + run: sudo npm install --save-dev @prettier/plugin-xml prettier@2.4.0 diff --git a/src/FileConventions.Test/FileConventions.Test.fs b/src/FileConventions.Test/FileConventions.Test.fs index 67ba593b9..fa0811b9a 100644 --- a/src/FileConventions.Test/FileConventions.Test.fs +++ b/src/FileConventions.Test/FileConventions.Test.fs @@ -202,6 +202,22 @@ let DetectUnpinnedNpmPackageInstallVersions3() = ) +[] +let DetectUnpinnedNpmPackageInstallVersions4() = + let fileInfo = + (FileInfo( + Path.Combine( + dummyFilesDirectory.FullName, + "DummyCIWithUnpinnedNpmPackageInstallVersion3.yml" + ) + )) + + Assert.That( + DetectUnpinnedNpmPackageInstallVersions fileInfo, + Is.EqualTo true + ) + + [] let DetectAsteriskInPackageReferenceItems1() = let fileInfo = From 871fe58a01bd117afcc9db951d8ed99b6bf834d1 Mon Sep 17 00:00:00 2001 From: realmarv Date: Thu, 6 Jul 2023 16:13:43 +0330 Subject: [PATCH 10/10] FileConventions: fix the function Fix DetectUnpinnedNpmPackageInstallVersions function. --- src/FileConventions/Library.fs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/FileConventions/Library.fs b/src/FileConventions/Library.fs index aab372311..76f05040c 100644 --- a/src/FileConventions/Library.fs +++ b/src/FileConventions/Library.fs @@ -79,9 +79,22 @@ let DetectUnpinnedNpmPackageInstallVersions(fileInfo: FileInfo) = let unpinnedNpmPackageInstallVersions = fileLines + |> Seq.filter(fun line -> npmPackageInstallRegex.IsMatch line) |> Seq.filter(fun line -> - npmPackageInstallRegex.IsMatch line - && npmPackageVersionRegex.IsMatch line |> not + let npmPackagesRegex = + Regex("(?<=npm install ).*$", RegexOptions.Compiled) + + let npmInstallPackages = npmPackagesRegex.Match line + + let numNpmInstallPackages = + npmInstallPackages.Value.Split(" ") + |> Seq.filter(fun word -> word.Trim().StartsWith("-") |> not) + |> Seq.length + + let numNpmInstallVersions = + npmPackageVersionRegex.Matches line |> Seq.length + + numNpmInstallPackages = numNpmInstallVersions |> not ) |> (fun unpinnedVersions -> Seq.length unpinnedVersions > 0)