1{ lib, ... }:
2
3let
4 domain = "http://glitchtip.local:8000";
5in
6
7{
8 name = "glitchtip";
9 meta.maintainers = with lib.maintainers; [
10 defelo
11 felbinger
12 ];
13
14 nodes.machine =
15 { pkgs, ... }:
16 {
17 services.glitchtip = {
18 enable = true;
19 port = 8000;
20 settings.GLITCHTIP_DOMAIN = domain;
21 environmentFiles = [
22 (builtins.toFile "glitchtip.env" ''
23 SECRET_KEY=8Hz7YCGzo7fiicHb8Qr22ZqwoIB7lSRx
24 '')
25 ];
26 };
27
28 environment.systemPackages = [ pkgs.sentry-cli ];
29
30 networking.hosts."127.0.0.1" = [ "glitchtip.local" ];
31 };
32
33 interactive.nodes.machine = {
34 services.glitchtip.listenAddress = "0.0.0.0";
35 networking.firewall.allowedTCPPorts = [ 8000 ];
36 virtualisation.forwardPorts = [
37 {
38 from = "host";
39 host.port = 8000;
40 guest.port = 8000;
41 }
42 ];
43 };
44
45 testScript = ''
46 import json
47 import re
48 import time
49
50 machine.wait_for_unit("glitchtip.service")
51 machine.wait_for_unit("glitchtip-worker.service")
52 machine.wait_for_open_port(8000)
53
54 origin_url = "${domain}"
55 cookie_jar_path = "/tmp/cookies.txt"
56 curl = f"curl -b {cookie_jar_path} -c {cookie_jar_path} -fS -H 'Origin: {origin_url}'"
57
58 # create superuser account
59 machine.succeed("DJANGO_SUPERUSER_PASSWORD=password glitchtip-manage createsuperuser --no-input --email=admin@example.com")
60
61 # login
62 machine.fail(f"{curl} -s {origin_url}/_allauth/browser/v1/auth/session") # get the csrf token, returns a 401
63 csrf_token = machine.succeed(f"grep csrftoken {cookie_jar_path} | cut -f7").rstrip()
64 machine.succeed(f"{curl} {origin_url}/_allauth/browser/v1/auth/login -s -H 'X-Csrftoken: {csrf_token}' -H 'Content-Type: application/json' -d '{{\"email\": \"admin@example.com\", \"password\": \"password\"}}'")
65
66 resp = json.loads(machine.succeed(f"{curl} {origin_url}/api/0/users/me/"))
67 assert resp["email"] == "admin@example.com"
68 assert resp["isSuperuser"] is True
69
70 # create organization
71 csrf_token = machine.succeed(f"grep csrftoken {cookie_jar_path} | cut -f7").rstrip()
72 machine.succeed(f"{curl} {origin_url}/api/0/organizations/ -s -H 'X-Csrftoken: {csrf_token}' -H 'Content-Type: application/json' -d '{{\"name\": \"main\"}}'")
73
74 resp = json.loads(machine.succeed(f"{curl} {origin_url}/api/0/organizations/"))
75 assert len(resp) == 1
76 assert resp[0]["name"] == "main"
77 assert resp[0]["slug"] == "main"
78
79 # create team
80 csrf_token = machine.succeed(f"grep csrftoken {cookie_jar_path} | cut -f7").rstrip()
81 machine.succeed(f"{curl} {origin_url}/api/0/organizations/main/teams/ -s -H 'X-Csrftoken: {csrf_token}' -H 'Content-Type: application/json' -d '{{\"slug\": \"test\"}}'")
82
83 # create project
84 csrf_token = machine.succeed(f"grep csrftoken {cookie_jar_path} | cut -f7").rstrip()
85 machine.succeed(f"{curl} {origin_url}/api/0/teams/main/test/projects/ -s -H 'X-Csrftoken: {csrf_token}' -H 'Content-Type: application/json' -d '{{\"name\": \"test\"}}'")
86
87 # fetch dsn
88 resp = json.loads(machine.succeed(f"{curl} {origin_url}/api/0/projects/main/test/keys/"))
89 assert len(resp) == 1
90 assert re.match(r"^http://[\da-f]+@glitchtip\.local:8000/\d+$", dsn := resp[0]["dsn"]["public"])
91
92 # send event
93 machine.succeed(f"SENTRY_DSN={dsn} sentry-cli send-event -m 'hello world'")
94
95 for _ in range(20):
96 resp = json.loads(machine.succeed(f"{curl} {origin_url}/api/0/organizations/main/issues/?query=is:unresolved"))
97 if len(resp) != 0: break
98 time.sleep(1)
99 assert len(resp) == 1
100 assert resp[0]["title"] == "hello world"
101 assert int(resp[0]["count"]) == 1
102 '';
103}