From fb77575b0b00ae232df6b07d6ce6cc0d02e35e7b Mon Sep 17 00:00:00 2001 From: Anton Sorokin Date: Thu, 13 Oct 2022 17:07:19 +0300 Subject: [PATCH] [#164] Add workflow for running Windows tests on CI Problem: we are not testing behavior of xrefcheck on Windows Solution: and add workflow to run golden and tasty tests on CI via github-actions windows runner Some subproblems appear: 1. Problem: CI build fails beacuse it needs `pcre` package Solution: add it (somehow), see `install pacman dependencies` in ci.yml 2. Problem: Network errors displayed different on different platforms Solution: collect output from both and use `assert_diff expected_linux.gold || assert_diff expected_windows.gold` 3: Problem: "Config matches" test is failing because checkout action clone files with CRLF, and test assert equality of two ByteStrings Solution: manually remove CR --- .github/workflows/ci.yml | 81 +++++++++++++++++++ CHANGES.md | 4 + README.md | 11 ++- exec/Main.hs | 3 +- package.yaml | 2 +- src/Xrefcheck/Command.hs | 3 +- src/Xrefcheck/System.hs | 2 +- tests/golden/check-git/check-git.bats | 8 +- tests/golden/check-ignore/check-ignore.bats | 6 +- .../check-ignoreExternalRefsTo.bats | 2 +- .../{expected.gold => expected_linux.gold} | 0 .../expected_windows.gold | 35 ++++++++ tests/golden/helpers.bash | 3 +- 13 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/ci.yml rename tests/golden/check-ignoreExternalRefsTo/{expected.gold => expected_linux.gold} (100%) create mode 100644 tests/golden/check-ignoreExternalRefsTo/expected_windows.gold diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..1b12e875 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,81 @@ +# SPDX-FileCopyrightText: 2020 Kowainik +# SPDX-FileCopyrightText: 2022 Serokell +# +# SPDX-License-Identifier: MPL-2.0 + +# Sources: +# • https://github.com/kowainik/validation-selective/blob/5b46cd4810bbaa09b704062ebbfa2bb47137425d/.github/workflows/ci.yml +# • https://kodimensional.dev/github-actions +# • https://github.com/serokell/tztime/blob/336f585c2c7125a8ba58ffbf3dbea4f36a7c40e7/.github/workflows/ci.yml + +name: CI + +on: [push] + +jobs: + xrefcheck-build-and-test: + runs-on: windows-latest + strategy: + matrix: + stack: ["2.7.5"] + ghc: ["9.0.2"] + include: + - ghc: "9.0.2" + stackyaml: stack.yaml + steps: + - uses: actions/checkout@v3 + with: + submodules: 'true' + + - uses: haskell/actions/setup@v2.0.1 + id: setup-haskell-stack + name: Setup Haskell Stack + with: + ghc-version: ${{ matrix.ghc }} + stack-version: ${{ matrix.stack }} + + - uses: actions/cache@v3 + name: Cache stack root + with: + path: ~/AppData/Roaming/stack + key: ${{ runner.os }}-${{ matrix.ghc }}-stack + + - uses: actions/cache@v3 + name: Cache AppData/Local/Programs/stack + with: + path: ~/AppData/Local/Programs/stack + key: ${{ runner.os }}-${{ matrix.ghc }}-appdata-stack + + +# When editing this action, make sure it can run without using cached folders. +# Yes, it tries to install mingw-w64-x86_64-pcre twice + - name: install pacman dependencies + run: | + stack --system-ghc exec -- pacman -S --needed --noconfirm pkgconf; + stack --system-ghc exec -- pacman -S --needed --noconfirm msys2-keyring; + stack --system-ghc exec -- pacman --noconfirm -Syuu; + stack --system-ghc exec -- pacman -S --needed --noconfirm mingw-w64-x86_64-pcre; + stack --system-ghc exec -- pacman --noconfirm -Syuu; + stack --system-ghc exec -- pacman -S --needed --noconfirm mingw-w64-x86_64-pcre; + stack --system-ghc exec -- pacman -S --needed --noconfirm pcre-devel; + + - name: Build + run: | + stack build --system-ghc --stack-yaml ${{ matrix.stackyaml }} --test --bench --no-run-tests --no-run-benchmarks --ghc-options '-Werror' + + - name: stack test xrefcheck:xrefcheck-tests + run: | + stack test --system-ghc --stack-yaml ${{ matrix.stackyaml }} xrefcheck:xrefcheck-tests + + - name: install xrefcheck to use with golden tests + run: | + stack --system-ghc --stack-yaml ${{ matrix.stackyaml }} install; + + - uses: mig4/setup-bats@v1 + name: Setup bats + + - name: Golden tests + run: | + export PATH=$PATH:/c/Users/runneradmin/AppData/Roaming/local/bin; + bats ./tests/golden/** + shell: bash diff --git a/CHANGES.md b/CHANGES.md index 173f7a9f..e45a1aee 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,10 @@ Unreleased + Now we notify user when there are scannable files that were not added to Git yet. Also added CLI option `--include-untracked` to scan such files and treat as existing. +* [#191](https://github.com/serokell/xrefcheck/pull/191) + + Now we consider slash `/` (and only it) as path separator in local links for all OS, + so xrefcheck's report is OS-independent + + Use utf-8 compatible codepage on Windows 0.2.2 ========== diff --git a/README.md b/README.md index 8422dc7b..a5ec5422 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,16 @@ This file should be committed to your repository. Run `stack install` to build everything and install the executable. If you wish to use `cabal`, you need to run [`stack2cabal`](https://hackage.haskell.org/package/stack2cabal) first! +### Run on Windows [↑](#xrefcheck) +On Windows, executable requires some dynamic libraries (DLLs). +They are shipped together with executable in [releases page](https://github.com/serokell/xrefcheck/releases). +If you have built executable from source using `stack install`, +those DLLs are downloaded by stack to a location that is not on `%PATH%` by default. +There are several ways to fix this: +- Add `%LocalAppData%\Programs\stack\x86_64-windows\msys2-<...>\mingw64\bin` to your PATH +- run `stack exec xrefcheck.exe -- ` instead of `xrefcheck.exe ` +- add DLLs from archive from releases page to a folder containing `xrefcheck.exe` + ## FAQ [↑](#xrefcheck) 1. How do I ignore specific files? @@ -138,7 +148,6 @@ If you wish to use `cabal`, you need to run [`stack2cabal`](https://hackage.hask ## Further work [↑](#xrefcheck) -- [ ] Support for non-Unix systems. - [ ] Support link detection in different languages, not only Markdown. - [ ] Haskell Haddock is first in turn. diff --git a/exec/Main.hs b/exec/Main.hs index da6b9959..404dab35 100644 --- a/exec/Main.hs +++ b/exec/Main.hs @@ -8,13 +8,14 @@ module Main where import Universum import Main.Utf8 (withUtf8) +import System.IO.CodePage (withCP65001) import Xrefcheck.CLI (Command (..), getCommand) import Xrefcheck.Command (defaultAction) import Xrefcheck.Config (defConfigText) main :: IO () -main = withUtf8 $ do +main = withUtf8 $ withCP65001 $ do command <- getCommand case command of DefaultCommand options -> diff --git a/package.yaml b/package.yaml index 1879a18d..60f30533 100644 --- a/package.yaml +++ b/package.yaml @@ -111,7 +111,6 @@ library: - reflection - nyan-interpolation - safe-exceptions - - code-page executables: xrefcheck: @@ -128,6 +127,7 @@ executables: - xrefcheck - universum - with-utf8 + - code-page tests: xrefcheck-tests: diff --git a/src/Xrefcheck/Command.hs b/src/Xrefcheck/Command.hs index fbe687c6..16620a86 100644 --- a/src/Xrefcheck/Command.hs +++ b/src/Xrefcheck/Command.hs @@ -15,7 +15,6 @@ import Fmt (build, fmt, fmtLn) import System.Console.Pretty (supportsPretty) import System.Directory (doesFileExist) import Text.Interpolation.Nyan -import System.IO.CodePage (withCP65001) import Xrefcheck.CLI (Options (..), addExclusionOptions, addNetworkingOptions, defaultConfigPaths) import Xrefcheck.Config @@ -49,7 +48,7 @@ findFirstExistingFile = \case if exists then pure (Just file) else findFirstExistingFile files defaultAction :: Options -> IO () -defaultAction Options{..} = withCP65001 $ do +defaultAction Options{..} = do coloringSupported <- supportsPretty give (if coloringSupported then oColorMode else WithoutColors) $ do config <- case oConfigPath of diff --git a/src/Xrefcheck/System.hs b/src/Xrefcheck/System.hs index 37b9fd58..20f340f6 100644 --- a/src/Xrefcheck/System.hs +++ b/src/Xrefcheck/System.hs @@ -22,8 +22,8 @@ import GHC.IO.Unsafe (unsafePerformIO) import System.Directory (canonicalizePath) import System.Environment (lookupEnv) import System.FilePath.Glob qualified as Glob -import Text.Interpolation.Nyan import System.FilePath.Posix (isRelative, ()) +import Text.Interpolation.Nyan import Xrefcheck.Util (normaliseWithNoTrailing) diff --git a/tests/golden/check-git/check-git.bats b/tests/golden/check-git/check-git.bats index fb614e44..cb5cc0b3 100644 --- a/tests/golden/check-git/check-git.bats +++ b/tests/golden/check-git/check-git.bats @@ -31,11 +31,9 @@ load '../helpers' assert_output --partial "All repository links are valid." # this is printed to stderr - assert_output --partial - <" assert_failure - assert_output --partial "option --ignore: Glob pattern compilation failed. -Error message is: -compile :: bad <>, expected number followed by - in to-ignore -" + assert_output --partial "option --ignore: Glob pattern compilation failed." + assert_output --partial "compile :: bad <>, expected number followed by - in to-ignore" } diff --git a/tests/golden/check-ignoreExternalRefsTo/check-ignoreExternalRefsTo.bats b/tests/golden/check-ignoreExternalRefsTo/check-ignoreExternalRefsTo.bats index 2d5108dd..6417f3ce 100644 --- a/tests/golden/check-ignoreExternalRefsTo/check-ignoreExternalRefsTo.bats +++ b/tests/golden/check-ignoreExternalRefsTo/check-ignoreExternalRefsTo.bats @@ -22,7 +22,7 @@ load '../helpers' -c config-check-enabled.yaml \ -r . - assert_diff expected.gold + assert_diff expected_linux.gold || assert_diff expected_windows.gold } @test "Ignore localhost, no config specified" { diff --git a/tests/golden/check-ignoreExternalRefsTo/expected.gold b/tests/golden/check-ignoreExternalRefsTo/expected_linux.gold similarity index 100% rename from tests/golden/check-ignoreExternalRefsTo/expected.gold rename to tests/golden/check-ignoreExternalRefsTo/expected_linux.gold diff --git a/tests/golden/check-ignoreExternalRefsTo/expected_windows.gold b/tests/golden/check-ignoreExternalRefsTo/expected_windows.gold new file mode 100644 index 00000000..2f4c9d52 --- /dev/null +++ b/tests/golden/check-ignoreExternalRefsTo/expected_windows.gold @@ -0,0 +1,35 @@ +=== Invalid references found === + + ➥ In file check-ignoreExternalRefsTo.md + bad reference (external) at src:7:10-53: + - text: "web-site" + - link: https://localhost:20000/web-site + - anchor: - + + ⛂ InternalException (HostCannotConnect "localhost" [Network.Socket.connect: : failed (Connection refused (WSAECONNREFUSED)),Network.Socket.connect: : failed (Connection refused (WSAECONNREFUSED))]) + + ➥ In file check-ignoreExternalRefsTo.md + bad reference (external) at src:9:10-45: + - text: "team" + - link: https://127.0.0.1:20000/team + - anchor: - + + ⛂ InternalException (HostCannotConnect "127.0.0.1" [Network.Socket.connect: : failed (Connection refused (WSAECONNREFUSED))]) + + ➥ In file check-ignoreExternalRefsTo.md + bad reference (external) at src:11:10-44: + - text: "blog" + - link: http://localhost:20000/blog + - anchor: - + + ⛂ ConnectionFailure Network.Socket.connect: : failed (Connection refused (WSAECONNREFUSED)) + + ➥ In file check-ignoreExternalRefsTo.md + bad reference (external) at src:13:10-44: + - text: "labs" + - link: http://127.0.0.1:20000/labs + - anchor: - + + ⛂ ConnectionFailure Network.Socket.connect: : failed (Connection refused (WSAECONNREFUSED)) + +Invalid references dumped, 4 in total. diff --git a/tests/golden/helpers.bash b/tests/golden/helpers.bash index 851afd44..bc7994ca 100644 --- a/tests/golden/helpers.bash +++ b/tests/golden/helpers.bash @@ -67,5 +67,6 @@ assert_diff() { : "{output_file?}" diff $output_file $1 \ - --ignore-tab-expansion + --ignore-tab-expansion \ + --strip-trailing-cr }