refactor: jq for tea-login, build-time avatar png, shared leaf-sign script
This commit is contained in:
parent
935e967718
commit
e0cfed7fe8
2 changed files with 59 additions and 70 deletions
|
|
@ -10,6 +10,13 @@
|
|||
let
|
||||
userName = config.hyperhive.user.name;
|
||||
homeDir = "/home/${userName}";
|
||||
# Same 512×512 rasterization of the agent icon the matrix avatar
|
||||
# sync uses (./matrix.nix — identical derivation, same store path).
|
||||
# Only forced when an icon is configured (the avatar-sync unit below
|
||||
# is gated on `hyperhive.icon != null`).
|
||||
iconPng = pkgs.runCommand "hive-agent-icon.png" { nativeBuildInputs = [ pkgs.librsvg ]; } ''
|
||||
rsvg-convert -f png -w 512 -h 512 ${config.hyperhive.icon} -o $out
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.hyperhive.forge.url = lib.mkOption {
|
||||
|
|
@ -65,7 +72,7 @@ in
|
|||
};
|
||||
path = [
|
||||
pkgs.curl
|
||||
pkgs.python3
|
||||
pkgs.jq
|
||||
pkgs.coreutils
|
||||
];
|
||||
environment.HOME_DIR = homeDir;
|
||||
|
|
@ -84,8 +91,7 @@ in
|
|||
USER=$(curl -sf --max-time 5 \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
"$FORGE_URL/api/v1/user" \
|
||||
| python3 -c 'import sys,json; print(json.load(sys.stdin).get("login",""))' \
|
||||
2>/dev/null || true)
|
||||
| jq -r '.login // empty' 2>/dev/null || true)
|
||||
if [ -z "$USER" ]; then
|
||||
echo "tea-login: could not resolve username from forge API; skipping"
|
||||
exit 0
|
||||
|
|
@ -123,7 +129,7 @@ in
|
|||
# Without this path unit, RemainAfterExit=true would prevent systemd
|
||||
# from ever re-running the service. See
|
||||
# docs/persistence.md::forge-avatar-sync.
|
||||
systemd.paths.forge-avatar-sync = {
|
||||
systemd.paths.forge-avatar-sync = lib.mkIf (config.hyperhive.icon != null) {
|
||||
description = "trigger forge-avatar-sync when forge-token appears";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
pathConfig.PathExistsGlob = "/agents/*/state/forge-token";
|
||||
|
|
@ -132,8 +138,12 @@ in
|
|||
# One-shot: hyperhive.icon → Forgejo profile avatar. Shape contract:
|
||||
# docs/conventions.md::Best-effort oneshot services.
|
||||
# RemainAfterExit = false so the .path trigger above can re-fire
|
||||
# this unit when the forge-token arrives after boot.
|
||||
systemd.services.forge-avatar-sync = {
|
||||
# this unit when the forge-token arrives after boot. The PNG is
|
||||
# rasterized at build time (`iconPng`, shared shape with the matrix
|
||||
# avatar sync), so the unit only exists when an icon is configured
|
||||
# and needs no librsvg at runtime — Forgejo's Go image library
|
||||
# can't decode SVG, hence PNG.
|
||||
systemd.services.forge-avatar-sync = lib.mkIf (config.hyperhive.icon != null) {
|
||||
description = "sync agent icon to Forgejo user avatar (best-effort)";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "tea-login.service" ];
|
||||
|
|
@ -147,14 +157,8 @@ in
|
|||
pkgs.curl
|
||||
pkgs.coreutils
|
||||
pkgs.jq
|
||||
pkgs.librsvg
|
||||
];
|
||||
script = ''
|
||||
ICON=/etc/hyperhive/icon.svg
|
||||
if [ ! -f "$ICON" ]; then
|
||||
echo "forge-avatar-sync: no icon configured; skipping"
|
||||
exit 0
|
||||
fi
|
||||
FORGE_URL=${lib.escapeShellArg config.hyperhive.forge.url}
|
||||
# $HYPERHIVE_STATE_DIR is set system-wide by the meta flake
|
||||
# (systemd.globalEnvironment) to `/agents/<name>/state`.
|
||||
|
|
@ -164,15 +168,7 @@ in
|
|||
exit 0
|
||||
fi
|
||||
TOKEN=$(cat "$TOKEN_FILE")
|
||||
# Rasterize SVG → PNG (Forgejo's Go image library can't decode SVG).
|
||||
PNG=$(mktemp --suffix=.png)
|
||||
if ! rsvg-convert -f png -w 512 -h 512 "$ICON" -o "$PNG" 2>/dev/null; then
|
||||
echo "forge-avatar-sync: rsvg-convert failed; skipping"
|
||||
rm -f "$PNG"
|
||||
exit 0
|
||||
fi
|
||||
IMAGE=$(base64 -w 0 < "$PNG")
|
||||
rm -f "$PNG"
|
||||
IMAGE=$(base64 -w 0 < ${iconPng})
|
||||
# Forgejo POST /user/avatar expects {"image":"<base64>"} — just the
|
||||
# raw base64 string, NOT a data URI (data:image/png;base64,...).
|
||||
# Use jq to build the payload so the large base64 value is safely quoted.
|
||||
|
|
|
|||
Loading…
Reference in a new issue