Combine build reports for GitHub if there are too many
Signed-off-by: magic_rb <richard@brezak.sk>
This commit is contained in:
parent
7480ee03b3
commit
dd2df67009
|
@ -59,12 +59,14 @@ class BuildTrigger(Trigger):
|
||||||
builds_scheduler: str,
|
builds_scheduler: str,
|
||||||
skipped_builds_scheduler: str,
|
skipped_builds_scheduler: str,
|
||||||
jobs: list[dict[str, Any]],
|
jobs: list[dict[str, Any]],
|
||||||
|
report_status: bool,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
if "name" not in kwargs:
|
if "name" not in kwargs:
|
||||||
kwargs["name"] = "trigger"
|
kwargs["name"] = "trigger"
|
||||||
self.project = project
|
self.project = project
|
||||||
self.jobs = jobs
|
self.jobs = jobs
|
||||||
|
self.report_status = report_status
|
||||||
self.config = None
|
self.config = None
|
||||||
self.builds_scheduler = builds_scheduler
|
self.builds_scheduler = builds_scheduler
|
||||||
self.skipped_builds_scheduler = skipped_builds_scheduler
|
self.skipped_builds_scheduler = skipped_builds_scheduler
|
||||||
|
@ -102,6 +104,7 @@ class BuildTrigger(Trigger):
|
||||||
props.setProperty("virtual_builder_name", name, source)
|
props.setProperty("virtual_builder_name", name, source)
|
||||||
props.setProperty("status_name", f"nix-build .#checks.{attr}", source)
|
props.setProperty("status_name", f"nix-build .#checks.{attr}", source)
|
||||||
props.setProperty("virtual_builder_tags", "", source)
|
props.setProperty("virtual_builder_tags", "", source)
|
||||||
|
props.setProperty("report_status", self.report_status, source)
|
||||||
|
|
||||||
drv_path = job.get("drvPath")
|
drv_path = job.get("drvPath")
|
||||||
system = job.get("system")
|
system = job.get("system")
|
||||||
|
@ -145,6 +148,15 @@ class BuildTrigger(Trigger):
|
||||||
return {"step": f"({', '.join(summary)})"}
|
return {"step": f"({', '.join(summary)})"}
|
||||||
|
|
||||||
|
|
||||||
|
class NixBuildCombined(steps.BuildStep):
|
||||||
|
"""Shows the error message of a failed evaluation."""
|
||||||
|
|
||||||
|
name = "nix-build-combined"
|
||||||
|
|
||||||
|
def run(self) -> Generator[Any, object, Any]:
|
||||||
|
return self.build.results
|
||||||
|
|
||||||
|
|
||||||
class NixEvalCommand(buildstep.ShellMixin, steps.BuildStep):
|
class NixEvalCommand(buildstep.ShellMixin, steps.BuildStep):
|
||||||
"""Parses the output of `nix-eval-jobs` and triggers a `nix-build` build for
|
"""Parses the output of `nix-eval-jobs` and triggers a `nix-build` build for
|
||||||
every attribute.
|
every attribute.
|
||||||
|
@ -190,16 +202,32 @@ class NixEvalCommand(buildstep.ShellMixin, steps.BuildStep):
|
||||||
if not system or system in self.supported_systems: # report eval errors
|
if not system or system in self.supported_systems: # report eval errors
|
||||||
filtered_jobs.append(job)
|
filtered_jobs.append(job)
|
||||||
|
|
||||||
|
self.number_of_jobs = len(filtered_jobs)
|
||||||
|
|
||||||
self.build.addStepsAfterCurrentStep(
|
self.build.addStepsAfterCurrentStep(
|
||||||
[
|
[ # noqa: RUF005
|
||||||
BuildTrigger(
|
BuildTrigger(
|
||||||
self.project,
|
self.project,
|
||||||
builds_scheduler=f"{project_id}-nix-build",
|
builds_scheduler=f"{project_id}-nix-build",
|
||||||
skipped_builds_scheduler=f"{project_id}-nix-skipped-build",
|
skipped_builds_scheduler=f"{project_id}-nix-skipped-build",
|
||||||
name="build flake",
|
name="build flake",
|
||||||
jobs=filtered_jobs,
|
jobs=filtered_jobs,
|
||||||
|
report_status=(self.number_of_jobs <= 2),
|
||||||
),
|
),
|
||||||
],
|
]
|
||||||
|
+ [
|
||||||
|
Trigger(
|
||||||
|
waitForFinish=True,
|
||||||
|
schedulerNames=[f"{project_id}-nix-build-combined"],
|
||||||
|
haltOnFailure=True,
|
||||||
|
flunkOnFailure=True,
|
||||||
|
sourceStamps=[],
|
||||||
|
alwaysUseLatest=False,
|
||||||
|
updateSourceStamp=False,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
if self.number_of_jobs > 2
|
||||||
|
else [],
|
||||||
)
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -600,6 +628,23 @@ def nix_register_gcroot_config(
|
||||||
factory=factory,
|
factory=factory,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def nix_build_combined_config(
|
||||||
|
project: GitProject,
|
||||||
|
worker_names: list[str],
|
||||||
|
) -> BuilderConfig:
|
||||||
|
factory = util.BuildFactory()
|
||||||
|
factory.addStep(NixBuildCombined())
|
||||||
|
|
||||||
|
return util.BuilderConfig(
|
||||||
|
name=f"{project.name}/nix-build-combined",
|
||||||
|
project=project.name,
|
||||||
|
workernames=worker_names,
|
||||||
|
collapseRequests=False,
|
||||||
|
env={},
|
||||||
|
factory=factory,
|
||||||
|
properties=dict(status_name="nix-build-combined"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def config_for_project(
|
def config_for_project(
|
||||||
config: dict[str, Any],
|
config: dict[str, Any],
|
||||||
|
@ -653,6 +698,11 @@ def config_for_project(
|
||||||
name=f"{project.project_id}-nix-skipped-build",
|
name=f"{project.project_id}-nix-skipped-build",
|
||||||
builderNames=[f"{project.name}/nix-skipped-build"],
|
builderNames=[f"{project.name}/nix-skipped-build"],
|
||||||
),
|
),
|
||||||
|
# this is triggered from `nix-eval` when the build contains too many outputs
|
||||||
|
schedulers.Triggerable(
|
||||||
|
name=f"{project.project_id}-nix-build-combined",
|
||||||
|
builderNames=[f"{project.name}/nix-build-combined"],
|
||||||
|
),
|
||||||
schedulers.Triggerable(
|
schedulers.Triggerable(
|
||||||
name=f"{project.project_id}-nix-register-gcroot",
|
name=f"{project.project_id}-nix-register-gcroot",
|
||||||
builderNames=[f"{project.name}/nix-register-gcroot"],
|
builderNames=[f"{project.name}/nix-register-gcroot"],
|
||||||
|
@ -693,6 +743,7 @@ def config_for_project(
|
||||||
),
|
),
|
||||||
nix_skipped_build_config(project, [SKIPPED_BUILDER_NAME]),
|
nix_skipped_build_config(project, [SKIPPED_BUILDER_NAME]),
|
||||||
nix_register_gcroot_config(project, worker_names),
|
nix_register_gcroot_config(project, worker_names),
|
||||||
|
nix_build_combined_config(project, worker_names),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ from abc import ABC, abstractmethod
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from itertools import starmap
|
from itertools import starmap
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any, Callable
|
||||||
|
|
||||||
from buildbot.config.builder import BuilderConfig
|
from buildbot.config.builder import BuilderConfig
|
||||||
from buildbot.plugins import util
|
from buildbot.plugins import util
|
||||||
|
@ -20,6 +20,7 @@ from buildbot.www.oauth2 import GitHubAuth
|
||||||
from pydantic import BaseModel, ConfigDict, Field
|
from pydantic import BaseModel, ConfigDict, Field
|
||||||
from twisted.logger import Logger
|
from twisted.logger import Logger
|
||||||
from twisted.python import log
|
from twisted.python import log
|
||||||
|
from twisted.internet import defer
|
||||||
|
|
||||||
from .common import (
|
from .common import (
|
||||||
ThreadDeferredBuildStep,
|
ThreadDeferredBuildStep,
|
||||||
|
@ -309,6 +310,32 @@ class GithubAuthBackend(ABC):
|
||||||
) -> list[BuildStep]:
|
) -> list[BuildStep]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class ModifyingGitHubStatusPush(GitHubStatusPush):
|
||||||
|
def checkConfig(self, modifyingFilter: Callable[[Any], Any | None] = lambda x: x, **kwargs: Any) -> Any:
|
||||||
|
self.modifyingFilter = modifyingFilter
|
||||||
|
|
||||||
|
return super().checkConfig(**kwargs)
|
||||||
|
|
||||||
|
def reconfigService(self, modifyingFilter: Callable[[Any], Any | None] = lambda x: x, **kwargs: Any) -> Any:
|
||||||
|
self.modifyingFilter = modifyingFilter
|
||||||
|
|
||||||
|
return super().reconfigService(**kwargs)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def sendMessage(self, reports: Any) -> Any:
|
||||||
|
reports = self.modifyingFilter(reports)
|
||||||
|
if reports is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
result = yield super().sendMessage(reports)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def filter_for_combined_builds(reports: Any) -> Any | None:
|
||||||
|
properties = reports[0]["builds"][0]["properties"]
|
||||||
|
|
||||||
|
if "report_status" in properties and not properties["report_status"][0]:
|
||||||
|
return None
|
||||||
|
return reports
|
||||||
|
|
||||||
class GithubLegacyAuthBackend(GithubAuthBackend):
|
class GithubLegacyAuthBackend(GithubAuthBackend):
|
||||||
auth_type: GitHubLegacyConfig
|
auth_type: GitHubLegacyConfig
|
||||||
|
@ -329,12 +356,13 @@ class GithubLegacyAuthBackend(GithubAuthBackend):
|
||||||
return [GitHubLegacySecretService(self.token)]
|
return [GitHubLegacySecretService(self.token)]
|
||||||
|
|
||||||
def create_reporter(self) -> ReporterBase:
|
def create_reporter(self) -> ReporterBase:
|
||||||
return GitHubStatusPush(
|
return ModifyingGitHubStatusPush(
|
||||||
token=self.token.get(),
|
token=self.token.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
|
||||||
context=Interpolate("buildbot/%(prop:status_name)s"),
|
context=Interpolate("buildbot/%(prop:status_name)s"),
|
||||||
|
modifyingFilter=filter_for_combined_builds,
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_reload_builder_steps(
|
def create_reload_builder_steps(
|
||||||
|
@ -416,12 +444,13 @@ class GithubAppAuthBackend(GithubAuthBackend):
|
||||||
self.project_id_map[props["projectname"]]
|
self.project_id_map[props["projectname"]]
|
||||||
].get()
|
].get()
|
||||||
|
|
||||||
return GitHubStatusPush(
|
return ModifyingGitHubStatusPush(
|
||||||
token=WithProperties("%(github_token)s", github_token=get_github_token),
|
token=WithProperties("%(github_token)s", github_token=get_github_token),
|
||||||
# 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
|
||||||
context=Interpolate("buildbot/%(prop:status_name)s"),
|
context=Interpolate("buildbot/%(prop:status_name)s"),
|
||||||
|
modifyingFilter=filter_for_combined_builds,
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_reload_builder_steps(
|
def create_reload_builder_steps(
|
||||||
|
|
|
@ -482,7 +482,9 @@ in
|
||||||
dbUrl = config.services.buildbot-nix.master.dbUrl;
|
dbUrl = config.services.buildbot-nix.master.dbUrl;
|
||||||
|
|
||||||
package = cfg.buildbotNixpkgs.buildbot.overrideAttrs (old: {
|
package = cfg.buildbotNixpkgs.buildbot.overrideAttrs (old: {
|
||||||
patches = old.patches ++ [ ./0001-master-reporters-github-render-token-for-each-reques.patch ];
|
patches = old.patches ++ [
|
||||||
|
./0001-master-reporters-github-render-token-for-each-reques.patch
|
||||||
|
];
|
||||||
});
|
});
|
||||||
pythonPackages =
|
pythonPackages =
|
||||||
let
|
let
|
||||||
|
|
Loading…
Reference in a new issue