[#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
This commit is contained in:
Anton Sorokin 2022-10-13 17:07:19 +03:00
parent aba295b478
commit fb77575b0b
No known key found for this signature in database
GPG Key ID: 4B53B91ADFBFB649
13 changed files with 143 additions and 17 deletions

81
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,81 @@
# SPDX-FileCopyrightText: 2020 Kowainik
# SPDX-FileCopyrightText: 2022 Serokell <https://serokell.io/>
#
# 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

View File

@ -26,6 +26,10 @@ Unreleased
+ Now we notify user when there are scannable files that were not added to Git + 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 yet. Also added CLI option `--include-untracked` to scan such files and treat
as existing. 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 0.2.2
========== ==========

View File

@ -98,6 +98,16 @@ This file should be committed to your repository.
Run `stack install` to build everything and install the executable. 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! 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 -- <args>` instead of `xrefcheck.exe <args>`
- add DLLs from archive from releases page to a folder containing `xrefcheck.exe`
## FAQ [](#xrefcheck) ## FAQ [](#xrefcheck)
1. How do I ignore specific files? 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) ## Further work [](#xrefcheck)
- [ ] Support for non-Unix systems.
- [ ] Support link detection in different languages, not only Markdown. - [ ] Support link detection in different languages, not only Markdown.
- [ ] Haskell Haddock is first in turn. - [ ] Haskell Haddock is first in turn.

View File

@ -8,13 +8,14 @@ module Main where
import Universum import Universum
import Main.Utf8 (withUtf8) import Main.Utf8 (withUtf8)
import System.IO.CodePage (withCP65001)
import Xrefcheck.CLI (Command (..), getCommand) import Xrefcheck.CLI (Command (..), getCommand)
import Xrefcheck.Command (defaultAction) import Xrefcheck.Command (defaultAction)
import Xrefcheck.Config (defConfigText) import Xrefcheck.Config (defConfigText)
main :: IO () main :: IO ()
main = withUtf8 $ do main = withUtf8 $ withCP65001 $ do
command <- getCommand command <- getCommand
case command of case command of
DefaultCommand options -> DefaultCommand options ->

View File

@ -111,7 +111,6 @@ library:
- reflection - reflection
- nyan-interpolation - nyan-interpolation
- safe-exceptions - safe-exceptions
- code-page
executables: executables:
xrefcheck: xrefcheck:
@ -128,6 +127,7 @@ executables:
- xrefcheck - xrefcheck
- universum - universum
- with-utf8 - with-utf8
- code-page
tests: tests:
xrefcheck-tests: xrefcheck-tests:

View File

@ -15,7 +15,6 @@ import Fmt (build, fmt, fmtLn)
import System.Console.Pretty (supportsPretty) import System.Console.Pretty (supportsPretty)
import System.Directory (doesFileExist) import System.Directory (doesFileExist)
import Text.Interpolation.Nyan import Text.Interpolation.Nyan
import System.IO.CodePage (withCP65001)
import Xrefcheck.CLI (Options (..), addExclusionOptions, addNetworkingOptions, defaultConfigPaths) import Xrefcheck.CLI (Options (..), addExclusionOptions, addNetworkingOptions, defaultConfigPaths)
import Xrefcheck.Config import Xrefcheck.Config
@ -49,7 +48,7 @@ findFirstExistingFile = \case
if exists then pure (Just file) else findFirstExistingFile files if exists then pure (Just file) else findFirstExistingFile files
defaultAction :: Options -> IO () defaultAction :: Options -> IO ()
defaultAction Options{..} = withCP65001 $ do defaultAction Options{..} = do
coloringSupported <- supportsPretty coloringSupported <- supportsPretty
give (if coloringSupported then oColorMode else WithoutColors) $ do give (if coloringSupported then oColorMode else WithoutColors) $ do
config <- case oConfigPath of config <- case oConfigPath of

View File

@ -22,8 +22,8 @@ import GHC.IO.Unsafe (unsafePerformIO)
import System.Directory (canonicalizePath) import System.Directory (canonicalizePath)
import System.Environment (lookupEnv) import System.Environment (lookupEnv)
import System.FilePath.Glob qualified as Glob import System.FilePath.Glob qualified as Glob
import Text.Interpolation.Nyan
import System.FilePath.Posix (isRelative, (</>)) import System.FilePath.Posix (isRelative, (</>))
import Text.Interpolation.Nyan
import Xrefcheck.Util (normaliseWithNoTrailing) import Xrefcheck.Util (normaliseWithNoTrailing)

View File

@ -31,11 +31,9 @@ load '../helpers'
assert_output --partial "All repository links are valid." assert_output --partial "All repository links are valid."
# this is printed to stderr # this is printed to stderr
assert_output --partial - <<EOF assert_output --partial "Those files are not added by Git, so we're not scanning them:"
Those files are not added by Git, so we're not scanning them: assert_output --partial "- git.md"
- git.md assert_output --partial "Please run \"git add\" before running xrefcheck or enable --include-untracked CLI option to check these files."
Please run "git add" before running xrefcheck or enable --include-untracked CLI option to check these files.
EOF
} }
@test "Git: bad file not tracked, --include-untracked enabled, check failure" { @test "Git: bad file not tracked, --include-untracked enabled, check failure" {

View File

@ -102,8 +102,6 @@ EOF
run xrefcheck\ run xrefcheck\
--ignore "<to-ignore>" --ignore "<to-ignore>"
assert_failure assert_failure
assert_output --partial "option --ignore: Glob pattern compilation failed. assert_output --partial "option --ignore: Glob pattern compilation failed."
Error message is: assert_output --partial "compile :: bad <>, expected number followed by - in to-ignore"
compile :: bad <>, expected number followed by - in to-ignore
"
} }

View File

@ -22,7 +22,7 @@ load '../helpers'
-c config-check-enabled.yaml \ -c config-check-enabled.yaml \
-r . -r .
assert_diff expected.gold assert_diff expected_linux.gold || assert_diff expected_windows.gold
} }
@test "Ignore localhost, no config specified" { @test "Ignore localhost, no config specified" {

View File

@ -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: <socket: N>: failed (Connection refused (WSAECONNREFUSED)),Network.Socket.connect: <socket: N>: 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: <socket: N>: 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: <socket: N>: 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: <socket: N>: failed (Connection refused (WSAECONNREFUSED))
Invalid references dumped, 4 in total.

View File

@ -67,5 +67,6 @@ assert_diff() {
: "{output_file?}" : "{output_file?}"
diff $output_file $1 \ diff $output_file $1 \
--ignore-tab-expansion --ignore-tab-expansion \
--strip-trailing-cr
} }