diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d60a230bb..290ca9187 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,5 @@ on: - pull_request: + pull_request: env: NUSHELL_CARGO_PROFILE: ci @@ -11,19 +11,15 @@ jobs: steps: - uses: actions/checkout@v4 - - name: 'Fetch main branch' + - name: "Fetch main branch" run: | - git fetch origin main --depth 1 + git fetch origin main --depth 1 - uses: hustcer/setup-nu@v3.9 with: - version: '*' - check-latest: true - features: full # dataframe and extra included + version: "*" + check-latest: true + features: full # dataframe and extra included - name: toolkit check pr shell: nu {0} run: | - nu -c "use toolkit.nu *; check pr" - - name: run nu-check on modified files - shell: nu {0} - run: | - nu ./check-files.nu + nu -c 'use toolkit.nu *; check pr --and-exit' diff --git a/toolkit.nu b/toolkit.nu index e038b651d..6547f40f4 100644 --- a/toolkit.nu +++ b/toolkit.nu @@ -4,61 +4,98 @@ # the main purpose of `toolkit` is to offer an easy to use interface for the # developer during a PR cycle. - -# check that all the tests pass +# Check that all the tests pass. +# +# Input: +# Optional file paths to check or infer them from Git export def test [ -] { - print "toolkit test: not implemented!" + --full # Check all files instead of input + --and-exit # Exit with error count +]: [list -> int, nothing -> int] { + with files --full=$full --and-exit=$and_exit { |files| + print "test: not implemented!" + [0] # success code + } } -# run all the necessary checks and tests to submit a perfect PR +# Run all the necessary checks and tests to submit a perfect PR. +# +# Input: +# Optional file paths to check or infer them from Git export def "check pr" [ -] { - generate-file-list - test + --full # Check all files instead of input + --and-exit # Exit with error count +]: [list -> int, nothing -> int] { + with files --full=$full --and-exit=$and_exit { |files| + [ + { lint } + { test } + ] | par-each { |task| $files | do $task } # TODO: buffer output + } } -export def main [] { help toolkit } - -export def generate-file-list [ --full ] { - let start = "let files = [" - - mut files = [""] +# you are here +export def main []: nothing -> nothing { + help toolkit +} - if $full { - # all the *.nu files in the repo - # exept for `before_v0.60` - print "checking all files..." - mut $files = glob **/*.nu --exclude [before_v0.60/**] +# wrap file lookup and exit codes +def "with files" [ + task: closure + --full + --and-exit +]: [list -> int, nothing -> int] { + let files = match [$in, $full] { + [_ true] => (glob **/*.nu --exclude [before_v0.60/**]) + [null _] => (git diff --name-only origin | lines) + [$files _] => $files + } + let error_count = $files + | where $it ends-with .nu and ($it | path exists) + | each { path expand } + | do $task $files # run the closure with both input and param + | math sum # it MUST return a non-empty list of ints + if $and_exit { + exit $error_count } else { - # only the *.nu files changed in comparison with origin/main - $files = (git diff --name-only origin/main | lines | filter { str ends-with '.nu'} | each { path expand }) + $error_count } +} - - let new_list = $files | str join ",\n" | append "]" - - let final = " - - mut exit_code = 0 - for file in $files { - let diagnostics_table = nu --ide-check 10 $file | to text | ['[', $in, ']'] | str join | from json - let result = $diagnostics_table | where type == \"diagnostic\" | is-empty - if $result { - print $\"✔ ($file) is ok\" - } else { - print $\"❌ ($file) has errors:\" - print ($diagnostics_table | where type == \"diagnostic\" | reject span) - $exit_code = 1 - } +# Check the input file with nu --ide-check. +export def "lint ide-check" []: path -> int { + let file = $in + let stub = $env.STUB_IDE_CHECK? | default false | into bool + let diagnostics = if $stub { + do { nu -n -c $"use '($file)'" } + | complete + | [[severity message]; [$in.exit_code $in.stderr]] + | where severity != 0 + } else { + nu --ide-check 10 $file + | $"[($in)]" + | from nuon + | where type == diagnostic + | select severity message } - print $\"💚 All files checked!\" - -exit $exit_code -" + let error_count = $diagnostics | length + if $error_count == 0 { + print $"lint: ✔ ($file) is ok" + } else { + print $"lint: ❌ ($file) has errors:\n($diagnostics | table)" + } + $error_count +} - $start - | append $new_list - | append $final - | save "check-files.nu" --force +# Check that all the files parse. +# +# Input: +# Optional file paths to check or infer them from Git +export def lint [ + --full # Check all files instead of input + --and-exit # Exit with error count +]: [list -> int, nothing -> int] { + with files --full=$full --and-exit=$and_exit { + par-each { lint ide-check } + } }