summary refs log tree commit diff
path: root/pkgs/servers/invidious/default.nix
blob: 7e939f51bc952e8518e4833602b484003a5e49cf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
{ lib, crystal, fetchFromGitHub, librsvg, pkg-config, libxml2, openssl, sqlite, lsquic, nixosTests }:
let
  # When updating, always update the following:
  #  * the git revision
  #  * the version attribute
  #  * the source hash (sha256)
  # If the shards.lock file changed, also the following:
  #  * shards.nix (by running `crystal2nix` in invidious’ source tree)
  #  * If the lsquic.cr dependency changed: lsquic in lsquic.nix (version, sha256)
  #  * If the lsquic version changed: boringssl' in lsquic.nix (version, sha256)
  rev = "21879da80d2dfa97e789a13b90e82e466c4854e3";
in
crystal.buildCrystalPackage rec {
  pname = "invidious";
  version = "unstable-2021-11-08";

  src = fetchFromGitHub {
    owner = "iv-org";
    repo = pname;
    inherit rev;
    sha256 = "0jvnwjdh2l0hxfvzim00r3zbs528bb93y1nk0bjrbbrcfv5cn5ss";
  };

  postPatch =
    let
      # Replacing by the value (templates) of the variables ensures that building
      # fails if upstream changes the way the metadata is formatted.
      branchTemplate = ''{{ "#{`git branch | sed -n '/* /s///p'`.strip}" }}'';
      commitTemplate = ''{{ "#{`git rev-list HEAD --max-count=1 --abbrev-commit`.strip}" }}'';
      versionTemplate = ''{{ "#{`git log -1 --format=%ci | awk '{print $1}' | sed s/-/./g`.strip}" }}'';
      # This always uses the latest commit which invalidates the cache even if
      # the assets were not changed
      assetCommitTemplate = ''{{ "#{`git rev-list HEAD --max-count=1 --abbrev-commit -- assets`.strip}" }}'';
    in
    ''
      # Use the version metadata from the derivation instead of using git at
      # build-time
      substituteInPlace src/invidious.cr \
          --replace ${lib.escapeShellArg branchTemplate} '"master"' \
          --replace ${lib.escapeShellArg commitTemplate} '"${lib.substring 0 7 rev}"' \
          --replace ${lib.escapeShellArg versionTemplate} '"${lib.replaceChars ["-"] ["."] (lib.substring 9 10 version)}"' \
          --replace ${lib.escapeShellArg assetCommitTemplate} '"${lib.substring 0 7 rev}"'

      # Patch the assets and locales paths to be absolute
      substituteInPlace src/invidious.cr \
          --replace 'public_folder "assets"' 'public_folder "${placeholder "out"}/share/invidious/assets"'
      substituteInPlace src/invidious/helpers/i18n.cr \
          --replace 'File.read("locales/' 'File.read("${placeholder "out"}/share/invidious/locales/'

      # Reference sql initialisation/migration scripts by absolute path
      substituteInPlace src/invidious/helpers/helpers.cr \
            --replace 'config/sql' '${placeholder "out"}/share/invidious/config/sql'

      substituteInPlace src/invidious/users.cr \
          --replace 'Process.run(%(rsvg-convert' 'Process.run(%(${lib.getBin librsvg}/bin/rsvg-convert'
    '';

  nativeBuildInputs = [ pkg-config ];
  buildInputs = [ libxml2 openssl sqlite ];

  format = "crystal";
  shardsFile = ./shards.nix;
  crystalBinaries.invidious.src = "src/invidious.cr";

  postConfigure = ''
    # lib includes nix store paths which can’t be patched, so the links have to
    # be dereferenced first.
    cp -rL lib lib2
    rm -r lib
    mv lib2 lib
    chmod +w -R lib
    cp ${lsquic}/lib/liblsquic.a lib/lsquic/src/lsquic/ext
  '';

  postInstall = ''
    mkdir -p $out/share/invidious/config

    # Copy static parts
    cp -r assets locales $out/share/invidious
    cp -r config/sql $out/share/invidious/config
  '';

  # Invidious tries to open config/config.yml and connect to the database, even
  # when running --help. This specifies a minimal configuration in an
  # environment variable. Even though the database is bogus, --help still
  # works.
  installCheckPhase = ''
    INVIDIOUS_CONFIG="database_url: sqlite3:///dev/null" $out/bin/invidious --help
  '';

  passthru.tests = { inherit (nixosTests) invidious; };

  meta = with lib; {
    description = "An open source alternative front-end to YouTube";
    homepage = "https://invidious.io/";
    license = licenses.agpl3;
    maintainers = with maintainers; [ infinisil sbruder ];
  };
}