From 29d4f12c61126d891b6d474e9a844f4222217d76 Mon Sep 17 00:00:00 2001 From: Andrey Demidenko Date: Wed, 4 Aug 2021 12:21:34 +0300 Subject: [PATCH] [#81] Add config option for localhost links Problem: Almost all the time we can't validate localhost links, so we just skip them. But to run ftp links tests (#47) we need to refer to localhost. Solution: Add config option whether to ignore localhost links and provide bats tests for this new feature. Co-authored-by: Alexander Bantyev --- .buildkite/pipeline.yml | 13 ++- .gitmodules | 10 +++ CHANGES.md | 3 + ci.nix | 5 +- exec/Main.hs | 6 +- src-files/def-config.yaml | 3 + src/Xrefcheck/CLI.hs | 25 +++++- src/Xrefcheck/Config.hs | 2 + src/Xrefcheck/Verify.hs | 11 ++- tests/configs/github-config.yaml | 3 + tests/golden/check-localhost.bats | 90 +++++++++++++++++++ .../golden/check-localhost/check-localhost.md | 13 +++ .../config-check-disabled.yaml | 19 ++++ .../check-localhost/config-check-enabled.yaml | 19 ++++ tests/golden/check-localhost/expected.gold | 43 +++++++++ .../check-localhost/expected.gold.license | 2 + tests/golden/helpers/bats-assert | 1 + tests/golden/helpers/bats-support | 1 + 18 files changed, 258 insertions(+), 11 deletions(-) create mode 100644 .gitmodules create mode 100644 tests/golden/check-localhost.bats create mode 100644 tests/golden/check-localhost/check-localhost.md create mode 100644 tests/golden/check-localhost/config-check-disabled.yaml create mode 100644 tests/golden/check-localhost/config-check-enabled.yaml create mode 100644 tests/golden/check-localhost/expected.gold create mode 100644 tests/golden/check-localhost/expected.gold.license create mode 160000 tests/golden/helpers/bats-assert create mode 160000 tests/golden/helpers/bats-support diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 27b48e4..6df7cf5 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -1,33 +1,44 @@ -# SPDX-FileCopyrightText: 2019 Serokell +# SPDX-FileCopyrightText: 2019-2021 Serokell # # SPDX-License-Identifier: MPL-2.0 steps: - command: nix-build ci.nix -A trailing-whitespace-check label: Check trailing whitespaces + - command: nix-build ci.nix -A xrefcheck-lib-and-tests label: Library and tests + + - command: nix run -f ci.nix pkgs.bats pkgs.diffutils xrefcheck-static -c bash -c "cd tests/golden && bats ./" + label: Golden tests (bats) + - command: nix-build ci.nix -A xrefcheck-static label: Executable artifact_paths: - "result/bin/xrefcheck" + - command: nix-build ci.nix -A xrefcheck-windows label: Windows executable artifact_paths: - "result/bin/*" + - command: nix run -f ci.nix xrefcheck-static -c xrefcheck --ignored tests/markdowns label: Xrefcheck itself + - command: nix run -f ci.nix pkgs.reuse -c reuse lint label: REUSE lint + - command: - nix run -f ci.nix pkgs.curl pkgs.gitAndTools.hub -c bash -c "curl https://raw.githubusercontent.com/serokell/scratch/release-binary/scripts/release-binary.sh | bash" label: Create a pre-release branches: master + - command: - nix-build docker - nix run -f ci.nix pkgs.skopeo -c ./scripts/upload-docker-image.sh "docker-archive:$(readlink result)" "docker://docker.io/serokell/xrefcheck:latest" label: Push to dockerhub branches: master + - command: - nix-build docker - nix run -f ci.nix pkgs.skopeo -c ./scripts/upload-docker-image.sh "docker-archive:$(readlink result)" "docker://docker.io/serokell/xrefcheck:${BUILDKITE_BRANCH}" diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..7fc150b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: 2021 Serokell +# +# SPDX-License-Identifier: MPL-2.0 + +[submodule "tests/golden/helpers/bats-assert"] + path = tests/golden/helpers/bats-assert + url = git@github.com:bats-core/bats-assert.git +[submodule "tests/golden/helpers/bats-support"] + path = tests/golden/helpers/bats-support + url = git@github.com:bats-core/bats-support.git diff --git a/CHANGES.md b/CHANGES.md index cb2b377..15c4e2f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,9 @@ Unreleased ========== +* [#85](https://github.com/serokell/xrefcheck/pull/85) + + Make possible to specify whether ignore localhost links, use + `check-localhost` CLA argument (by default localhost links will not be checked). 0.2.1 ========== diff --git a/ci.nix b/ci.nix index 7899cf7..b6245f2 100644 --- a/ci.nix +++ b/ci.nix @@ -18,7 +18,10 @@ rec { project-src = pkgs.haskell-nix.haskellLib.cleanGit { name = "xrefcheck"; - src = ./.; + src = pkgs.haskell-nix.haskellLib.cleanSourceWith { + filter = path: type: !(pkgs.lib.hasInfix "tests/golden/helpers" path); + src = ./.; + }; }; xrefcheck-lib-and-tests = (import ./xrefcheck.nix { linux = true; }); diff --git a/exec/Main.hs b/exec/Main.hs index ad7e99f..114ab20 100644 --- a/exec/Main.hs +++ b/exec/Main.hs @@ -53,8 +53,10 @@ defaultAction Options{..} = do when oVerbose $ fmtLn $ "=== Repository data ===\n\n" <> indentF 2 (build repoInfo) - verifyRes <- allowRewrite showProgressBar $ \rw -> - verifyRepo rw (cVerification config) oMode root repoInfo + verifyRes <- allowRewrite showProgressBar $ \rw -> do + let fullConfig = addVerifyOptions (cVerification config) oVerifyOptions + verifyRepo rw fullConfig oMode root repoInfo + case verifyErrors verifyRes of Nothing -> fmtLn "All repository links are valid." diff --git a/src-files/def-config.yaml b/src-files/def-config.yaml index 22e40da..c980c95 100644 --- a/src-files/def-config.yaml +++ b/src-files/def-config.yaml @@ -39,6 +39,9 @@ verification: ignoreRefs: [] + # Check localhost links. + checkLocalhost: false + # Parameters of scanners for various file types. scanners: diff --git a/src/Xrefcheck/CLI.hs b/src/Xrefcheck/CLI.hs index dfbc8fa..7a81c51 100644 --- a/src/Xrefcheck/CLI.hs +++ b/src/Xrefcheck/CLI.hs @@ -11,6 +11,8 @@ module Xrefcheck.CLI , shouldCheckExternal , Command (..) , Options (..) + , VerifyOptions (..) + , addVerifyOptions , TraversalOptions (..) , addTraversalOptions , defaultConfigPaths @@ -22,11 +24,12 @@ import qualified Data.List as L import qualified Data.Text as T import Data.Version (showVersion) import Options.Applicative - (Parser, ReadM, command, eitherReader, execParser, flag', footerDoc, fullDesc, help, helper, + (Parser, ReadM, command, eitherReader, execParser, flag, flag', footerDoc, fullDesc, help, helper, hsubparser, info, infoOption, long, metavar, option, progDesc, short, strOption, switch, value) import Options.Applicative.Help.Pretty (Doc, displayS, fill, fillSep, indent, renderPretty, text) import Paths_xrefcheck (version) +import Xrefcheck.Config (VerifyConfig (..)) import Xrefcheck.Core import Xrefcheck.Scan @@ -56,6 +59,7 @@ data Options = Options , oVerbose :: Bool , oShowProgressBar :: Maybe Bool , oTraversalOptions :: TraversalOptions + , oVerifyOptions :: VerifyOptions } data TraversalOptions = TraversalOptions @@ -69,6 +73,17 @@ addTraversalOptions TraversalConfig{..} (TraversalOptions ignored) = , .. } +newtype VerifyOptions = VerifyOptions + { voCheckLocalhost :: Maybe Bool + } + +addVerifyOptions :: VerifyConfig -> VerifyOptions -> VerifyConfig +addVerifyOptions VerifyConfig{..} (VerifyOptions checkLocalhost) = + VerifyConfig + { vcCheckLocalhost = fromMaybe vcCheckLocalhost checkLocalhost + , .. + } + -- | Where to try to seek configuration if specific path is not set. defaultConfigPaths :: [FilePath] defaultConfigPaths = ["./xrefcheck.yaml", "./.xrefcheck.yaml"] @@ -132,6 +147,7 @@ optionsParser = do , pure Nothing ] oTraversalOptions <- traversalOptionsParser + oVerifyOptions <- verifyOptionsParser return Options{..} traversalOptionsParser :: Parser TraversalOptions @@ -142,6 +158,13 @@ traversalOptionsParser = do help "Files and folders which we pretend do not exist." return TraversalOptions{..} +verifyOptionsParser :: Parser VerifyOptions +verifyOptionsParser = do + voCheckLocalhost <- flag Nothing (Just True) $ + long "check-localhost" <> + help "Check localhost links." + return VerifyOptions{..} + dumpConfigOptions :: Parser Command dumpConfigOptions = hsubparser $ command "dump-config" $ diff --git a/src/Xrefcheck/Config.hs b/src/Xrefcheck/Config.hs index bffc0ee..53fc1c7 100644 --- a/src/Xrefcheck/Config.hs +++ b/src/Xrefcheck/Config.hs @@ -50,6 +50,8 @@ data VerifyConfig = VerifyConfig -- ^ Prefixes of files, references in which we should not analyze. , vcIgnoreRefs :: Maybe [Regex] -- ^ Regular expressions that match external references we should not verify. + , vcCheckLocalhost :: Bool + -- ^ If True - we will check localhost links. } -- | Configs for all the supported scanners. diff --git a/src/Xrefcheck/Verify.hs b/src/Xrefcheck/Verify.hs index 16253ae..b779ec7 100644 --- a/src/Xrefcheck/Verify.hs +++ b/src/Xrefcheck/Verify.hs @@ -271,17 +271,16 @@ verifyReference checkExternalResource :: VerifyConfig -> Text -> IO (VerifyResult VerifyError) checkExternalResource VerifyConfig{..} link - | isIgnored = return mempty - | doesReferLocalhost = return mempty + | skipCheck = return mempty | otherwise = fmap toVerifyRes $ do makeRequest HEAD 0.3 >>= \case Right () -> return $ Right () Left _ -> makeRequest GET 0.7 where - isIgnored = - let maybeIsIgnored = doesMatchAnyRegex link <$> vcIgnoreRefs - in fromMaybe False maybeIsIgnored - doesReferLocalhost = any (`T.isInfixOf` link) ["://localhost", "://127.0.0.1"] + skipCheck = isIgnored || (not vcCheckLocalhost && isLocalLink) + where + isIgnored = maybe False (doesMatchAnyRegex link) vcIgnoreRefs + isLocalLink = any (`T.isInfixOf` link) ["://localhost", "://127.0.0.1"] doesMatchAnyRegex :: Text -> ([Regex] -> Bool) doesMatchAnyRegex src = any $ \regex -> diff --git a/tests/configs/github-config.yaml b/tests/configs/github-config.yaml index 6e925d4..84337b3 100644 --- a/tests/configs/github-config.yaml +++ b/tests/configs/github-config.yaml @@ -45,6 +45,9 @@ verification: ignoreRefs: [] + # Check localhost links. + checkLocalhost: false + # Parameters of scanners for various file types. scanners: diff --git a/tests/golden/check-localhost.bats b/tests/golden/check-localhost.bats new file mode 100644 index 0000000..ef8f9e4 --- /dev/null +++ b/tests/golden/check-localhost.bats @@ -0,0 +1,90 @@ +#!/usr/bin/env bats + +# SPDX-FileCopyrightText: 2021 Serokell +# +# SPDX-License-Identifier: MPL-2.0 + +load 'helpers/bats-support/load' +load 'helpers/bats-assert/load' + +# this function is used for: +# - delete all color characters +# - replace socket port with N +# - replace multiple connection retry errors with single one +# (because at some machine there are one error and at others - two) +prepare () { + sed -r "s/[[:cntrl:]]\[[0-9]{1,3}m//g" \ + | sed 's/socket: [0-9]*/socket: N/g' \ + | sed 's/Network.Socket.connect: : does not exist (Connection refused),//g' +} + +@test "Config: check-localhost=false, CLA --check-localhost not provided" { + run xrefcheck \ + -c check-localhost/config-check-disabled.yaml \ + -r check-localhost + + assert_output --partial "All repository links are valid." +} + +@test "Config: check-localhost=false, CLA --check-localhost provided" { + xrefcheck \ + -c check-localhost/config-check-disabled.yaml \ + -r check-localhost \ + --check-localhost \ + | prepare > /tmp/check-localhost.test || true + + diff /tmp/check-localhost.test check-localhost/expected.gold \ + --ignore-space-change \ + --ignore-blank-lines \ + --new-file # treat absent files as empty + + rm /tmp/check-localhost.test +} + +@test "Config: check-localhost=true, CLA --check-localhost not provided" { + xrefcheck \ + -c check-localhost/config-check-enabled.yaml \ + -r check-localhost \ + | prepare > /tmp/check-localhost.test || true + + diff /tmp/check-localhost.test check-localhost/expected.gold \ + --ignore-space-change \ + --ignore-blank-lines \ + --new-file # treat absent files as empty + + rm /tmp/check-localhost.test +} + +@test "Config: check-localhost=true, CLA --check-localhost provided" { + xrefcheck \ + -c check-localhost/config-check-enabled.yaml \ + -r check-localhost \ + --check-localhost \ + | prepare > /tmp/check-localhost.test || true + + diff /tmp/check-localhost.test check-localhost/expected.gold \ + --ignore-space-change \ + --ignore-blank-lines \ + --new-file # treat absent files as empty + + rm /tmp/check-localhost.test +} + +@test "Config: missing, CLA --check-localhost not provided" { + run xrefcheck + + assert_output --partial "All repository links are valid." +} + +@test "Config: missing, CLA --check-localhost provided" { + xrefcheck \ + --check-localhost \ + | prepare > /tmp/check-localhost.test || true + + diff /tmp/check-localhost.test check-localhost/expected.gold \ + --ignore-space-change \ + --ignore-blank-lines \ + --new-file # treat absent files as empty + + rm /tmp/check-localhost.test +} diff --git a/tests/golden/check-localhost/check-localhost.md b/tests/golden/check-localhost/check-localhost.md new file mode 100644 index 0000000..b16e3e5 --- /dev/null +++ b/tests/golden/check-localhost/check-localhost.md @@ -0,0 +1,13 @@ + + +Serokell [web-site](https://localhost/web-site) + +Serokell [team](https://127.0.0.1/team) + +Serokell [blog](http://localhost/blog) + +Serokell [labs](http://127.0.0.1/labs) diff --git a/tests/golden/check-localhost/config-check-disabled.yaml b/tests/golden/check-localhost/config-check-disabled.yaml new file mode 100644 index 0000000..1ac46ea --- /dev/null +++ b/tests/golden/check-localhost/config-check-disabled.yaml @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2021 Serokell +# +# SPDX-License-Identifier: Unlicense + +traversal: + ignored: [] + +verification: + anchorSimilarityThreshold: 0.5 + externalRefCheckTimeout: 10s + notScanned: [] + virtualFiles: [] + ignoreRefs: [] + checkLocalhost: false + ignoreAuthFailures: true + +scanners: + markdown: + flavor: GitHub diff --git a/tests/golden/check-localhost/config-check-enabled.yaml b/tests/golden/check-localhost/config-check-enabled.yaml new file mode 100644 index 0000000..3784d07 --- /dev/null +++ b/tests/golden/check-localhost/config-check-enabled.yaml @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2021 Serokell +# +# SPDX-License-Identifier: Unlicense + +traversal: + ignored: [] + +verification: + anchorSimilarityThreshold: 0.5 + externalRefCheckTimeout: 10s + notScanned: [] + virtualFiles: [] + ignoreRefs: [] + checkLocalhost: true + ignoreAuthFailures: true + +scanners: + markdown: + flavor: GitHub diff --git a/tests/golden/check-localhost/expected.gold b/tests/golden/check-localhost/expected.gold new file mode 100644 index 0000000..66baf6f --- /dev/null +++ b/tests/golden/check-localhost/expected.gold @@ -0,0 +1,43 @@ +=== Invalid references found === + + ➥ In file ./check-localhost/check-localhost.md + bad reference (external) at src:7:10-47: + - text: "web-site" + - link: https://localhost/web-site + - anchor: - + + ⛂ InternalException (HostCannotConnect "localhost" [Network.Socket.connect: : does not exist (Connection refused)]) + + + + ➥ In file ./check-localhost/check-localhost.md + bad reference (external) at src:9:10-39: + - text: "team" + - link: https://127.0.0.1/team + - anchor: - + + ⛂ InternalException (HostCannotConnect "127.0.0.1" [Network.Socket.connect: : does not exist (Connection refused)]) + + + + ➥ In file ./check-localhost/check-localhost.md + bad reference (external) at src:11:10-38: + - text: "blog" + - link: http://localhost/blog + - anchor: - + + ⛂ ConnectionFailure Network.Socket.connect: : does not exist (Connection refused) + + + + ➥ In file ./check-localhost/check-localhost.md + bad reference (external) at src:13:10-38: + - text: "labs" + - link: http://127.0.0.1/labs + - anchor: - + + ⛂ ConnectionFailure Network.Socket.connect: : does not exist (Connection refused) + + + +Invalid references dumped, 4 in total. diff --git a/tests/golden/check-localhost/expected.gold.license b/tests/golden/check-localhost/expected.gold.license new file mode 100644 index 0000000..b2fc740 --- /dev/null +++ b/tests/golden/check-localhost/expected.gold.license @@ -0,0 +1,2 @@ +# SPDX-FileCopyrightText: 2021 Serokell +# SPDX-License-Identifier: Unlicense diff --git a/tests/golden/helpers/bats-assert b/tests/golden/helpers/bats-assert new file mode 160000 index 0000000..672ad18 --- /dev/null +++ b/tests/golden/helpers/bats-assert @@ -0,0 +1 @@ +Subproject commit 672ad1823a4d2f0c475fdbec0c4497498eec5f41 diff --git a/tests/golden/helpers/bats-support b/tests/golden/helpers/bats-support new file mode 160000 index 0000000..d140a65 --- /dev/null +++ b/tests/golden/helpers/bats-support @@ -0,0 +1 @@ +Subproject commit d140a65044b2d6810381935ae7f0c94c7023c8c3