Skip to content

Commit

Permalink
scripts/styleChecker.fsx: add
Browse files Browse the repository at this point in the history
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 <StartupCode$FSI_0002>.$FSI_0002.main@()
Stopped due to error
Error: Process completed with exit code 1.
```

[1] actions/checkout#1048
  • Loading branch information
tehraninasab committed Aug 9, 2023
1 parent a096b47 commit 2ec433e
Show file tree
Hide file tree
Showing 2 changed files with 306 additions and 1 deletion.
4 changes: 3 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ jobs:
fetch-depth: 0
# workaround for https://github.com/actions/runner/issues/2033
- name: ownership workaround
run: git config --global --add safe.directory '*'
run: git config --system --add safe.directory '*'
- name: Print versions
run: |
git --version
Expand Down Expand Up @@ -213,3 +213,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
303 changes: 303 additions & 0 deletions scripts/styleChecker.fsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
#!/usr/bin/env -S dotnet fsi

#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

0 comments on commit 2ec433e

Please sign in to comment.