From 9078613eafb0ca78c695b347ae04306e0b5fe909 Mon Sep 17 00:00:00 2001 From: realmarv Date: Tue, 4 Apr 2023 13:39:57 +0330 Subject: [PATCH 1/4] scripts/styleChecker.fsx: add Add styleChecker.fsx script to check style of our F#, TS and YML codes. The `git respore package.json` command in the styleChecker.fsx script was failing with the following error, even when I was running the `git config --global --add safe.directory '*'` command in both the styleChecker.fsx script and in the CI. In the issue [1], it's suggested by someone to use --system instead of --global in the mentioned command, when the git command is running in a container, which solved the problem. ``` fatal: detected dubious ownership in repository at '/__w/conventions/conventions' To add an exception for this directory, call: git config --global --add safe.directory /__w/conventions/conventions Error when running 'git restore package.json' Fsdk.Process+ProcessFailed: Exception of type 'Fsdk.Process+ProcessFailed' was thrown. at Fsdk.Process.ProcessResult.Unwrap(String errMsg) at Fsdk.Process.ProcessResult.UnwrapDefault() at FSI_0002.RunPrettier(String arguments) at .$FSI_0002.main@() Stopped due to error Error: Process completed with exit code 1. ``` [1] https://github.com/actions/checkout/issues/1048 --- .github/workflows/CI.yml | 5 + scripts/styleChecker.fsx | 304 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 309 insertions(+) create mode 100755 scripts/styleChecker.fsx diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 5c23e7db2..c7db8ee17 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -169,6 +169,9 @@ jobs: submodules: recursive # needed because of commit-lint, see https://github.com/conventional-changelog/commitlint/issues/3376 fetch-depth: 0 + # workaround for https://github.com/actions/runner/issues/2033 + - name: ownership workaround + run: git config --system --add safe.directory '*' - name: Print versions run: | git --version @@ -253,3 +256,5 @@ jobs: dotnet tool install fantomless-tool --version 4.7.997-prerelease dotnet fantomless --recurse . git diff --exit-code + - name: Check style of our F#, TypeScript and YML code + run: sudo dotnet fsi scripts/styleChecker.fsx diff --git a/scripts/styleChecker.fsx b/scripts/styleChecker.fsx new file mode 100755 index 000000000..2378c493c --- /dev/null +++ b/scripts/styleChecker.fsx @@ -0,0 +1,304 @@ +#!/usr/bin/env -S dotnet fsi + +#r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" +#load "../src/FileConventions/Helpers.fs" + +open System +open System.IO + +open Fsdk +open Fsdk.Process + +open Helpers + +let fantomlessToolVersion = "4.7.997-prerelease" +let prettierVersion = "2.8.3" + +let InstallFantomlessTool(version: string) = + let isFantomlessInstalled = + let installedPackages: string = + Process + .Execute( + { + Command = "dotnet" + Arguments = "tool list" + }, + Echo.Off + ) + .UnwrapDefault() + + installedPackages.Split Environment.NewLine + |> Seq.map(fun line -> + line.Contains "fantomless-tool" + && line.Contains fantomlessToolVersion + ) + |> Seq.contains true + + if not(isFantomlessInstalled) then + Process + .Execute( + { + Command = "dotnet" + Arguments = "new tool-manifest --force" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + + Process + .Execute( + { + Command = "dotnet" + Arguments = + $"tool install fantomless-tool --version {version}" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + + Process + .Execute( + { + Command = "dotnet" + Arguments = "tool restore" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let UnwrapProcessResult + (suggestion: string) + (raiseError: bool) + (processResult: ProcessResult) + : string = + let errMsg = + sprintf + "Error when running '%s %s'" + processResult.Details.Command + processResult.Details.Args + + match processResult.Result with + | Success output -> + Console.WriteLine output + output + | Error(_, output) -> + if processResult.Details.Echo = Echo.Off then + output.PrintToConsole() + Console.WriteLine() + Console.Out.Flush() + + let fullErrMsg = errMsg + Environment.NewLine + suggestion + Console.Error.WriteLine fullErrMsg + + if raiseError then + raise <| ProcessFailed errMsg + else + fullErrMsg + | WarningsOrAmbiguous output -> + if processResult.Details.Echo = Echo.Off then + output.PrintToConsole() + Console.WriteLine() + Console.Out.Flush() + + let fullErrMsg = sprintf "%s (with warnings?)" errMsg + Console.Error.WriteLine fullErrMsg + fullErrMsg + +let IsProcessSuccessful(processResult: ProcessResult) : bool = + match processResult.Result with + | Success output -> true + | _ -> false + +let InstallPrettier(version: string) = + let isPrettierInstalled = + Process.Execute( + { + Command = "npm" + Arguments = $"list prettier@{version}" + }, + Echo.All + ) + |> IsProcessSuccessful + + if not(isPrettierInstalled) then + Process.Execute( + { + Command = "npm" + Arguments = $"install prettier@{version}" + }, + Echo.Off + ) + |> UnwrapProcessResult "" true + |> ignore + +let StyleFSharpFiles(rootDir: DirectoryInfo) = + InstallFantomlessTool(fantomlessToolVersion) + + Process + .Execute( + { + Command = "dotnet" + Arguments = $"fantomless --recurse {rootDir.FullName}" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let RunPrettier(arguments: string) = + + // We need this step so we can change the files using `npx prettier --write` in the next step. + // Otherwise we get permission denied error in the CI. + Process + .Execute( + { + Command = "chmod" + Arguments = "777 --recursive ." + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + + Process.Execute( + { + Command = "npx" + Arguments = $"prettier {arguments}" + }, + Echo.Off + ) + |> UnwrapProcessResult "" true + |> ignore + + + // Since after installing commitlint dependencies package.json file changes, we need to + // run the following command to ignore package.json file + Process + .Execute( + { + Command = "git" + Arguments = "restore package.json" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let StyleTypeScriptFiles() = + RunPrettier "--quote-props=consistent --write ./**/*.ts" + +let StyleYmlFiles() = + RunPrettier "--quote-props=consistent --write ./**/*.yml" + +let ContainsFiles (rootDir: DirectoryInfo) (searchPattern: string) = + Helpers.GetFiles rootDir searchPattern |> Seq.length > 0 + +let GitDiff() : ProcessResult = + + // Since we changed file modes in the prettier step we need the following command to + // make git ignore mode changes in files and doesn't include them in the git diff command. + Process + .Execute( + { + Command = "git" + Arguments = "config core.fileMode false" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + + let processResult = + Process.Execute( + { + Command = "git" + Arguments = "diff --exit-code" + }, + Echo.Off + ) + + processResult + +let GitRestore() = + Process + .Execute( + { + Command = "git" + Arguments = "restore ." + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let CheckStyleOfFSharpFiles(rootDir: DirectoryInfo) : bool = + let suggestion = + "Please style your F# code using: `dotnet fantomless --recurse .`" + + GitRestore() + + let success = + if ContainsFiles rootDir "*.fs" || ContainsFiles rootDir ".fsx" then + StyleFSharpFiles rootDir + let processResult = GitDiff() + UnwrapProcessResult suggestion false processResult |> ignore + IsProcessSuccessful processResult + + else + true + + success + +let CheckStyleOfTypeScriptFiles(rootDir: DirectoryInfo) : bool = + let suggestion = + "Please style your TypeScript code using: `npx prettier --quote-props=consistent --write ./**/*.ts`" + + GitRestore() + + let success = + if ContainsFiles rootDir "*.ts" then + InstallPrettier prettierVersion + StyleTypeScriptFiles() + let processResult = GitDiff() + UnwrapProcessResult suggestion false processResult |> ignore + IsProcessSuccessful processResult + + else + true + + success + +let CheckStyleOfYmlFiles(rootDir: DirectoryInfo) : bool = + let suggestion = + "Please style your YML code using: `npx prettier --quote-props=consistent --write ./**/*.yml`" + + GitRestore() + + let success = + if ContainsFiles rootDir "*.yml" then + InstallPrettier prettierVersion + StyleYmlFiles() + let processResult = GitDiff() + UnwrapProcessResult suggestion false processResult |> ignore + IsProcessSuccessful processResult + else + true + + success + + +let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo + +let processSuccessStates = + [| + CheckStyleOfFSharpFiles rootDir + CheckStyleOfTypeScriptFiles rootDir + CheckStyleOfYmlFiles rootDir + |] + +if processSuccessStates |> Seq.contains false then + Environment.Exit 1 From 9a67af1f50b9e418e526147efeea49d2ebf7aa9b Mon Sep 17 00:00:00 2001 From: realmarv Date: Thu, 6 Apr 2023 17:15:24 +0330 Subject: [PATCH 2/4] scripts/styleChecker.fsx: check C# & XAML files --- .github/workflows/CI.yml | 2 +- scripts/styleChecker.fsx | 101 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c7db8ee17..3f5a88bf6 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -256,5 +256,5 @@ jobs: dotnet tool install fantomless-tool --version 4.7.997-prerelease dotnet fantomless --recurse . git diff --exit-code - - name: Check style of our F#, TypeScript and YML code + - name: Check style of our F#, C#, TypeScript, YML and XAML code run: sudo dotnet fsi scripts/styleChecker.fsx diff --git a/scripts/styleChecker.fsx b/scripts/styleChecker.fsx index 2378c493c..516fb7322 100755 --- a/scripts/styleChecker.fsx +++ b/scripts/styleChecker.fsx @@ -14,6 +14,7 @@ open Helpers let fantomlessToolVersion = "4.7.997-prerelease" let prettierVersion = "2.8.3" +let pluginXmlVersion = "v2.2.0" let InstallFantomlessTool(version: string) = let isFantomlessInstalled = @@ -149,6 +150,69 @@ let StyleFSharpFiles(rootDir: DirectoryInfo) = .UnwrapDefault() |> ignore +let StyleCSharpFiles(rootDir: DirectoryInfo) = + Process + .Execute( + { + Command = "dotnet" + Arguments = $"format whitespace {rootDir.FullName} --folder" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let InstallPrettierPluginXml(version: string) = + let isPrettierPluginXmlInstalled = + Process.Execute( + { + Command = "npm" + Arguments = $"list @prettier/plugin-xml@{version}" + }, + Echo.Off + ) + |> IsProcessSuccessful + + if not(isPrettierPluginXmlInstalled) then + Process + .Execute( + { + Command = "npm" + Arguments = $"install @prettier/plugin-xml@{version}" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let StyleXamlFiles() = + InstallPrettier(prettierVersion) + InstallPrettierPluginXml(pluginXmlVersion) + + Process + .Execute( + { + Command = "npm" + Arguments = + $"install --save-dev prettier@{prettierVersion} @prettier/plugin-xml@{pluginXmlVersion}" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + + Process + .Execute( + { + Command = "./node_modules/.bin/prettier" + Arguments = + "--xml-whitespace-sensitivity ignore --tab-width 4 --prose-wrap preserve --write '**/*.xaml'" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + let RunPrettier(arguments: string) = // We need this step so we can change the files using `npx prettier --write` in the next step. @@ -290,14 +354,51 @@ let CheckStyleOfYmlFiles(rootDir: DirectoryInfo) : bool = success +let CheckStyleOfCSharpFiles(rootDir: DirectoryInfo) : bool = + let suggestion = + "Please style your C# code using: `dotnet format whitespace . --folder" + + GitRestore() + + let success = + if ContainsFiles rootDir "*.cs" then + StyleCSharpFiles rootDir + let processResult = GitDiff() + UnwrapProcessResult suggestion false processResult |> ignore + IsProcessSuccessful processResult + else + true + + success + +let CheckStyleOfXamlFiles(rootDir: DirectoryInfo) : bool = + let suggestion = + "Please style your XAML code using:" + + Environment.NewLine + + "`./node_modules/.bin/prettier --xml-whitespace-sensitivity ignore --tab-width 4 --prose-wrap preserve --write '**/*.xaml`" + + GitRestore() + + let success = + if ContainsFiles rootDir "*.xaml" then + StyleXamlFiles() + let processResult = GitDiff() + UnwrapProcessResult suggestion false processResult |> ignore + IsProcessSuccessful processResult + else + true + + success let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo let processSuccessStates = [| CheckStyleOfFSharpFiles rootDir + CheckStyleOfCSharpFiles rootDir CheckStyleOfTypeScriptFiles rootDir CheckStyleOfYmlFiles rootDir + CheckStyleOfXamlFiles rootDir |] if processSuccessStates |> Seq.contains false then From 635d10b6f1b0557301675ecfd0306d0b2e588d13 Mon Sep 17 00:00:00 2001 From: realmarv Date: Wed, 5 Jul 2023 14:08:57 +0330 Subject: [PATCH 3/4] scripts/styleChecker.fsx: refactor --- scripts/styleChecker.fsx | 84 ++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 25 deletions(-) diff --git a/scripts/styleChecker.fsx b/scripts/styleChecker.fsx index 516fb7322..f36bf04fa 100755 --- a/scripts/styleChecker.fsx +++ b/scripts/styleChecker.fsx @@ -72,8 +72,8 @@ let InstallFantomlessTool(version: string) = |> ignore let UnwrapProcessResult - (suggestion: string) - (raiseError: bool) + (maybeSuggestion: Option) + (ignoreErrorExitCode: bool) (processResult: ProcessResult) : string = let errMsg = @@ -92,13 +92,18 @@ let UnwrapProcessResult Console.WriteLine() Console.Out.Flush() - let fullErrMsg = errMsg + Environment.NewLine + suggestion + let fullErrMsg = + match maybeSuggestion with + | Some suggestion -> errMsg + Environment.NewLine + suggestion + | None -> errMsg + Console.Error.WriteLine fullErrMsg - if raiseError then - raise <| ProcessFailed errMsg - else + if ignoreErrorExitCode then fullErrMsg + else + raise <| ProcessFailed errMsg + | WarningsOrAmbiguous output -> if processResult.Details.Echo = Echo.Off then output.PrintToConsole() @@ -133,11 +138,11 @@ let InstallPrettier(version: string) = }, Echo.Off ) - |> UnwrapProcessResult "" true + |> UnwrapProcessResult None false |> ignore let StyleFSharpFiles(rootDir: DirectoryInfo) = - InstallFantomlessTool(fantomlessToolVersion) + InstallFantomlessTool fantomlessToolVersion Process .Execute( @@ -186,8 +191,8 @@ let InstallPrettierPluginXml(version: string) = |> ignore let StyleXamlFiles() = - InstallPrettier(prettierVersion) - InstallPrettierPluginXml(pluginXmlVersion) + InstallPrettier prettierVersion + InstallPrettierPluginXml pluginXmlVersion Process .Execute( @@ -201,12 +206,21 @@ let StyleXamlFiles() = .UnwrapDefault() |> ignore + let pattern = $"**{Path.DirectorySeparatorChar}*.xaml" + Process .Execute( { - Command = "./node_modules/.bin/prettier" + Command = + Path.Combine( + Directory.GetCurrentDirectory(), + "node_modules", + ".bin", + "prettier" + ) + Arguments = - "--xml-whitespace-sensitivity ignore --tab-width 4 --prose-wrap preserve --write '**/*.xaml'" + $"--xml-whitespace-sensitivity ignore --tab-width 4 --prose-wrap preserve --write {pattern}" }, Echo.Off ) @@ -235,7 +249,7 @@ let RunPrettier(arguments: string) = }, Echo.Off ) - |> UnwrapProcessResult "" true + |> UnwrapProcessResult None false |> ignore @@ -253,10 +267,16 @@ let RunPrettier(arguments: string) = |> ignore let StyleTypeScriptFiles() = - RunPrettier "--quote-props=consistent --write ./**/*.ts" + let pattern = + $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.ts" + + RunPrettier $"--quote-props=consistent --write {pattern}" let StyleYmlFiles() = - RunPrettier "--quote-props=consistent --write ./**/*.yml" + let pattern = + $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.yml" + + RunPrettier $"--quote-props=consistent --write {pattern}" let ContainsFiles (rootDir: DirectoryInfo) (searchPattern: string) = Helpers.GetFiles rootDir searchPattern |> Seq.length > 0 @@ -301,7 +321,7 @@ let GitRestore() = let CheckStyleOfFSharpFiles(rootDir: DirectoryInfo) : bool = let suggestion = - "Please style your F# code using: `dotnet fantomless --recurse .`" + Some "Please style your F# code using: `dotnet fantomless --recurse .`" GitRestore() @@ -309,7 +329,7 @@ let CheckStyleOfFSharpFiles(rootDir: DirectoryInfo) : bool = if ContainsFiles rootDir "*.fs" || ContainsFiles rootDir ".fsx" then StyleFSharpFiles rootDir let processResult = GitDiff() - UnwrapProcessResult suggestion false processResult |> ignore + UnwrapProcessResult suggestion true processResult |> ignore IsProcessSuccessful processResult else @@ -318,8 +338,12 @@ let CheckStyleOfFSharpFiles(rootDir: DirectoryInfo) : bool = success let CheckStyleOfTypeScriptFiles(rootDir: DirectoryInfo) : bool = + let pattern = + $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.ts" + let suggestion = - "Please style your TypeScript code using: `npx prettier --quote-props=consistent --write ./**/*.ts`" + Some + $"Please style your TypeScript code using: `npx prettier --quote-props=consistent --write {pattern}`" GitRestore() @@ -328,7 +352,7 @@ let CheckStyleOfTypeScriptFiles(rootDir: DirectoryInfo) : bool = InstallPrettier prettierVersion StyleTypeScriptFiles() let processResult = GitDiff() - UnwrapProcessResult suggestion false processResult |> ignore + UnwrapProcessResult suggestion true processResult |> ignore IsProcessSuccessful processResult else @@ -337,8 +361,12 @@ let CheckStyleOfTypeScriptFiles(rootDir: DirectoryInfo) : bool = success let CheckStyleOfYmlFiles(rootDir: DirectoryInfo) : bool = + let pattern = + $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.yml" + let suggestion = - "Please style your YML code using: `npx prettier --quote-props=consistent --write ./**/*.yml`" + Some + $"Please style your YML code using: `npx prettier --quote-props=consistent --write {pattern}`" GitRestore() @@ -347,7 +375,7 @@ let CheckStyleOfYmlFiles(rootDir: DirectoryInfo) : bool = InstallPrettier prettierVersion StyleYmlFiles() let processResult = GitDiff() - UnwrapProcessResult suggestion false processResult |> ignore + UnwrapProcessResult suggestion true processResult |> ignore IsProcessSuccessful processResult else true @@ -356,7 +384,8 @@ let CheckStyleOfYmlFiles(rootDir: DirectoryInfo) : bool = let CheckStyleOfCSharpFiles(rootDir: DirectoryInfo) : bool = let suggestion = - "Please style your C# code using: `dotnet format whitespace . --folder" + Some + "Please style your C# code using: `dotnet format whitespace . --folder" GitRestore() @@ -364,7 +393,7 @@ let CheckStyleOfCSharpFiles(rootDir: DirectoryInfo) : bool = if ContainsFiles rootDir "*.cs" then StyleCSharpFiles rootDir let processResult = GitDiff() - UnwrapProcessResult suggestion false processResult |> ignore + UnwrapProcessResult suggestion true processResult |> ignore IsProcessSuccessful processResult else true @@ -372,10 +401,15 @@ let CheckStyleOfCSharpFiles(rootDir: DirectoryInfo) : bool = success let CheckStyleOfXamlFiles(rootDir: DirectoryInfo) : bool = + let prettierPath = Path.Combine(".", "node_modules", ".bin", "prettier") + + let pattern = $"**{Path.DirectorySeparatorChar}*.xaml" + let suggestion = "Please style your XAML code using:" + Environment.NewLine - + "`./node_modules/.bin/prettier --xml-whitespace-sensitivity ignore --tab-width 4 --prose-wrap preserve --write '**/*.xaml`" + + $"`{prettierPath} --xml-whitespace-sensitivity ignore --tab-width 4 --prose-wrap preserve --write {pattern}`" + |> Some GitRestore() @@ -383,7 +417,7 @@ let CheckStyleOfXamlFiles(rootDir: DirectoryInfo) : bool = if ContainsFiles rootDir "*.xaml" then StyleXamlFiles() let processResult = GitDiff() - UnwrapProcessResult suggestion false processResult |> ignore + UnwrapProcessResult suggestion true processResult |> ignore IsProcessSuccessful processResult else true From d5775a11257df17135c38b479155a7729c7fdb74 Mon Sep 17 00:00:00 2001 From: realmarv Date: Wed, 2 Aug 2023 13:26:37 +0330 Subject: [PATCH 4/4] scripts: split styleChecker script Split styleChecker into styleCheck and styleApply. --- .github/workflows/CI.yml | 2 +- scripts/eofConvention.fsx | 3 + scripts/executableConvention.fsx | 5 +- ...rsionsInDotNetProjectsAndFSharpScripts.fsx | 3 +- ...consistentNugetVersionsInFSharpScripts.fsx | 4 +- scripts/inconsistentVersionsInGitHubCI.fsx | 4 +- scripts/mixedLineEndings.fsx | 4 +- .../nonVerboseFlagsInGitHubCIAndScripts.fsx | 4 +- scripts/shebangConvention.fsx | 4 +- scripts/styleApply.fsx | 20 + scripts/styleCheck.fsx | 188 ++++++++ scripts/styleChecker.fsx | 439 ------------------ scripts/unpinnedDotnetToolInstallVersions.fsx | 4 +- .../unpinnedGitHubActionsImageVersions.fsx | 4 +- ...ackageReferenceVersionsInFSharpScripts.fsx | 4 +- ...ugetPackageReferenceVersionsInProjects.fsx | 4 +- scripts/wrapLatestCommitMsg.fsx | 2 + src/FileConventions/Config.fs | 5 + src/FileConventions/FileConventions.fsproj | 5 + src/FileConventions/Helpers.fs | 176 +++++++ src/FileConventions/Library.fs | 84 ++++ 21 files changed, 517 insertions(+), 451 deletions(-) create mode 100755 scripts/styleApply.fsx create mode 100755 scripts/styleCheck.fsx delete mode 100755 scripts/styleChecker.fsx create mode 100644 src/FileConventions/Config.fs diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3f5a88bf6..8a6e7c7a0 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -257,4 +257,4 @@ jobs: dotnet fantomless --recurse . git diff --exit-code - name: Check style of our F#, C#, TypeScript, YML and XAML code - run: sudo dotnet fsi scripts/styleChecker.fsx + run: sudo dotnet fsi scripts/styleCheck.fsx diff --git a/scripts/eofConvention.fsx b/scripts/eofConvention.fsx index fee536187..b55e47246 100755 --- a/scripts/eofConvention.fsx +++ b/scripts/eofConvention.fsx @@ -4,8 +4,11 @@ open System.IO open System #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" #r "nuget: YamlDotNet, Version=16.1.3" + +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" #load "../src/FileConventions/Library.fs" diff --git a/scripts/executableConvention.fsx b/scripts/executableConvention.fsx index 365552de0..45fa509f3 100755 --- a/scripts/executableConvention.fsx +++ b/scripts/executableConvention.fsx @@ -4,9 +4,12 @@ open System open System.IO #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" #r "nuget: YamlDotNet, Version=16.1.3" -#load "../src/FileConventions/Library.fs" + +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo let currentDir = Directory.GetCurrentDirectory() |> DirectoryInfo diff --git a/scripts/inconsistentNugetVersionsInDotNetProjectsAndFSharpScripts.fsx b/scripts/inconsistentNugetVersionsInDotNetProjectsAndFSharpScripts.fsx index 55110affc..7646e60cb 100755 --- a/scripts/inconsistentNugetVersionsInDotNetProjectsAndFSharpScripts.fsx +++ b/scripts/inconsistentNugetVersionsInDotNetProjectsAndFSharpScripts.fsx @@ -10,8 +10,9 @@ open System.IO #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" #r "nuget: YamlDotNet, Version=16.1.3" -#load "../src/FileConventions/Library.fs" +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" #load "../src/FileConventions/NugetVersionsCheck.fs" #load "../src/FileConventions/CombinedVersionCheck.fs" diff --git a/scripts/inconsistentNugetVersionsInFSharpScripts.fsx b/scripts/inconsistentNugetVersionsInFSharpScripts.fsx index 5458c12e7..60996b154 100755 --- a/scripts/inconsistentNugetVersionsInFSharpScripts.fsx +++ b/scripts/inconsistentNugetVersionsInFSharpScripts.fsx @@ -4,10 +4,12 @@ open System.IO open System.Linq #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" #r "nuget: YamlDotNet, Version=16.1.3" -#load "../src/FileConventions/Library.fs" +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo let currentDir = Directory.GetCurrentDirectory() |> DirectoryInfo diff --git a/scripts/inconsistentVersionsInGitHubCI.fsx b/scripts/inconsistentVersionsInGitHubCI.fsx index 84098ba9f..e80706498 100755 --- a/scripts/inconsistentVersionsInGitHubCI.fsx +++ b/scripts/inconsistentVersionsInGitHubCI.fsx @@ -3,10 +3,12 @@ open System.IO #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" #r "nuget: YamlDotNet, Version=16.1.3" -#load "../src/FileConventions/Library.fs" +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo diff --git a/scripts/mixedLineEndings.fsx b/scripts/mixedLineEndings.fsx index 208b0dca3..095f4cca3 100755 --- a/scripts/mixedLineEndings.fsx +++ b/scripts/mixedLineEndings.fsx @@ -4,10 +4,12 @@ open System open System.IO #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" #r "nuget: YamlDotNet, Version=16.1.3" -#load "../src/FileConventions/Library.fs" +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo diff --git a/scripts/nonVerboseFlagsInGitHubCIAndScripts.fsx b/scripts/nonVerboseFlagsInGitHubCIAndScripts.fsx index f89eb79d8..a089e59ba 100755 --- a/scripts/nonVerboseFlagsInGitHubCIAndScripts.fsx +++ b/scripts/nonVerboseFlagsInGitHubCIAndScripts.fsx @@ -4,10 +4,12 @@ open System open System.IO #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" #r "nuget: YamlDotNet, Version=16.1.3" -#load "../src/FileConventions/Library.fs" +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo diff --git a/scripts/shebangConvention.fsx b/scripts/shebangConvention.fsx index ceb39ddff..16eff1b2c 100755 --- a/scripts/shebangConvention.fsx +++ b/scripts/shebangConvention.fsx @@ -4,10 +4,12 @@ open System open System.IO #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" #r "nuget: YamlDotNet, Version=16.1.3" -#load "../src/FileConventions/Library.fs" +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo diff --git a/scripts/styleApply.fsx b/scripts/styleApply.fsx new file mode 100755 index 000000000..36affebea --- /dev/null +++ b/scripts/styleApply.fsx @@ -0,0 +1,20 @@ +#!/usr/bin/env -S dotnet fsi + +#r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" +#r "nuget: YamlDotNet, Version=16.1.3" +#load "../src/FileConventions/Config.fs" +#load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" + +open System.IO + +open FileConventions + +let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo + +StyleFSharpFiles rootDir +StyleTypeScriptFiles() +StyleYmlFiles() +StyleCSharpFiles rootDir +StyleXamlFiles() diff --git a/scripts/styleCheck.fsx b/scripts/styleCheck.fsx new file mode 100755 index 000000000..1e5d8b9b9 --- /dev/null +++ b/scripts/styleCheck.fsx @@ -0,0 +1,188 @@ +#!/usr/bin/env -S dotnet fsi + +#r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" +#r "nuget: YamlDotNet, Version=16.1.3" +#load "../src/FileConventions/Config.fs" +#load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" + +open System +open System.IO + +open Fsdk +open Fsdk.Process + +open Helpers +open FileConventions + +let ContainsFiles (rootDir: DirectoryInfo) (searchPattern: string) = + Helpers.GetFiles rootDir searchPattern |> Seq.length > 0 + +let GitDiff() : ProcessResult = + + // Since we changed file modes in the prettier step we need the following command to + // make git ignore mode changes in files and doesn't include them in the git diff command. + Process + .Execute( + { + Command = "git" + Arguments = "config core.fileMode false" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + + let processResult = + Process.Execute( + { + Command = "git" + Arguments = "diff --exit-code" + }, + Echo.Off + ) + + processResult + +let GitRestore() = + Process + .Execute( + { + Command = "git" + Arguments = "restore ." + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let CheckStyleOfFSharpFiles(rootDir: DirectoryInfo) : bool = + let suggestion = + Some "Please style your F# code using: `dotnet fantomless --recurse .`" + + GitRestore() + + let success = + if ContainsFiles rootDir "*.fs" || ContainsFiles rootDir ".fsx" then + StyleFSharpFiles rootDir + let processResult = GitDiff() + UnwrapProcessResult suggestion true processResult |> ignore + IsProcessSuccessful processResult + + else + true + + success + +let CheckStyleOfTypeScriptFiles(rootDir: DirectoryInfo) : bool = + let pattern = + $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.ts" + + let suggestion = + Some + $"Please style your TypeScript code using: `npx prettier --quote-props=consistent --write {pattern}`" + + GitRestore() + + let success = + if ContainsFiles rootDir "*.ts" then + StyleTypeScriptFiles() + let processResult = GitDiff() + UnwrapProcessResult suggestion true processResult |> ignore + IsProcessSuccessful processResult + + else + true + + success + +let CheckStyleOfYmlFiles(rootDir: DirectoryInfo) : bool = + let pattern = + $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.yml" + + let suggestion = + Some + $"Please style your YML code using: `npx prettier --quote-props=consistent --write {pattern}`" + + GitRestore() + + let success = + if ContainsFiles rootDir "*.yml" then + StyleYmlFiles() + let processResult = GitDiff() + UnwrapProcessResult suggestion true processResult |> ignore + IsProcessSuccessful processResult + else + true + + success + +let CheckStyleOfCSharpFiles(rootDir: DirectoryInfo) : bool = + let suggestion = + Some + "Please style your C# code using: `dotnet format whitespace . --folder" + + GitRestore() + + let success = + if ContainsFiles rootDir "*.cs" then + StyleCSharpFiles rootDir + let processResult = GitDiff() + UnwrapProcessResult suggestion true processResult |> ignore + IsProcessSuccessful processResult + else + true + + success + +let CheckStyleOfXamlFiles(rootDir: DirectoryInfo) : bool = + let prettierPath = Path.Combine(".", "node_modules", ".bin", "prettier") + + let pattern = $"**{Path.DirectorySeparatorChar}*.xaml" + + let suggestion = + "Please style your XAML code using:" + + Environment.NewLine + + $"`{prettierPath} --xml-whitespace-sensitivity ignore --tab-width 4 --prose-wrap preserve --write {pattern}`" + |> Some + + GitRestore() + + let success = + if ContainsFiles rootDir "*.xaml" then + StyleXamlFiles() + let processResult = GitDiff() + UnwrapProcessResult suggestion true processResult |> ignore + IsProcessSuccessful processResult + else + true + + success + +let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo + +// We need this step so we can change the files using `npx prettier --write` in the prettier calls. +// Otherwise we get permission denied error in the CI. +Process + .Execute( + { + Command = "chmod" + Arguments = "777 --recursive ." + }, + Echo.Off + ) + .UnwrapDefault() +|> ignore + +let processSuccessStates = + [| + CheckStyleOfFSharpFiles rootDir + CheckStyleOfCSharpFiles rootDir + CheckStyleOfTypeScriptFiles rootDir + CheckStyleOfYmlFiles rootDir + CheckStyleOfXamlFiles rootDir + |] + +if processSuccessStates |> Seq.contains false then + Environment.Exit 1 diff --git a/scripts/styleChecker.fsx b/scripts/styleChecker.fsx deleted file mode 100755 index f36bf04fa..000000000 --- a/scripts/styleChecker.fsx +++ /dev/null @@ -1,439 +0,0 @@ -#!/usr/bin/env -S dotnet fsi - -#r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" -#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" -#load "../src/FileConventions/Helpers.fs" - -open System -open System.IO - -open Fsdk -open Fsdk.Process - -open Helpers - -let fantomlessToolVersion = "4.7.997-prerelease" -let prettierVersion = "2.8.3" -let pluginXmlVersion = "v2.2.0" - -let InstallFantomlessTool(version: string) = - let isFantomlessInstalled = - let installedPackages: string = - Process - .Execute( - { - Command = "dotnet" - Arguments = "tool list" - }, - Echo.Off - ) - .UnwrapDefault() - - installedPackages.Split Environment.NewLine - |> Seq.map(fun line -> - line.Contains "fantomless-tool" - && line.Contains fantomlessToolVersion - ) - |> Seq.contains true - - if not(isFantomlessInstalled) then - Process - .Execute( - { - Command = "dotnet" - Arguments = "new tool-manifest --force" - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - - Process - .Execute( - { - Command = "dotnet" - Arguments = - $"tool install fantomless-tool --version {version}" - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - - Process - .Execute( - { - Command = "dotnet" - Arguments = "tool restore" - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - -let UnwrapProcessResult - (maybeSuggestion: Option) - (ignoreErrorExitCode: bool) - (processResult: ProcessResult) - : string = - let errMsg = - sprintf - "Error when running '%s %s'" - processResult.Details.Command - processResult.Details.Args - - match processResult.Result with - | Success output -> - Console.WriteLine output - output - | Error(_, output) -> - if processResult.Details.Echo = Echo.Off then - output.PrintToConsole() - Console.WriteLine() - Console.Out.Flush() - - let fullErrMsg = - match maybeSuggestion with - | Some suggestion -> errMsg + Environment.NewLine + suggestion - | None -> errMsg - - Console.Error.WriteLine fullErrMsg - - if ignoreErrorExitCode then - fullErrMsg - else - raise <| ProcessFailed errMsg - - | WarningsOrAmbiguous output -> - if processResult.Details.Echo = Echo.Off then - output.PrintToConsole() - Console.WriteLine() - Console.Out.Flush() - - let fullErrMsg = sprintf "%s (with warnings?)" errMsg - Console.Error.WriteLine fullErrMsg - fullErrMsg - -let IsProcessSuccessful(processResult: ProcessResult) : bool = - match processResult.Result with - | Success output -> true - | _ -> false - -let InstallPrettier(version: string) = - let isPrettierInstalled = - Process.Execute( - { - Command = "npm" - Arguments = $"list prettier@{version}" - }, - Echo.All - ) - |> IsProcessSuccessful - - if not(isPrettierInstalled) then - Process.Execute( - { - Command = "npm" - Arguments = $"install prettier@{version}" - }, - Echo.Off - ) - |> UnwrapProcessResult None false - |> ignore - -let StyleFSharpFiles(rootDir: DirectoryInfo) = - InstallFantomlessTool fantomlessToolVersion - - Process - .Execute( - { - Command = "dotnet" - Arguments = $"fantomless --recurse {rootDir.FullName}" - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - -let StyleCSharpFiles(rootDir: DirectoryInfo) = - Process - .Execute( - { - Command = "dotnet" - Arguments = $"format whitespace {rootDir.FullName} --folder" - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - -let InstallPrettierPluginXml(version: string) = - let isPrettierPluginXmlInstalled = - Process.Execute( - { - Command = "npm" - Arguments = $"list @prettier/plugin-xml@{version}" - }, - Echo.Off - ) - |> IsProcessSuccessful - - if not(isPrettierPluginXmlInstalled) then - Process - .Execute( - { - Command = "npm" - Arguments = $"install @prettier/plugin-xml@{version}" - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - -let StyleXamlFiles() = - InstallPrettier prettierVersion - InstallPrettierPluginXml pluginXmlVersion - - Process - .Execute( - { - Command = "npm" - Arguments = - $"install --save-dev prettier@{prettierVersion} @prettier/plugin-xml@{pluginXmlVersion}" - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - - let pattern = $"**{Path.DirectorySeparatorChar}*.xaml" - - Process - .Execute( - { - Command = - Path.Combine( - Directory.GetCurrentDirectory(), - "node_modules", - ".bin", - "prettier" - ) - - Arguments = - $"--xml-whitespace-sensitivity ignore --tab-width 4 --prose-wrap preserve --write {pattern}" - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - -let RunPrettier(arguments: string) = - - // We need this step so we can change the files using `npx prettier --write` in the next step. - // Otherwise we get permission denied error in the CI. - Process - .Execute( - { - Command = "chmod" - Arguments = "777 --recursive ." - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - - Process.Execute( - { - Command = "npx" - Arguments = $"prettier {arguments}" - }, - Echo.Off - ) - |> UnwrapProcessResult None false - |> ignore - - - // Since after installing commitlint dependencies package.json file changes, we need to - // run the following command to ignore package.json file - Process - .Execute( - { - Command = "git" - Arguments = "restore package.json" - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - -let StyleTypeScriptFiles() = - let pattern = - $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.ts" - - RunPrettier $"--quote-props=consistent --write {pattern}" - -let StyleYmlFiles() = - let pattern = - $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.yml" - - RunPrettier $"--quote-props=consistent --write {pattern}" - -let ContainsFiles (rootDir: DirectoryInfo) (searchPattern: string) = - Helpers.GetFiles rootDir searchPattern |> Seq.length > 0 - -let GitDiff() : ProcessResult = - - // Since we changed file modes in the prettier step we need the following command to - // make git ignore mode changes in files and doesn't include them in the git diff command. - Process - .Execute( - { - Command = "git" - Arguments = "config core.fileMode false" - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - - let processResult = - Process.Execute( - { - Command = "git" - Arguments = "diff --exit-code" - }, - Echo.Off - ) - - processResult - -let GitRestore() = - Process - .Execute( - { - Command = "git" - Arguments = "restore ." - }, - Echo.Off - ) - .UnwrapDefault() - |> ignore - -let CheckStyleOfFSharpFiles(rootDir: DirectoryInfo) : bool = - let suggestion = - Some "Please style your F# code using: `dotnet fantomless --recurse .`" - - GitRestore() - - let success = - if ContainsFiles rootDir "*.fs" || ContainsFiles rootDir ".fsx" then - StyleFSharpFiles rootDir - let processResult = GitDiff() - UnwrapProcessResult suggestion true processResult |> ignore - IsProcessSuccessful processResult - - else - true - - success - -let CheckStyleOfTypeScriptFiles(rootDir: DirectoryInfo) : bool = - let pattern = - $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.ts" - - let suggestion = - Some - $"Please style your TypeScript code using: `npx prettier --quote-props=consistent --write {pattern}`" - - GitRestore() - - let success = - if ContainsFiles rootDir "*.ts" then - InstallPrettier prettierVersion - StyleTypeScriptFiles() - let processResult = GitDiff() - UnwrapProcessResult suggestion true processResult |> ignore - IsProcessSuccessful processResult - - else - true - - success - -let CheckStyleOfYmlFiles(rootDir: DirectoryInfo) : bool = - let pattern = - $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.yml" - - let suggestion = - Some - $"Please style your YML code using: `npx prettier --quote-props=consistent --write {pattern}`" - - GitRestore() - - let success = - if ContainsFiles rootDir "*.yml" then - InstallPrettier prettierVersion - StyleYmlFiles() - let processResult = GitDiff() - UnwrapProcessResult suggestion true processResult |> ignore - IsProcessSuccessful processResult - else - true - - success - -let CheckStyleOfCSharpFiles(rootDir: DirectoryInfo) : bool = - let suggestion = - Some - "Please style your C# code using: `dotnet format whitespace . --folder" - - GitRestore() - - let success = - if ContainsFiles rootDir "*.cs" then - StyleCSharpFiles rootDir - let processResult = GitDiff() - UnwrapProcessResult suggestion true processResult |> ignore - IsProcessSuccessful processResult - else - true - - success - -let CheckStyleOfXamlFiles(rootDir: DirectoryInfo) : bool = - let prettierPath = Path.Combine(".", "node_modules", ".bin", "prettier") - - let pattern = $"**{Path.DirectorySeparatorChar}*.xaml" - - let suggestion = - "Please style your XAML code using:" - + Environment.NewLine - + $"`{prettierPath} --xml-whitespace-sensitivity ignore --tab-width 4 --prose-wrap preserve --write {pattern}`" - |> Some - - GitRestore() - - let success = - if ContainsFiles rootDir "*.xaml" then - StyleXamlFiles() - let processResult = GitDiff() - UnwrapProcessResult suggestion true processResult |> ignore - IsProcessSuccessful processResult - else - true - - success - -let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo - -let processSuccessStates = - [| - CheckStyleOfFSharpFiles rootDir - CheckStyleOfCSharpFiles rootDir - CheckStyleOfTypeScriptFiles rootDir - CheckStyleOfYmlFiles rootDir - CheckStyleOfXamlFiles rootDir - |] - -if processSuccessStates |> Seq.contains false then - Environment.Exit 1 diff --git a/scripts/unpinnedDotnetToolInstallVersions.fsx b/scripts/unpinnedDotnetToolInstallVersions.fsx index 304a66dbe..918800aa9 100755 --- a/scripts/unpinnedDotnetToolInstallVersions.fsx +++ b/scripts/unpinnedDotnetToolInstallVersions.fsx @@ -4,10 +4,12 @@ open System open System.IO #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" #r "nuget: YamlDotNet, Version=16.1.3" -#load "../src/FileConventions/Library.fs" +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo diff --git a/scripts/unpinnedGitHubActionsImageVersions.fsx b/scripts/unpinnedGitHubActionsImageVersions.fsx index 1b30c0a59..eb2002aeb 100755 --- a/scripts/unpinnedGitHubActionsImageVersions.fsx +++ b/scripts/unpinnedGitHubActionsImageVersions.fsx @@ -4,10 +4,12 @@ open System open System.IO #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" #r "nuget: YamlDotNet, Version=16.1.3" -#load "../src/FileConventions/Library.fs" +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo diff --git a/scripts/unpinnedNugetPackageReferenceVersionsInFSharpScripts.fsx b/scripts/unpinnedNugetPackageReferenceVersionsInFSharpScripts.fsx index d48fc1e29..d5dcfe2cf 100755 --- a/scripts/unpinnedNugetPackageReferenceVersionsInFSharpScripts.fsx +++ b/scripts/unpinnedNugetPackageReferenceVersionsInFSharpScripts.fsx @@ -4,10 +4,12 @@ open System open System.IO #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" #r "nuget: YamlDotNet, Version=16.1.3" -#load "../src/FileConventions/Library.fs" +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo diff --git a/scripts/unpinnedNugetPackageReferenceVersionsInProjects.fsx b/scripts/unpinnedNugetPackageReferenceVersionsInProjects.fsx index 7d3a73f05..56196a0dc 100755 --- a/scripts/unpinnedNugetPackageReferenceVersionsInProjects.fsx +++ b/scripts/unpinnedNugetPackageReferenceVersionsInProjects.fsx @@ -4,10 +4,12 @@ open System open System.IO #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" +#r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" #r "nuget: YamlDotNet, Version=16.1.3" -#load "../src/FileConventions/Library.fs" +#load "../src/FileConventions/Config.fs" #load "../src/FileConventions/Helpers.fs" +#load "../src/FileConventions/Library.fs" let rootDir = Path.Combine(__SOURCE_DIRECTORY__, "..") |> DirectoryInfo let currentDir = Directory.GetCurrentDirectory() |> DirectoryInfo diff --git a/scripts/wrapLatestCommitMsg.fsx b/scripts/wrapLatestCommitMsg.fsx index 8e7f65044..5d89072bf 100755 --- a/scripts/wrapLatestCommitMsg.fsx +++ b/scripts/wrapLatestCommitMsg.fsx @@ -8,6 +8,8 @@ open System.Linq #r "nuget: Mono.Unix, Version=7.1.0-final.1.21458.1" #r "nuget: YamlDotNet, Version=16.1.3" +#load "../src/FileConventions/Config.fs" +#load "../src/FileConventions/Helpers.fs" #load "../src/FileConventions/Library.fs" #r "nuget: Fsdk, Version=0.6.0--date20230214-0422.git-1ea6f62" diff --git a/src/FileConventions/Config.fs b/src/FileConventions/Config.fs new file mode 100644 index 000000000..58f739e52 --- /dev/null +++ b/src/FileConventions/Config.fs @@ -0,0 +1,5 @@ +module Config + +let FantomlessToolVersion = "4.7.997-prerelease" +let PrettierVersion = "2.8.3" +let PluginXmlVersion = "v2.2.0" diff --git a/src/FileConventions/FileConventions.fsproj b/src/FileConventions/FileConventions.fsproj index 9cfc3dac0..b5951e073 100644 --- a/src/FileConventions/FileConventions.fsproj +++ b/src/FileConventions/FileConventions.fsproj @@ -6,6 +6,11 @@ + + + + + diff --git a/src/FileConventions/Helpers.fs b/src/FileConventions/Helpers.fs index 53c207183..7aadc2b72 100644 --- a/src/FileConventions/Helpers.fs +++ b/src/FileConventions/Helpers.fs @@ -4,6 +4,9 @@ open System open System.IO open System.Linq +open Fsdk +open Fsdk.Process + let NotInDir (dirName: string) (fileInfo: FileInfo) = not( fileInfo.FullName.Contains @@ -59,3 +62,176 @@ let AssertNoInvalidFiles (invalidFiles: seq) (message: string) = |> String.concat Environment.NewLine) failwith message + +let InstallFantomlessTool(version: string) = + let isFantomlessInstalled = + let installedPackages: string = + Process + .Execute( + { + Command = "dotnet" + Arguments = "tool list" + }, + Echo.Off + ) + .UnwrapDefault() + + installedPackages.Split Environment.NewLine + |> Seq.map(fun line -> + line.Contains "fantomless-tool" && line.Contains version + ) + |> Seq.contains true + + if not(isFantomlessInstalled) then + Process + .Execute( + { + Command = "dotnet" + Arguments = "new tool-manifest --force" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + + Process + .Execute( + { + Command = "dotnet" + Arguments = + $"tool install fantomless-tool --version {version}" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + + Process + .Execute( + { + Command = "dotnet" + Arguments = "tool restore" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let UnwrapProcessResult + (maybeSuggestion: Option) + (ignoreErrorExitCode: bool) + (processResult: ProcessResult) + : string = + let errMsg = + sprintf + "Error when running '%s %s'" + processResult.Details.Command + processResult.Details.Args + + match processResult.Result with + | Success output -> + Console.WriteLine output + output + | Error(_, output) -> + if processResult.Details.Echo = Echo.Off then + output.PrintToConsole() + Console.WriteLine() + Console.Out.Flush() + + let fullErrMsg = + match maybeSuggestion with + | Some suggestion -> errMsg + Environment.NewLine + suggestion + | None -> errMsg + + Console.Error.WriteLine fullErrMsg + + if ignoreErrorExitCode then + fullErrMsg + else + raise <| ProcessFailed errMsg + + | WarningsOrAmbiguous output -> + if processResult.Details.Echo = Echo.Off then + output.PrintToConsole() + Console.WriteLine() + Console.Out.Flush() + + let fullErrMsg = sprintf "%s (with warnings?)" errMsg + Console.Error.WriteLine fullErrMsg + fullErrMsg + +let IsProcessSuccessful(processResult: ProcessResult) : bool = + match processResult.Result with + | Success _ -> true + | _ -> false + +let InstallPrettier(version: string) = + let isPrettierInstalled = + Process.Execute( + { + Command = "npm" + Arguments = $"list prettier@{version}" + }, + Echo.All + ) + |> IsProcessSuccessful + + if not(isPrettierInstalled) then + Process.Execute( + { + Command = "npm" + Arguments = $"install prettier@{version}" + }, + Echo.Off + ) + |> UnwrapProcessResult None false + |> ignore + +let InstallPrettierPluginXml(version: string) = + let isPrettierPluginXmlInstalled = + Process.Execute( + { + Command = "npm" + Arguments = $"list @prettier/plugin-xml@{version}" + }, + Echo.Off + ) + |> IsProcessSuccessful + + if not(isPrettierPluginXmlInstalled) then + Process + .Execute( + { + Command = "npm" + Arguments = $"install @prettier/plugin-xml@{version}" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let RunPrettier(arguments: string) = + + Process.Execute( + { + Command = "npx" + Arguments = $"prettier {arguments}" + }, + Echo.Off + ) + |> UnwrapProcessResult None false + |> ignore + + + // Since after installing commitlint dependencies package.json file changes, we need to + // run the following command to ignore package.json file + Process + .Execute( + { + Command = "git" + Arguments = "restore package.json" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore diff --git a/src/FileConventions/Library.fs b/src/FileConventions/Library.fs index e471f54cd..a60dd5774 100644 --- a/src/FileConventions/Library.fs +++ b/src/FileConventions/Library.fs @@ -5,10 +5,15 @@ open System.IO open System.Linq open System.Text.RegularExpressions +open Fsdk +open Fsdk.Process open Mono open Mono.Unix.Native open YamlDotNet.RepresentationModel +open Helpers +open Config + let SplitByEOLs (text: string) (numberOfEOLs: uint) = if numberOfEOLs = 0u then invalidArg @@ -495,3 +500,82 @@ let NonVerboseFlags(fileInfo: FileInfo) = let IsExecutable(fileInfo: FileInfo) = let hasExecuteAccess = Syscall.access(fileInfo.FullName, AccessModes.X_OK) hasExecuteAccess = 0 + +let StyleFSharpFiles(rootDir: DirectoryInfo) = + InstallFantomlessTool FantomlessToolVersion + + Process + .Execute( + { + Command = "dotnet" + Arguments = $"fantomless --recurse {rootDir.FullName}" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let StyleCSharpFiles(rootDir: DirectoryInfo) = + Process + .Execute( + { + Command = "dotnet" + Arguments = $"format whitespace {rootDir.FullName} --folder" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let StyleXamlFiles() = + InstallPrettier PrettierVersion + InstallPrettierPluginXml PluginXmlVersion + + Process + .Execute( + { + Command = "npm" + Arguments = + $"install --save-dev prettier@{PrettierVersion} @prettier/plugin-xml@{PluginXmlVersion}" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + + let pattern = $"**{Path.DirectorySeparatorChar}*.xaml" + + Process + .Execute( + { + Command = + Path.Combine( + Directory.GetCurrentDirectory(), + "node_modules", + ".bin", + "prettier" + ) + + Arguments = + $"--xml-whitespace-sensitivity ignore --tab-width 4 --prose-wrap preserve --write {pattern}" + }, + Echo.Off + ) + .UnwrapDefault() + |> ignore + +let StyleTypeScriptFiles() = + InstallPrettier PrettierVersion + + let pattern = + $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.ts" + + RunPrettier $"--quote-props=consistent --write {pattern}" + +let StyleYmlFiles() = + InstallPrettier PrettierVersion + + let pattern = + $".{Path.DirectorySeparatorChar}**{Path.DirectorySeparatorChar}*.yml" + + RunPrettier $"--quote-props=consistent --write {pattern}"