From eecea56131acf27dd7fed6844e0a81aa74cd5966 Mon Sep 17 00:00:00 2001
From: Maximilian Bosch <maximilian@mbosch.me>
Date: Tue, 30 Mar 2021 22:35:39 +0200
Subject: [PATCH] Implement VM-test for gitea plugin

---
 flake.nix                           | 192 ++++++++++++++++++++++++++++
 src/lib/Hydra/Plugin/GiteaStatus.pm |   2 +-
 2 files changed, 193 insertions(+), 1 deletion(-)

diff --git a/flake.nix b/flake.nix
index 2e2a6574..b61f7602 100644
--- a/flake.nix
+++ b/flake.nix
@@ -494,6 +494,198 @@
             '';
         };
 
+        tests.gitea.x86_64-linux =
+          with import (nixpkgs + "/nixos/lib/testing-python.nix") { system = "x86_64-linux"; };
+          makeTest {
+            machine = { pkgs, ... }: {
+              imports = [ hydraServer ];
+              services.hydra-dev.extraConfig = ''
+                <gitea_authorization>
+                root=d7f16a3412e01a43a414535b16007c6931d3a9c7
+                </gitea_authorization>
+              '';
+              nix = {
+                distributedBuilds = true;
+                buildMachines = [{
+                  hostName = "localhost";
+                  systems = [ "x86_64-linux" ];
+                }];
+                binaryCaches = [];
+              };
+              services.gitea = {
+                enable = true;
+                database.type = "postgres";
+                disableRegistration = true;
+                httpPort = 3001;
+              };
+              services.openssh.enable = true;
+              environment.systemPackages = with pkgs; [ gitea git jq gawk ];
+              networking.firewall.allowedTCPPorts = [ 3000 ];
+            };
+            skipLint = true;
+            testScript = let
+              scripts.mktoken = pkgs.writeText "token.sql" ''
+                INSERT INTO access_token (id, uid, name, created_unix, updated_unix, token_hash, token_salt, token_last_eight) VALUES (1, 1, 'hydra', 1617107360, 1617107360, 'a930f319ca362d7b49a4040ac0af74521c3a3c3303a86f327b01994430672d33b6ec53e4ea774253208686c712495e12a486', 'XRjWE9YW0g', '31d3a9c7');
+              '';
+
+              scripts.git-setup = pkgs.writeShellScript "setup.sh" ''
+                set -x
+                mkdir -p /tmp/repo $HOME/.ssh
+                cat ${snakeoilKeypair.privkey} > $HOME/.ssh/privk
+                chmod 0400 $HOME/.ssh/privk
+                git -C /tmp/repo init
+                cp ${smallDrv} /tmp/repo/jobset.nix
+                git -C /tmp/repo add .
+                git config --global user.email test@localhost
+                git config --global user.name test
+                git -C /tmp/repo commit -m 'Initial import'
+                git -C /tmp/repo remote add origin gitea@machine:root/repo
+                GIT_SSH_COMMAND='ssh -i $HOME/.ssh/privk -o StrictHostKeyChecking=no' \
+                  git -C /tmp/repo push origin master
+                git -C /tmp/repo log >&2
+              '';
+
+              scripts.hydra-setup = pkgs.writeShellScript "hydra.sh" ''
+                set -x
+                su -l hydra -c "hydra-create-user root --email-address \
+                  'alice@example.org' --password foobar --role admin"
+
+                URL=http://localhost:3000
+                USERNAME="root"
+                PASSWORD="foobar"
+                PROJECT_NAME="trivial"
+                JOBSET_NAME="trivial"
+                mycurl() {
+                  curl --referer $URL -H "Accept: application/json" \
+                    -H "Content-Type: application/json" $@
+                }
+
+                cat >data.json <<EOF
+                { "username": "$USERNAME", "password": "$PASSWORD" }
+                EOF
+                mycurl -X POST -d '@data.json' $URL/login -c hydra-cookie.txt
+
+                cat >data.json <<EOF
+                {
+                  "displayname":"Trivial",
+                  "enabled":"1",
+                  "visible":"1"
+                }
+                EOF
+                mycurl --silent -X PUT $URL/project/$PROJECT_NAME \
+                  -d @data.json -b hydra-cookie.txt
+
+                cat >data.json <<EOF
+                {
+                  "description": "Trivial",
+                  "checkinterval": "60",
+                  "enabled": "1",
+                  "visible": "1",
+                  "keepnr": "1",
+                  "enableemail": true,
+                  "emailoverride": "hydra@localhost",
+                  "type": 0,
+                  "nixexprinput": "git",
+                  "nixexprpath": "jobset.nix",
+                  "inputs": {
+                    "git": {"value": "http://localhost:3001/root/repo.git", "type": "git"},
+                    "gitea_repo_name": {"value": "repo", "type": "string"},
+                    "gitea_repo_owner": {"value": "root", "type": "string"},
+                    "gitea_status_repo": {"value": "git", "type": "string"}
+                  }
+                }
+                EOF
+
+                mycurl --silent -X PUT $URL/jobset/$PROJECT_NAME/$JOBSET_NAME \
+                  -d @data.json -b hydra-cookie.txt
+              '';
+
+              api_token = "d7f16a3412e01a43a414535b16007c6931d3a9c7";
+
+              snakeoilKeypair = {
+                privkey = pkgs.writeText "privkey.snakeoil" ''
+                  -----BEGIN EC PRIVATE KEY-----
+                  MHcCAQEEIHQf/khLvYrQ8IOika5yqtWvI0oquHlpRLTZiJy5dRJmoAoGCCqGSM49
+                  AwEHoUQDQgAEKF0DYGbBwbj06tA3fd/+yP44cvmwmHBWXZCKbS+RQlAKvLXMWkpN
+                  r1lwMyJZoSGgBHoUahoYjTh9/sJL7XLJtA==
+                  -----END EC PRIVATE KEY-----
+                '';
+
+                pubkey = pkgs.lib.concatStrings [
+                  "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHA"
+                  "yNTYAAABBBChdA2BmwcG49OrQN33f/sj+OHL5sJhwVl2Qim0vkUJQCry1zFpKTa"
+                  "9ZcDMiWaEhoAR6FGoaGI04ff7CS+1yybQ= sakeoil"
+                ];
+              };
+
+              smallDrv = pkgs.writeText "jobset.nix" ''
+                { trivial = builtins.derivation {
+                    name = "trivial";
+                    system = "x86_64-linux";
+                    builder = "/bin/sh";
+                    allowSubstitutes = false;
+                    preferLocalBuild = true;
+                    args = ["-c" "echo success > $out; exit 0"];
+                  };
+                 }
+              '';
+            in ''
+              import json
+
+              machine.start()
+              machine.wait_for_unit("multi-user.target")
+              machine.wait_for_open_port(3000)
+              machine.wait_for_open_port(3001)
+
+              machine.succeed(
+                  "su -l gitea -c 'GITEA_WORK_DIR=/var/lib/gitea gitea admin create-user "
+                  + "--username root --password root --email test@localhost'"
+              )
+              machine.succeed("su -l postgres -c 'psql gitea < ${scripts.mktoken}'")
+
+              machine.succeed(
+                  "curl --fail -X POST http://localhost:3001/api/v1/user/repos "
+                  + "-H 'Accept: application/json' -H 'Content-Type: application/json' "
+                  + f"-H 'Authorization: token ${api_token}'"
+                  + ' -d \'{"auto_init":false, "description":"string", "license":"mit", "name":"repo", "private":false}\'''
+              )
+
+              machine.succeed(
+                  "curl --fail -X POST http://localhost:3001/api/v1/user/keys "
+                  + "-H 'Accept: application/json' -H 'Content-Type: application/json' "
+                  + f"-H 'Authorization: token ${api_token}'"
+                  + ' -d \'{"key":"${snakeoilKeypair.pubkey}","read_only":true,"title":"SSH"}\'''
+              )
+
+              machine.succeed(
+                  "${scripts.git-setup}"
+              )
+
+              machine.succeed(
+                  "${scripts.hydra-setup}"
+              )
+
+              machine.wait_until_succeeds(
+                  'curl -Lf -s http://localhost:3000/build/1 -H "Accept: application/json" '
+                  + '|  jq .buildstatus | xargs test 0 -eq'
+              )
+
+              data = machine.succeed(
+                  'curl -Lf -s "http://localhost:3001/api/v1/repos/root/repo/statuses/$(cd /tmp/repo && git show | head -n1 | awk "{print \\$2}")" '
+                  + "-H 'Accept: application/json' -H 'Content-Type: application/json' "
+                  + f"-H 'Authorization: token ${api_token}'"
+              )
+
+              response = json.loads(data)
+
+              assert len(response) == 2, "Expected exactly two status updates for latest commit!"
+              assert response[0]['status'] == "success", "Expected latest status to be success!"
+              assert response[1]['status'] == "pending", "Expected first status to be pending!"
+
+              machine.shutdown()
+            '';
+          };
+
         tests.ldap.x86_64-linux =
           with import (nixpkgs + "/nixos/lib/testing-python.nix") { system = "x86_64-linux"; };
           makeTest {
diff --git a/src/lib/Hydra/Plugin/GiteaStatus.pm b/src/lib/Hydra/Plugin/GiteaStatus.pm
index f5d36685..9c67c2a5 100644
--- a/src/lib/Hydra/Plugin/GiteaStatus.pm
+++ b/src/lib/Hydra/Plugin/GiteaStatus.pm
@@ -62,7 +62,7 @@ sub common {
 
             my $rev = $i->revision;
             my $domain = URI->new($i->uri)->host;
-            my $url = "http://$domain:3000/api/v1/repos/$repoOwner/$repoName/statuses/$rev";
+            my $url = "http://$domain:3001/api/v1/repos/$repoOwner/$repoName/statuses/$rev";
 
             print STDERR "GiteaStatus POSTing $state to $url\n";
             my $req = HTTP::Request->new('POST', $url);