1 { lib, stdenv, crystal, fetchFromGitea, librsvg, pkg-config, libxml2, openssl, shards, sqlite, videojs, nixosTests }:
3 # All versions, revisions, and checksums are stored in ./versions.json.
4 # The update process is the following:
5 # * pick the latest commit
6 # * update .invidious.rev, .invidious.version, and .invidious.hash
7 # * prefetch the videojs dependencies with scripts/fetch-player-dependencies.cr
8 # and update .videojs.hash (they are normally fetched during build
9 # but nix's sandboxing does not allow that)
10 # * if shard.lock changed
11 # * recreate shards.nix by running crystal2nix
12 # * update lsquic and boringssl if necessarry, lsquic.cr depends on
13 # the same version of lsquic and lsquic requires the boringssl
14 # commit mentioned in its README
15 versions = lib.importJSON ./versions.json;
17 crystal.buildCrystalPackage rec {
19 inherit (versions.invidious) version;
21 src = fetchFromGitea {
22 domain = "gitea.invidious.io";
25 fetchSubmodules = true;
26 inherit (versions.invidious) rev hash;
31 # Replacing by the value (templates) of the variables ensures that building
32 # fails if upstream changes the way the metadata is formatted.
33 branchTemplate = ''{{ "#{`git branch | sed -n '/* /s///p'`.strip}" }}'';
34 commitTemplate = ''{{ "#{`git rev-list HEAD --max-count=1 --abbrev-commit`.strip}" }}'';
35 versionTemplate = ''{{ "#{`git log -1 --format=%ci | awk '{print $1}' | sed s/-/./g`.strip}" }}'';
36 # This always uses the latest commit which invalidates the cache even if
37 # the assets were not changed
38 assetCommitTemplate = ''{{ "#{`git rev-list HEAD --max-count=1 --abbrev-commit -- assets`.strip}" }}'';
41 for d in ${videojs}/*; do ln -s "$d" assets/videojs; done
43 # Use the version metadata from the derivation instead of using git at
45 substituteInPlace src/invidious.cr \
46 --replace ${lib.escapeShellArg branchTemplate} '"master"' \
47 --replace ${lib.escapeShellArg commitTemplate} '"${lib.substring 0 7 versions.invidious.rev}"' \
48 --replace ${lib.escapeShellArg versionTemplate} '"${lib.concatStringsSep "." (lib.drop 2 (lib.splitString "-" version))}"' \
49 --replace ${lib.escapeShellArg assetCommitTemplate} '"${lib.substring 0 7 versions.invidious.rev}"'
51 # Patch the assets and locales paths to be absolute
52 substituteInPlace src/invidious.cr \
53 --replace 'public_folder "assets"' 'public_folder "${placeholder "out"}/share/invidious/assets"'
54 substituteInPlace src/invidious/helpers/i18n.cr \
55 --replace 'File.read("locales/' 'File.read("${placeholder "out"}/share/invidious/locales/'
57 # Reference sql initialisation/migration scripts by absolute path
58 substituteInPlace src/invidious/database/base.cr \
59 --replace 'config/sql' '${placeholder "out"}/share/invidious/config/sql'
61 substituteInPlace src/invidious/user/captcha.cr \
62 --replace 'Process.run(%(rsvg-convert' 'Process.run(%(${lib.getBin librsvg}/bin/rsvg-convert'
65 nativeBuildInputs = [ pkg-config shards ];
66 buildInputs = [ libxml2 openssl sqlite ];
69 shardsFile = ./shards.nix;
70 crystalBinaries.invidious = {
71 src = "src/invidious.cr";
77 "-Dskip_videojs_download"
82 mkdir -p $out/share/invidious/config
85 cp -r assets locales $out/share/invidious
86 cp -r config/sql $out/share/invidious/config
89 # Invidious tries to open and validate config/config.yml, even when
90 # running --help. This specifies a minimal configuration in an
91 # environment variable. Even though the database and hmac_key are
92 # bogus, --help still works.
93 installCheckPhase = ''
94 export INVIDIOUS_CONFIG="$(cat <<EOF
95 database_url: sqlite3:///dev/null
96 hmac_key: "this-is-required"
99 $out/bin/invidious --help
100 $out/bin/invidious --version
104 tests = { inherit (nixosTests) invidious; };
105 updateScript = ./update.sh;
109 description = "An open source alternative front-end to YouTube";
110 mainProgram = "invidious";
111 homepage = "https://invidious.io/";
112 license = licenses.agpl3Plus;
113 maintainers = with maintainers; [ sbruder ];