From 20ac2eb8053bd0efbc757e3f4fa9b21cfa4aa910 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 | 5 ++ README.md | 13 ++- tests/Test/Xrefcheck/ConfigSpec.hs | 6 +- .../check-ignoreExternalRefsTo.bats | 2 +- .../expected_linux.gold | 45 +++++++++++ .../expected_windows.gold | 45 +++++++++++ 7 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 tests/golden/check-ignoreExternalRefsTo/expected_linux.gold 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 456f42d6..a2ef7cf0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,6 +22,10 @@ Unreleased `` instead of `` should be used to disable checking for links in file, so it's clearer that file itself is not ignored (and links can target it). +* [#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 ========== @@ -58,6 +62,7 @@ Unreleased If you've got `Expected a LINK after "ignore link" annotation` message, see PR's description for examples and details. + 0.2.1 ========== diff --git a/README.md b/README.md index 6f878c7e..04047800 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,17 @@ Currently supported options include: ## Build instructions [↑](#xrefcheck) Run `stack install` to build everything and install the executable. -If you want to use cabal, you need to run (`stack2cabal`)[https://hackage.haskell.org/package/stack2cabal] first! +If you want 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 builded executable from source using `stack install`, +those DLLs are downloaded by stack to location 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` ### CI and nix [↑](#xrefcheck) @@ -183,7 +193,6 @@ You can do that too if you wish. ## For 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/tests/Test/Xrefcheck/ConfigSpec.hs b/tests/Test/Xrefcheck/ConfigSpec.hs index 38470bc5..8d234f36 100644 --- a/tests/Test/Xrefcheck/ConfigSpec.hs +++ b/tests/Test/Xrefcheck/ConfigSpec.hs @@ -10,7 +10,7 @@ import Universum import Control.Concurrent (forkIO, killThread) import Control.Exception qualified as E -import Data.ByteString qualified as BS +import Data.ByteString.Char8 qualified as BS import Data.List (isInfixOf) import Data.Yaml (ParseException (..), decodeEither') import Network.HTTP.Types (Status (..)) @@ -39,7 +39,9 @@ test_config = -- stack exec xrefcheck -- dump-config -t GitHub -o tests/configs/github-config.yaml [ testCase "Config matches" $ do config <- BS.readFile "tests/configs/github-config.yaml" - when (config /= defConfigText GitHub) $ + -- On Windows, git clone can replace \n with \r\n in some files + let removeCR = BS.filter (/= '\r') + when (removeCR config /= removeCR (defConfigText GitHub)) $ assertFailure $ toString $ unwords [ "Config does not match the expected format." , "Run" 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_linux.gold b/tests/golden/check-ignoreExternalRefsTo/expected_linux.gold new file mode 100644 index 00000000..f3895397 --- /dev/null +++ b/tests/golden/check-ignoreExternalRefsTo/expected_linux.gold @@ -0,0 +1,45 @@ + + +=== 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: : does not exist (Connection refused)]) + + + + ➥ 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: : does not exist (Connection refused)]) + + + + ➥ 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: : does not exist (Connection refused) + + + + ➥ 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: : does not exist (Connection refused) + + + +Invalid references dumped, 4 in total. diff --git a/tests/golden/check-ignoreExternalRefsTo/expected_windows.gold b/tests/golden/check-ignoreExternalRefsTo/expected_windows.gold new file mode 100644 index 00000000..ea841b4a --- /dev/null +++ b/tests/golden/check-ignoreExternalRefsTo/expected_windows.gold @@ -0,0 +1,45 @@ + + +=== Invalid references found === + + ➥ In file check-ignoreRefs.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-ignoreRefs.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-ignoreRefs.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-ignoreRefs.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.