feat(git-gate): include hostname in deploy key title

Closes #388 (part 1 of 3). Deploy key titles now carry the machine
hostname so keys provisioned on different hosts don't collide with
each other on the forge when a prior bottle was never torn down.

Title format: bot-bottle:<hostname>:<slug>:<repo-name>
This commit is contained in:
2026-07-17 02:27:11 +00:00
committed by didericis
parent eb63bd417d
commit 59be808ab1
2 changed files with 6 additions and 3 deletions
+2 -1
View File
@@ -10,6 +10,7 @@ from __future__ import annotations
import os import os
import dataclasses import dataclasses
import socket
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@@ -46,7 +47,7 @@ def _provision_dynamic_key(
owner_repo = entry.UpstreamPath owner_repo = entry.UpstreamPath
if owner_repo.endswith(".git"): if owner_repo.endswith(".git"):
owner_repo = owner_repo[:-4] owner_repo = owner_repo[:-4]
title = f"bot-bottle:{slug}:{entry.Name}" title = f"bot-bottle:{socket.gethostname()}:{slug}:{entry.Name}"
info(f"provisioning deploy key for git-gate.repos[{entry.Name!r}]") info(f"provisioning deploy key for git-gate.repos[{entry.Name!r}]")
key_id, private_key_bytes = provisioner.create(owner_repo, title) key_id, private_key_bytes = provisioner.create(owner_repo, title)
+4 -2
View File
@@ -6,6 +6,7 @@ Covers the pure `git_gate_render_gitconfig` renderer and the dynamic
from __future__ import annotations from __future__ import annotations
import socket
import tempfile import tempfile
import types import types
import unittest import unittest
@@ -126,8 +127,9 @@ class TestProvisionDynamicKey(unittest.TestCase):
self.assertEqual(b"PRIVATE-KEY-BYTES", key_file.read_bytes()) self.assertEqual(b"PRIVATE-KEY-BYTES", key_file.read_bytes())
id_file = Path(d) / "repo-deploy-key-id" id_file = Path(d) / "repo-deploy-key-id"
self.assertEqual("kid123", id_file.read_text()) self.assertEqual("kid123", id_file.read_text())
# owner_repo had .git stripped; title carries slug + name # owner_repo had .git stripped; title carries hostname + slug + name
self.assertEqual([("o/r", "bot-bottle:myslug:repo")], fake.created) hostname = socket.gethostname()
self.assertEqual([("o/r", f"bot-bottle:{hostname}:myslug:repo")], fake.created)
def test_missing_token_raises(self) -> None: def test_missing_token_raises(self) -> None:
with tempfile.TemporaryDirectory() as d, \ with tempfile.TemporaryDirectory() as d, \