about summary refs log tree commit diff
path: root/pkgs
diff options
context:
space:
mode:
authorRobert Hensing <roberth@users.noreply.github.com>2024-05-27 01:14:19 +0200
committerGitHub <noreply@github.com>2024-05-27 01:14:19 +0200
commite0c43a96d20d8604b84f07d016aeb90e2ff0e437 (patch)
tree46e123ce3f635f8289e3af7d0e0941990f1b963b /pkgs
parent5a279778af727927f638dcf136a1a04cd550b3e2 (diff)
testers.lycheeLinkCheck: init (#298665)
* testers.lycheeLinkCheck: init

Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/build-support/testers/default.nix4
-rw-r--r--pkgs/build-support/testers/lychee.nix69
-rw-r--r--pkgs/build-support/testers/test/default.nix2
-rw-r--r--pkgs/tools/networking/lychee/default.nix13
-rw-r--r--pkgs/tools/networking/lychee/tests/fail-emptyDirectory.nix28
-rw-r--r--pkgs/tools/networking/lychee/tests/fail.nix21
-rw-r--r--pkgs/tools/networking/lychee/tests/network.nix66
-rw-r--r--pkgs/tools/networking/lychee/tests/ok.nix12
8 files changed, 214 insertions, 1 deletions
diff --git a/pkgs/build-support/testers/default.nix b/pkgs/build-support/testers/default.nix
index 362622d9b7ee8..dbf9a6d6cb05b 100644
--- a/pkgs/build-support/testers/default.nix
+++ b/pkgs/build-support/testers/default.nix
@@ -1,6 +1,10 @@
 { pkgs, pkgsLinux, buildPackages, lib, callPackage, runCommand, stdenv, substituteAll, testers }:
 # Documentation is in doc/builders/testers.chapter.md
 {
+  # See https://nixos.org/manual/nixpkgs/unstable/#tester-lycheeLinkCheck
+  # or doc/builders/testers.chapter.md
+  inherit (callPackage ./lychee.nix {}) lycheeLinkCheck;
+
   # See https://nixos.org/manual/nixpkgs/unstable/#tester-testBuildFailure
   # or doc/builders/testers.chapter.md
   testBuildFailure = drv: drv.overrideAttrs (orig: {
diff --git a/pkgs/build-support/testers/lychee.nix b/pkgs/build-support/testers/lychee.nix
new file mode 100644
index 0000000000000..80088dc4f9638
--- /dev/null
+++ b/pkgs/build-support/testers/lychee.nix
@@ -0,0 +1,69 @@
+deps@{ formats, lib, lychee, stdenv, writeShellApplication }:
+let
+  inherit (lib) mapAttrsToList throwIf;
+  inherit (lib.strings) hasInfix hasPrefix escapeNixString;
+
+  toURL = v:
+    let s = "${v}";
+    in if hasPrefix builtins.storeDir s
+    then # lychee requires that paths on the file system are prefixed with file://
+      "file://${s}"
+    else s;
+
+  withCheckedName = name:
+    throwIf (hasInfix " " name) ''
+      lycheeLinkCheck: remap patterns must not contain spaces.
+      A space marks the end of the regex in lychee.toml.
+
+      Please change attribute name 'remap.${escapeNixString name}'
+    '';
+
+  # See https://nixos.org/manual/nixpkgs/unstable/#tester-lycheeLinkCheck
+  # or doc/builders/testers.chapter.md
+  lycheeLinkCheck = {
+    site,
+    remap ? { },
+    lychee ? deps.lychee,
+    extraConfig ? { },
+  }:
+    stdenv.mkDerivation (finalAttrs: {
+      name = "lychee-link-check";
+      inherit site;
+      nativeBuildInputs = [ finalAttrs.passthru.lychee ];
+      configFile = (formats.toml {}).generate "lychee.toml" finalAttrs.passthru.config;
+
+      # These can be overriden with overrideAttrs if needed.
+      passthru = {
+        inherit lychee remap;
+        config = {
+          include_fragments = true;
+        } // lib.optionalAttrs (finalAttrs.passthru.remap != { }) {
+          remap =
+            mapAttrsToList
+              (name: value: withCheckedName name "${name} ${toURL value}")
+              finalAttrs.passthru.remap;
+        } // extraConfig;
+        online = writeShellApplication {
+          name = "run-lychee-online";
+          runtimeInputs = [ finalAttrs.passthru.lychee ];
+          # Comment out to run shellcheck:
+          checkPhase = "";
+          text = ''
+            site=${finalAttrs.site}
+            configFile=${finalAttrs.configFile}
+            echo Checking links on $site
+            exec lychee --config $configFile $site "$@"
+          '';
+        };
+      };
+      buildCommand = ''
+        echo Checking internal links on $site
+        lychee --offline --config $configFile $site
+        touch $out
+      '';
+    });
+
+in
+{
+  inherit lycheeLinkCheck;
+}
diff --git a/pkgs/build-support/testers/test/default.nix b/pkgs/build-support/testers/test/default.nix
index da67711156bed..a815fe63e416e 100644
--- a/pkgs/build-support/testers/test/default.nix
+++ b/pkgs/build-support/testers/test/default.nix
@@ -12,6 +12,8 @@ let
 
 in
 lib.recurseIntoAttrs {
+  lycheeLinkCheck = lib.recurseIntoAttrs pkgs.lychee.tests;
+
   hasPkgConfigModules = pkgs.callPackage ../hasPkgConfigModules/tests.nix { };
 
   runNixOSTest-example = pkgs-with-overlay.testers.runNixOSTest ({ lib, ... }: {
diff --git a/pkgs/tools/networking/lychee/default.nix b/pkgs/tools/networking/lychee/default.nix
index 610869897b7b8..0763ee3021096 100644
--- a/pkgs/tools/networking/lychee/default.nix
+++ b/pkgs/tools/networking/lychee/default.nix
@@ -1,4 +1,5 @@
-{ lib
+{ callPackage
+, lib
 , stdenv
 , rustPlatform
 , fetchFromGitHub
@@ -6,6 +7,7 @@
 , openssl
 , Security
 , SystemConfiguration
+, testers
 }:
 
 rustPlatform.buildRustPackage rec {
@@ -41,6 +43,15 @@ rustPlatform.buildRustPackage rec {
     "--skip=src/lib.rs"
   ];
 
+  passthru.tests = {
+    # NOTE: These assume that testers.lycheeLinkCheck uses this exact derivation.
+    #       Which is true most of the time, but not necessarily after overriding.
+    ok = callPackage ./tests/ok.nix { };
+    fail = callPackage ./tests/fail.nix { };
+    fail-emptyDirectory = callPackage ./tests/fail-emptyDirectory.nix { };
+    network = testers.runNixOSTest ./tests/network.nix;
+  };
+
   meta = with lib; {
     description = "A fast, async, stream-based link checker written in Rust";
     homepage = "https://github.com/lycheeverse/lychee";
diff --git a/pkgs/tools/networking/lychee/tests/fail-emptyDirectory.nix b/pkgs/tools/networking/lychee/tests/fail-emptyDirectory.nix
new file mode 100644
index 0000000000000..9db4b23b1bc96
--- /dev/null
+++ b/pkgs/tools/networking/lychee/tests/fail-emptyDirectory.nix
@@ -0,0 +1,28 @@
+{ runCommand, testers, emptyDirectory }:
+let
+  sitePkg = runCommand "site" { } ''
+    dist=$out/dist
+    mkdir -p $dist
+    echo "<html><body><a href=\"https://example.com/foo\">foo</a></body></html>" > $dist/index.html
+    echo "<html><body></body></html>" > $dist/foo.html
+  '';
+  check = testers.lycheeLinkCheck {
+    site = sitePkg + "/dist";
+    remap = {
+      # Normally would recommend to append a subpath that hints why it's forbidden; see example in docs.
+      # However, we also want to test that a package is converted to a string *before*
+      # it's tested whether it's a store path. Mistake made during development caused:
+      # cannot check URI: InvalidUrlRemap("The remapping pattern must produce a valid URL, but it is not: /nix/store/4d0ix...empty-directory/foo
+      "https://example.com" = emptyDirectory;
+    };
+  };
+
+  failure = testers.testBuildFailure check;
+in
+  runCommand "link-check-fail" { inherit failure; } ''
+    # The details of the message might change, but we have to make sure the
+    # correct error is reported, so that we know it's not something else that
+    # went wrong.
+    grep 'empty-directory/foo.*Cannot find file' $failure/testBuildFailure.log >/dev/null
+    touch $out
+  ''
diff --git a/pkgs/tools/networking/lychee/tests/fail.nix b/pkgs/tools/networking/lychee/tests/fail.nix
new file mode 100644
index 0000000000000..5a83814d3c443
--- /dev/null
+++ b/pkgs/tools/networking/lychee/tests/fail.nix
@@ -0,0 +1,21 @@
+{ runCommand, testers }:
+let
+  sitePkg = runCommand "site" { } ''
+    dist=$out/dist
+    mkdir -p $dist
+    echo "<html><body><a href=\"https://example.com/foo.html#foos-missing-anchor\">foo</a></body></html>" > $dist/index.html
+    echo "<html><body><a href=\".\">index</a></body></html>" > $dist/foo.html
+  '';
+
+  linkCheck = testers.lycheeLinkCheck rec {
+    site = sitePkg + "/dist";
+    remap = { "https://exampl[e]\\.com" = site; };
+  };
+
+  failure = testers.testBuildFailure linkCheck;
+
+in
+  runCommand "link-check-fail" { inherit failure; } ''
+    grep -F foos-missing-anchor $failure/testBuildFailure.log >/dev/null
+    touch $out
+  ''
diff --git a/pkgs/tools/networking/lychee/tests/network.nix b/pkgs/tools/networking/lychee/tests/network.nix
new file mode 100644
index 0000000000000..8d7f908a58053
--- /dev/null
+++ b/pkgs/tools/networking/lychee/tests/network.nix
@@ -0,0 +1,66 @@
+{ config, hostPkgs, lib, ... }:
+let
+  sitePkg = hostPkgs.runCommand "site" { } ''
+    dist=$out/dist
+    mkdir -p $dist
+    echo "<html><body><a href=\"http://example/foo.html\">foo</a></body></html>" > $dist/index.html
+    echo "<html><body><a href=\".\">index</a></body></html>" > $dist/foo.html
+  '';
+  check = config.node.pkgs.testers.lycheeLinkCheck {
+    site = sitePkg;
+  };
+in
+{
+  name = "testers-lychee-link-check-run";
+  nodes.client = { ... }: { };
+  nodes.example = {
+    networking.firewall.allowedTCPPorts = [ 80 ];
+    services.nginx = {
+      enable = true;
+      virtualHosts."example" = {
+        locations."/" = {
+          root = "/var/www/example";
+          index = "index.html";
+        };
+      };
+    };
+
+  };
+  testScript = ''
+    start_all()
+
+    # SETUP
+
+    example.succeed("""
+        mkdir -p /var/www/example
+        echo '<h1>hi</h1>' > /var/www/example/index.html
+    """)
+    client.wait_until_succeeds("""
+        curl --fail -v http://example
+    """)
+
+    # FAILURE CASE
+
+    client.succeed("""
+        exec 1>&2
+        r=0
+        ${lib.getExe check.online} || {
+          r=$?
+        }
+        if [[ $r -ne 2 ]]; then
+            echo "lycheeLinkCheck unexpected exit code $r"
+            exit 1
+        fi
+    """)
+
+    # SUCCESS CASE
+
+    example.succeed("""
+        echo '<h1>foo</h1>' > /var/www/example/foo.html
+    """)
+
+    client.succeed("""
+        ${lib.getExe check.online}
+    """)
+  '';
+}
diff --git a/pkgs/tools/networking/lychee/tests/ok.nix b/pkgs/tools/networking/lychee/tests/ok.nix
new file mode 100644
index 0000000000000..6a6c0b9c87b49
--- /dev/null
+++ b/pkgs/tools/networking/lychee/tests/ok.nix
@@ -0,0 +1,12 @@
+{ runCommand, testers }:
+let
+  sitePkg = runCommand "site" { } ''
+    dist=$out/dist
+    mkdir -p $dist
+    echo "<html><body><a href=\"https://example.com/foo.html\">foo</a><a href=\"https://nixos.org/this-is-ignored.html\">bar</a></body></html>" > $dist/index.html
+    echo "<html><body><a href=\".\">index</a></body></html>" > $dist/foo.html
+  '';
+in testers.lycheeLinkCheck rec {
+  site = sitePkg + "/dist";
+  remap = { "https://example.com" = site; };
+}