Compare commits
32 Commits
feat/disab
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
7c75138ca9
|
|||
|
8c970f6391
|
|||
|
|
a9581bcdc4 | ||
|
|
26e4d5eb54 | ||
|
|
8bc95a96f7 | ||
|
|
82cd5e0e23 | ||
|
|
c3ed183c64 | ||
|
|
b45f0d1fa7 | ||
|
|
e4fe9d43c1 | ||
|
|
9df4b65c67 | ||
|
|
1d011baed8 | ||
|
|
52b2e4f021 | ||
|
|
f089ff87f5 | ||
|
|
43006db835 | ||
|
|
4ebfaba862 | ||
|
|
41daeb3cc9 | ||
|
|
3b1b5009f3 | ||
|
|
54699ae671 | ||
|
|
503871bac4 | ||
|
|
6dde18cb5e | ||
|
|
e0f65d4d3d | ||
|
|
5e2e9672cf | ||
|
|
650871b586 | ||
|
|
b2030cd4ef | ||
|
|
44780c786e | ||
|
|
2db62e86e7 | ||
|
|
b88b06dd3c | ||
|
|
d042e3c82c | ||
|
|
f1b26134d7 | ||
|
|
23fa93c5f8 | ||
|
|
66730993fc | ||
|
|
25d1e8900a |
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
runner: ubuntu-24.04-arm
|
runner: ubuntu-24.04-arm
|
||||||
runs-on: ${{ matrix.runner }}
|
runs-on: ${{ matrix.runner }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: cachix/install-nix-action@v31
|
- uses: cachix/install-nix-action@v31
|
||||||
|
|||||||
4
.github/workflows/update-flakes.yml
vendored
4
.github/workflows/update-flakes.yml
vendored
@@ -11,12 +11,12 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: cachix/install-nix-action@v31
|
- uses: cachix/install-nix-action@v31
|
||||||
- name: Update flake inputs
|
- name: Update flake inputs
|
||||||
run: nix flake update
|
run: nix flake update
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: peter-evans/create-pull-request@v5
|
uses: peter-evans/create-pull-request@v8
|
||||||
with:
|
with:
|
||||||
commit-message: "flake.lock: Update"
|
commit-message: "flake.lock: Update"
|
||||||
title: "Update flake inputs"
|
title: "Update flake inputs"
|
||||||
|
|||||||
22
flake.lock
generated
22
flake.lock
generated
@@ -3,16 +3,16 @@
|
|||||||
"nix": {
|
"nix": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1767367029,
|
"lastModified": 1768160797,
|
||||||
"narHash": "sha256-RsVlkBkxvPPePEo59AVolBFdayxny9FFv8X4aNq9qFc=",
|
"narHash": "sha256-TVKn52SoKq8mMyW/x3NPPskGVurFdnGGV0DGvnL0gak=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"rev": "394a8da9dd9c046de715e451a96b70e64ce4aa7a",
|
"rev": "fb562abba93fb15f66a71a9fc1d94bb1ea21a2d4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "2.32-maintenance",
|
"ref": "2.33-maintenance",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@@ -20,27 +20,27 @@
|
|||||||
"nix-eval-jobs": {
|
"nix-eval-jobs": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1760478325,
|
"lastModified": 1767025318,
|
||||||
"narHash": "sha256-hA+NOH8KDcsuvH7vJqSwk74PyZP3MtvI/l+CggZcnTc=",
|
"narHash": "sha256-i68miKHGdueWggcDAF+Kca9g6S3ipkW629XbMpQYfn0=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nix-eval-jobs",
|
"repo": "nix-eval-jobs",
|
||||||
"rev": "daa42f9e9c84aeff1e325dd50fda321f53dfd02c",
|
"rev": "79dd7adbb5f75b08fb4b9bddd712ebc52baa46bc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"ref": "v2.32.1",
|
"ref": "v2.33.0",
|
||||||
"repo": "nix-eval-jobs",
|
"repo": "nix-eval-jobs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1767475907,
|
"lastModified": 1768332487,
|
||||||
"narHash": "sha256-w10AFfl20h5MSBCsCegD4xtmcgDlQQeoFsOaIFwHOrE=",
|
"narHash": "sha256-Q0bSMhDIhb/S7r+XRyuPy58kEXa0rmpw5j99ubJzovg=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "7a0d60a03534a2d14b0805616aa1fd403fccfa55",
|
"rev": "6b0609442afc4ce51ff1466e7db555c2e2fc28d4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11-small";
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11-small";
|
||||||
|
|
||||||
inputs.nix = {
|
inputs.nix = {
|
||||||
url = "github:NixOS/nix/2.32-maintenance";
|
url = "github:NixOS/nix/2.33-maintenance";
|
||||||
# We want to control the deps precisely
|
# We want to control the deps precisely
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
inputs.nix-eval-jobs = {
|
inputs.nix-eval-jobs = {
|
||||||
url = "github:nix-community/nix-eval-jobs/v2.32.1";
|
url = "github:nix-community/nix-eval-jobs/v2.33.0";
|
||||||
# We want to control the deps precisely
|
# We want to control the deps precisely
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
|||||||
71
gitea_hydra_server.py
Normal file
71
gitea_hydra_server.py
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#/usr/bin/env python3
|
||||||
|
|
||||||
|
#imports
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
#Vars
|
||||||
|
baseurl="git.dynamicdiscord.de"
|
||||||
|
owner="ahtlon"
|
||||||
|
repo="infrastructure"
|
||||||
|
host="127.0.0.1"
|
||||||
|
port=27364
|
||||||
|
|
||||||
|
def _get_api_response():
|
||||||
|
###https://docs.gitea.com/api/1.21/#tag/repository/operation/repoListPullRequests
|
||||||
|
###GET /api/v1/repos/{owner}/{repo}/pulls
|
||||||
|
url=(f"https://{baseurl}/api/v1/repos/{owner}/{repo}/pulls?state=open")
|
||||||
|
headers={"Accept": "application/json"}
|
||||||
|
req=urllib.request.Request(url, headers=headers)
|
||||||
|
with urllib.request.urlopen(req) as resp:
|
||||||
|
return json.loads(resp.read().decode("utf-8"))
|
||||||
|
|
||||||
|
def _parse_response():
|
||||||
|
target_repo_url=f"https://{baseurl}/{owner}/{repo}.git"
|
||||||
|
pulls: dict={}
|
||||||
|
response=_get_api_response()
|
||||||
|
for pr in response:
|
||||||
|
pr["target_repo_url"]=target_repo_url
|
||||||
|
pulls[str(pr["number"])]=pr
|
||||||
|
return pulls
|
||||||
|
|
||||||
|
class PullsHandler(BaseHTTPRequestHandler):
|
||||||
|
_VALID_PATHS={"/", "/gitea-pulls-sorted.json"}
|
||||||
|
|
||||||
|
def do_GET(self):
|
||||||
|
if self.path not in self._VALID_PATHS:
|
||||||
|
self.send_error(404, "Not Found")
|
||||||
|
return
|
||||||
|
|
||||||
|
answer=dict(_parse_response())
|
||||||
|
|
||||||
|
body=json.dumps(answer, indent=2, sort_keys=True).encode("utf-8")
|
||||||
|
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-Type", "application/json; charset=utf-8")
|
||||||
|
self.send_header("Content-Length", str(len(body)))
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(body)
|
||||||
|
|
||||||
|
def log_message(self, fmt, *args):
|
||||||
|
print(
|
||||||
|
f"[gitea-translator] {self.address_string()} - {fmt % args}",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print(
|
||||||
|
f"[gitea-translator] Starting, pulling from {baseurl}/{owner}/{repo}",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
server=HTTPServer((host, port), PullsHandler)
|
||||||
|
print(
|
||||||
|
f"[gitea-translator] online @ {host}:{port}",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
server.serve_forever()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
125
hydra-api.yaml
125
hydra-api.yaml
@@ -574,6 +574,131 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/JobsetEvalBuilds'
|
$ref: '#/components/schemas/JobsetEvalBuilds'
|
||||||
|
|
||||||
|
/jobset/{project-id}/{jobset-id}/latest-eval:
|
||||||
|
get:
|
||||||
|
summary: Redirects to the latest finished evaluation for a jobset
|
||||||
|
parameters:
|
||||||
|
- name: project-id
|
||||||
|
in: path
|
||||||
|
description: project identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: jobset-id
|
||||||
|
in: path
|
||||||
|
description: jobset identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'302':
|
||||||
|
description: the evaluation to redirect to
|
||||||
|
headers:
|
||||||
|
Location:
|
||||||
|
example: /eval/1?name={jobset-id}
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
/job/{project-id}/{jobset-id}/{job-id}/latest:
|
||||||
|
get:
|
||||||
|
summary: Redirects to the latest succesful build for a job
|
||||||
|
parameters:
|
||||||
|
- name: project-id
|
||||||
|
in: path
|
||||||
|
description: project identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: jobset-id
|
||||||
|
in: path
|
||||||
|
description: jobset identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: job-id
|
||||||
|
in: path
|
||||||
|
description: job identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'302':
|
||||||
|
description: the build to redirect to
|
||||||
|
headers:
|
||||||
|
Location:
|
||||||
|
example: /build/1
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
/job/{project-id}/{jobset-id}/{job-id}/latest-for/{system}:
|
||||||
|
get:
|
||||||
|
summary: Redirects to the latest succesful build for a job
|
||||||
|
parameters:
|
||||||
|
- name: project-id
|
||||||
|
in: path
|
||||||
|
description: project identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: jobset-id
|
||||||
|
in: path
|
||||||
|
description: jobset identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: job-id
|
||||||
|
in: path
|
||||||
|
description: job identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: system
|
||||||
|
in: path
|
||||||
|
description: system
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: x86_64-linux
|
||||||
|
responses:
|
||||||
|
'302':
|
||||||
|
description: the build to redirect to
|
||||||
|
headers:
|
||||||
|
Location:
|
||||||
|
example: /build/1
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
/job/{project-id}/{jobset-id}/{job-id}/latest-finished:
|
||||||
|
get:
|
||||||
|
summary: Redirects to the latest succesful build for a job from a finished evaluation
|
||||||
|
parameters:
|
||||||
|
- name: project-id
|
||||||
|
in: path
|
||||||
|
description: project identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: jobset-id
|
||||||
|
in: path
|
||||||
|
description: jobset identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: job-id
|
||||||
|
in: path
|
||||||
|
description: job identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'302':
|
||||||
|
description: the build to redirect to
|
||||||
|
headers:
|
||||||
|
Location:
|
||||||
|
example: /build/1
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
|
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ static BuildResult performBuild(
|
|||||||
auto drvOutput = DrvOutput { outputHash, outputName };
|
auto drvOutput = DrvOutput { outputHash, outputName };
|
||||||
successP->builtOutputs.insert_or_assign(
|
successP->builtOutputs.insert_or_assign(
|
||||||
std::move(outputName),
|
std::move(outputName),
|
||||||
Realisation { drvOutput, *outputPath });
|
Realisation { {.outPath = *outputPath}, drvOutput });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -537,12 +537,12 @@ void State::notifyBuildFinished(pqxx::work & txn, BuildID buildId,
|
|||||||
|
|
||||||
std::shared_ptr<PathLocks> State::acquireGlobalLock()
|
std::shared_ptr<PathLocks> State::acquireGlobalLock()
|
||||||
{
|
{
|
||||||
Path lockPath = hydraData + "/queue-runner/lock";
|
auto lockPath = std::filesystem::path(hydraData) / "queue-runner/lock";
|
||||||
|
|
||||||
createDirs(dirOf(lockPath));
|
createDirs(lockPath.parent_path());
|
||||||
|
|
||||||
auto lock = std::make_shared<PathLocks>();
|
auto lock = std::make_shared<PathLocks>();
|
||||||
if (!lock->lockPaths(PathSet({lockPath}), "", false)) return 0;
|
if (!lock->lockPaths({lockPath}, "", false)) return 0;
|
||||||
|
|
||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "state.hh"
|
#include "state.hh"
|
||||||
#include "hydra-build-result.hh"
|
#include "hydra-build-result.hh"
|
||||||
|
#include <nix/store/derived-path.hh>
|
||||||
#include <nix/store/globals.hh>
|
#include <nix/store/globals.hh>
|
||||||
#include <nix/store/parsed-derivations.hh>
|
#include <nix/store/parsed-derivations.hh>
|
||||||
#include <nix/util/thread-pool.hh>
|
#include <nix/util/thread-pool.hh>
|
||||||
@@ -487,24 +488,24 @@ Step::ptr State::createStep(ref<Store> destStore,
|
|||||||
it's not runnable yet, and other threads won't make it
|
it's not runnable yet, and other threads won't make it
|
||||||
runnable while step->created == false. */
|
runnable while step->created == false. */
|
||||||
step->drv = std::make_unique<Derivation>(localStore->readDerivation(drvPath));
|
step->drv = std::make_unique<Derivation>(localStore->readDerivation(drvPath));
|
||||||
{
|
DerivationOptions<nix::SingleDerivedPath> drvOptions;
|
||||||
try {
|
try {
|
||||||
step->drvOptions = std::make_unique<DerivationOptions>(
|
drvOptions = derivationOptionsFromStructuredAttrs(
|
||||||
DerivationOptions::fromStructuredAttrs(
|
*localStore,
|
||||||
step->drv->env,
|
step->drv->inputDrvs,
|
||||||
step->drv->structuredAttrs ? &*step->drv->structuredAttrs : nullptr));
|
step->drv->env,
|
||||||
} catch (Error & e) {
|
get(step->drv->structuredAttrs));
|
||||||
e.addTrace({}, "while parsing derivation '%s'", localStore->printStorePath(drvPath));
|
} catch (Error & e) {
|
||||||
throw;
|
e.addTrace({}, "while parsing derivation '%s'", localStore->printStorePath(drvPath));
|
||||||
}
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
step->preferLocalBuild = step->drvOptions->willBuildLocally(*localStore, *step->drv);
|
step->preferLocalBuild = drvOptions.willBuildLocally(*localStore, *step->drv);
|
||||||
step->isDeterministic = getOr(step->drv->env, "isDetermistic", "0") == "1";
|
step->isDeterministic = getOr(step->drv->env, "isDetermistic", "0") == "1";
|
||||||
|
|
||||||
step->systemType = step->drv->platform;
|
step->systemType = step->drv->platform;
|
||||||
{
|
{
|
||||||
StringSet features = step->requiredSystemFeatures = step->drvOptions->getRequiredSystemFeatures(*step->drv);
|
StringSet features = step->requiredSystemFeatures = drvOptions.getRequiredSystemFeatures(*step->drv);
|
||||||
if (step->preferLocalBuild)
|
if (step->preferLocalBuild)
|
||||||
features.insert("local");
|
features.insert("local");
|
||||||
if (!features.empty()) {
|
if (!features.empty()) {
|
||||||
|
|||||||
@@ -172,7 +172,6 @@ struct Step
|
|||||||
|
|
||||||
nix::StorePath drvPath;
|
nix::StorePath drvPath;
|
||||||
std::unique_ptr<nix::Derivation> drv;
|
std::unique_ptr<nix::Derivation> drv;
|
||||||
std::unique_ptr<nix::DerivationOptions> drvOptions;
|
|
||||||
nix::StringSet requiredSystemFeatures;
|
nix::StringSet requiredSystemFeatures;
|
||||||
bool preferLocalBuild;
|
bool preferLocalBuild;
|
||||||
bool isDeterministic;
|
bool isDeterministic;
|
||||||
|
|||||||
@@ -220,11 +220,11 @@ sub scmdiff : Path('/api/scmdiff') Args(0) {
|
|||||||
my $clonePath = getSCMCacheDir . "/git/" . sha256_hex($uri);
|
my $clonePath = getSCMCacheDir . "/git/" . sha256_hex($uri);
|
||||||
die if ! -d $clonePath;
|
die if ! -d $clonePath;
|
||||||
my ($stdout1, $stderr1);
|
my ($stdout1, $stderr1);
|
||||||
run3(['git', '-C', $clonePath, 'log', "$rev1..$rev2"], \undef, \$stdout1, \$stderr1);
|
run3(['git', '--git-dir', '.git', '-C', $clonePath, 'log', "$rev1..$rev2"], \undef, \$stdout1, \$stderr1);
|
||||||
$diff .= $stdout1 if $? == 0;
|
$diff .= $stdout1 if $? == 0;
|
||||||
|
|
||||||
my ($stdout2, $stderr2);
|
my ($stdout2, $stderr2);
|
||||||
run3(['git', '-C', $clonePath, 'diff', "$rev1..$rev2"], \undef, \$stdout2, \$stderr2);
|
run3(['git', '--git-dir', '.git', '-C', $clonePath, 'diff', "$rev1..$rev2"], \undef, \$stdout2, \$stderr2);
|
||||||
$diff .= $stdout2 if $? == 0;
|
$diff .= $stdout2 if $? == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,11 +106,11 @@ sub doEmailLogin {
|
|||||||
my $allowed_domains = $c->config->{allowed_domains} // ($c->config->{persona_allowed_domains} // "");
|
my $allowed_domains = $c->config->{allowed_domains} // ($c->config->{persona_allowed_domains} // "");
|
||||||
if ($allowed_domains ne "") {
|
if ($allowed_domains ne "") {
|
||||||
my $email_ok = 0;
|
my $email_ok = 0;
|
||||||
my @domains = split ',', $allowed_domains;
|
my @domains = split /,/, $allowed_domains;
|
||||||
map { $_ =~ s/^\s*(.*?)\s*$/$1/ } @domains;
|
map { $_ =~ s/^\s*(.*?)\s*$/$1/ } @domains;
|
||||||
|
|
||||||
foreach my $domain (@domains) {
|
foreach my $domain (@domains) {
|
||||||
$email_ok = $email_ok || ((split '@', $email)[1] eq $domain);
|
$email_ok = $email_ok || ((split /@/, $email)[1] eq $domain);
|
||||||
}
|
}
|
||||||
error($c, "Your email address does not belong to a domain that is allowed to log in.\n")
|
error($c, "Your email address does not belong to a domain that is allowed to log in.\n")
|
||||||
unless $email_ok;
|
unless $email_ok;
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ sub buildFinished {
|
|||||||
|
|
||||||
my $to = $build->jobset->emailoverride ne "" ? $build->jobset->emailoverride : $build->maintainers;
|
my $to = $build->jobset->emailoverride ne "" ? $build->jobset->emailoverride : $build->maintainers;
|
||||||
|
|
||||||
foreach my $address (split ",", ($to // "")) {
|
foreach my $address (split /,/, ($to // "")) {
|
||||||
$address = trim $address;
|
$address = trim $address;
|
||||||
|
|
||||||
$addresses{$address} //= { builds => [] };
|
$addresses{$address} //= { builds => [] };
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ sub _parseValue {
|
|||||||
$start_options = 2;
|
$start_options = 2;
|
||||||
}
|
}
|
||||||
foreach my $option (@parts[$start_options .. $#parts]) {
|
foreach my $option (@parts[$start_options .. $#parts]) {
|
||||||
(my $key, my $value) = split('=', $option);
|
(my $key, my $value) = split(/=/, $option);
|
||||||
$options->{$key} = $value;
|
$options->{$key} = $value;
|
||||||
}
|
}
|
||||||
return ($uri, $branch, $deepClone, $options);
|
return ($uri, $branch, $deepClone, $options);
|
||||||
@@ -265,7 +265,7 @@ sub getCommits {
|
|||||||
|
|
||||||
my $res = [];
|
my $res = [];
|
||||||
foreach my $line (split /\n/, $out) {
|
foreach my $line (split /\n/, $out) {
|
||||||
my ($revision, $author, $email, $date) = split "\t", $line;
|
my ($revision, $author, $email, $date) = split /\t/, $line;
|
||||||
push @$res, { revision => $revision, author => decode("utf-8", $author), email => $email };
|
push @$res, { revision => $revision, author => decode("utf-8", $author), email => $email };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ sub _iterate {
|
|||||||
$pulls->{$pull->{number}} = $pull;
|
$pulls->{$pull->{number}} = $pull;
|
||||||
}
|
}
|
||||||
# TODO Make Link header parsing more robust!!!
|
# TODO Make Link header parsing more robust!!!
|
||||||
my @links = split ',', ($res->header("Link") // "");
|
my @links = split /,/, ($res->header("Link") // "");
|
||||||
my $next = "";
|
my $next = "";
|
||||||
foreach my $link (@links) {
|
foreach my $link (@links) {
|
||||||
my ($url, $rel) = split ";", $link;
|
my ($url, $rel) = split /;/, $link;
|
||||||
if (trim($rel) eq 'rel="next"') {
|
if (trim($rel) eq 'rel="next"') {
|
||||||
$next = substr trim($url), 1, -1;
|
$next = substr trim($url), 1, -1;
|
||||||
last;
|
last;
|
||||||
|
|||||||
@@ -83,10 +83,10 @@ sub _iterate {
|
|||||||
$refs->{$ref_name} = $ref;
|
$refs->{$ref_name} = $ref;
|
||||||
}
|
}
|
||||||
# TODO Make Link header parsing more robust!!!
|
# TODO Make Link header parsing more robust!!!
|
||||||
my @links = split ',', $res->header("Link");
|
my @links = split /,/, $res->header("Link");
|
||||||
my $next = "";
|
my $next = "";
|
||||||
foreach my $link (@links) {
|
foreach my $link (@links) {
|
||||||
my ($url, $rel) = split ";", $link;
|
my ($url, $rel) = split /;/, $link;
|
||||||
if (trim($rel) eq 'rel="next"') {
|
if (trim($rel) eq 'rel="next"') {
|
||||||
$next = substr trim($url), 1, -1;
|
$next = substr trim($url), 1, -1;
|
||||||
last;
|
last;
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ sub _iterate {
|
|||||||
$pulls->{$pull->{iid}} = $pull;
|
$pulls->{$pull->{iid}} = $pull;
|
||||||
}
|
}
|
||||||
# TODO Make Link header parsing more robust!!!
|
# TODO Make Link header parsing more robust!!!
|
||||||
my @links = split ',', $res->header("Link");
|
my @links = split /,/, $res->header("Link");
|
||||||
my $next = "";
|
my $next = "";
|
||||||
foreach my $link (@links) {
|
foreach my $link (@links) {
|
||||||
my ($url, $rel) = split ";", $link;
|
my ($url, $rel) = split /;/, $link;
|
||||||
if (trim($rel) eq 'rel="next"') {
|
if (trim($rel) eq 'rel="next"') {
|
||||||
$next = substr trim($url), 1, -1;
|
$next = substr trim($url), 1, -1;
|
||||||
last;
|
last;
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ sub getCommits {
|
|||||||
my $res = [];
|
my $res = [];
|
||||||
foreach my $line (split /\n/, $out) {
|
foreach my $line (split /\n/, $out) {
|
||||||
if ($line ne "") {
|
if ($line ne "") {
|
||||||
my ($revision, $author, $email) = split "\t", $line;
|
my ($revision, $author, $email) = split /\t/, $line;
|
||||||
push @$res, { revision => $revision, author => $author, email => $email };
|
push @$res, { revision => $revision, author => $author, email => $email };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,19 +12,31 @@ sub supportedInputTypes {
|
|||||||
$inputTypes->{'path'} = 'Local path or URL';
|
$inputTypes->{'path'} = 'Local path or URL';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub _parseValue {
|
||||||
|
# The input is a local path or URL, optionally followed by a
|
||||||
|
# time period specified in seconds.
|
||||||
|
my ($config, $value) = @_;
|
||||||
|
my @parts = split ' ', $value;
|
||||||
|
(my $uri, my $freq) = @parts;
|
||||||
|
# By default don't check a path more often than every 30 seconds,
|
||||||
|
# but the second path argument can change that value or the global
|
||||||
|
# path_input_cache_validity_seconds configuration, in that order.
|
||||||
|
my $timeout = defined $freq ? $freq : ($config->{path_input_cache_validity_seconds} // 30);
|
||||||
|
|
||||||
|
return ($uri, $timeout);
|
||||||
|
}
|
||||||
|
|
||||||
sub fetchInput {
|
sub fetchInput {
|
||||||
my ($self, $type, $name, $value) = @_;
|
my ($self, $type, $name, $value) = @_;
|
||||||
|
|
||||||
return undef if $type ne "path";
|
return undef if $type ne "path";
|
||||||
|
|
||||||
my $uri = $value;
|
my ($uri, $timeout) = _parseValue($self->{config}, $value);
|
||||||
|
|
||||||
my $timestamp = time;
|
my $timestamp = time;
|
||||||
my $sha256;
|
my $sha256;
|
||||||
my $storePath;
|
my $storePath;
|
||||||
|
|
||||||
my $timeout = $self->{config}->{path_input_cache_validity_seconds} // 30;
|
|
||||||
|
|
||||||
# Some simple caching: don't check a path more than once every N seconds.
|
# Some simple caching: don't check a path more than once every N seconds.
|
||||||
(my $cachedInput) = $self->{db}->resultset('CachedPathInputs')->search(
|
(my $cachedInput) = $self->{db}->resultset('CachedPathInputs')->search(
|
||||||
{srcpath => $uri, lastseen => {">", $timestamp - $timeout}},
|
{srcpath => $uri, lastseen => {">", $timestamp - $timeout}},
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ sub isBuildEligibleForDynamicRunCommand {
|
|||||||
sub configSectionMatches {
|
sub configSectionMatches {
|
||||||
my ($name, $project, $jobset, $job) = @_;
|
my ($name, $project, $jobset, $job) = @_;
|
||||||
|
|
||||||
my @elems = split ':', $name;
|
my @elems = split /:/, $name;
|
||||||
|
|
||||||
die "invalid section name '$name'\n" if scalar(@elems) > 3;
|
die "invalid section name '$name'\n" if scalar(@elems) > 3;
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,11 @@ __PACKAGE__->table("jobsetevalinputs");
|
|||||||
data_type: 'text'
|
data_type: 'text'
|
||||||
is_nullable: 1
|
is_nullable: 1
|
||||||
|
|
||||||
|
=head2 shortRevLength
|
||||||
|
|
||||||
|
data_type: 'number'
|
||||||
|
is_nullable: 1
|
||||||
|
|
||||||
=head2 value
|
=head2 value
|
||||||
|
|
||||||
data_type: 'text'
|
data_type: 'text'
|
||||||
@@ -102,6 +107,8 @@ __PACKAGE__->add_columns(
|
|||||||
{ data_type => "text", is_nullable => 1 },
|
{ data_type => "text", is_nullable => 1 },
|
||||||
"revision",
|
"revision",
|
||||||
{ data_type => "text", is_nullable => 1 },
|
{ data_type => "text", is_nullable => 1 },
|
||||||
|
"shortRevLength",
|
||||||
|
{ data_type => "integer", is_nullable => 1 },
|
||||||
"value",
|
"value",
|
||||||
{ data_type => "text", is_nullable => 1 },
|
{ data_type => "text", is_nullable => 1 },
|
||||||
"dependency",
|
"dependency",
|
||||||
@@ -183,4 +190,28 @@ sub json_hint {
|
|||||||
return \%hint;
|
return \%hint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Revision to be rendered by the frontend
|
||||||
|
sub frontend_revision() {
|
||||||
|
my ($self) = @_;
|
||||||
|
my $type = $self->get_column('type');
|
||||||
|
if ($type eq 'svn' or $type eq 'svn-checkout' or $type eq 'bzr' or $type eq 'bzr-checkout') {
|
||||||
|
return 'r' . $self->get_column('revision');
|
||||||
|
} elsif ($type eq 'git') {
|
||||||
|
# Find the longest revision length of this URI
|
||||||
|
my $schema = $self->result_source->schema;
|
||||||
|
my $maxLength = $schema
|
||||||
|
->resultset('JobsetEvalInputs')
|
||||||
|
->search({ uri => $self->get_column('uri')})
|
||||||
|
->get_column('shortRevLength')
|
||||||
|
->max;
|
||||||
|
# Fall back to a fixed value if there was no value
|
||||||
|
return substr($self->get_column('revision'), 0, $maxLength || 12);
|
||||||
|
} elsif ($type eq 'bzr') {
|
||||||
|
return substr($self->get_column('revision'), 0, 12);
|
||||||
|
} else {
|
||||||
|
return $self->get_column('revision');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
@@ -347,13 +347,24 @@ BLOCK renderDiffUri;
|
|||||||
url = res.0;
|
url = res.0;
|
||||||
branch = res.1;
|
branch = res.1;
|
||||||
IF bi1.type == "hg" || bi1.type == "git" %]
|
IF bi1.type == "hg" || bi1.type == "git" %]
|
||||||
<a target="_blank" [% HTML.attributes(href => c.uri_for('/api/scmdiff', {
|
[% IF url.substr(0, 19) == "https://github.com/";
|
||||||
uri = url,
|
github_url = url.replace('\.git$', '') %]
|
||||||
rev1 = bi1.revision,
|
<a target="_blank" [% HTML.attributes(href =>
|
||||||
rev2 = bi2.revision,
|
github_url
|
||||||
type = bi1.type,
|
_ "/compare/"
|
||||||
branch = branch
|
_ bi1.revision
|
||||||
})) %]>[% HTML.escape(contents) %]</a>
|
_ "..."
|
||||||
|
_ bi2.revision,
|
||||||
|
) %]>[% HTML.escape(contents) %]</a>
|
||||||
|
[% ELSE %]
|
||||||
|
<a target="_blank" [% HTML.attributes(href => c.uri_for('/api/scmdiff', {
|
||||||
|
uri = url,
|
||||||
|
rev1 = bi1.revision,
|
||||||
|
rev2 = bi2.revision,
|
||||||
|
type = bi1.type,
|
||||||
|
branch = branch
|
||||||
|
})) %]>[% HTML.escape(contents) %]</a>
|
||||||
|
[% END %]
|
||||||
[% ELSE;
|
[% ELSE;
|
||||||
contents;
|
contents;
|
||||||
END;
|
END;
|
||||||
@@ -411,7 +422,7 @@ BLOCK renderInputDiff; %]
|
|||||||
[% ELSIF bi1.uri == bi2.uri && bi1.revision != bi2.revision %]
|
[% ELSIF bi1.uri == bi2.uri && bi1.revision != bi2.revision %]
|
||||||
[% IF bi1.type == "git" %]
|
[% IF bi1.type == "git" %]
|
||||||
<tr><td>
|
<tr><td>
|
||||||
<b>[% HTML.escape(bi1.name) %]</b></td><td><tt>[% INCLUDE renderDiffUri contents=(bi1.revision.substr(0, 12) _ ' to ' _ bi2.revision.substr(0, 12)) %]</tt>
|
<b>[% HTML.escape(bi1.name) %]</b></td><td><tt>[% INCLUDE renderDiffUri contents=(bi1.frontend_revision _ ' to ' _ bi2.frontend_revision) %]</tt>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<tr><td>
|
<tr><td>
|
||||||
@@ -452,16 +463,10 @@ BLOCK renderPager %]
|
|||||||
|
|
||||||
|
|
||||||
BLOCK renderShortEvalInput;
|
BLOCK renderShortEvalInput;
|
||||||
IF input.type == "svn" || input.type == "svn-checkout" || input.type == "bzr" || input.type == "bzr-checkout" %]
|
IF input.type == "build" || input.type == "sysbuild" %]
|
||||||
r[% input.revision %]
|
|
||||||
[% ELSIF input.type == "git" %]
|
|
||||||
<tt>[% input.revision.substr(0, 7) | html %]</tt>
|
|
||||||
[% ELSIF input.type == "hg" %]
|
|
||||||
<tt>[% input.revision.substr(0, 12) | html %]</tt>
|
|
||||||
[% ELSIF input.type == "build" || input.type == "sysbuild" %]
|
|
||||||
<a [% HTML.attributes(href => c.uri_for('/build' input.get_column('dependency'))) %]>[% HTML.escape(input.get_column('dependency')) %]</a>
|
<a [% HTML.attributes(href => c.uri_for('/build' input.get_column('dependency'))) %]>[% HTML.escape(input.get_column('dependency')) %]</a>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<tt>[% input.revision | html %]</tt>
|
<tt>[% input.frontend_revision | html %]</tt>
|
||||||
[% END;
|
[% END;
|
||||||
END;
|
END;
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ else
|
|||||||
revCount="$(cat "$tmpDir/[% input.name %]/rev-count")"
|
revCount="$(cat "$tmpDir/[% input.name %]/rev-count")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
args+=(--arg '[% input.name %]' "{ outPath = $inputDir; rev = \"[% input.revision %]\"; shortRev = \"[% input.revision.substr(0, 7) %]\"; revCount = $revCount; }")
|
args+=(--arg '[% input.name %]' "{ outPath = $inputDir; rev = \"[% input.revision %]\"; shortRev = \"[% input.frontend_revision %]\"; revCount = $revCount; }")
|
||||||
|
|
||||||
[%+ ELSIF input.type == "hg" %]
|
[%+ ELSIF input.type == "hg" %]
|
||||||
|
|
||||||
|
|||||||
@@ -891,6 +891,7 @@ sub checkJobsetWrapped {
|
|||||||
, type => $input->{type}
|
, type => $input->{type}
|
||||||
, uri => $input->{uri}
|
, uri => $input->{uri}
|
||||||
, revision => $input->{revision}
|
, revision => $input->{revision}
|
||||||
|
, shortRevLength => length($input->{shortRev})
|
||||||
, value => $input->{value}
|
, value => $input->{value}
|
||||||
, dependency => $input->{id}
|
, dependency => $input->{id}
|
||||||
, path => $input->{storePath} || "" # !!! temporary hack
|
, path => $input->{storePath} || "" # !!! temporary hack
|
||||||
|
|||||||
@@ -487,11 +487,12 @@ create table JobsetEvalInputs (
|
|||||||
altNr integer not null,
|
altNr integer not null,
|
||||||
|
|
||||||
-- Copied from the jobsetinputs from which the build was created.
|
-- Copied from the jobsetinputs from which the build was created.
|
||||||
type text not null,
|
type text not null,
|
||||||
uri text,
|
uri text,
|
||||||
revision text,
|
revision text,
|
||||||
value text,
|
shortRevLength smallint, -- length of a short revision at the time this was checked out
|
||||||
dependency integer, -- build ID of the input, for type == 'build'
|
value text,
|
||||||
|
dependency integer, -- build ID of the input, for type == 'build'
|
||||||
|
|
||||||
path text,
|
path text,
|
||||||
|
|
||||||
|
|||||||
@@ -1,90 +1,7 @@
|
|||||||
sql_files = files(
|
# Install all SQL files in this directory.
|
||||||
'hydra.sql',
|
# This includes hydra.sql, test.sql, update-dbix.pl, and all upgrade-*.sql files.
|
||||||
'test.sql',
|
install_subdir('.',
|
||||||
'update-dbix.pl',
|
install_dir: hydra_libexecdir / 'sql',
|
||||||
'upgrade-2.sql',
|
strip_directory: true,
|
||||||
'upgrade-3.sql',
|
exclude_files: ['meson.build', 'update-dbix-harness.sh'],
|
||||||
'upgrade-4.sql',
|
|
||||||
'upgrade-5.sql',
|
|
||||||
'upgrade-6.sql',
|
|
||||||
'upgrade-7.sql',
|
|
||||||
'upgrade-8.sql',
|
|
||||||
'upgrade-9.sql',
|
|
||||||
'upgrade-10.sql',
|
|
||||||
'upgrade-11.sql',
|
|
||||||
'upgrade-12.sql',
|
|
||||||
'upgrade-13.sql',
|
|
||||||
'upgrade-14.sql',
|
|
||||||
'upgrade-15.sql',
|
|
||||||
'upgrade-16.sql',
|
|
||||||
'upgrade-17.sql',
|
|
||||||
'upgrade-18.sql',
|
|
||||||
'upgrade-19.sql',
|
|
||||||
'upgrade-20.sql',
|
|
||||||
'upgrade-21.sql',
|
|
||||||
'upgrade-22.sql',
|
|
||||||
'upgrade-23.sql',
|
|
||||||
'upgrade-24.sql',
|
|
||||||
'upgrade-25.sql',
|
|
||||||
'upgrade-26.sql',
|
|
||||||
'upgrade-27.sql',
|
|
||||||
'upgrade-28.sql',
|
|
||||||
'upgrade-29.sql',
|
|
||||||
'upgrade-30.sql',
|
|
||||||
'upgrade-31.sql',
|
|
||||||
'upgrade-32.sql',
|
|
||||||
'upgrade-33.sql',
|
|
||||||
'upgrade-34.sql',
|
|
||||||
'upgrade-35.sql',
|
|
||||||
'upgrade-36.sql',
|
|
||||||
'upgrade-37.sql',
|
|
||||||
'upgrade-38.sql',
|
|
||||||
'upgrade-39.sql',
|
|
||||||
'upgrade-40.sql',
|
|
||||||
'upgrade-41.sql',
|
|
||||||
'upgrade-42.sql',
|
|
||||||
'upgrade-43.sql',
|
|
||||||
'upgrade-44.sql',
|
|
||||||
'upgrade-45.sql',
|
|
||||||
'upgrade-46.sql',
|
|
||||||
'upgrade-47.sql',
|
|
||||||
'upgrade-48.sql',
|
|
||||||
'upgrade-49.sql',
|
|
||||||
'upgrade-50.sql',
|
|
||||||
'upgrade-51.sql',
|
|
||||||
'upgrade-52.sql',
|
|
||||||
'upgrade-53.sql',
|
|
||||||
'upgrade-54.sql',
|
|
||||||
'upgrade-55.sql',
|
|
||||||
'upgrade-56.sql',
|
|
||||||
'upgrade-57.sql',
|
|
||||||
'upgrade-58.sql',
|
|
||||||
'upgrade-59.sql',
|
|
||||||
'upgrade-60.sql',
|
|
||||||
'upgrade-61.sql',
|
|
||||||
'upgrade-62.sql',
|
|
||||||
'upgrade-63.sql',
|
|
||||||
'upgrade-64.sql',
|
|
||||||
'upgrade-65.sql',
|
|
||||||
'upgrade-66.sql',
|
|
||||||
'upgrade-67.sql',
|
|
||||||
'upgrade-68.sql',
|
|
||||||
'upgrade-69.sql',
|
|
||||||
'upgrade-70.sql',
|
|
||||||
'upgrade-71.sql',
|
|
||||||
'upgrade-72.sql',
|
|
||||||
'upgrade-73.sql',
|
|
||||||
'upgrade-74.sql',
|
|
||||||
'upgrade-75.sql',
|
|
||||||
'upgrade-76.sql',
|
|
||||||
'upgrade-77.sql',
|
|
||||||
'upgrade-78.sql',
|
|
||||||
'upgrade-79.sql',
|
|
||||||
'upgrade-80.sql',
|
|
||||||
'upgrade-81.sql',
|
|
||||||
'upgrade-82.sql',
|
|
||||||
'upgrade-83.sql',
|
|
||||||
'upgrade-84.sql',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
install_data(sql_files, install_dir: hydra_libexecdir / 'sql')
|
|
||||||
|
|||||||
1
src/sql/upgrade-85.sql
Normal file
1
src/sql/upgrade-85.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE JobsetEvalInputs ADD COLUMN shortRevLength smallint;
|
||||||
@@ -109,7 +109,7 @@ subtest "Build: not substitutable, unsubstitutable" => sub {
|
|||||||
subtest "Second notification: step_finished" => sub {
|
subtest "Second notification: step_finished" => sub {
|
||||||
my ($channelName, $pid, $payload) = @{$dbh->func("pg_notifies")};
|
my ($channelName, $pid, $payload) = @{$dbh->func("pg_notifies")};
|
||||||
is($channelName, "step_finished", "The event is for the step finishing");
|
is($channelName, "step_finished", "The event is for the step finishing");
|
||||||
my ($buildId, $stepNr, $logFile) = split "\t", $payload;
|
my ($buildId, $stepNr, $logFile) = split /\t/, $payload;
|
||||||
is($buildId, $build->id, "The payload is the build's ID");
|
is($buildId, $build->id, "The payload is the build's ID");
|
||||||
is($stepNr, 1, "The payload is the build's step number");
|
is($stepNr, 1, "The payload is the build's step number");
|
||||||
isnt($logFile, undef, "The log file is passed");
|
isnt($logFile, undef, "The log file is passed");
|
||||||
|
|||||||
Reference in New Issue
Block a user