Support per installation tokens directly in GitHubStatusPush
Signed-off-by: magic_rb <richard@brezak.sk>
This commit is contained in:
parent
4b8c544db8
commit
c3346978d5
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue