Compare commits
61 Commits
nix-2.30
...
update-fla
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83a864607c | ||
|
|
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 | ||
|
|
a31f5d654c | ||
|
|
6659391e26 | ||
|
|
3b901f19a4 | ||
|
|
673e18415e | ||
|
|
13ddeeb08c | ||
|
|
ed15b0a8ce | ||
|
|
f1b26134d7 | ||
|
|
425d78763d | ||
|
|
53d8e26b59 | ||
|
|
a439b7f591 | ||
|
|
7d12fa6a55 | ||
|
|
7a67ba925d | ||
|
|
662d1198d4 | ||
|
|
34ff66a460 | ||
|
|
7a42a3810c | ||
|
|
3bd87005f7 | ||
|
|
95fb69f60d | ||
|
|
241ab71800 | ||
|
|
78ed8d7aa5 | ||
|
|
4bd941daa8 | ||
|
|
0414ae64eb | ||
|
|
449791b1c7 | ||
|
|
d7b40c4233 | ||
|
|
524b232032 | ||
|
|
58846b0a1c | ||
|
|
f1463d4bce | ||
|
|
94eaad22bc | ||
|
|
a499063834 | ||
|
|
7fa3da755e | ||
|
|
c6263c280c | ||
|
|
4a0c5a2570 | ||
|
|
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
|
||||
runs-on: ${{ matrix.runner }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- 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
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v6
|
||||
- uses: cachix/install-nix-action@v31
|
||||
- name: Update flake inputs
|
||||
run: nix flake update
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
commit-message: "flake.lock: Update"
|
||||
title: "Update flake inputs"
|
||||
|
||||
23
flake.lock
generated
23
flake.lock
generated
@@ -3,16 +3,16 @@
|
||||
"nix": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1758562014,
|
||||
"narHash": "sha256-IazqNpt3jNldKy+rivmlGuo9pC1IczV0Xjk5+5EQEzQ=",
|
||||
"lastModified": 1772065213,
|
||||
"narHash": "sha256-DbYpmZAD6aebwxepBop5Ub4S39sLg9UIJziTbeD832k=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nix",
|
||||
"rev": "f2b45e014b909bb5e6a9f99a8a511deed3b3e2a4",
|
||||
"rev": "0769726d44b0782fecbd7b9749e24320c77af317",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "2.30-maintenance",
|
||||
"ref": "2.33-maintenance",
|
||||
"repo": "nix",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -20,31 +20,32 @@
|
||||
"nix-eval-jobs": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1752066681,
|
||||
"narHash": "sha256-e10zYtdc5nDHs2iLf/h92+uW5WOUZGqohfaU919B/TI=",
|
||||
"lastModified": 1767025318,
|
||||
"narHash": "sha256-i68miKHGdueWggcDAF+Kca9g6S3ipkW629XbMpQYfn0=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-eval-jobs",
|
||||
"rev": "fae2b990f19c10b7d5718b6eff1df30188ca780e",
|
||||
"rev": "79dd7adbb5f75b08fb4b9bddd712ebc52baa46bc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "v2.33.0",
|
||||
"repo": "nix-eval-jobs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1759652726,
|
||||
"narHash": "sha256-2VjnimOYDRb3DZHyQ2WH2KCouFqYm9h0Rr007Al/WSA=",
|
||||
"lastModified": 1772934839,
|
||||
"narHash": "sha256-6mMYkB7BTTsc4thtCFbh3Aj5yth3EPI6L9L5DR6tpWc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "06b2985f0cc9eb4318bf607168f4b15af1e5e81d",
|
||||
"rev": "d351a3bce30b8f0d0a36281754b62942977fabe5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-25.05-small",
|
||||
"ref": "nixos-25.11-small",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
{
|
||||
description = "A Nix-based continuous build system";
|
||||
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05-small";
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11-small";
|
||||
|
||||
inputs.nix = {
|
||||
url = "github:NixOS/nix/2.30-maintenance";
|
||||
url = "github:NixOS/nix/2.33-maintenance";
|
||||
# We want to control the deps precisely
|
||||
flake = false;
|
||||
};
|
||||
|
||||
inputs.nix-eval-jobs = {
|
||||
url = "github:nix-community/nix-eval-jobs";
|
||||
url = "github:nix-community/nix-eval-jobs/v2.33.0";
|
||||
# We want to control the deps precisely
|
||||
flake = false;
|
||||
};
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
manual = forEachSystem (system: let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
hydra = self.packages.${pkgs.hostPlatform.system}.hydra;
|
||||
hydra = self.packages.${pkgs.stdenv.hostPlatform.system}.hydra;
|
||||
in
|
||||
pkgs.runCommand "hydra-manual-${hydra.version}" { }
|
||||
''
|
||||
|
||||
125
hydra-api.yaml
125
hydra-api.yaml
@@ -574,6 +574,131 @@ paths:
|
||||
schema:
|
||||
$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:
|
||||
schemas:
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ project('hydra', 'cpp',
|
||||
default_options: [
|
||||
'debug=true',
|
||||
'optimization=2',
|
||||
'cpp_std=c++20',
|
||||
'cpp_std=c++23',
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
hydra = { pkgs, lib,... }: {
|
||||
_file = ./default.nix;
|
||||
imports = [ ./hydra.nix ];
|
||||
services.hydra-dev.package = lib.mkDefault self.packages.${pkgs.hostPlatform.system}.hydra;
|
||||
services.hydra-dev.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.hydra;
|
||||
};
|
||||
|
||||
hydraTest = { pkgs, ... }: {
|
||||
|
||||
@@ -364,7 +364,7 @@ in
|
||||
requires = [ "hydra-init.service" ];
|
||||
restartTriggers = [ hydraConf ];
|
||||
after = [ "hydra-init.service" "network.target" ];
|
||||
path = with pkgs; [ hostname-debian cfg.package jq ];
|
||||
path = with pkgs; [ hostname-debian cfg.package ];
|
||||
environment = env // {
|
||||
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-evaluator";
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
, perl
|
||||
, pixz
|
||||
, boost
|
||||
, postgresql_13
|
||||
, postgresql_17
|
||||
, nlohmann_json
|
||||
, prometheus-cpp
|
||||
|
||||
@@ -192,7 +192,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
subversion
|
||||
breezy
|
||||
openldap
|
||||
postgresql_13
|
||||
postgresql_17
|
||||
pixz
|
||||
nix-eval-jobs
|
||||
];
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <nix/util/current-process.hh>
|
||||
#include <nix/util/processes.hh>
|
||||
#include <nix/util/util.hh>
|
||||
#include <nix/store/export-import.hh>
|
||||
#include <nix/store/serve-protocol.hh>
|
||||
#include <nix/store/serve-protocol-impl.hh>
|
||||
#include <nix/store/ssh.hh>
|
||||
@@ -104,7 +105,7 @@ static void copyClosureTo(
|
||||
std::chrono::seconds(600));
|
||||
|
||||
conn.to << ServeProto::Command::ImportPaths;
|
||||
destStore.exportPaths(missing, conn.to);
|
||||
exportPaths(destStore, missing, conn.to);
|
||||
conn.to.flush();
|
||||
|
||||
if (readInt(conn.from) != 1)
|
||||
@@ -262,16 +263,18 @@ static BuildResult performBuild(
|
||||
// Since this a `BasicDerivation`, `staticOutputHashes` will not
|
||||
// do any real work.
|
||||
auto outputHashes = staticOutputHashes(localStore, drv);
|
||||
for (auto & [outputName, output] : drvOutputs) {
|
||||
auto outputPath = output.second;
|
||||
// We’ve just asserted that the output paths of the derivation
|
||||
// were known
|
||||
assert(outputPath);
|
||||
auto outputHash = outputHashes.at(outputName);
|
||||
auto drvOutput = DrvOutput { outputHash, outputName };
|
||||
result.builtOutputs.insert_or_assign(
|
||||
std::move(outputName),
|
||||
Realisation { drvOutput, *outputPath });
|
||||
if (auto * successP = result.tryGetSuccess()) {
|
||||
for (auto & [outputName, output] : drvOutputs) {
|
||||
auto outputPath = output.second;
|
||||
// We’ve just asserted that the output paths of the derivation
|
||||
// were known
|
||||
assert(outputPath);
|
||||
auto outputHash = outputHashes.at(outputName);
|
||||
auto drvOutput = DrvOutput { outputHash, outputName };
|
||||
successP->builtOutputs.insert_or_assign(
|
||||
std::move(outputName),
|
||||
Realisation { {.outPath = *outputPath}, drvOutput });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,54 +339,68 @@ void RemoteResult::updateWithBuildResult(const nix::BuildResult & buildResult)
|
||||
startTime = buildResult.startTime;
|
||||
stopTime = buildResult.stopTime;
|
||||
timesBuilt = buildResult.timesBuilt;
|
||||
errorMsg = buildResult.errorMsg;
|
||||
isNonDeterministic = buildResult.isNonDeterministic;
|
||||
|
||||
switch ((BuildResult::Status) buildResult.status) {
|
||||
case BuildResult::Built:
|
||||
std::visit(overloaded{
|
||||
[&](const BuildResult::Success & success) {
|
||||
stepStatus = bsSuccess;
|
||||
break;
|
||||
case BuildResult::Substituted:
|
||||
case BuildResult::AlreadyValid:
|
||||
stepStatus = bsSuccess;
|
||||
isCached = true;
|
||||
break;
|
||||
case BuildResult::PermanentFailure:
|
||||
stepStatus = bsFailed;
|
||||
canCache = true;
|
||||
errorMsg = "";
|
||||
break;
|
||||
case BuildResult::InputRejected:
|
||||
case BuildResult::OutputRejected:
|
||||
stepStatus = bsFailed;
|
||||
canCache = true;
|
||||
break;
|
||||
case BuildResult::TransientFailure:
|
||||
stepStatus = bsFailed;
|
||||
canRetry = true;
|
||||
errorMsg = "";
|
||||
break;
|
||||
case BuildResult::TimedOut:
|
||||
stepStatus = bsTimedOut;
|
||||
errorMsg = "";
|
||||
break;
|
||||
case BuildResult::MiscFailure:
|
||||
stepStatus = bsAborted;
|
||||
canRetry = true;
|
||||
break;
|
||||
case BuildResult::LogLimitExceeded:
|
||||
stepStatus = bsLogLimitExceeded;
|
||||
break;
|
||||
case BuildResult::NotDeterministic:
|
||||
stepStatus = bsNotDeterministic;
|
||||
canRetry = false;
|
||||
canCache = true;
|
||||
break;
|
||||
default:
|
||||
stepStatus = bsAborted;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (success.status) {
|
||||
case BuildResult::Success::Built:
|
||||
break;
|
||||
case BuildResult::Success::Substituted:
|
||||
case BuildResult::Success::AlreadyValid:
|
||||
case BuildResult::Success::ResolvesToAlreadyValid:
|
||||
isCached = true;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
},
|
||||
[&](const BuildResult::Failure & failure) {
|
||||
errorMsg = failure.errorMsg;
|
||||
isNonDeterministic = failure.isNonDeterministic;
|
||||
switch (failure.status) {
|
||||
case BuildResult::Failure::PermanentFailure:
|
||||
stepStatus = bsFailed;
|
||||
canCache = true;
|
||||
errorMsg = "";
|
||||
break;
|
||||
case BuildResult::Failure::InputRejected:
|
||||
case BuildResult::Failure::OutputRejected:
|
||||
stepStatus = bsFailed;
|
||||
canCache = true;
|
||||
break;
|
||||
case BuildResult::Failure::TransientFailure:
|
||||
stepStatus = bsFailed;
|
||||
canRetry = true;
|
||||
errorMsg = "";
|
||||
break;
|
||||
case BuildResult::Failure::TimedOut:
|
||||
stepStatus = bsTimedOut;
|
||||
errorMsg = "";
|
||||
break;
|
||||
case BuildResult::Failure::MiscFailure:
|
||||
stepStatus = bsAborted;
|
||||
canRetry = true;
|
||||
break;
|
||||
case BuildResult::Failure::LogLimitExceeded:
|
||||
stepStatus = bsLogLimitExceeded;
|
||||
break;
|
||||
case BuildResult::Failure::NotDeterministic:
|
||||
stepStatus = bsNotDeterministic;
|
||||
canRetry = false;
|
||||
canCache = true;
|
||||
break;
|
||||
case BuildResult::Failure::CachedFailure:
|
||||
case BuildResult::Failure::DependencyFailed:
|
||||
case BuildResult::Failure::NoSubstituters:
|
||||
case BuildResult::Failure::HashMismatch:
|
||||
stepStatus = bsAborted;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
},
|
||||
}, buildResult.inner);
|
||||
}
|
||||
|
||||
/* Utility guard object to auto-release a semaphore on destruction. */
|
||||
@@ -405,7 +422,7 @@ void State::buildRemote(ref<Store> destStore,
|
||||
std::function<void(StepState)> updateStep,
|
||||
NarMemberDatas & narMembers)
|
||||
{
|
||||
assert(BuildResult::TimedOut == 8);
|
||||
assert(BuildResult::Failure::TimedOut == 8);
|
||||
|
||||
auto [logFile, logFD] = build_remote::openLogFile(logDir, step->drvPath);
|
||||
AutoDelete logFileDel(logFile, false);
|
||||
@@ -514,7 +531,7 @@ void State::buildRemote(ref<Store> destStore,
|
||||
|
||||
updateStep(ssBuilding);
|
||||
|
||||
BuildResult buildResult = build_remote::performBuild(
|
||||
auto buildResult = build_remote::performBuild(
|
||||
conn,
|
||||
*localStore,
|
||||
step->drvPath,
|
||||
@@ -556,8 +573,9 @@ void State::buildRemote(ref<Store> destStore,
|
||||
wakeDispatcher();
|
||||
|
||||
StorePathSet outputs;
|
||||
for (auto & [_, realisation] : buildResult.builtOutputs)
|
||||
outputs.insert(realisation.outPath);
|
||||
if (auto * successP = buildResult.tryGetSuccess())
|
||||
for (auto & [_, realisation] : successP->builtOutputs)
|
||||
outputs.insert(realisation.outPath);
|
||||
|
||||
/* Copy the output paths. */
|
||||
if (!machine->isLocalhost() || localStore != std::shared_ptr<Store>(destStore)) {
|
||||
@@ -590,15 +608,17 @@ void State::buildRemote(ref<Store> destStore,
|
||||
/* Register the outputs of the newly built drv */
|
||||
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) {
|
||||
auto outputHashes = staticOutputHashes(*localStore, *step->drv);
|
||||
for (auto & [outputName, realisation] : buildResult.builtOutputs) {
|
||||
// Register the resolved drv output
|
||||
destStore->registerDrvOutput(realisation);
|
||||
if (auto * successP = buildResult.tryGetSuccess()) {
|
||||
for (auto & [outputName, realisation] : successP->builtOutputs) {
|
||||
// Register the resolved drv output
|
||||
destStore->registerDrvOutput(realisation);
|
||||
|
||||
// Also register the unresolved one
|
||||
auto unresolvedRealisation = realisation;
|
||||
unresolvedRealisation.signatures.clear();
|
||||
unresolvedRealisation.id.drvHash = outputHashes.at(outputName);
|
||||
destStore->registerDrvOutput(unresolvedRealisation);
|
||||
// Also register the unresolved one
|
||||
auto unresolvedRealisation = realisation;
|
||||
unresolvedRealisation.signatures.clear();
|
||||
unresolvedRealisation.id.drvHash = outputHashes.at(outputName);
|
||||
destStore->registerDrvOutput(unresolvedRealisation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -537,12 +537,12 @@ void State::notifyBuildFinished(pqxx::work & txn, BuildID buildId,
|
||||
|
||||
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>();
|
||||
if (!lock->lockPaths(PathSet({lockPath}), "", false)) return 0;
|
||||
if (!lock->lockPaths({lockPath}, "", false)) return 0;
|
||||
|
||||
return lock;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "state.hh"
|
||||
#include "hydra-build-result.hh"
|
||||
#include <nix/store/derived-path.hh>
|
||||
#include <nix/store/globals.hh>
|
||||
#include <nix/store/parsed-derivations.hh>
|
||||
#include <nix/util/thread-pool.hh>
|
||||
@@ -487,23 +488,24 @@ Step::ptr State::createStep(ref<Store> destStore,
|
||||
it's not runnable yet, and other threads won't make it
|
||||
runnable while step->created == false. */
|
||||
step->drv = std::make_unique<Derivation>(localStore->readDerivation(drvPath));
|
||||
{
|
||||
auto parsedOpt = StructuredAttrs::tryParse(step->drv->env);
|
||||
try {
|
||||
step->drvOptions = std::make_unique<DerivationOptions>(
|
||||
DerivationOptions::fromStructuredAttrs(step->drv->env, parsedOpt ? &*parsedOpt : nullptr));
|
||||
} catch (Error & e) {
|
||||
e.addTrace({}, "while parsing derivation '%s'", localStore->printStorePath(drvPath));
|
||||
throw;
|
||||
}
|
||||
DerivationOptions<nix::SingleDerivedPath> drvOptions;
|
||||
try {
|
||||
drvOptions = derivationOptionsFromStructuredAttrs(
|
||||
*localStore,
|
||||
step->drv->inputDrvs,
|
||||
step->drv->env,
|
||||
get(step->drv->structuredAttrs));
|
||||
} catch (Error & e) {
|
||||
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->systemType = step->drv->platform;
|
||||
{
|
||||
StringSet features = step->requiredSystemFeatures = step->drvOptions->getRequiredSystemFeatures(*step->drv);
|
||||
StringSet features = step->requiredSystemFeatures = drvOptions.getRequiredSystemFeatures(*step->drv);
|
||||
if (step->preferLocalBuild)
|
||||
features.insert("local");
|
||||
if (!features.empty()) {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <nix/store/serve-protocol-impl.hh>
|
||||
#include <nix/store/serve-protocol-connection.hh>
|
||||
#include <nix/store/machines.hh>
|
||||
#include <nix/store/globals.hh>
|
||||
|
||||
|
||||
typedef unsigned int BuildID;
|
||||
@@ -171,7 +172,6 @@ struct Step
|
||||
|
||||
nix::StorePath drvPath;
|
||||
std::unique_ptr<nix::Derivation> drv;
|
||||
std::unique_ptr<nix::DerivationOptions> drvOptions;
|
||||
nix::StringSet requiredSystemFeatures;
|
||||
bool preferLocalBuild;
|
||||
bool isDeterministic;
|
||||
|
||||
@@ -220,11 +220,11 @@ sub scmdiff : Path('/api/scmdiff') Args(0) {
|
||||
my $clonePath = getSCMCacheDir . "/git/" . sha256_hex($uri);
|
||||
die if ! -d $clonePath;
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,11 +106,11 @@ sub doEmailLogin {
|
||||
my $allowed_domains = $c->config->{allowed_domains} // ($c->config->{persona_allowed_domains} // "");
|
||||
if ($allowed_domains ne "") {
|
||||
my $email_ok = 0;
|
||||
my @domains = split ',', $allowed_domains;
|
||||
my @domains = split /,/, $allowed_domains;
|
||||
map { $_ =~ s/^\s*(.*?)\s*$/$1/ } @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")
|
||||
unless $email_ok;
|
||||
|
||||
@@ -10,7 +10,6 @@ use Hydra::Helper::CatalystUtils;
|
||||
use Hydra::Helper::Nix;
|
||||
use File::Temp;
|
||||
use POSIX qw(strftime);
|
||||
use IPC::Run qw(run);
|
||||
|
||||
sub supportedInputTypes {
|
||||
my ($self, $inputTypes) = @_;
|
||||
@@ -45,12 +44,11 @@ sub fetchInput {
|
||||
my $ua = LWP::UserAgent->new();
|
||||
_iterate("https://api.bitbucket.com/2.0/repositories/$owner/$repo/pullrequests?state=OPEN", $auth, \%pulls, $ua);
|
||||
my $tempdir = File::Temp->newdir("bitbucket-pulls" . "XXXXX", TMPDIR => 1);
|
||||
my $filename = "$tempdir/bitbucket-pulls.json";
|
||||
my $filename = "$tempdir/bitbucket-pulls-sorted.json";
|
||||
open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!";
|
||||
print $fh encode_json \%pulls;
|
||||
print $fh JSON::MaybeXS->new(canonical => 1, pretty => 1)->encode(\%pulls);
|
||||
close $fh;
|
||||
run(["jq", "-S", "."], '<', $filename, '>', "$tempdir/bitbucket-pulls-sorted.json") or die "jq command failed: $?";
|
||||
my $storePath = addToStore("$tempdir/bitbucket-pulls-sorted.json");
|
||||
my $storePath = addToStore($filename);
|
||||
my $timestamp = time;
|
||||
return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) };
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ sub buildFinished {
|
||||
|
||||
my $to = $build->jobset->emailoverride ne "" ? $build->jobset->emailoverride : $build->maintainers;
|
||||
|
||||
foreach my $address (split ",", ($to // "")) {
|
||||
foreach my $address (split /,/, ($to // "")) {
|
||||
$address = trim $address;
|
||||
|
||||
$addresses{$address} //= { builds => [] };
|
||||
|
||||
@@ -38,7 +38,7 @@ sub _parseValue {
|
||||
$start_options = 2;
|
||||
}
|
||||
foreach my $option (@parts[$start_options .. $#parts]) {
|
||||
(my $key, my $value) = split('=', $option);
|
||||
(my $key, my $value) = split(/=/, $option);
|
||||
$options->{$key} = $value;
|
||||
}
|
||||
return ($uri, $branch, $deepClone, $options);
|
||||
@@ -265,7 +265,7 @@ sub getCommits {
|
||||
|
||||
my $res = [];
|
||||
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 };
|
||||
}
|
||||
|
||||
|
||||
@@ -63,9 +63,9 @@ sub common {
|
||||
my $accessToken = $self->{config}->{gitea_authorization}->{$repoOwner};
|
||||
|
||||
my $rev = $i->revision;
|
||||
my $domain = URI->new($i->uri)->host;
|
||||
my $host;
|
||||
unless (defined $gitea_url) {
|
||||
my $domain = URI->new($i->uri)->host;
|
||||
$host = "https://$domain";
|
||||
} else {
|
||||
$host = $gitea_url->value;
|
||||
|
||||
@@ -31,10 +31,10 @@ sub _iterate {
|
||||
$pulls->{$pull->{number}} = $pull;
|
||||
}
|
||||
# TODO Make Link header parsing more robust!!!
|
||||
my @links = split ',', ($res->header("Link") // "");
|
||||
my @links = split /,/, ($res->header("Link") // "");
|
||||
my $next = "";
|
||||
foreach my $link (@links) {
|
||||
my ($url, $rel) = split ";", $link;
|
||||
my ($url, $rel) = split /;/, $link;
|
||||
if (trim($rel) eq 'rel="next"') {
|
||||
$next = substr trim($url), 1, -1;
|
||||
last;
|
||||
|
||||
@@ -10,7 +10,6 @@ use Hydra::Helper::CatalystUtils;
|
||||
use Hydra::Helper::Nix;
|
||||
use File::Temp;
|
||||
use POSIX qw(strftime);
|
||||
use IPC::Run qw(run);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
@@ -19,9 +18,8 @@ tags) from GitHub following a certain naming scheme
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This plugin reads the list of branches or tags using GitHub's REST API. The name
|
||||
of the reference must follow a particular prefix. This list is stored in the
|
||||
nix-store and used as an input to declarative jobsets.
|
||||
This plugin reads the list of branches or tags using GitHub's REST API. This
|
||||
list is stored in the nix-store and used as an input to declarative jobsets.
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
@@ -35,7 +33,7 @@ The declarative project C<spec.json> file must contains an input such as
|
||||
|
||||
"pulls": {
|
||||
"type": "github_refs",
|
||||
"value": "[owner] [repo] heads|tags - [prefix]",
|
||||
"value": "[owner] [repo] [type] - [prefix]",
|
||||
"emailresponsible": false
|
||||
}
|
||||
|
||||
@@ -43,12 +41,11 @@ In the above snippet, C<[owner]> is the repository owner and C<[repo]> is the
|
||||
repository name. Also note a literal C<->, which is placed there for the future
|
||||
use.
|
||||
|
||||
C<heads|tags> denotes that one of these two is allowed, that is, the third
|
||||
position should hold either the C<heads> or the C<tags> keyword. In case of the former, the plugin
|
||||
will fetch all branches, while in case of the latter, it will fetch the tags.
|
||||
C<[type]> is the type of ref to list. Typical values are "heads", "tags", and
|
||||
"pull". "." will include all types.
|
||||
|
||||
C<prefix> denotes the prefix the reference name must start with, in order to be
|
||||
included.
|
||||
included. "." will include all references.
|
||||
|
||||
For example, C<"value": "nixos hydra heads - release/"> refers to
|
||||
L<https://github.com/nixos/hydra> repository, and will fetch all branches that
|
||||
@@ -86,10 +83,10 @@ sub _iterate {
|
||||
$refs->{$ref_name} = $ref;
|
||||
}
|
||||
# TODO Make Link header parsing more robust!!!
|
||||
my @links = split ',', $res->header("Link");
|
||||
my @links = split /,/, $res->header("Link");
|
||||
my $next = "";
|
||||
foreach my $link (@links) {
|
||||
my ($url, $rel) = split ";", $link;
|
||||
my ($url, $rel) = split /;/, $link;
|
||||
if (trim($rel) eq 'rel="next"') {
|
||||
$next = substr trim($url), 1, -1;
|
||||
last;
|
||||
@@ -103,8 +100,6 @@ sub fetchInput {
|
||||
return undef if $input_type ne "github_refs";
|
||||
|
||||
my ($owner, $repo, $type, $fut, $prefix) = split ' ', $value;
|
||||
die "type field is neither 'heads' nor 'tags', but '$type'"
|
||||
unless $type eq 'heads' or $type eq 'tags';
|
||||
|
||||
my $auth = $self->{config}->{github_authorization}->{$owner};
|
||||
my $githubEndpoint = $self->{config}->{github_endpoint} // "https://api.github.com";
|
||||
@@ -112,12 +107,11 @@ sub fetchInput {
|
||||
my $ua = LWP::UserAgent->new();
|
||||
_iterate("$githubEndpoint/repos/$owner/$repo/git/matching-refs/$type/$prefix?per_page=100", $auth, \%refs, $ua);
|
||||
my $tempdir = File::Temp->newdir("github-refs" . "XXXXX", TMPDIR => 1);
|
||||
my $filename = "$tempdir/github-refs.json";
|
||||
my $filename = "$tempdir/github-refs-sorted.json";
|
||||
open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!";
|
||||
print $fh encode_json \%refs;
|
||||
print $fh JSON::MaybeXS->new(canonical => 1, pretty => 1)->encode(\%refs);
|
||||
close $fh;
|
||||
run(["jq", "-S", "."], '<', $filename, '>', "$tempdir/github-refs-sorted.json") or die "jq command failed: $?";
|
||||
my $storePath = addToStore("$tempdir/github-refs-sorted.json");
|
||||
my $storePath = addToStore($filename);
|
||||
my $timestamp = time;
|
||||
return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) };
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ use Hydra::Helper::CatalystUtils;
|
||||
use Hydra::Helper::Nix;
|
||||
use File::Temp;
|
||||
use POSIX qw(strftime);
|
||||
use IPC::Run qw(run);
|
||||
|
||||
sub supportedInputTypes {
|
||||
my ($self, $inputTypes) = @_;
|
||||
@@ -50,10 +49,10 @@ sub _iterate {
|
||||
$pulls->{$pull->{iid}} = $pull;
|
||||
}
|
||||
# TODO Make Link header parsing more robust!!!
|
||||
my @links = split ',', $res->header("Link");
|
||||
my @links = split /,/, $res->header("Link");
|
||||
my $next = "";
|
||||
foreach my $link (@links) {
|
||||
my ($url, $rel) = split ";", $link;
|
||||
my ($url, $rel) = split /;/, $link;
|
||||
if (trim($rel) eq 'rel="next"') {
|
||||
$next = substr trim($url), 1, -1;
|
||||
last;
|
||||
@@ -83,12 +82,11 @@ sub fetchInput {
|
||||
_iterate($url, $baseUrl, \%pulls, $ua, $target_repo_url);
|
||||
|
||||
my $tempdir = File::Temp->newdir("gitlab-pulls" . "XXXXX", TMPDIR => 1);
|
||||
my $filename = "$tempdir/gitlab-pulls.json";
|
||||
my $filename = "$tempdir/gitlab-pulls-sorted.json";
|
||||
open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!";
|
||||
print $fh encode_json \%pulls;
|
||||
print $fh JSON::MaybeXS->new(canonical => 1, pretty => 1, utf8 => 1)->encode(\%pulls);
|
||||
close $fh;
|
||||
run(["jq", "-S", "."], '<', $filename, '>', "$tempdir/gitlab-pulls-sorted.json") or die "jq command failed: $?";
|
||||
my $storePath = addToStore("$tempdir/gitlab-pulls-sorted.json");
|
||||
my $storePath = addToStore($filename);
|
||||
my $timestamp = time;
|
||||
return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) };
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ sub getCommits {
|
||||
my $res = [];
|
||||
foreach my $line (split /\n/, $out) {
|
||||
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 };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,19 +12,31 @@ sub supportedInputTypes {
|
||||
$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 {
|
||||
my ($self, $type, $name, $value) = @_;
|
||||
|
||||
return undef if $type ne "path";
|
||||
|
||||
my $uri = $value;
|
||||
my ($uri, $timeout) = _parseValue($self->{config}, $value);
|
||||
|
||||
my $timestamp = time;
|
||||
my $sha256;
|
||||
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.
|
||||
(my $cachedInput) = $self->{db}->resultset('CachedPathInputs')->search(
|
||||
{srcpath => $uri, lastseen => {">", $timestamp - $timeout}},
|
||||
|
||||
@@ -85,7 +85,7 @@ sub isBuildEligibleForDynamicRunCommand {
|
||||
sub configSectionMatches {
|
||||
my ($name, $project, $jobset, $job) = @_;
|
||||
|
||||
my @elems = split ':', $name;
|
||||
my @elems = split /:/, $name;
|
||||
|
||||
die "invalid section name '$name'\n" if scalar(@elems) > 3;
|
||||
|
||||
|
||||
@@ -563,7 +563,7 @@ makeQueries('', "");
|
||||
makeQueries('ForProject', "and jobset_id in (select id from jobsets j where j.project = ?)");
|
||||
makeQueries('ForJobset', "and jobset_id = ?");
|
||||
makeQueries('ForJob', "and jobset_id = ? and job = ?");
|
||||
makeQueries('ForJobName', "and jobset_id = (select id from jobsets j where j.name = ?) and job = ?");
|
||||
makeQueries('ForJobName', "and jobset_id = (select id from jobsets j where j.project = ? and j.name = ?) and job = ?");
|
||||
|
||||
sub as_json {
|
||||
my ($self) = @_;
|
||||
|
||||
@@ -66,6 +66,11 @@ __PACKAGE__->table("jobsetevalinputs");
|
||||
data_type: 'text'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 shortRevLength
|
||||
|
||||
data_type: 'number'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 value
|
||||
|
||||
data_type: 'text'
|
||||
@@ -102,6 +107,8 @@ __PACKAGE__->add_columns(
|
||||
{ data_type => "text", is_nullable => 1 },
|
||||
"revision",
|
||||
{ data_type => "text", is_nullable => 1 },
|
||||
"shortRevLength",
|
||||
{ data_type => "integer", is_nullable => 1 },
|
||||
"value",
|
||||
{ data_type => "text", is_nullable => 1 },
|
||||
"dependency",
|
||||
@@ -183,4 +190,28 @@ sub json_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;
|
||||
|
||||
@@ -568,7 +568,7 @@ END;
|
||||
running the following command:</p>
|
||||
|
||||
<div class="card bg-light"><div class="card-body p-2"><code>
|
||||
<span class="shell-prompt"># </span>nix build [% HTML.escape(eval.flake) %]#hydraJobs.[% HTML.escape(job) %]
|
||||
<span class="shell-prompt"># </span>nix build '[% HTML.escape(eval.flake) %]#hydraJobs.[% HTML.escape(job) %]'
|
||||
</code></div></div>
|
||||
|
||||
[% ELSE %]
|
||||
|
||||
@@ -347,13 +347,24 @@ BLOCK renderDiffUri;
|
||||
url = res.0;
|
||||
branch = res.1;
|
||||
IF bi1.type == "hg" || bi1.type == "git" %]
|
||||
<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>
|
||||
[% IF url.substr(0, 19) == "https://github.com/";
|
||||
github_url = url.replace('\.git$', '') %]
|
||||
<a target="_blank" [% HTML.attributes(href =>
|
||||
github_url
|
||||
_ "/compare/"
|
||||
_ bi1.revision
|
||||
_ "..."
|
||||
_ 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;
|
||||
contents;
|
||||
END;
|
||||
@@ -411,7 +422,7 @@ BLOCK renderInputDiff; %]
|
||||
[% ELSIF bi1.uri == bi2.uri && bi1.revision != bi2.revision %]
|
||||
[% IF bi1.type == "git" %]
|
||||
<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>
|
||||
[% ELSE %]
|
||||
<tr><td>
|
||||
@@ -452,16 +463,10 @@ BLOCK renderPager %]
|
||||
|
||||
|
||||
BLOCK renderShortEvalInput;
|
||||
IF input.type == "svn" || input.type == "svn-checkout" || input.type == "bzr" || input.type == "bzr-checkout" %]
|
||||
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" %]
|
||||
IF 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>
|
||||
[% ELSE %]
|
||||
<tt>[% input.revision | html %]</tt>
|
||||
<tt>[% input.frontend_revision | html %]</tt>
|
||||
[% END;
|
||||
END;
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
[% INCLUDE includeFlot %]
|
||||
|
||||
[% IF !jobExists(jobset, job) %]
|
||||
<div class="alert alert-warning">This job is not a member of the <a
|
||||
[% HTML.attributes(href => c.uri_for('/jobset' project.name jobset.name
|
||||
<div class="alert alert-warning">This job is not a member of the
|
||||
<a [% HTML.attributes(href => c.uri_for('/jobset' project.name jobset.name
|
||||
'evals')) %]>latest evaluation</a> of its jobset. This means it was
|
||||
removed or had an evaluation error.</div>
|
||||
[% END %]
|
||||
|
||||
@@ -117,7 +117,7 @@ else
|
||||
revCount="$(cat "$tmpDir/[% input.name %]/rev-count")"
|
||||
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" %]
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ sub fetchInputSystemBuild {
|
||||
$jobsetName ||= $jobset->name;
|
||||
|
||||
my @latestBuilds = $db->resultset('LatestSucceededForJobName')
|
||||
->search({}, {bind => [$jobsetName, $jobName]});
|
||||
->search({}, {bind => [$projectName, $jobsetName, $jobName]});
|
||||
|
||||
my @validBuilds = ();
|
||||
foreach my $build (@latestBuilds) {
|
||||
@@ -891,6 +891,7 @@ sub checkJobsetWrapped {
|
||||
, type => $input->{type}
|
||||
, uri => $input->{uri}
|
||||
, revision => $input->{revision}
|
||||
, shortRevLength => length($input->{shortRev})
|
||||
, value => $input->{value}
|
||||
, dependency => $input->{id}
|
||||
, path => $input->{storePath} || "" # !!! temporary hack
|
||||
|
||||
@@ -487,11 +487,12 @@ create table JobsetEvalInputs (
|
||||
altNr integer not null,
|
||||
|
||||
-- Copied from the jobsetinputs from which the build was created.
|
||||
type text not null,
|
||||
uri text,
|
||||
revision text,
|
||||
value text,
|
||||
dependency integer, -- build ID of the input, for type == 'build'
|
||||
type text not null,
|
||||
uri text,
|
||||
revision text,
|
||||
shortRevLength smallint, -- length of a short revision at the time this was checked out
|
||||
value text,
|
||||
dependency integer, -- build ID of the input, for type == 'build'
|
||||
|
||||
path text,
|
||||
|
||||
|
||||
@@ -1,90 +1,7 @@
|
||||
sql_files = files(
|
||||
'hydra.sql',
|
||||
'test.sql',
|
||||
'update-dbix.pl',
|
||||
'upgrade-2.sql',
|
||||
'upgrade-3.sql',
|
||||
'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 all SQL files in this directory.
|
||||
# This includes hydra.sql, test.sql, update-dbix.pl, and all upgrade-*.sql files.
|
||||
install_subdir('.',
|
||||
install_dir: hydra_libexecdir / 'sql',
|
||||
strip_directory: true,
|
||||
exclude_files: ['meson.build', 'update-dbix-harness.sh'],
|
||||
)
|
||||
|
||||
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 {
|
||||
my ($channelName, $pid, $payload) = @{$dbh->func("pg_notifies")};
|
||||
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($stepNr, 1, "The payload is the build's step number");
|
||||
isnt($logFile, undef, "The log file is passed");
|
||||
|
||||
Reference in New Issue
Block a user