do merges locally

This commit is contained in:
Jörg Thalheim 2024-04-06 15:08:21 +02:00
parent e2eadbb009
commit 956e8e0a67
2 changed files with 50 additions and 20 deletions

View file

@ -12,13 +12,13 @@ from pathlib import Path
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
from buildbot.configurators import ConfiguratorBase from buildbot.configurators import ConfiguratorBase
from buildbot.interfaces import WorkerSetupError
from buildbot.plugins import reporters, schedulers, secrets, steps, util, worker from buildbot.plugins import reporters, schedulers, secrets, steps, util, worker
from buildbot.process import buildstep, logobserver, remotecommand from buildbot.process import buildstep, logobserver, remotecommand
from buildbot.process.project import Project from buildbot.process.project import Project
from buildbot.process.properties import Interpolate, Properties from buildbot.process.properties import Interpolate, Properties
from buildbot.process.results import ALL_RESULTS, statusToString from buildbot.process.results import ALL_RESULTS, statusToString
from buildbot.steps.trigger import Trigger from buildbot.steps.trigger import Trigger
from buildbot.util import asyncSleep
from buildbot.www.authz.endpointmatchers import EndpointMatcherBase, Match from buildbot.www.authz.endpointmatchers import EndpointMatcherBase, Match
if TYPE_CHECKING: if TYPE_CHECKING:
@ -327,9 +327,9 @@ def reload_github_projects(
) )
# The builtin retry mechanism doesn't seem to work for github, # GitHub somtimes fires the PR webhook before it has computed the merge commit
# since github is sometimes not delivering the pull request ref fast enough. # This is a workaround to fetch the merge commit and checkout the PR branch in CI
class GitWithRetry(steps.Git): class GitLocalPrMerge(steps.Git):
@defer.inlineCallbacks @defer.inlineCallbacks
def run_vc( def run_vc(
self, self,
@ -337,19 +337,50 @@ class GitWithRetry(steps.Git):
revision: str, revision: str,
patch: str, patch: str,
) -> Generator[Any, object, Any]: ) -> Generator[Any, object, Any]:
retry_counter = 0 build_props = self.build.getProperties()
while True: merge_base = build_props.getProperty("github.base.sha")
try: pr_head = build_props.getProperty("github.head.sha")
# Not a PR, fallback to default behavior
if merge_base is None or pr_head is None:
res = yield super().run_vc(branch, revision, patch) res = yield super().run_vc(branch, revision, patch)
except Exception as e: # noqa: BLE001 return res
retry_counter += 1
if retry_counter == 3: # The code below is a modified version of Git.run_vc
msg = "Failed to clone" self.stdio_log: Log = yield self.addLogForRemoteCommands("stdio")
raise BuildbotNixError(msg) from e
log: Log = yield self.addLog("log") self.stdio_log.addStdout(f"Merging {merge_base} into {pr_head}\n")
yield log.addStderr(f"Retrying git clone (error: {e})\n")
yield asyncSleep(2 << retry_counter) # 2, 4, 8 git_installed = yield self.checkFeatureSupport()
else:
if not git_installed:
msg = "git is not installed on worker"
raise WorkerSetupError(msg)
patched = yield self.sourcedirIsPatched()
if patched:
yield self._dovccmd(["clean", "-f", "-f", "-d", "-x"])
yield self._dovccmd(["fetch", "-f", "-t", self.repourl, merge_base, pr_head])
yield self._dovccmd(["checkout", "--detach", "-f", pr_head])
yield self._dovccmd(
[
"-c",
"user.email=buildbot@example.com",
"-c",
"user.name=buildbot",
"merge",
"--no-ff",
"-m",
f"Merge {merge_base} into {pr_head}",
merge_base,
]
)
self.updateSourceProperty("got_revision", pr_head)
res = yield self.parseCommitDescription()
return res return res
@ -371,7 +402,7 @@ def nix_eval_config(
f"https://git:%(secret:{github_token_secret})s@github.com/%(prop:project)s", f"https://git:%(secret:{github_token_secret})s@github.com/%(prop:project)s",
) )
factory.addStep( factory.addStep(
GitWithRetry( GitLocalPrMerge(
repourl=url_with_secret, repourl=url_with_secret,
method="clean", method="clean",
submodules=True, submodules=True,

View file

@ -81,7 +81,6 @@ ignore = [
"PLR2004", # Magic value used in comparison "PLR2004", # Magic value used in comparison
# not compatible with twisted logger: https://docs.twisted.org/en/twisted-18.7.0/core/howto/logger.html # not compatible with twisted logger: https://docs.twisted.org/en/twisted-18.7.0/core/howto/logger.html
"PGH002", # `warn` is deprecated in favor of `warning`
"G010", # Logging statement uses `warn` instead of `warning` "G010", # Logging statement uses `warn` instead of `warning`
] ]