diff --git a/services/gerrit/checks.js b/services/gerrit/checks.js new file mode 100644 index 0000000..dd6a814 --- /dev/null +++ b/services/gerrit/checks.js @@ -0,0 +1,113 @@ +/* Inspired from the Lix setup. + * Original-Author: puckipedia + */ +Gerrit.install((plugin) => { + // TODO: can we just use `plugin.serverInfo().plugin` and control the settings over there. + const configuration = { + baseUri: @BASE_URI@, + supportedProjects: @SUPPORTED_PROJECTS@, + }; + + function makeBuildbotUri(suffix) { + return `${configuration.baseUri}/${suffix}`; + } + + let builders = []; + let fetchBuilders = async () => { + if (builders.length > 0) return; + let data = await (await fetch(makeBuildbotUri(`api/v2/builders`), { credentials: 'include' })).json(); + builders = data.builders; + }; + + + let checksProvider; + checksProvider = { + async fetch({ repo, patchsetSha, changeNumber, patchsetNumber }, runBefore = false) { + if (!configuration.supportedProjects.includes(repo)) { + return { responseCode: 'OK' }; + } + + let num = changeNumber.toString(10); + + let branch = `refs/changes/${num.substr(-2)}/${num}/${patchsetNumber}`; + + let changeFetch = await fetch(makeBuildbotUri(`api/v2/changes?limit=1&order=-changeid&revision=${patchsetSha}&branch=${branch}`), { credentials: 'include' }); + if (changeFetch.status == 400) { + if ((await changeFetch.json()).error === 'invalid origin' && !runBefore) { + return await checksProvider.fetch({ repo, patchsetSha, changeNumber, patchsetNumber }, true); + } + + return { responseCode: 'OK' }; + } else if (changeFetch.status === 403) { + return { responseCode: 'NOT_LOGGED_IN', loginCallback() { + window.open(configuration.baseUri); + } }; + } + + let changes = await changeFetch.json(); + if (changes.meta.total === 0) { + return { responseCode: 'OK' }; + } + + let { changeid } = changes.changes[0]; + let { builds } = await (await fetch(makeBuildbotUri(`api/v2/changes/${changeid}/builds?property=owners&property=workername`), { credentials: 'include' })).json(); + await fetchBuilders(); + let links = []; + let runs = []; + for (let build of builds) { + let name = `unknown builder ${build.builderid}`; + for (let builder of builders) { + if (builder.builderid === build.builderid) { + name = builder.name; + break; + } + } + + if (name === `${repo}/nix-eval`) { + links.push({ + url: makeBuildbotUri(`#/builders/${build.builderid}/builds/${build.number}`), + primary: true, + icon: 'external', + }); + } + + let checkrun = { + attempt: build.buildrequestid, + // FIXME: generalize this accordingly once auto-discovery is available. + checkName: name.replace(/^hydraJobs\./, ''), + externalId: build.buildrequestid.toString(), + status: build.complete ? 'COMPLETED' : (typeof build.started_at !== 'number' ? 'SCHEDULED' : 'RUNNING'), + checkLink: makeBuildbotUri(`#/builders/${build.builderid}/builds/${build.number}`), + labelName: 'Verified', + results: [], + links: [{ + url: makeBuildbotUri(`#/builders/${build.builderid}/builds/${build.number}`), + primary: true, + icon: 'external', + }], + }; + + if (build.started_at !== null) { + checkrun.startedTimestamp = new Date(build.started_at * 1000); + } + + if (build.complete_at !== null) { + checkrun.finishedTimestamp = new Date(build.complete_at * 1000); + } + + if (build.results !== null) { + checkrun.results = [{ + category: build.results < 2 ? 'SUCCESS' : 'ERROR', + summary: build.state_string, + }]; + } + + runs.push(checkrun); + } + + return { responseCode: 'OK', runs, links }; + } + }; + + plugin.checks().register(checksProvider); +}); diff --git a/services/gerrit/default.nix b/services/gerrit/default.nix index 3796dc1..61e7ca8 100644 --- a/services/gerrit/default.nix +++ b/services/gerrit/default.nix @@ -72,6 +72,21 @@ in plugins = with pkgs.gerritPlugins; [ oauth metrics-reporter-prometheus + # Buildbot checks plugin (writeText because services.gerrit.plugins expects packages) + (pkgs.runCommand "checks.js" { + BASE_URI = builtins.toJSON "https://buildbot.forkos.org"; + SUPPORTED_PROJECTS = builtins.toJSON [ + "infra" + "nixpkgs" + "buildbot-test" + ]; + } + '' + echo "configuring buildbot checks plugin for $BASE_URI with $SUPPORTED_PROJECTS project list" + substitute ${./checks.js} $out \ + --replace-fail "@BASE_URI@" "$BASE_URI" \ + --replace-fail "@SUPPORTED_PROJECTS@" "$SUPPORTED_PROJECTS" + '') ]; package = pkgs.gerrit; @@ -126,7 +141,7 @@ in # Other settings log.jsonLogging = true; log.textLogging = false; - sshd.advertisedAddress = "${cfg.canonicalDomain}:${cfg.port}"; + sshd.advertisedAddress = "${cfg.canonicalDomain}:${toString cfg.port}"; cache.web_sessions.maxAge = "3 months"; plugins.allowRemoteAdmin = false; change.enableAttentionSet = true;