Release NixOS 23.11
[NixPkgs.git] / nixos / tests / forgejo.nix
blob6acd6acb50fa9ab4b142b04424009f460485afd1
1 { system ? builtins.currentSystem
2 , config ? { }
3 , pkgs ? import ../.. { inherit system config; }
4 }:
6 with import ../lib/testing-python.nix { inherit system pkgs; };
7 with pkgs.lib;
9 let
10   ## gpg --faked-system-time='20230301T010000!' --quick-generate-key snakeoil ed25519 sign
11   signingPrivateKey = ''
12     -----BEGIN PGP PRIVATE KEY BLOCK-----
14     lFgEY/6jkBYJKwYBBAHaRw8BAQdADXiZRV8RJUyC9g0LH04wLMaJL9WTc+szbMi7
15     5fw4yP8AAQCl8EwGfzSLm/P6fCBfA3I9znFb3MEHGCCJhJ6VtKYyRw7ktAhzbmFr
16     ZW9pbIiUBBMWCgA8FiEE+wUM6VW/NLtAdSixTWQt6LZ4x50FAmP+o5ACGwMFCQPC
17     ZwAECwkIBwQVCgkIBRYCAwEAAh4FAheAAAoJEE1kLei2eMedFTgBAKQs1oGFZrCI
18     TZP42hmBTKxGAI1wg7VSdDEWTZxut/2JAQDGgo2sa4VHMfj0aqYGxrIwfP2B7JHO
19     GCqGCRf9O/hzBA==
20     =9Uy3
21     -----END PGP PRIVATE KEY BLOCK-----
22   '';
23   signingPrivateKeyId = "4D642DE8B678C79D";
25   supportedDbTypes = [ "mysql" "postgres" "sqlite3" ];
26   makeGForgejoTest = type: nameValuePair type (makeTest {
27     name = "forgejo-${type}";
28     meta.maintainers = with maintainers; [ bendlas emilylange ];
30     nodes = {
31       server = { config, pkgs, ... }: {
32         virtualisation.memorySize = 2047;
33         services.forgejo = {
34           enable = true;
35           database = { inherit type; };
36           settings.service.DISABLE_REGISTRATION = true;
37           settings."repository.signing".SIGNING_KEY = signingPrivateKeyId;
38           settings.actions.ENABLED = true;
39         };
40         environment.systemPackages = [ config.services.forgejo.package pkgs.gnupg pkgs.jq pkgs.file ];
41         services.openssh.enable = true;
43         specialisation.runner = {
44           inheritParentConfig = true;
45           configuration.services.gitea-actions-runner.instances."test" = {
46             enable = true;
47             name = "ci";
48             url = "http://localhost:3000";
49             labels = [
50               # don't require docker/podman
51               "native:host"
52             ];
53             tokenFile = "/var/lib/forgejo/runner_token";
54           };
55         };
56         specialisation.dump = {
57           inheritParentConfig = true;
58           configuration.services.forgejo.dump = {
59             enable = true;
60             type = "tar.zst";
61             file = "dump.tar.zst";
62           };
63         };
64       };
65       client1 = { config, pkgs, ... }: {
66         environment.systemPackages = [ pkgs.git ];
67       };
68       client2 = { config, pkgs, ... }: {
69         environment.systemPackages = [ pkgs.git ];
70       };
71     };
73     testScript = { nodes, ... }:
74       let
75         inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey;
76         serverSystem = nodes.server.system.build.toplevel;
77         dumpFile = with nodes.server.specialisation.dump.configuration.services.forgejo.dump; "${backupDir}/${file}";
78       in
79       ''
80         import json
81         GIT_SSH_COMMAND = "ssh -i $HOME/.ssh/privk -o StrictHostKeyChecking=no"
82         REPO = "forgejo@server:test/repo"
83         PRIVK = "${snakeOilPrivateKey}"
85         start_all()
87         client1.succeed("mkdir /tmp/repo")
88         client1.succeed("mkdir -p $HOME/.ssh")
89         client1.succeed(f"cat {PRIVK} > $HOME/.ssh/privk")
90         client1.succeed("chmod 0400 $HOME/.ssh/privk")
91         client1.succeed("git -C /tmp/repo init")
92         client1.succeed("echo hello world > /tmp/repo/testfile")
93         client1.succeed("git -C /tmp/repo add .")
94         client1.succeed("git config --global user.email test@localhost")
95         client1.succeed("git config --global user.name test")
96         client1.succeed("git -C /tmp/repo commit -m 'Initial import'")
97         client1.succeed(f"git -C /tmp/repo remote add origin {REPO}")
99         server.wait_for_unit("forgejo.service")
100         server.wait_for_open_port(3000)
101         server.wait_for_open_port(22)
102         server.succeed("curl --fail http://localhost:3000/")
104         server.succeed(
105             "su -l forgejo -c 'gpg --homedir /var/lib/forgejo/data/home/.gnupg "
106             + "--import ${toString (pkgs.writeText "forgejo.key" signingPrivateKey)}'"
107         )
109         assert "BEGIN PGP PUBLIC KEY BLOCK" in server.succeed("curl http://localhost:3000/api/v1/signing-key.gpg")
111         server.succeed(
112             "curl --fail http://localhost:3000/user/sign_up | grep 'Registration is disabled. "
113             + "Please contact your site administrator.'"
114         )
115         server.succeed(
116             "su -l forgejo -c 'GITEA_WORK_DIR=/var/lib/forgejo gitea admin user create "
117             + "--username test --password totallysafe --email test@localhost'"
118         )
120         api_token = server.succeed(
121             "curl --fail -X POST http://test:totallysafe@localhost:3000/api/v1/users/test/tokens "
122             + "-H 'Accept: application/json' -H 'Content-Type: application/json' -d "
123             + "'{\"name\":\"token\",\"scopes\":[\"all\"]}' | jq '.sha1' | xargs echo -n"
124         )
126         server.succeed(
127             "curl --fail -X POST http://localhost:3000/api/v1/user/repos "
128             + "-H 'Accept: application/json' -H 'Content-Type: application/json' "
129             + f"-H 'Authorization: token {api_token}'"
130             + ' -d \'{"auto_init":false, "description":"string", "license":"mit", "name":"repo", "private":false}\'''
131         )
133         server.succeed(
134             "curl --fail -X POST http://localhost:3000/api/v1/user/keys "
135             + "-H 'Accept: application/json' -H 'Content-Type: application/json' "
136             + f"-H 'Authorization: token {api_token}'"
137             + ' -d \'{"key":"${snakeOilPublicKey}","read_only":true,"title":"SSH"}\'''
138         )
140         client1.succeed(
141             f"GIT_SSH_COMMAND='{GIT_SSH_COMMAND}' git -C /tmp/repo push origin master"
142         )
144         client2.succeed("mkdir -p $HOME/.ssh")
145         client2.succeed(f"cat {PRIVK} > $HOME/.ssh/privk")
146         client2.succeed("chmod 0400 $HOME/.ssh/privk")
147         client2.succeed(f"GIT_SSH_COMMAND='{GIT_SSH_COMMAND}' git clone {REPO}")
148         client2.succeed('test "$(cat repo/testfile | xargs echo -n)" = "hello world"')
150         with subtest("Testing git protocol version=2 over ssh"):
151             git_protocol = client2.succeed(f"GIT_SSH_COMMAND='{GIT_SSH_COMMAND}' GIT_TRACE2_EVENT=true git -C repo fetch |& grep negotiated-version")
152             version = json.loads(git_protocol).get("value")
153             assert version == "2", f"git did not negotiate protocol version 2, but version {version} instead."
155         server.wait_until_succeeds(
156             'test "$(curl http://localhost:3000/api/v1/repos/test/repo/commits '
157             + '-H "Accept: application/json" | jq length)" = "1"',
158             timeout=10
159         )
161         with subtest("Testing runner registration"):
162             server.succeed(
163                 "su -l forgejo -c 'GITEA_WORK_DIR=/var/lib/forgejo gitea actions generate-runner-token' | sed 's/^/TOKEN=/' | tee /var/lib/forgejo/runner_token"
164             )
165             server.succeed("${serverSystem}/specialisation/runner/bin/switch-to-configuration test")
166             server.wait_for_unit("gitea-runner-test.service")
167             server.succeed("journalctl -o cat -u gitea-runner-test.service | grep -q 'Runner registered successfully'")
169         with subtest("Testing backup service"):
170             server.succeed("${serverSystem}/specialisation/dump/bin/switch-to-configuration test")
171             server.systemctl("start forgejo-dump")
172             assert "Zstandard compressed data" in server.succeed("file ${dumpFile}")
173             server.copy_from_vm("${dumpFile}")
174       '';
175   });
178 listToAttrs (map makeGForgejoTest supportedDbTypes)