1#!/usr/bin/env python3
2import json
3import os
4import secrets
5import subprocess
6import sys
7import tempfile
8import urllib.error
9import urllib.request
10
11from api import instance
12
13
14data = json.load(sys.stdin)
15container, address = instance(data["serviceId"])
16script = """
17IFS= read -r password
18cd /app/gitea
19su-exec git /usr/local/bin/gitea admin user create \
20 --username studio-automation --email studio-automation@users.invalid \
21 --password "$password" --must-change-password=false >/dev/null 2>&1 || true
22su-exec git /usr/local/bin/gitea admin user change-password \
23 --username studio-automation --password "$password" >/dev/null
24su-exec git /usr/local/bin/gitea admin user must-change-password \
25 --unset studio-automation >/dev/null
26"""
27result = subprocess.run(
28 ["podman", "--url", "unix:///run/podman/podman.sock", "exec", "-i", container,
29 "/bin/sh", "-ec", script],
30 input=data["automation_password"] + "\n", text=True, capture_output=True,
31)
32if result.returncode:
33 raise RuntimeError("could not prepare Forgejo automation account")
34
35path = "nomad/jobs/" + data["serviceId"]
36request = urllib.request.Request(
37 "http://127.0.0.1:4646/v1/var/" + path,
38 headers={"X-Nomad-Token": os.environ["NOMAD_TOKEN"]},
39)
40with urllib.request.urlopen(request, timeout=5) as response:
41 variable = json.load(response)
42current = variable["Items"].get("automation_token")
43if current:
44 check = urllib.request.Request(address + "/api/v1/user", headers={"Authorization": "token " + current})
45 try:
46 with urllib.request.urlopen(check, timeout=5) as response:
47 response.read()
48 except urllib.error.HTTPError as error:
49 if error.code not in (401, 403):
50 raise
51 current = None
52if not current:
53 generated = subprocess.run(
54 ["podman", "--url", "unix:///run/podman/podman.sock", "exec", container,
55 "/bin/sh", "-ec", "cd /app/gitea; su-exec git /usr/local/bin/gitea admin user generate-access-token --username studio-automation --token-name studio-" + secrets.token_hex(8) + " --raw"],
56 check=True, capture_output=True, text=True,
57 ).stdout.strip()
58 if len(generated) < 20:
59 raise ValueError("Forgejo did not generate an automation token")
60 with tempfile.NamedTemporaryFile("w", suffix=".nv.hcl", delete=False) as file:
61 file.write("items {\n" + "".join(
62 f" {key} = {json.dumps(value)}\n"
63 for key, value in {**variable["Items"], "automation_token": generated}.items()
64 ) + "}\n")
65 filename = file.name
66 try:
67 subprocess.run(["nomad", "var", "put", "-in=hcl", "-out=none",
68 f"-check-index={variable['ModifyIndex']}", path, "@" + filename], check=True)
69 finally:
70 os.unlink(filename)