Compare commits

...

10 commits

Author SHA1 Message Date
magic_rb 62e7fc4d88 Actually fix Cachix, attempt 3
Signed-off-by: magic_rb <richard@brezak.sk>
2024-07-27 14:14:23 +00:00
Jörg Thalheim 225d286fa7 make release 2024-07-26 20:26:45 +00:00
Jörg Thalheim f5fd4bf2a8 fix cachix usage 2024-07-26 17:39:07 +00:00
Jörg Thalheim eb746d95a4 make first release 2024-07-26 13:50:07 +02:00
Jörg Thalheim 2620f2cd31
Merge pull request #217 from MagicRB/combined-build-reports-github
Combined build reports GitHub
2024-07-26 13:47:13 +02:00
Jörg Thalheim c9b6d013d7
Merge pull request #235 from MagicRB/catch-silent-disable-of-cachix
Add check, which catchis silent disabling of cachix
2024-07-26 13:05:23 +02:00
magic_rb 36ef50e49f
Add check, which catchis silent disabling of cachix
Signed-off-by: magic_rb <richard@brezak.sk>
2024-07-26 12:23:05 +02:00
magic_rb 0ecf33f8d4
Reformat gitea_projects.py, __init__.py, and github_projects.py
Signed-off-by: magic_rb <richard@brezak.sk>
2024-07-26 11:53:06 +02:00
magic_rb 19d5cdd29a Hide gcroot registration steps from the reporters
Signed-off-by: magic_rb <richard@brezak.sk>
2024-07-26 11:37:23 +02:00
magic_rb d44dc3da09
Fix Gitea backend using the Gitea url as a webhook url
Signed-off-by: magic_rb <richard@brezak.sk>
2024-07-26 11:37:10 +02:00
6 changed files with 147 additions and 32 deletions

View file

@ -533,6 +533,7 @@ def nix_build_config(
updateSourceStamp=False,
doStepIf=do_register_gcroot_if,
copy_properties=["out_path", "attr"],
set_properties={"report_status": False},
),
)
factory.addStep(
@ -597,6 +598,7 @@ def nix_skipped_build_config(
updateSourceStamp=False,
doStepIf=do_register_gcroot_if,
copy_properties=["out_path", "attr"],
set_properties={"report_status": False},
),
)
return util.BuilderConfig(
@ -641,6 +643,7 @@ def nix_register_gcroot_config(
factory=factory,
)
def nix_build_combined_config(
project: GitProject,
worker_names: list[str],
@ -908,7 +911,7 @@ class NixConfigurator(ConfiguratorBase):
backends["github"] = GithubBackend(self.config.github, self.config.url)
if self.config.gitea is not None:
backends["gitea"] = GiteaBackend(self.config.gitea)
backends["gitea"] = GiteaBackend(self.config.gitea, self.config.url)
auth: AuthBase | None = (
backends[self.config.auth_backend].create_auth()

View file

@ -180,4 +180,3 @@ def filter_for_combined_builds(reports: Any) -> Any | None:
if "report_status" in properties and not properties["report_status"][0]:
return None
return reports

View file

@ -1,7 +1,8 @@
import os
import signal
from collections.abc import Callable
from pathlib import Path
from typing import Any, Callable
from typing import Any
from urllib.parse import urlparse
from buildbot.config.builder import BuilderConfig
@ -13,9 +14,9 @@ from buildbot.www.avatar import AvatarBase
from buildbot_gitea.auth import GiteaAuth # type: ignore[import]
from buildbot_gitea.reporter import GiteaStatusPush # type: ignore[import]
from pydantic import BaseModel
from twisted.internet import defer
from twisted.logger import Logger
from twisted.python import log
from twisted.internet import defer
from .common import (
ThreadDeferredBuildStep,
@ -106,13 +107,22 @@ class GiteaProject(GitProject):
# TODO Gitea doesn't include this information
return False # self.data["owner"]["type"] == "Organization"
class ModifyingGiteaStatusPush(GiteaStatusPush):
def checkConfig(self, modifyingFilter: Callable[[Any], Any | None] = lambda x: x, **kwargs: Any) -> Any:
def checkConfig(
self,
modifyingFilter: Callable[[Any], Any | None] = lambda x: x, # noqa: N803
**kwargs: Any,
) -> Any:
self.modifyingFilter = modifyingFilter
return super().checkConfig(**kwargs)
def reconfigService(self, modifyingFilter: Callable[[Any], Any | None] = lambda x: x, **kwargs: Any) -> Any:
def reconfigService(
self,
modifyingFilter: Callable[[Any], Any | None] = lambda x: x, # noqa: N803
**kwargs: Any,
) -> Any:
self.modifyingFilter = modifyingFilter
return super().reconfigService(**kwargs)
@ -129,9 +139,12 @@ class ModifyingGiteaStatusPush(GiteaStatusPush):
class GiteaBackend(GitBackend):
config: GiteaConfig
webhook_secret: str
instance_url: str
def __init__(self, config: GiteaConfig) -> None:
def __init__(self, config: GiteaConfig, instance_url: str) -> None:
self.config = config
self.instance_url = instance_url
def create_reload_builder(self, worker_names: list[str]) -> BuilderConfig:
"""Updates the flake an opens a PR for it."""
@ -140,7 +153,10 @@ class GiteaBackend(GitBackend):
ReloadGiteaProjects(self.config, self.config.project_cache_file),
)
factory.addStep(
CreateGiteaProjectHooks(self.config),
CreateGiteaProjectHooks(
self.config,
self.instance_url,
),
)
return util.BuilderConfig(
name=self.reload_builder_name,
@ -150,8 +166,8 @@ class GiteaBackend(GitBackend):
def create_reporter(self) -> ReporterBase:
return ModifyingGiteaStatusPush(
self.config.instance_url,
Interpolate(self.config.token),
baseURL=self.config.instance_url,
token=Interpolate(self.config.token),
context=Interpolate("buildbot/%(prop:status_name)s"),
context_pr=Interpolate("buildbot/%(prop:status_name)s"),
modifyingFilter=filter_for_combined_builds,
@ -221,14 +237,19 @@ class GiteaBackend(GitBackend):
def create_repo_hook(
token: str, webhook_secret: str, owner: str, repo: str, webhook_url: str
token: str,
webhook_secret: str,
owner: str,
repo: str,
gitea_url: str,
instance_url: str,
) -> None:
hooks = paginated_github_request(
f"{webhook_url}/api/v1/repos/{owner}/{repo}/hooks?limit=100",
f"{gitea_url}/api/v1/repos/{owner}/{repo}/hooks?limit=100",
token,
)
config = dict(
url=webhook_url + "change_hook/gitea",
url=instance_url + "change_hook/gitea",
content_type="json",
insecure_ssl="0",
secret=webhook_secret,
@ -246,13 +267,13 @@ def create_repo_hook(
"Content-Type": "application/json",
}
for hook in hooks:
if hook["config"]["url"] == webhook_url + "change_hook/gitea":
if hook["config"]["url"] == instance_url + "change_hook/gitea":
log.msg(f"hook for {owner}/{repo} already exists")
return
log.msg(f"creating hook for {owner}/{repo}")
http_request(
f"{webhook_url}/api/v1/repos/{owner}/{repo}/hooks",
f"{gitea_url}/api/v1/repos/{owner}/{repo}/hooks",
method="POST",
headers=headers,
data=data,
@ -263,13 +284,16 @@ class CreateGiteaProjectHooks(ThreadDeferredBuildStep):
name = "create_gitea_project_hooks"
config: GiteaConfig
instance_url: str
def __init__(
self,
config: GiteaConfig,
instance_url: str,
**kwargs: Any,
) -> None:
self.config = config
self.instance_url = instance_url
super().__init__(**kwargs)
def run_deferred(self) -> None:
@ -277,11 +301,12 @@ class CreateGiteaProjectHooks(ThreadDeferredBuildStep):
for repo in repos:
create_repo_hook(
self.config.token,
self.config.webhook_secret,
repo.owner.login,
repo.name,
self.config.instance_url,
token=self.config.token,
webhook_secret=self.config.webhook_secret,
owner=repo.owner.login,
repo=repo.name,
gitea_url=self.config.instance_url,
instance_url=self.instance_url,
)
def run_post(self) -> Any:

View file

@ -2,10 +2,11 @@ import json
import os
import signal
from abc import ABC, abstractmethod
from collections.abc import Callable
from dataclasses import dataclass
from itertools import starmap
from pathlib import Path
from typing import Any, Callable
from typing import Any
from buildbot.config.builder import BuilderConfig
from buildbot.plugins import util
@ -18,9 +19,9 @@ from buildbot.www.auth import AuthBase
from buildbot.www.avatar import AvatarBase, AvatarGitHub
from buildbot.www.oauth2 import GitHubAuth
from pydantic import BaseModel, ConfigDict, Field
from twisted.internet import defer
from twisted.logger import Logger
from twisted.python import log
from twisted.internet import defer
from .common import (
ThreadDeferredBuildStep,
@ -311,13 +312,22 @@ class GithubAuthBackend(ABC):
) -> list[BuildStep]:
pass
class ModifyingGitHubStatusPush(GitHubStatusPush):
def checkConfig(self, modifyingFilter: Callable[[Any], Any | None] = lambda x: x, **kwargs: Any) -> Any:
def checkConfig(
self,
modifyingFilter: Callable[[Any], Any | None] = lambda x: x, # noqa: N803
**kwargs: Any,
) -> Any:
self.modifyingFilter = modifyingFilter
return super().checkConfig(**kwargs)
def reconfigService(self, modifyingFilter: Callable[[Any], Any | None] = lambda x: x, **kwargs: Any) -> Any:
def reconfigService(
self,
modifyingFilter: Callable[[Any], Any | None] = lambda x: x, # noqa: N803
**kwargs: Any,
) -> Any:
self.modifyingFilter = modifyingFilter
return super().reconfigService(**kwargs)
@ -331,6 +341,7 @@ class ModifyingGitHubStatusPush(GitHubStatusPush):
result = yield super().sendMessage(reports)
return result
class GithubLegacyAuthBackend(GithubAuthBackend):
auth_type: GitHubLegacyConfig
@ -438,7 +449,6 @@ class GithubAppAuthBackend(GithubAuthBackend):
self.project_id_map[props["projectname"]]
].get()
return ModifyingGitHubStatusPush(
token=WithProperties("%(github_token)s", github_token=get_github_token),
# Since we dynamically create build steps,

View file

@ -1,6 +1,7 @@
{ config
, pkgs
, lib
, options
, ...
}:
let
@ -161,13 +162,51 @@ in
description = "Cachix name";
};
auth = lib.mkOption {
type = lib.types.attrTag {
signingKey = lib.mkOption {
description = ''
Use a signing key to authenticate with Cachix.
'';
type = lib.types.submodule {
options.file = lib.mkOption {
type = lib.types.path;
description = ''
Path to a file containing the signing key.
'';
};
};
};
authToken = lib.mkOption {
description = ''
Use an authentication token to authenticate with Cachix.
'';
type = lib.types.submodule {
options.file = lib.mkOption {
type = lib.types.path;
description = ''
Path to a file containing the authentication token.
'';
};
};
};
};
};
signingKeyFile = lib.mkOption {
type = lib.types.path;
type = lib.types.nullOr lib.types.path;
default = null;
visible = false;
description = "Cachix signing key";
};
authTokenFile = lib.mkOption {
type = lib.types.str;
type = lib.types.nullOr lib.types.path;
default = null;
visible = false;
description = "Cachix auth token";
};
};
@ -362,7 +401,38 @@ in
isSystemUser = true;
};
services.buildbot-nix.master.cachix.auth = lib.mkIf (cfg.cachix.authTokenFile != null || cfg.cachix.signingKeyFile != null)
(if (cfg.cachix.authTokenFile != null) then
lib.warn
"Obsolete option `services.buildbot-nix.master.cachix.authTokenFile' is used. It was renamed to `services.buildbot-nix.master.cachix.auth.authToken.file'."
{ authToken.file = cfg.cachix.authTokenFile; }
else if (cfg.cachix.signingKeyFile != null) then
lib.warn
"Obsolete option `services.buildbot-nix.master.cachix.signingKeyFile' is used. It was renamed to `services.buildbot-nix.master.cachix.auth.signingKey.file'."
{ signingKey.file = cfg.cachix.signingKeyFile; }
else
throw "Impossible, guarded by mkIf.");
assertions = [
{
assertion =
let
isNull = x: x == null;
in
isNull cfg.cachix.authTokenFile && isNull cfg.cachix.signingKeyFile ||
isNull cfg.cachix.authTokenFile && cfg.cachix.enable ||
isNull cfg.cachix.signingKeyFile && cfg.cachix.enable;
message = ''
The semantics of `options.services.buildbot-nix.master.cachix` recently changed
slightly, the option `name` is no longer null-able. To enable Cachix support
use `services.buildbot-nix.master.cachix.enable = true`.
Furthermore, the options `services.buildbot-nix.master.cachix.authTokenFile` and
`services.buildbot-nix.master.cachix.signingKeyFile` were renamed to
`services.buildbot-nix.master.cachix.auth.authToken.file` and
`services.buildbot-nix.master.cachix.auth.signingKey.file` respectively.
'';
}
{
assertion =
lib.versionAtLeast cfg.buildbotNixpkgs.buildbot.version "4.0.0";
@ -431,8 +501,16 @@ in
else
{
name = cfg.cachix.name;
signing_key_file = cfg.cachix.signingKeyFile;
auth_token_file = cfg.cachix.authTokenFile;
signing_key_file =
if cfg.cachix.auth ? "signingKey" then
cfg.cachix.auth.signingKey.file
else
null;
auth_token_file =
if cfg.cachix.auth ? "authToken" then
cfg.cachix.authTokenFile
else
null;
};
gitea = if !cfg.gitea.enable then
null
@ -541,10 +619,10 @@ in
)
++ lib.optional (cfg.authBackend == "gitea") "gitea-oauth-secret:${cfg.gitea.oauthSecretFile}"
++ lib.optional (cfg.authBackend == "github") "github-oauth-secret:${cfg.github.oauthSecretFile}"
++ lib.optionals cfg.cachix.enable [
++ lib.optional (cfg.cachix.enable && cfg.cachix ? "signingKey")
"cachix-signing-key:${builtins.toString cfg.cachix.signingKeyFile}"
++ lib.optional (cfg.cachix.enable && cfg.cachix ? "authToken")
"cachix-auth-token:${builtins.toString cfg.cachix.authTokenFile}"
]
++ lib.optionals cfg.gitea.enable [
"gitea-token:${cfg.gitea.tokenFile}"
"gitea-webhook-secret:${cfg.gitea.webhookSecretFile}"

View file

@ -20,7 +20,7 @@ classifiers = [
"Operating System :: OS Independent",
"Programming Language :: Python"
]
version = "0.0.1"
version = "0.1.1"
scripts = { buildbot-effects = "hercules_effects.cli:main" }
[tool.setuptools]