diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..10e67f84
--- /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' --haddock --no-haddock-deps
+
+ - 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/README.md b/README.md
index 7cfb98e8..846eae6a 100644
--- a/README.md
+++ b/README.md
@@ -164,7 +164,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)
@@ -179,7 +189,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 5cf76aec..258dfd25 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 (..))
@@ -37,7 +37,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-ignoreRefs/check-ignoreRefs.bats b/tests/golden/check-ignoreRefs/check-ignoreRefs.bats
index 2d5108dd..6417f3ce 100644
--- a/tests/golden/check-ignoreRefs/check-ignoreRefs.bats
+++ b/tests/golden/check-ignoreRefs/check-ignoreRefs.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-ignoreRefs/expected.gold b/tests/golden/check-ignoreRefs/expected_linux.gold
similarity index 100%
rename from tests/golden/check-ignoreRefs/expected.gold
rename to tests/golden/check-ignoreRefs/expected_linux.gold
diff --git a/tests/golden/check-ignoreRefs/expected_windows.gold b/tests/golden/check-ignoreRefs/expected_windows.gold
new file mode 100644
index 00000000..5c4d3a23
--- /dev/null
+++ b/tests/golden/check-ignoreRefs/expected_windows.gold
@@ -0,0 +1,43 @@
+=== 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.