Support per installation tokens directly in GitHubStatusPush

Signed-off-by: magic_rb <richard@brezak.sk>
This commit is contained in:
magic_rb 2024-07-11 20:55:12 +02:00 committed by mergify[bot]
parent 4b8c544db8
commit c3346978d5
3 changed files with 86 additions and 113 deletions

View file

@ -2,7 +2,6 @@ import json
import os import os
import signal import signal
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from itertools import starmap from itertools import starmap
from pathlib import Path from pathlib import Path
@ -257,114 +256,6 @@ class ReloadGithubProjects(ThreadDeferredBuildStep):
return util.SUCCESS return util.SUCCESS
class GitHubAppStatusPush(GitHubStatusPush):
token_source: Callable[[int], RepoToken]
project_id_source: Callable[[str], int]
saved_args: dict[str, Any]
saved_kwargs: dict[str, Any]
def checkConfig(
self,
token_source: Callable[[int], RepoToken],
project_id_source: Callable[[str], int],
context: Any = None,
baseURL: Any = None,
verbose: Any = False,
debug: Any = None,
verify: Any = None,
generators: Any = None,
**kwargs: dict[str, Any],
) -> Any:
if generators is None:
generators = self._create_default_generators()
if "token" in kwargs:
del kwargs["token"]
super().checkConfig(
token="",
context=context,
baseURL=baseURL,
verbose=verbose,
debug=debug,
verify=verify,
generators=generators,
**kwargs,
)
def reconfigService(
self,
token_source: Callable[[int], RepoToken],
project_id_source: Callable[[str], int],
context: Any = None,
baseURL: Any = None,
verbose: Any = False,
debug: Any = None,
verify: Any = None,
generators: Any = None,
**kwargs: dict[str, Any],
) -> Any:
if "saved_args" not in self or self.saved_args is None:
self.saved_args = {}
self.token_source = token_source
self.project_id_source = project_id_source
self.saved_kwargs = kwargs
self.saved_args["context"] = context
self.saved_args["baseURL"] = baseURL
self.saved_args["verbose"] = verbose
self.saved_args["debug"] = debug
self.saved_args["verify"] = verify
self.saved_args["generators"] = generators
if generators is None:
generators = self._create_default_generators()
if "token" in kwargs:
del kwargs["token"]
super().reconfigService(
token="",
context=context,
baseURL=baseURL,
verbose=verbose,
debug=debug,
verify=verify,
generators=generators,
**kwargs,
)
def sendMessage(self, reports: Any) -> Any:
build = reports[0]["builds"][0]
sourcestamps = build["buildset"].get("sourcestamps")
if not sourcestamps:
return None
for sourcestamp in sourcestamps:
build["buildset"]["sourcestamps"] = [sourcestamp]
token: str
if "project" in sourcestamp and sourcestamp["project"] != "":
token = self.token_source(
self.project_id_source(sourcestamp["project"])
).get()
else:
token = ""
super().reconfigService(
token,
context=self.saved_args["context"],
baseURL=self.saved_args["baseURL"],
verbose=self.saved_args["verbose"],
debug=self.saved_args["debug"],
verify=self.saved_args["verify"],
generators=self.saved_args["generators"],
**self.saved_kwargs,
)
return super().sendMessage(reports)
return None
class GithubAuthBackend(ABC): class GithubAuthBackend(ABC):
@abstractmethod @abstractmethod
def get_general_token(self) -> RepoToken: def get_general_token(self) -> RepoToken:
@ -496,9 +387,10 @@ class GithubAppAuthBackend(GithubAuthBackend):
return [GitHubAppSecretService(self.installation_tokens, self.jwt_token)] return [GitHubAppSecretService(self.installation_tokens, self.jwt_token)]
def create_reporter(self) -> ReporterBase: def create_reporter(self) -> ReporterBase:
return GitHubAppStatusPush( return GitHubStatusPush(
token_source=lambda iid: self.installation_tokens[iid], token=lambda project: self.installation_tokens[
project_id_source=lambda project: self.project_id_map[project], self.project_id_map[project]
].get(),
# Since we dynamically create build steps, # Since we dynamically create build steps,
# we use `virtual_builder_name` in the webinterface # we use `virtual_builder_name` in the webinterface
# so that we distinguish what has beeing build # so that we distinguish what has beeing build

View file

@ -0,0 +1,66 @@
From 65dd3e63dc0dc34a531eee703baff715ba04d0a0 Mon Sep 17 00:00:00 2001
From: magic_rb <richard@brezak.sk>
Date: Wed, 10 Jul 2024 13:00:48 +0200
Subject: [PATCH 1/3] Support per installation tokens in `GithubStatusPush`
reporter
Signed-off-by: magic_rb <richard@brezak.sk>
---
master/buildbot/reporters/github.py | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/master/buildbot/reporters/github.py b/master/buildbot/reporters/github.py
index 3873c2676..e61e6495a 100644
--- a/master/buildbot/reporters/github.py
+++ b/master/buildbot/reporters/github.py
@@ -70,7 +70,14 @@ class GitHubStatusPush(ReporterBase):
generators=None,
**kwargs,
):
- token = yield self.renderSecrets(token)
+ headers = {}
+ if not callable(token):
+ token = yield self.renderSecrets(token)
+ headers['Authorization'] = 'token ' + token
+ else:
+ self.token_cache = {}
+ self.token_source = token
+
self.debug = debug
self.verify = verify
self.verbose = verbose
@@ -89,7 +96,7 @@ class GitHubStatusPush(ReporterBase):
self._http = yield httpclientservice.HTTPClientService.getService(
self.master,
baseURL,
- headers={'Authorization': 'token ' + token, 'User-Agent': 'Buildbot'},
+ headers={'User-Agent': 'Buildbot'} | headers,
debug=self.debug,
verify=self.verify,
)
@@ -135,6 +142,11 @@ class GitHubStatusPush(ReporterBase):
txgithub is based on twisted's webclient agent, which is much less reliable and featureful
as txrequest (support for proxy, connection pool, keep alive, retry, etc)
"""
+ headers = {}
+
+ if hasattr(self, 'token_source'):
+ headers['Authorization'] = 'token ' + self.token_source(f"{repo_user}/{repo_name}")
+
payload = {'state': state}
if description is not None:
@@ -147,7 +159,9 @@ class GitHubStatusPush(ReporterBase):
payload['context'] = context
return self._http.post(
- '/'.join(['/repos', repo_user, repo_name, 'statuses', sha]), json=payload
+ '/'.join(['/repos', repo_user, repo_name, 'statuses', sha]),
+ json=payload,
+ headers=headers,
)
def is_status_2xx(self, code):
--
2.44.1

View file

@ -409,7 +409,22 @@ in
in in
"${if hasSSL then "https" else "http"}://${cfg.domain}/"; "${if hasSSL then "https" else "http"}://${cfg.domain}/";
dbUrl = config.services.buildbot-nix.master.dbUrl; dbUrl = config.services.buildbot-nix.master.dbUrl;
package = cfg.package; package =
let
fixPatch = { patch, name }:
pkgs.runCommand "${name}.patch" { } ''
sed -r \
's~^(---|\+\+\+) (a|b)/master/(.+)$~\1 \2/\3~' \
${patch} >$out
'';
in
cfg.package.overrideAttrs (old: {
patches =
old.patches ++ [
./0001-Support-per-installation-tokens-in-GithubStatusPush-.patch #;
];
});
pythonPackages = ps: [ pythonPackages = ps: [
ps.requests ps.requests
ps.treq ps.treq