Compare commits

..

3661 Commits

Author SHA1 Message Date
7c75138ca9 fix
Some checks failed
Test / tests (ubuntu-latest, x86_64-linux) (push) Failing after 31s
Test / tests (ubuntu-24.04-arm, aarch64-linux) (push) Has been cancelled
Update Flakes / update-flakes (push) Failing after 1m3s
2026-03-12 19:10:04 +01:00
8c970f6391 Add translator server
Some checks failed
Test / tests (ubuntu-latest, x86_64-linux) (push) Failing after 1m7s
Test / tests (ubuntu-24.04-arm, aarch64-linux) (push) Has been cancelled
2026-03-11 20:59:12 +01:00
Janne Heß
a9581bcdc4 Merge pull request #1564 from d-goldin/fix/github-diff-url
fix: Github diffs URL
2026-01-30 19:11:11 +00:00
Dima
26e4d5eb54 fix: Github diffs URL
In https://github.com/NixOS/hydra/pull/1549 diffs were
offloaded to github for performance reasons.

While in some endpoints github accepts `.git` suffixed in the
repository name, in the comparison endpoint this does not seem
to be the case.

Specifically, on the main nixos org hydra this isn't working:

Example job: https://hydra.nixos.org/build/320178054

Generates a comparison link like so:
078d69f039...1cd347bf33

This just stips away the suffix and seems to work fine in local
testing.
2026-01-27 01:45:51 +01:00
John Ericson
8bc95a96f7 Merge pull request #1559 from NixOS/bump-nix
bump to nix v2.33
2026-01-23 23:56:48 +00:00
Amaan Qureshi
82cd5e0e23 Fix build after Nix bump 2026-01-23 18:49:40 -05:00
Jörg Thalheim
c3ed183c64 bump to nix v2.33 2026-01-23 18:49:35 -05:00
John Ericson
b45f0d1fa7 Merge pull request #1556 from Mindavi/bugfix/perlcritic-fixes
treewide: update split calls to make perlcritic happy
2026-01-23 23:22:23 +00:00
Rick van Schijndel
e4fe9d43c1 treewide: update split calls to make perlcritic happy
In nixpkgs this started to fail the hydra tests.
It's not completely clear why because it seems the perlcritic
rule has existed for quite some time.

Anyway, this should solve the issues.
2026-01-17 15:55:29 +01:00
Janne Heß
9df4b65c67 Merge pull request #1558 from NixOS/schema-changes
meson: add missing schema migration
2026-01-14 13:11:42 +00:00
Janne Heß
1d011baed8 Merge pull request #1557 from NixOS/update-flakes
Update flake inputs
2026-01-14 09:19:24 +00:00
github-merge-queue
52b2e4f021 flake.lock: Update 2026-01-14 09:53:02 +01:00
Jörg Thalheim
f089ff87f5 build: automatically include all sql files
To prevent issues as in 43006db8 we can just install all sql files by
default
2026-01-14 09:45:57 +01:00
Jörg Thalheim
43006db835 meson: add missing schema file
This is missing from: https://github.com/NixOS/hydra/pull/1548
2026-01-14 09:39:43 +01:00
Janne Heß
4ebfaba862 Merge pull request #1548 from NixOS/fix/hashlengths
feat: Use short revision from git
2026-01-13 14:34:55 +00:00
Janne Heß
41daeb3cc9 Merge pull request #1553 from NixOS/dependabot/github_actions/actions/checkout-6
build(deps): bump actions/checkout from 3 to 6
2026-01-05 15:25:52 +00:00
Janne Heß
3b1b5009f3 Merge pull request #1552 from NixOS/dependabot/github_actions/peter-evans/create-pull-request-8
build(deps): bump peter-evans/create-pull-request from 5 to 8
2026-01-05 15:23:08 +00:00
dependabot[bot]
54699ae671 build(deps): bump actions/checkout from 3 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-05 15:00:59 +00:00
dependabot[bot]
503871bac4 build(deps): bump peter-evans/create-pull-request from 5 to 8
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 5 to 8.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v5...v8)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-05 15:00:54 +00:00
Janne Heß
6dde18cb5e Merge pull request #1551 from knedlsepp/fix-scmdiff
Fix broken api/scmdiff endpoint
2026-01-05 13:37:12 +00:00
Josef Kemetmüller
e0f65d4d3d Fix broken api/scmdiff endpoint
Same fix as in #1215, which got accidentally removed in #1506.
2026-01-05 14:16:47 +01:00
Janne Heß
5e2e9672cf Merge pull request #1549 from NixOS/feat/github-diffs
feat: Offload git diffs to GitHub
2026-01-05 13:10:00 +00:00
Janne Heß
650871b586 Merge pull request #602 from kquick/pathinput_freq
Allow PathInput to take an optional frequency parameter.
2026-01-04 19:09:26 +00:00
Janne Heß
b2030cd4ef Merge pull request #1294 from arianvp/patch-2
Document redirects in Hydra API
2026-01-04 18:55:13 +00:00
Janne Heß
44780c786e Merge branch 'master' into pathinput_freq 2026-01-04 19:05:05 +01:00
Janne Heß
2db62e86e7 feat: Store the short rev length 2026-01-04 19:01:49 +01:00
Arian van Putten
b88b06dd3c Document redirects in Hydra API
This documents useful redirects that Hydra exposes
2026-01-04 19:01:31 +01:00
Janne Heß
d042e3c82c refactor: Revision for the frontend from one place 2026-01-04 18:23:44 +01:00
Janne Heß
a31f5d654c Merge pull request #1270 from b-bondurant/sysbuild-fix
Use project name in sysbuild query
2026-01-04 15:53:17 +00:00
Janne Heß
6659391e26 Merge pull request #1252 from MaxHearnden/master
Only guess domain when gitea_url is not set
2026-01-04 15:38:42 +00:00
Janne Heß
3b901f19a4 Merge branch 'master' into sysbuild-fix 2026-01-04 16:30:35 +01:00
Janne Heß
673e18415e Merge branch 'master' into master 2026-01-04 16:29:27 +01:00
Janne Heß
13ddeeb08c Merge pull request #1550 from NixOS/feat/update-flake
feat: Update flake inputs
2026-01-04 15:22:22 +00:00
Janne Heß
ed15b0a8ce feat: Update flake inputs 2026-01-04 15:58:57 +01:00
Janne Heß
f1b26134d7 feat: Offload git diffs to GitHub
If we are on GitHub, use their scm diff by default which is more
feature-rich and offloads the diff work to stronger infrastructure
2026-01-04 15:49:25 +01:00
Janne Heß
425d78763d Merge pull request #1543 from diogotcorreia/fix-link-not-in-last-eval
fix: broken anchor tag in job.tt
2026-01-04 13:39:25 +00:00
Janne Heß
53d8e26b59 Merge pull request #1546 from jmbaur/jared/local-repro
build: quote flake URI for local repro instructions
2026-01-04 13:38:45 +00:00
Janne Heß
a439b7f591 Merge pull request #1547 from emhamm/hydra-fix-gitlab-pull-with-umlaute
hydra/plugins/gitlabpulls: use utf-8 encoding for gitlab-pulls-sorted…
2026-01-04 13:38:22 +00:00
Marian Hammer
7d12fa6a55 hydra/plugins/gitlabpulls: use utf-8 encoding for gitlab-pulls-sorted.json
unbreaks umlaute
2025-12-12 14:40:03 +01:00
Jared Baur
7a67ba925d build: quote flake URI for local repro instructions
Often times flake URIs have ampersands in them, making them unsuitable
for pasting into shells directly.
2025-12-10 14:17:45 -08:00
Diogo Correia
662d1198d4 fix: broken anchor tag in job.tt 2025-12-05 00:52:06 +01:00
John Ericson
34ff66a460 Merge pull request #1541 from NixOS/nixos-25.11
flake.nix: update to nixos-25.11
2025-11-25 21:23:57 +00:00
Martin Weinelt
7a42a3810c flake.nix: update to nixos-25.11
And squashes eval warnings from accessing pkgs.hostPlatform.
2025-11-25 15:23:17 +01:00
Martin Weinelt
3bd87005f7 Merge pull request #1540 from NixOS/pg17-update
package.nix: update postgresql to 17
2025-11-25 12:50:27 +00:00
Martin Weinelt
95fb69f60d package.nix: update postgresql to 17
NixOS 25.11 does not ship with PostgreSQL 13 any more.
2025-11-25 13:27:04 +01:00
Jörg Thalheim
241ab71800 Merge pull request #1536 from NixOS/fix-1535
Revert "Deduplicate protocol code more with `ServeProto::BasicClientConnection`
2025-11-06 19:23:48 +00:00
Jörg Thalheim
78ed8d7aa5 Merge pull request #1533 from hacker1024/patch-3
GithubRefs: Allow arbitrary ref types
2025-11-06 09:38:05 +00:00
John Ericson
4bd941daa8 Revert "Deduplicate protocol code more with ServeProto::BasicClientConnection"
This reverts commit 58846b0a1c.
2025-10-30 14:01:38 -04:00
John Ericson
0414ae64eb Merge pull request #1531 from NixOS/nix-2.32
Bump Nix 2.32
2025-10-16 06:17:02 +00:00
John Ericson
449791b1c7 Upgrade Nix to 2.32 2025-10-16 01:58:08 -04:00
Joshua Leivenzon
d7b40c4233 GithubRefs: Allow arbitrary ref types
GitHub's reference list API does not actually restrict the specified type, so don't artificially restrict it.

The API does not actually make a distinction between the "type" and "prefix" at all, but this is maintained for backwards compatibility. The two are simply concatenated.
2025-10-16 16:35:31 +11:00
John Ericson
524b232032 Merge pull request #1532 from NixOS/proto-dedup
Deduplicate protocol code more with `ServeProto::BasicClientConnection`
2025-10-15 22:15:30 +00:00
John Ericson
58846b0a1c Deduplicate protocol code more with ServeProto::BasicClientConnection
I did this in Nix for this purpose, but didn't get around to actually
taking advantage of it here, until now.
2025-10-15 18:00:20 -04:00
John Ericson
f1463d4bce Merge pull request #1522 from NixOS/no-jq
hydra-plugins: replace jq with perl's own canonical json output
2025-10-10 14:19:58 +00:00
John Ericson
94eaad22bc Merge pull request #1528 from NixOS/nix-2.31
Bump to nix/nix-eval-jobs 2.31
2025-10-08 21:07:05 +00:00
Jörg Thalheim
a499063834 bump to nix/nix-eval-jobs 2.31 2025-10-08 16:47:31 -04:00
John Ericson
3059dc16a3 Merge pull request #1502 from NixOS/nix-2.30-fix
Update hydra to nix 2.30
2025-10-06 20:39:33 +00:00
John Ericson
d36b943e93 Skip content-addressing test for now
It is hard to debug.
2025-10-06 16:18:17 -04:00
Jörg Thalheim
4b2d60e185 bump to nix/nix-eval-jobs 2.30 2025-10-06 16:18:17 -04:00
John Ericson
528a623b32 Merge pull request #1492 from NixOS/update-flakes
Update flake inputs
2025-10-06 18:31:46 +00:00
github-merge-queue
06be60349b flake.lock: Update 2025-10-06 14:08:38 -04:00
Jörg Thalheim
274027eb50 Merge pull request #1521 from NixOS/download-regression
Fix download regression
2025-09-13 08:10:38 +00:00
Jörg Thalheim
a329537e55 Merge pull request #1523 from NixOS/gitea
tests: Gitea test nitpicks
2025-09-13 08:01:10 +00:00
Jörg Thalheim
5f8ae153b4 tests: Gitea test nitpicks
- Add proper waitpid() for child process cleanup
- Simplify file existence check loop with early exit
- Rename variables for clarity ($uri -> $request_uri, remove unused $i)
2025-09-13 09:36:53 +02:00
Jörg Thalheim
990fe22f80 add regression test for download api 2025-09-13 09:27:31 +02:00
Jörg Thalheim
7fa3da755e hydra-plugins: replace jq with perl's own canonical json output 2025-09-13 09:18:05 +02:00
Jörg Thalheim
56f07573ea Avoid shadowing internal run function by renaming it to runCommand
see https://github.com/NixOS/hydra/issues/1520
2025-09-12 21:45:58 +02:00
Martin Weinelt
8481acda2f Merge pull request #1516 from Notarin/master
docs: tiny typo fix in README.md
2025-08-30 12:11:30 +00:00
Notarin Steele
75824e546f docs: tiny typo fix in README.md 2025-08-29 22:28:38 -04:00
Jörg Thalheim
b0c1f689c2 Merge pull request #1506 from NixOS/ipc
Stop shelling out
2025-08-29 09:15:49 +00:00
Jörg Thalheim
a4d7e7df93 Merge pull request #1514 from NixOS/no-eval-cache
hydra-eval-jobset: disable eval cache
2025-08-29 09:15:34 +00:00
Jörg Thalheim
5cc6ae3ca3 replace all system() shell invocation with safer non-shell alternative 2025-08-28 13:08:59 +02:00
Jörg Thalheim
19280b3466 perlcritic: run with --quiet flag to not log all files
we only want warnings, we don't care which files have been checked.
2025-08-28 13:08:59 +02:00
Jörg Thalheim
c6139736ed add perlcritic module to disallow system/exec 2025-08-28 13:08:59 +02:00
Jörg Thalheim
29734ae51f replace backtick operator with run3 2025-08-28 13:08:59 +02:00
Jörg Thalheim
38b4d5fa0f perlcritic: no longer allow qx/backticks 2025-08-28 13:08:59 +02:00
Jörg Thalheim
137761f8cc hydra-eval-jobset: disable eval cache 2025-08-28 12:08:01 +02:00
Jörg Thalheim
06d20bb8e0 Merge pull request #1513 from dermetfan/doc-force-push
document `force` parameter for `/api/push`
2025-08-27 08:28:42 +00:00
Robin Stumm
c25a2f626d document force parameter for /api/push 2025-08-26 14:38:18 +02:00
Jörg Thalheim
0d2a030661 Merge pull request #1510 from NixOS/fix/too-much-xss
Fix too much XSS protections
2025-08-14 16:26:09 +00:00
Janne Heß
fd0b8ec8e0 Fix too much XSS protections
- Fixes build graphs
- Fixes pagination
- Fixes pressure of new queue runner
2025-08-14 12:25:17 +02:00
Jörg Thalheim
81fd47df42 Merge pull request #1504 from ulucs/patch-1
Correctly apply the setting `allow_import_from_derivation = true`
2025-08-13 06:48:18 +00:00
Jörg Thalheim
2c4460942d Merge pull request #1509 from SuperSandro2000/patch-2
Fix webhook-secrets.conf permissions for real
2025-08-13 06:47:48 +00:00
Martin Weinelt
2e41e7e8e2 Merge pull request #1507 from NixOS/compare-active-jobsets
jobset-eval: reduce compare options to active jobsets
2025-08-12 22:42:08 +00:00
Sandro
242eb72dbb Fix webhook-secrets.conf permissions for real
I did not notice in #1508 that the hydra evaluator now crashed because the hydra config is shared between all components, all of them need to be able to read the secret.
2025-08-12 23:38:05 +02:00
Janne Heß
bddf15de46 Merge pull request #1508 from SuperSandro2000/patch-2
Fix webhook-secrets.conf permissions
2025-08-12 16:55:57 +00:00
Sandro
5f530d7d56 Fix webhook-secrets.conf permissions
The secret is read by hydra-server which is run under hydra-www so that needs to be able to read the file.
2025-08-12 16:36:39 +02:00
Martin Weinelt
e851d9f9f6 jobset-eval: reduce compare options to active jobsets
The list of jobsets is very high on hydra.nixos.org and the compare to
dropdown listing goes over multiple full pages in the busy projects.

If we ignore jobsets that we disable this interface becomes more usable
again.
2025-08-12 12:40:12 +02:00
Janne Heß
f7bda020c6 Merge commit from fork
webhooks: implement authentication for GitHub and Gitea
2025-08-12 12:10:29 +02:00
Janne Heß
dea1e168f5 Merge commit from fork
Fix GHSA-7qwg-q53v-vh99
2025-08-12 12:06:18 +02:00
Jörg Thalheim
b47b187553 webhooks: implement authentication for GitHub and Gitea
- Add HMAC-SHA256 signature verification for webhooks
- Support multiple secrets for rotation
- Add security logging for authentication events
- Maintain backward compatibility (auth optional during migration)
- Add comprehensive test coverage

Without authentication, anyone could trigger job evaluations by sending
POST requests to webhook endpoints. This could lead to resource exhaustion
through repeated requests or manipulation of build scheduling. While not
a data breach risk, it allows unauthorized control over CI/CD operations.
2025-08-10 12:41:47 +02:00
Janne Heß
c6424f37a6 templates: Hopefully escape all template inputs 2025-08-10 12:40:21 +02:00
Janne Heß
b94f47ed27 templates: Make whitespace in [% %] consistent 2025-08-10 12:40:21 +02:00
Janne Heß
615798a51e templates: Use HTML.attributes for all links 2025-08-10 12:40:21 +02:00
Janne Heß
99a6656b40 build: Properly escape all input values 2025-08-10 12:40:21 +02:00
Janne Heß
33b5c6fb41 product-list: Escape untrusted values 2025-08-10 12:40:21 +02:00
Janne Heß
5f226f3b6f hydra-queue-runner: Validate metric type 2025-08-10 12:40:21 +02:00
Janne Heß
7c4f0ab01a hydra-queue-runner: Validate hydra-metrics unit 2025-08-10 12:40:21 +02:00
Janne Heß
0d3842aa2f hydra-queue-runner: Validate metric name in hydra-metrics 2025-08-10 12:40:21 +02:00
Janne Heß
a0ba36db79 hydra-queue-runner: Validate release name 2025-08-10 12:40:21 +02:00
Janne Heß
552ca356ae hydra-queue-runner: Verify product names in hydra-build-products 2025-08-10 12:40:20 +02:00
John Ericson
79ba8fdd04 Merge pull request #1505 from NixOS/no-built-scripts-meson-shell
package.nix: fix PATH for devshell
2025-08-05 14:35:14 +00:00
ulucs
b98f9f8e48 Change the default value for allow_import_from_derivation configuration option to false 2025-08-05 14:29:56 +02:00
ulucs
476c1a6200 Add parentheses to fix operator precedence 2025-08-05 12:43:51 +02:00
Jörg Thalheim
c645b7ff67 package.nix: fix PATH for devshell
We don't install scripts to build so this must point to src
2025-08-05 00:22:46 +02:00
John Ericson
c12d0a66d8 Merge pull request #1503 from NixOS/libpqxx-and-ci
Libpqxx and ci
2025-08-04 22:13:09 +00:00
Jörg Thalheim
2f6ec150ec ci: also build on aarch64-linux 2025-08-04 17:44:16 -04:00
Jörg Thalheim
2b4f4cf6f4 cache build with the magic nix cache 2025-08-04 17:44:16 -04:00
Jörg Thalheim
e33b4f88dc queue-runner: Add missing signal.h include for SIGINT and kill() 2025-08-04 17:44:16 -04:00
Jörg Thalheim
a9b89ee779 Migrate from deprecated notification_receiver to connection::listen()
libpqxx 7.10.1 deprecates the notification_receiver class.
2025-08-04 17:44:16 -04:00
Jörg Thalheim
84b4fe36b6 Fix libpqxx 7.10.1 API compatibility
- Replace deprecated exec_params/exec_params0 calls with exec()
- Wrap all parameterized queries with pqxx::params{}
- Add .no_rows()/.one_row() to exec calls that don't return results
2025-08-04 17:44:16 -04:00
Jörg Thalheim
081d0c079a hydra-eval-jobs: unset NIX_PATH 2025-08-04 17:44:16 -04:00
Jörg Thalheim
a75c5a405c docs/hacking: document how to run single tests 2025-08-04 17:44:16 -04:00
Janne Heß
85b330be41 hydra-queue-runner: Fix potential UB
Removing two characters from a string when it starts with " can lead to
a substring call with -1
2025-08-02 17:21:27 +02:00
Janne Heß
1657f6fff4 hydra-queue-runner: Fix crash when < > are in hydra-build-products
This prevents a forever-hanging build (don't know why) when < or > are
in the path of hydra-build-products. This is not to prevent any XSS (see
next commits), just to prevent the DOS (if you can even call it that).
2025-08-02 17:21:27 +02:00
Janne Heß
957884d174 Merge pull request #1501 from NixOS/fix/useless-message
Remove useless previous eval message
2025-08-02 12:26:54 +00:00
Janne Heß
05a05667d8 Merge branch 'master' into fix/useless-message 2025-08-02 14:21:44 +02:00
Janne Heß
0527fddd6a Remove useless previous eval message
This message serves no purpose and looks like something went wrong.
There is nothing wrong, there is just no previous evaluation.
2025-08-02 14:20:59 +02:00
Janne Heß
0017a1d0f3 Merge pull request #1498 from NixOS/feat/new-q-runner-machine-status
machine-status: Render new queue runner details
2025-08-02 12:11:07 +00:00
Janne Heß
e9895e81af Merge branch 'master' into feat/new-q-runner-machine-status 2025-08-02 14:05:55 +02:00
Janne Heß
424a767035 Merge pull request #1500 from NixOS/feat/improve-developer-expercience
Improve general developer experience
2025-08-02 12:05:41 +00:00
Janne Heß
7096ae3a5b machine-status: Fixup double localhost during development 2025-08-02 14:05:23 +02:00
Janne Heß
ec3d0c696b Fix the evaluator not finding hydra-eval-jobset 2025-08-02 13:53:25 +02:00
Janne Heß
d2c10bf851 Fixup static libraries in development server 2025-08-02 13:53:22 +02:00
Janne Heß
80b9d82ea4 Fix meson and ninja commands and link bootstrap 2025-08-02 13:41:39 +02:00
Janne Heß
85ab735653 Add nix-direnv 2025-08-02 13:41:16 +02:00
Janne Heß
632a59172a machine-status: Make new runner status prettier
- Remove bottom margin
- Properly format memory in human format
- Calculate free memory
- Format the load with 2 digits after comma
- Lpad pressure percentages
- Use a macro to render pressure
- Score -> Scheduling Score
- More spacing in the load
- Add IRQ pressure
2025-08-01 11:25:14 +02:00
Janne Heß
95f5d331ee Merge pull request #1499 from NixOS/feat/document-pg-conncetion
Document how to connect to postgres
2025-07-31 16:54:32 +00:00
Janne Heß
6e9e13333f Document how to connect to postgres 2025-07-31 18:48:47 +02:00
Janne Heß
7b1968236d machine-status: Render new queue runner details 2025-07-31 18:45:04 +02:00
Janne Heß
b812bb5017 Merge pull request #869 from andir/patch-1
Add Queue Runner Status to the topbar
2025-07-17 21:31:27 +00:00
Janne Heß
61573c71d1 Merge pull request #1497 from helsinki-systems/feat/show-new-q-runner-status
Show queue runner v2 status
2025-07-17 21:30:36 +00:00
Janne Heß
f50263976c Merge branch 'master' into patch-1 2025-07-17 23:21:18 +02:00
Janne Heß
c413b275ff Merge pull request #1206 from iwanders/CORE-21733-add-link-to-raw-log
Add a link to the raw log.
2025-07-16 20:18:43 +00:00
John Ericson
f7a9113166 Merge pull request #1494 from SuperSandro2000/patch-2
module: sync with nixpkgs
2025-07-16 19:44:14 +00:00
Janne Heß
97ec796db5 Merge branch 'master' into CORE-21733-add-link-to-raw-log 2025-07-16 18:42:40 +02:00
Janne Heß
42400ef20c Merge pull request #1156 from helsinki-systems/fix/local-store-detection
Fix local store detection and related issues
2025-07-16 16:31:15 +00:00
Janne Heß
2fcfa969b8 Merge branch 'master' into fix/local-store-detection 2025-07-16 18:25:54 +02:00
Janne Heß
4f3b783d30 Merge pull request #1493 from NixOS/hostname-utility
Replace nettools with hostname-debian
2025-07-16 16:22:17 +00:00
Janne Heß
80980f8b32 Fix PATH for the foreman scripts 2025-07-16 17:39:19 +02:00
Janne Heß
d0008d4238 Show queue runner v2 status
This is guarded behind a setting and will overwrite everything that was
learned from the machines file. Also drops `sshKeys` since that wasn't
used anyway.
2025-07-16 17:39:06 +02:00
Janne Heß
3b89d2d6b5 Merge pull request #1495 from Erethon/fix-nix-download-url
fix: Update Nix download url
2025-07-15 19:16:32 +00:00
Dionysis Grigoropoulos
62fcacb7d2 fix: Update Nix download url 2025-07-15 19:45:13 +03:00
Sandro
b3b48bc237 module: sync with nixpkgs 2025-07-04 12:01:42 +02:00
Martin Weinelt
c544042051 Replace nettools with hostname-debian
As far as I understand we include nettools for its hostname executable
used by the Sys-Hostname-Long perl package. But if we just need that then
the hostname-debian package provides a simpler and better maintained
version.
2025-07-04 06:46:35 +02:00
Jörg Thalheim
aa62c7f7db Merge pull request #1490 from NixOS/update-flakes
Update flake inputs
2025-06-24 23:19:28 +00:00
Mic92
605a0e9ce9 flake.lock: Update 2025-06-25 01:03:35 +02:00
Jörg Thalheim
6786e52eb5 Merge pull request #1489 from NixOS/ci
github: update test workflow to use latest nix &  add update-flakes action
2025-06-24 16:51:54 +00:00
Jörg Thalheim
9efe38c60b add update-flakes action 2025-06-24 18:46:33 +02:00
Jörg Thalheim
c621f27482 test: bump used nix version 2025-06-24 18:45:14 +02:00
John Ericson
ed500ca434 Merge pull request #1202 from thejohncrafter/doc-request-base
docs: refine instructions for proxy setting
2025-06-15 22:14:38 +00:00
Julien Marquet
635aff50dd docs: refine instructions for proxy setting 2025-05-27 12:45:12 -04:00
Jörg Thalheim
2e3c168ec4 Merge pull request #1487 from tomjnixon/reverse_proxy_docs
doc/manual: correct nginx reverse proxy example
2025-05-27 04:58:53 +00:00
John Ericson
362524b563 Merge pull request #1485 from NixOS/nix-2.29
Nix 2.29
2025-05-26 05:17:23 +00:00
John Ericson
de3646cb13 Merge pull request #1488 from NixOS/nixpkgs-25.05
flake.lock: Update Nixpkgs to 25.05
2025-05-26 01:11:40 +00:00
John Ericson
278a3ebfd5 Fix build with Nix 2.29 2025-05-25 20:53:18 -04:00
John Ericson
dafa252d08 flake.lock: Update Nix and nix-eval-jobs to 2.29
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/70921714cb3b5e6041b7413459541838651079f3?narHash=sha256-ZbB3IH9OlJvo14GlQZbYHzJojf/HCDT38GzYTod8DaU%3D' (2025-04-23)
  → 'github:NixOS/nix/d761dad79c79af17aa476a29749bd9d69747548f?narHash=sha256-rCpANMHFIlafta6J/G0ILRd%2BWNSnzv/lzi40Y8f1AR8%3D' (2025-05-25)
• Updated input 'nix-eval-jobs':
    'github:nix-community/nix-eval-jobs/1260c6599d22dfd8c25fea6893c3d031996b20e1?narHash=sha256-n220U5pjzCtTtOJtbga4Xr/PyllowKw9anSevgCqJEw%3D' (2025-04-11)
  → 'github:nix-community/nix-eval-jobs/d9262e535e35454daebcebd434bdb9c1486bb998?narHash=sha256-AJ22q6yWc1hPkqssXMxQqD6QUeJ6hbx52xWHhKsmuP0%3D' (2025-05-25)
2025-05-25 20:52:39 -04:00
John Ericson
8a50488f6c flake.lock: Update Nixpkgs to 25.05
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/eea3403f7ca9f9942098f4f2756adab4ec924b2b?narHash=sha256-JT1wMjLIypWJA0N2V27WpUw8feDmTok4Dwkb0oYXDS4%3D' (2025-04-23)
  → 'github:NixOS/nixpkgs/db1aed32009f408e4048c1dd0beaf714dd34ed93?narHash=sha256-8A7HjmnvCpDjmETrZY1QwzKunR63LiP7lHu1eA5q6JI%3D' (2025-05-24)
2025-05-25 20:51:14 -04:00
Thomas Nixon
8bb7d27588 doc/manual: correct nginx reverse proxy example
- hydra does not remove the base URI from the request before processing
  it, so this must be done in the reverse proxy. in nginx this is done
  by giving proxy_pass a URI rather than a protocol/host/port; see:

  https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

- proxy_redirect is not correct/required: hydra uses proxy headers to
  correctly form redirects in most cases, and where it doesn't it
  produces local redirects which aren't matched by this directive anyway
2025-05-23 23:39:44 +01:00
Martin Weinelt
35c9264306 Merge pull request #1484 from NixOS/nix-keep-options
Migrate from "gc-" prefixed nix options
2025-05-23 22:19:15 +00:00
Martin Weinelt
da1aebe970 Migrate from "gc-" prefixed nix options
These have been deprecated, e.g. gc-keep-outputs is now just
keep-outputs.
2025-05-15 04:08:57 +02:00
Jörg Thalheim
183bc39d1a Merge pull request #1483 from SuperSandro2000/patch-2
Add missing slash
2025-05-09 15:49:33 +00:00
Sandro
2ae27dd20d Add missing slash
error: access to absolute path '/nix/store/sai35xfsrba2a2vasmzxakmn54wdfa13-sourcepackaging' is forbidden in pure evaluation mode (use '--impure' to override)
2025-05-05 00:10:59 +02:00
Jörg Thalheim
1b5c2fb747 Merge pull request #1479 from qowoz/queue-runner
queue runner: attempt at slightly smarter scheduling criteria
2025-05-01 07:02:54 +00:00
Jörg Thalheim
8d068fea3e Merge pull request #1482 from NixOS/hydra-passthru
Expose nix package in hydra package
2025-04-29 18:35:50 +00:00
Jörg Thalheim
8218a9ad1b hydra: expose nix-cli package
This makes it easier in other packages to get the nix version used to
build Hydra.
2025-04-29 20:27:30 +02:00
John Ericson
455f1a0665 Merge pull request #1481 from NixOS/nix-flake-false
Use Nix without the flake
2025-04-23 22:04:54 +00:00
John Ericson
89fcb931ce Use Nix without the flake
This is what we do for `nix-eval-jobs` already. It allows for more
fine-grained control over dependencies.
2025-04-23 17:58:52 -04:00
Martin Weinelt
b023cc8f87 Merge pull request #1480 from NixOS/update-nix
flake.lock: Update
2025-04-23 18:05:14 +00:00
Martin Weinelt
23755bf001 flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/a4962f73b5fc874d4b16baef47921daf349addfc' (2025-04-07)
  → 'github:NixOS/nix/70921714cb3b5e6041b7413459541838651079f3' (2025-04-23)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/db8f4fe18ce772a9c8f3adf321416981c8fe9371' (2025-04-07)
  → 'github:NixOS/nixpkgs/eea3403f7ca9f9942098f4f2756adab4ec924b2b' (2025-04-23)
2025-04-23 18:27:14 +02:00
Pierre Bourdon
720db63d52 queue runner: attempt at slightly smarter scheduling criteria
Instead of just going for "whatever is the oldest build we know of",
use the following first:

- Is the step more constrained? If so, schedule it first to avoid
  filling up "more desirable" build slots with less constrained builds.

- Does the step have more dependents? If so, schedule it first to try
  and maximize open parallelism and breadth of scheduling options.

(cherry picked from commit b8d03adaf4)
2025-04-20 13:44:06 +10:00
John Ericson
bdde73acbd Merge pull request #1478 from qowoz/fix-actions
jobset-eval: fix actions not showing up sometimes for new jobs
2025-04-16 16:49:31 +00:00
Pierre Bourdon
0ab357e435 jobset-eval: fix actions not showing up sometimes for new jobs
New jobs have their "new" status take precedence over them being
"failed" or "queued", which means actions that can act on "failed" or
"queued" jobs weren't shown to the user when they could only act on
"new" jobs.

(cherry picked from commit 9a4a5dd624)
2025-04-16 09:50:32 +10:00
Jörg Thalheim
6fcfa9e796 Merge commit from fork
Re-enable restrict-eval for non-flakes
2025-04-15 06:48:18 +02:00
Martin Weinelt
ffbde9c9e3 Merge pull request #1474 from NixOS/machine-status-colspan
web: increase colspan for machine row in machine status
2025-04-13 14:37:52 +00:00
Martin Weinelt
cf33a9158a web: increase colspan for machine row in machine status 2025-04-13 08:29:01 +02:00
John Ericson
5f6b075754 Merge pull request #1470 from qowoz/eval-view
Fix displaying eval errors in jobset eval view
2025-04-11 15:49:05 +00:00
Jörg Thalheim
8d75026513 re-enable restrict-eval for non-flakes 2025-04-11 13:42:55 +02:00
Maximilian Bosch
f1a976d3fd Fix displaying eval errors in jobset eval view
Quickfix for something that annoyed me once too often.

Specifically, I'm talking about `/eval/1#tabs-errors`.

To not fetch long errors on each request, this is only done on-demand.
I.e., when the tab is opened, an iframe is requested with the errors.
This iframe uses a template for both the jobset view and the jobset-eval
view. It is differentiated by checking if `jobset` or `eval` is defined.

However, the jobset-eval view also has a `jobset` variable in its stash
which means that in both cases the `if` path was used. Since
`jobset.fetcherrormsg` isn't defined in the eval case though, you always
got an empty error.

The band-aid fix is relatively simple: swap if and else: the `eval`
variable is not defined in the stash of the jobset view, so now this is
a useful condition to decide which view we're in.

(cherry picked from commit 70c3d75f73)
2025-04-11 09:03:11 +10:00
Jörg Thalheim
d5ad16abc2 Merge pull request #1472 from SuperSandro2000/without-aws-sdk
Fix compilation with a nix which was compiled withou aws sdk
2025-04-10 15:24:38 +00:00
Sandro Jäckel
7e0157e387 Fix compilation with a nix which was compiled withou aws sdk 2025-04-09 17:53:14 +02:00
John Ericson
c8de5b99e3 Merge pull request #1471 from NixOS/queue-runner-machines-json
Queue-runner: Always produce a machines JSON object
2025-04-08 21:44:23 +00:00
John Ericson
a5b17d0686 Queue-runner: Always produce a machines JSON object
Even if there are no machines, there should at least be an empty object.
2025-04-08 17:38:19 -04:00
John Ericson
1c52c4c0ed Merge pull request #1456 from NixOS/hydra.nixos.org-rebased
web: replace 'errormsg' with 'errormsg IS NULL' in most cases
2025-04-07 19:05:51 +00:00
Pierre Bourdon
b4322edd05 web: replace 'errormsg' with 'errormsg IS NULL' in most cases
This is implement in an extremely hacky way due to poor DBIx feature
support. Ideally, what we'd need is a way to tell DBIx to ignore the
errormsg column unless explicitly requested, and to automatically add a
computed 'errormsg IS NULL' column in others. Since it does not support
that, this commit instead hacks some support via method overrides while
taking care to not break anything obvious.
2025-04-07 14:48:07 -04:00
John Ericson
8350f964ee Merge pull request #1469 from NixOS/release-reservations
queue-runner: release machine reservation while copying outputs
2025-04-07 18:19:16 +00:00
Pierre Bourdon
143a07bff0 queue-runner: release machine reservation while copying outputs
This allows for better builder usage when the queue runner is busy. To
avoid running into uncontrollable imbalances between builder/queue
runner, we only release the machine reservation after the local
throttler has found a slot to start copying the outputs for that build.

As opposed to asserting uniqueness to understand resource utilization,
we just switch to using `std::unique_ptr`.
2025-04-07 14:01:50 -04:00
John Ericson
cc4b206d85 Merge pull request #1466 from NixOS/bump-nixpkgs
Bump nixpkgs
2025-04-07 17:32:38 +00:00
John Ericson
e77444da98 Merge pull request #1468 from NixOS/steps-waiting-for-download-slot
Add metric for builds waiting for download slot
2025-04-07 17:28:00 +00:00
K900
8a6482bb1c Add metric for builds waiting for download slot
(cherry picked from commit f23ec71227911891807706b6b978836e4d80edde)
2025-04-07 13:16:49 -04:00
Jörg Thalheim
b3a433336e bump nixpkgs 2025-04-07 19:09:46 +02:00
Jörg Thalheim
68b2d6da0a Merge pull request #1467 from NixOS/merge-queue
Make github actions ci merge-queue friendly
2025-04-07 17:02:43 +00:00
Jörg Thalheim
c94ba404fd don't build hydra twice in a pull request + enable merge queue 2025-04-07 18:57:32 +02:00
Jörg Thalheim
56170dd117 Merge pull request #1464 from NixOS/more-hydra.nixos.org-changes
More hydra.nixos.org changes
2025-04-07 16:50:36 +00:00
Jörg Thalheim
d4b55f8190 Merge pull request #1465 from NixOS/gitea
test/gitea: fix eval
2025-04-07 18:48:57 +02:00
Jörg Thalheim
78687e23cf test/gitea: fix eval 2025-04-07 18:43:12 +02:00
Jörg Thalheim
f02fc5e2ff Merge pull request #1463 from NixOS/fix-nixos-tests
Fix evaluation of NixOS tests, avoid `with`
2025-04-07 18:37:50 +02:00
Pierre Bourdon
8e02589ac8 queue-runner: switch to pseudorandom ordering of builds processing
We don't rely on sequential / monotonic build IDs processing anymore, so
randomizing actually has the advantage of mixing builds for different
systems together, to avoid only one chunk of builds for a single system
getting processed while builders for other systems are starved.
2025-04-07 12:33:35 -04:00
Pierre Bourdon
52a0199a9b queue runner: introduce some parallelism for remote paths lookup
Each output for a given step being ingested is looked up in parallel,
which should basically multiply the speed of builds ingestion by the
average number of outputs per derivation.
2025-04-07 12:33:35 -04:00
Pierre Bourdon
9265fc5002 queue-runner: reduce the time between queue monitor restarts
This will induce more DB queries (though these are fairly cheap), but at
the benefit of processing bumps within 1m instead of within 10m.
2025-04-07 12:33:35 -04:00
Pierre Bourdon
d8ffa6b56a queue-runner: remove id > X from new builds query
Running the query with/without it shows that it makes no difference to
postgres, since there's an index on finished=0 already. This allows a
few simplifications, but also paves the way towards running multiple
parallel monitor threads in the future.
2025-04-07 12:33:35 -04:00
Pierre Bourdon
efcf6815d9 queue-runner: add prom metrics to allow detecting internal bottlenecks
By looking at the ratio of running vs. waiting for the dispatcher and
the queue monitor, we should get better visibility into what hydra is
currently bottlenecked on.

There are other side effects we can try to measure to get to the same
result, but having a simple way doesn't cost us much.
2025-04-07 12:33:35 -04:00
Pierre Bourdon
1e2d3211d9 queue-runner: limit parallelism of CPU intensive operations
My current theory is that running more parallel xz than available CPU
cores is reducing our overall throughput by requiring more scheduling
overhead and more cache thrashing.
2025-04-07 12:33:35 -04:00
Pierre Bourdon
5a9985f96c web: Skip System on /machines
It is redundant
2025-04-07 12:33:35 -04:00
John Ericson
0d0c4f278b Fix evaluation of NixOS tests, avoid with 2025-04-07 12:32:28 -04:00
John Ericson
3fdb18a4bc Merge pull request #1462 from NixOS/web-changes
A number of Perl-side changes from the hydra.nixos.org branch
2025-04-07 12:17:16 -04:00
Maximilian Bosch
6133693097 readIntoSocket: fix with store URIs containing an &
The third argument to `open()` in `-|` mode is passed to a shell if it's
a string. In my case the store URI contains
`?secret-key=${signingKey.directory}/secret&compression=zstd`

For the `nix store cat` case this means that

* until `&` the process will be started in the background. This fails
  immediately because no path to cat is specified.
* `compression=zstd` is a variable assignment
* the `$path` argument to `store cat` is attempted to be executed as
  another command

Passing just the list solves the problem.

(cherry picked from commit 3ee51dbe589458cc54ff753317bbc6db530bddc0)
2025-04-07 11:59:49 -04:00
git@71rd.net
abe35881e4 Stream files from store instead of buffering them
When an artifact is requested from hydra the output is first copied
from the nix store into memory and then sent as a response, delaying
the download and taking up significant amounts of memory.

As reported in https://github.com/NixOS/hydra/issues/1357

Instead of calling a command and blocking while reading in the entire
output, this adds read_into_socket(). the function takes a
command, starting a subprocess with that command, returning a file
descriptor attached to stdout.
This file descriptor is then by responsebuilder of Catalyst to steam
the output directly

(cherry picked from commit 459aa0a5983a0bd546399c08231468d6e9282f54)
2025-04-07 11:59:49 -04:00
ajs124
99359c251a lazy-load evaluation errors
Closes #1362
2025-04-07 11:54:47 -04:00
Maximilian Bosch
9d8f30affe Only show stepname if it doesn't equal the name of the drv
When building e.g. nixpkgs, the "Running builds" view will mostly look
like this

    hello.x86_64-linux (Build of hello-X.Y)
    exa.x86_64-linux (Build of exa-X.Y)
    ...

This doesn't provide any useful information. Showing the step name only
makes sense if it's not a child of the job's derivation. With this
patch, that information will only be shown if the drv name (i.e. w/o
`/nix/store/` prefix, .drv ext & hash) is not equal to the drv name of
the job itself (build.nixname).
2025-04-07 11:54:47 -04:00
Maximilian Bosch
33b982f408 Running builds view: show build step names
When using Hydra to build machine configurations, you'll often see
"nixosConfigurations.foo" five times, i.e. for each build step being
run. This isn't very helpful I think because in such a case, a single
build step can also be compiling the Linux kernel.

This change also fetches the `drvpath` and `type` from the `buildsteps`
relation. We're already joining it, so this doesn't make much difference
(confirmed via query logging that this doesn't cause extra SQL queries).

Unfortunately build steps don't have a human readable name, so I'm
deriving it from the drvpath by stripping away the hash (assuming that
it'll never contain a `-` and that `/nix/store/` is used as prefix). I
decided against using the Nix bindings for that to avoid too much
overhead due to store operations for each build step.
2025-04-07 11:54:47 -04:00
Maximilian Bosch
a816e8e22c Make "timed out" and "log limit exceeded" builds aborted
In 73694087a0 I gave builds that failed
because of a timeout or exceeded log limit a stop sign and I stand by
that reasoning: with that it's possible to distinguish between actual
build failures and rather transient things such as timeouts.

Back then I considered it a feature that these are shown in a different
tab, but I don't think that's a good idea anymore. When using a jobset to
e.g. track the regressions from a mass rebuild (like a compiler or gcc
update), "Newly failed builds" should exclusively display regressions (and
flaky builds of course, not much I can do about that).

Also, when a bunch of builds fail in such a jobset because of e.g. a
broken connection to a builder that results in a timeout, I want to be
able to restart them all w/o rebuilding actual regressions.

To make it clear that we not only have "Aborted" builds in the tab, I
renamed the label to "Aborted / Timed out".
2025-04-07 11:54:47 -04:00
Pierre Bourdon
0159135fc7 web: include current step status on /machines 2025-04-07 11:54:47 -04:00
John Ericson
1d2d3ae6b7 Merge pull request #1461 from NixOS/nix-2.28
Nix 2.28
2025-04-07 11:52:45 -04:00
John Ericson
257b211832 Merge pull request #1460 from NixOS/nix-2.27
Nix 2.27
2025-04-07 11:37:43 -04:00
John Ericson
d6a5df25bf Fix the build 2025-04-07 11:36:59 -04:00
John Ericson
6534a54ee5 Fix Nix code
Can now at least enter dev shell, but build is still broken.
2025-04-07 11:28:34 -04:00
John Ericson
1595064bee flake.lock: Update to nix and nix-eval-jobs 2.28
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/d0f98c76f962147610489e84c10033ca92e9c532?narHash=sha256-u6RhBWQ1XohTZ4Ub5ml1PTcaxQgtqFNng6Sohy1rojw%3D' (2025-04-07)
  → 'github:NixOS/nix/a4962f73b5fc874d4b16baef47921daf349addfc?narHash=sha256-r%2BpsCOW77vTSTNbxTVrYHeh6OgB0QukbnyUVDwg8s4I%3D' (2025-04-07)
• Updated input 'nix-eval-jobs':
    'github:nix-community/nix-eval-jobs/62f9c9e8d00d2ff6ab27a6197ab459a8e0808e59?narHash=sha256-PypQspB7h7EENe4RQQUQj2Ay8J1%2BO49AKNO9JbAU4Ek%3D' (2025-04-07)
  → 'github:nix-community/nix-eval-jobs/cba718bafe5dc1607c2b6761ecf53c641a6f3b21?narHash=sha256-v5n6t49X7MOpqS9j0FtI6TWOXvxuZMmGsp2OfUK5QfA%3D' (2025-04-07)
2025-04-07 11:16:09 -04:00
John Ericson
1cb1e139c4 Fix build (due to C++ API changes) 2025-04-07 11:12:12 -04:00
John Ericson
6b97e3ab7b flake.lock: Update to nix and nix-eval-jobs 2.27
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/e310c19a1aeb1ce1ed4d41d5ab2d02db596e0918?narHash=sha256-q/RgA4bB7zWai4oPySq9mch7qH14IEeom2P64SXdqHs%3D' (2025-02-18)
  → 'github:NixOS/nix/d0f98c76f962147610489e84c10033ca92e9c532?narHash=sha256-u6RhBWQ1XohTZ4Ub5ml1PTcaxQgtqFNng6Sohy1rojw%3D' (2025-04-07)
• Updated input 'nix-eval-jobs':
    'github:nix-community/nix-eval-jobs/f7418fc1fa45b96d37baa95ff3c016dd5be3876b?narHash=sha256-Lo4KFBNcY8tmBuCmEr2XV0IUZtxXHmbXPNLkov/QSU0%3D' (2025-03-26)
  → 'github:nix-community/nix-eval-jobs/62f9c9e8d00d2ff6ab27a6197ab459a8e0808e59?narHash=sha256-PypQspB7h7EENe4RQQUQj2Ay8J1%2BO49AKNO9JbAU4Ek%3D' (2025-04-07)
2025-04-07 11:02:52 -04:00
Jörg Thalheim
cad08f87d2 Merge pull request #1458 from NixOS/meson
docs: fix contribution guide for new meson-based build
2025-03-29 15:37:06 +01:00
Jörg Thalheim
3fef32b364 gitignore hydra-data as created by foreman 2025-03-29 14:31:18 +00:00
Jörg Thalheim
ae18a7b3ae fix development workflow after switching to meson-based build 2025-03-29 14:31:18 +00:00
Jörg Thalheim
b657bcdfb7 Merge pull request #1457 from dermetfan/fix-1429
hydra-eval-jobset: do not wait on n-e-j inside transaction
2025-03-29 11:36:13 +01:00
Jörg Thalheim
3b4c4972c2 Merge pull request #1449 from knedlsepp/fix-metrics-rendering-with-special-characters
Fix rendering of metrics with special characters
2025-03-29 08:52:07 +01:00
John Ericson
b2fe3f5218 Merge pull request #1455 from qowoz/226-constituent
nix-eval-jobs + constituent globs
2025-03-27 23:18:39 -04:00
Maximilian Bosch
9911f0107f Reimplement (named) constituent jobs (+globbing) based on nix-eval-jobs
Depends on https://github.com/nix-community/nix-eval-jobs/pull/349 & #1421.

Almost equivalent to #1425, but with a small change: when having e.g. an
aggregate job with a glob that matches nothing, the jobset evaluation is
failed now. This was the intended behavior before (hydra-eval-jobset
fails hard if an aggregate is broken), the code-path was never reached
however since the aggregate was never marked as broken in this case
before.
2025-03-28 11:12:54 +10:00
zowoq
feebb61897 flake.lock: Update
Flake lock file updates:

• Updated input 'nix-eval-jobs':
    'github:nix-community/nix-eval-jobs/4b392b284877d203ae262e16af269f702df036bc?narHash=sha256-3wIReAqdTALv39gkWXLMZQvHyBOc3yPkWT2ZsItxedY%3D' (2025-02-14)
  → 'github:nix-community/nix-eval-jobs/f7418fc1fa45b96d37baa95ff3c016dd5be3876b?narHash=sha256-Lo4KFBNcY8tmBuCmEr2XV0IUZtxXHmbXPNLkov/QSU0%3D' (2025-03-26)
2025-03-28 11:12:54 +10:00
zowoq
4bcbed2f1b hydraTest: remove outdated postgresql version
error: postgresql_12 has been removed since it reached its EOL upstream
2025-03-28 11:12:48 +10:00
Robin Stumm
987dad3371 hydra-eval-jobset: do not wait on n-e-j inside transaction
fixes #1429
2025-03-26 20:23:26 +01:00
John Ericson
d2db3c7446 Merge pull request #1450 from NixOS/hydra-compress-race
Fix race condition in hydra-compress-logs
2025-03-16 14:37:39 -04:00
John Ericson
97dcdae068 Merge pull request #1451 from NixOS/revert-to-fix-hangs
Revert "Use `LegacySSHStore`"
2025-03-03 10:18:28 -05:00
John Ericson
9a5bd39d4c Revert "Use LegacySSHStore"
There were some hangs caused by this. Need to fix them, ideally
reproducing the issue in a test, before trying this again.

This reverts commit 4a4a0f901c.
2025-03-03 10:12:38 -05:00
Martin Weinelt
f1deb22c02 Fix race condition in hydra-compress-logs 2025-03-02 03:08:26 +01:00
Josef Kemetmüller
d22d030503 Fix rendering of metrics with special characters
My main motivation here is to get metrics with brackets to work in order
to support "pytest" test names:

- test_foo.py::test_bar[1]
- test_foo.py::test_bar[2]

I couldn't find an "HTML escape"-style function that would generate
valid html `id` attribute names from random strings, so I went with a
hash digest instead.
2025-02-27 09:25:42 +01:00
John Ericson
18c0d76210 Merge pull request #1444 from NixOS/use-legacy-ssh-store
Use `LegacySSHStore`
2025-02-18 14:37:17 -05:00
John Ericson
4a4a0f901c Use LegacySSHStore
In https://github.com/NixOS/nix/pull/10748 it is extended with
everything we need.
2025-02-18 14:07:42 -05:00
John Ericson
881462bb4e Merge pull request #1447 from NixOS/newer-2.6
Bump to newer 2.26.* Nix version
2025-02-18 13:00:40 -05:00
John Ericson
af72b694d8 Bump to newer 2.26.* Nix version
Needed one more thing before trying out using `LegacySSHStore` directly.

Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/674a87462cb93f605d4fbeef607d3453e7e5a7d8?narHash=sha256-TBoHqnIdVWhsBcL05vO2B1hSl9m//5Mz2NU%2BPMk3h3Y%3D' (2025-02-16)
  → 'github:NixOS/nix/e310c19a1aeb1ce1ed4d41d5ab2d02db596e0918?narHash=sha256-q/RgA4bB7zWai4oPySq9mch7qH14IEeom2P64SXdqHs%3D' (2025-02-18)
2025-02-18 12:43:31 -05:00
John Ericson
c92342d12f Merge pull request #1446 from NixOS/newer-2.6
Bump to newer 2.26.* Nix version
2025-02-16 19:10:10 -05:00
John Ericson
df07670a21 Bump to newer 2.26.* Nix version
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/970942f45836172fda410a638853382952189eb9?narHash=sha256-jGFuyYKJjJZsBRoi7ZcaVKt1OYxusz/ld1HA7VD2w/0%3D' (2025-02-12)
  → 'github:NixOS/nix/674a87462cb93f605d4fbeef607d3453e7e5a7d8?narHash=sha256-TBoHqnIdVWhsBcL05vO2B1hSl9m//5Mz2NU%2BPMk3h3Y%3D' (2025-02-16)
2025-02-16 18:44:32 -05:00
John Ericson
51944a5fa5 Merge pull request #1443 from NixOS/nix-2.26
Nix 2.26
2025-02-13 22:13:32 -05:00
John Ericson
341b2f1309 Update build system to depend on Nix 2.26 2025-02-13 21:54:35 -05:00
John Ericson
4dc0f11379 Update flake.nix for Nix 2.26
Flake lock file updates:

• Removed input 'libgit2'
• Updated input 'nix':
    'github:NixOS/nix/d652513e4519ed4eb48c92f8670e5a71c7793fc3?narHash=sha256-mIpJgIwPS4o4xYhN1B%2B/fHESEXoxpu6nVoZTzZ0MfTg%3D' (2025-02-12)
  → 'github:NixOS/nix/970942f45836172fda410a638853382952189eb9?narHash=sha256-jGFuyYKJjJZsBRoi7ZcaVKt1OYxusz/ld1HA7VD2w/0%3D' (2025-02-12)
• Removed input 'nix/libgit2'
• Updated input 'nix-eval-jobs':
    'github:nix-community/nix-eval-jobs/6d4fd5a93d7bc953ffa4dcd6d53ad7056a71eff7?narHash=sha256-1dZLPw%2BnlFQzzswfyTxW%2B8VF1AJ4ZvoYvLTjlHiz1SA%3D' (2025-02-13)
  → 'github:nix-community/nix-eval-jobs/4b392b284877d203ae262e16af269f702df036bc?narHash=sha256-3wIReAqdTALv39gkWXLMZQvHyBOc3yPkWT2ZsItxedY%3D' (2025-02-14)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/dbebdd67a6006bb145d98c8debf9140ac7e651d0?narHash=sha256-Xc9lEtentPCEtxc/F1e6jIZsd4MPDYv4Kugl9WtXlz0%3D' (2024-09-18)
  → 'github:NixOS/nixpkgs/97a719c9f0a07923c957cf51b20b329f9fb9d43f?narHash=sha256-1o1qR0KYozYGRrnqytSpAhVBYLNBHX%2BLv6I39zGRzKM%3D' (2025-02-13)
2025-02-13 21:54:31 -05:00
John Ericson
ea09952b7e Merge pull request #1442 from NixOS/clean-up-flake-lockfile
Clean up flake lockfile stuff
2025-02-13 20:52:40 -05:00
John Ericson
81d21979ef Clean up flake lockfile stuff
The `flake = false;` for `nix-eval-jobs` didn't fully take before.

Flake lock file updates:

• Removed input 'nix-eval-jobs/flake-parts'
• Removed input 'nix-eval-jobs/flake-parts/nixpkgs-lib'
• Removed input 'nix-eval-jobs/nix-github-actions'
• Removed input 'nix-eval-jobs/nixpkgs'
• Removed input 'nix-eval-jobs/treefmt-nix'
• Removed input 'nix-eval-jobs/treefmt-nix/nixpkgs'
2025-02-13 20:23:08 -05:00
John Ericson
0ed9a82912 Merge pull request #1441 from NixOS/nix-2.25
Nix 2.25
2025-02-13 19:53:07 -05:00
John Ericson
80241fc8be Make code change necessary for building with Nix 2.25 2025-02-13 19:10:09 -05:00
John Ericson
4347833f45 Rework to synchronize deps
Bypass `nix-eval-job`'s flake, and just call-package it, for
fine-grained control.
2025-02-13 19:03:37 -05:00
John Ericson
8835cbd10f flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/a7fdef6858dd45b9d7bda7c92324c63faee7f509?narHash=sha256-XFznzb8L4SdUm9u%2Bw3DPpMWJhffuv%2B/6%2BaiVl00slns%3D' (2024-09-19)
  → 'github:NixOS/nix/d652513e4519ed4eb48c92f8670e5a71c7793fc3?narHash=sha256-mIpJgIwPS4o4xYhN1B%2B/fHESEXoxpu6nVoZTzZ0MfTg%3D' (2025-02-12)
• Updated input 'nix-eval-jobs':
    'github:nix-community/nix-eval-jobs/889ea1406736b53cf165b6c28398aae3969418d1?narHash=sha256-3wwtKpS5tUBdjaGeSia7CotonbiRB6K5Kp0dsUt3nzU%3D' (2024-12-10)
  → 'github:nix-community/nix-eval-jobs/6d4fd5a93d7bc953ffa4dcd6d53ad7056a71eff7?narHash=sha256-1dZLPw%2BnlFQzzswfyTxW%2B8VF1AJ4ZvoYvLTjlHiz1SA%3D' (2025-02-13)
2025-02-13 18:46:36 -05:00
John Ericson
9ad8ac586c Merge pull request #1440 from NixOS/legacy-ssh-expose-ssh-master
Use new `CommonSSHStoreConfig::createSSHMaster`
2025-02-13 18:30:41 -05:00
John Ericson
9a6928d93b Use new CommonSSHStoreConfig::createSSHMaster
This avoids some duplicated code, leveraging the same `StoreReference`
type that also undergirds the machine file dedup we just did prior.

By using `LegacySSHStoreConfig`, we're also taking a baby step towards
using the store interface rather than messing around with the protocol
internals.
2025-02-13 18:13:38 -05:00
John Ericson
810781a802 Merge pull request #1439 from NixOS/nix-next
Dedup machine file parsing, and other improvements
2025-02-13 18:10:08 -05:00
John Ericson
af9b0663f2 Merge branch 'master' into nix-next 2025-02-13 17:54:15 -05:00
Jörg Thalheim
c6f98202cd Merge pull request #1438 from NixOS/log-malformed-json
Log malformed JSON received from `nix-eval-jobs`
2025-02-12 12:58:18 +07:00
John Ericson
1dbc7f5845 Log malformed JSON received from nix-eval-jobs 2025-02-11 22:34:49 -05:00
John Ericson
c52845f560 Merge pull request #1421 from NixOS/nix-eval-jobs
Use `nix-eval-jobs` and delete `hydra-eval-jobs`
2025-02-07 19:41:38 -05:00
John Ericson
85383b9522 Render the nix-eval-jobs version too 2025-02-07 16:55:28 -05:00
Pierre Bourdon
2f92846e5a hydra-eval-jobs: remove, replaced by nix-eval-jobs
(cherry picked from commit ed7c58708cd3affd62a598a22a500ed2adf318bf)
2025-02-07 16:55:28 -05:00
Pierre Bourdon
d84ff32ce6 hydra-eval-jobset: Use nix-eval-jobs instead of hydra-eval-jobs
incrementally ingest eval results

nix-eval-jobs streams output, unlike hydra-eval-jobs. Now that we've
migrated, we can use this to:

1. Use less RAM by avoiding buffering a whole eval's worth of metadata
   into a Perl string and an array of JSON objects.
2. Make evals latency a bit lower by allowing the queue runner to start
   ingesting builds faster.

Also use the newly-restored constituents support in `nix-eval-jobs`

Note, we pass --workers and --max-memory-size to n-e-j

Lost in the h-e-j -> n-e-j migration, causing evaluation to always be
single threaded and limited to 4GiB RAM. Follow the config settings like
h-e-j used to do (via C++ code).

`nix-eval-jobs` should check `hydraJobs` and then `checks` with flakes

(cherry picked from commit 6d4ccff43c41adaf6e4b2b9bced7243bc2f6e97b)
(cherry picked from commit b0e9b4b2f99f9d8f5c4e780e89f955c394b5ced4)
(cherry picked from commit cdfc5c81e8037d3e4818a3e459d0804b2c157ea9)
(cherry picked from commit 4b107e6ff36bd89958fba36e0fe0340903e7cd13)

Co-Authored-By: Maximilian Bosch <maximilian@mbosch.me>
2025-02-07 16:55:28 -05:00
Pierre Bourdon
0c9726af59 flake: add nix-eval-jobs as input
(cherry picked from commit 684cc50d86608cccf7500ce00af89ea34c488473)
2025-02-07 16:55:28 -05:00
John Ericson
5100b85537 Merge pull request #1436 from obsidiansystems/test-aliased-constituents
Improve tests around constituents
2025-02-07 16:45:17 -05:00
John Ericson
141b5fd0b5 Improve tests around constituents
- Test how shorter names are preferred when multiple jobs resolve to the
  same derivation.

- Test the exact aggregate map we get, by looking in the DB.
2025-02-07 16:39:13 -05:00
John Ericson
8d78648e65 Merge pull request #1435 from obsidiansystems/flake-tests
Test using Hydra with flakes
2025-02-07 11:21:02 -05:00
John Ericson
8a8ac14877 Test using Hydra with flakes
It seemed there was no self-contained end-to-end test actually doing
this?!

Among other things, this will help ensure that the switch-over to
`nix-eval-jobs` is correct.
2025-02-06 21:30:49 -05:00
John Ericson
250668a19f Merge pull request #1426 from NixOS/queue-runner-wants-after
Make hydra-queue-runner want network-online.target
2024-12-05 19:28:15 -05:00
Martin Weinelt
efadb6a26c Make hydra-queue-runner want network-online.target
Just ordering yourself after network-online.target will not guarantee
that it will be loaded. You'll have to either want or require it. Hence
the following trace on recent nixpkgs versions:

evaluation warning: hydra-queue-runner.service is ordered after 'network-online.target' but doesn't depend on it
2024-12-03 01:44:55 +01:00
Janne Heß
3b16941b14 Merge pull request #1424 from AsterisMono/fix-darwin-tmp-path
reproduce.tt: Use realpath for tmpDir to fix macOS compatibility
2024-11-26 08:53:13 +01:00
Aaron Honeycutt
9de9cb0ad8 Update README (#1271)
* Update version in example

* Update docs to fix invalid indentifier when using 'hello'

* fix build issue for hello example

---------

Co-authored-by: Aaron Honeycutt <aaronhoneycutt@proton.me>
2024-11-26 08:52:24 +01:00
John Ericson
e75a4cbda8 Merge pull request #1422 from NixOS/meson
autotools -> meson
2024-11-25 10:13:36 -05:00
Chatnoir Miki
6456c1d7d6 reproduce.tt: Use realpath for tmpDir to fix macOS compatibility 2024-11-25 11:41:47 +08:00
Pierre Bourdon
182a48c9fb autotools -> meson
Original commit message:

> There are some known regressions regarding local testing setups - since
> everything was kinda half written with the expectation that build dir =
> source dir (which should not be true anymore). But everything builds and
> the test suite runs fine, after several hours spent debugging random
> crashes in libpqxx with MALLOC_PERTURB_...

I have not experienced regressions with local testing.

(cherry picked from commit 4b886d9c45cd2d7fe9b0a8dbc05c7318d46f615d)
2024-11-24 15:58:26 -05:00
John Ericson
f974891c76 Merge pull request #1420 from NixOS/nix-2.23
`sshPublicHostKey` fix for `master`
2024-10-24 17:03:20 +02:00
John Ericson
8515cb183e Merge branch 'nix-2.22' into nix-2.23 2024-10-21 11:23:41 -04:00
John Ericson
60dd7ec187 Merge branch 'nix-2.21' into nix-2.22 2024-10-21 11:23:30 -04:00
John Ericson
53b04ddf74 Merge branch 'nix-2.20' into nix-2.21 2024-10-21 11:23:20 -04:00
Martin Weinelt
4e2c06ec2c queue-runner: don't decode base64 hostkey in hydra
Nix expects a base64 encoded hostkey in SSHMaster, so make sure we don't
decode this prematurely in hydra.

Reported-By: Puck Meerburg <puck@puck.moe>
2024-10-21 11:22:44 -04:00
Jörg Thalheim
d3966d3e4c Merge pull request #1419 from NixOS/refactor-flake
make nixos module hydra from this repository by default
2024-10-20 15:06:48 +02:00
Jörg Thalheim
f442d74f6e remove unused nix dev flake inputs 2024-10-19 16:51:21 +00:00
Jörg Thalheim
a9a5b14331 make nixos module hydra from this repository by default
When people reach out to the git repository they probably want to use
hydra from the same source.
This also removes the need for an overlay with simpler and more
performant direct use of the nixpkgs passed in. Before it was
re-importing nixpkgs.

test
2024-10-19 16:42:38 +00:00
Jörg Thalheim
e6b9f0dec7 Merge pull request #1416 from Mindavi/bugfix/git-init-suppress-hint
nix-prefetch-git: set branch name to suppress hint from git
2024-10-19 18:20:08 +02:00
Jörg Thalheim
72899596df Merge pull request #1417 from Mindavi/bugfix/s3backup
S3Backup: fix compilation issue for undef MACHINE_LOCAL_STORE var
2024-10-19 18:19:39 +02:00
Jörg Thalheim
bdeec354c3 Merge pull request #1418 from NixOS/module-package
Make the in-tree package the default package
2024-10-19 18:09:02 +02:00
Martin Weinelt
1222ba03a6 Make the in-tree package the default package
There is an overlay for the `hydra` name, but `hydra_unstable` was used, which can refer to the nixpkgs package and lead to and outdated hydra version and requires configuring the correct package attribute downstream.
2024-10-19 17:30:59 +02:00
Rick van Schijndel
8a54924d2a nix-prefetch-git: set branch name to suppress hint from git
In my system logs I see this every time a new eval starts:

```
hydra-evaluator[PID]: hint: Using 'master' as the name for the initial branch. This default branch name
hydra-evaluator[PID]: hint: is subject to change. To configure the initial branch name to use in all
hydra-evaluator[PID]: hint: of your new repositories, which will suppress this warning, call:
hydra-evaluator[PID]: hint:
hydra-evaluator[PID]: hint:         git config --global init.defaultBranch <name>
hydra-evaluator[PID]: hint:
hydra-evaluator[PID]: hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hydra-evaluator[PID]: hint: 'development'. The just-created branch can be renamed via this command:
hydra-evaluator[PID]: hint:
hydra-evaluator[PID]: hint:         git branch -m <name>
```

This ensures this hint is not logged anymore and unclutters the syslog.
I presume it does not really matter what name is chosen for the branch.
2024-10-17 22:25:13 +02:00
Rick van Schijndel
2a7b070da0 S3Backup: fix compilation issue where MACHINE_LOCAL_STORE variable is undefined
See https://github.com/NixOS/hydra/pull/1414#issuecomment-2412350929

The variable is defined in src/lib/Hydra/Helper/Nix.pm

Error message without this patch:

```
hydra-evaluator[PID]: Couldn't require Hydra::Plugin::S3Backup : Global symbol "$MACHINE_LOCAL_STORE" requires explicit package name (did you forget to declare "my $MACHINE_LOCAL_STORE"?) at /nix/store/xxx-hydra-0-unstable-2024-09-24/libexec/hydra/lib/Hydra/Plugin/S3Backup.pm line 95.
hydra-evaluator[PID]: Compilation failed in require at /nix/store/xxx-hydra-perl-deps/lib/perl5/site_perl/5.38.2/Module/Runtime.pm line 314.
hydra-evaluator[PID]:  at /nix/store/xxx-hydra-perl-deps/lib/perl5/site_perl/5.38.2/Module/Pluggable.pm line 32.
```
2024-10-17 22:18:58 +02:00
John Ericson
c69e30122b Merge pull request #1411 from NixOS/nix-2.24-upgrade-wip
Nix 2.24 upgrade wip
2024-10-08 01:07:18 -04:00
John Ericson
750275d6e8 Avoid trailing slash that broke lookup 2024-10-07 11:43:58 -04:00
John Ericson
ceb8b48cce Fix type error with NAR accesssor 2024-09-24 12:14:23 -04:00
John Ericson
95003f2eb5 Merge pull request #1415 from NixOS/nix-2.23
Update to Nix 2.23
2024-09-24 12:00:47 -04:00
John Ericson
012cbd43f5 Add missing include 2024-09-24 11:51:17 -04:00
John Ericson
9a75361781 Merge branch 'nix-2.23' into nix-2.24-upgrade-wip 2024-09-24 11:50:03 -04:00
John Ericson
029116422d Update to Nix 2.23
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/1c8150ac312b5f9ba1b3f6768ff43b09867e5883' (2024-04-23)
  → 'github:NixOS/nix/5ffd239adc9b7fddca7a2a59a8b87da5af14ec4d' (2024-09-23)
2024-09-24 11:38:01 -04:00
John Ericson
108e409559 Merge branch 'nix-2.22' 2024-09-24 11:25:33 -04:00
John Ericson
1a5bd9e103 Merge remote-tracking branch 'upstream/nix-2.21' into nix-2.22 2024-09-24 11:25:10 -04:00
John Ericson
647191cd4a Merge remote-tracking branch 'upstream/nix-2.21' 2024-09-24 11:23:21 -04:00
Jörg Thalheim
73e51b94b1 Merge pull request #1414 from cleverca22/fix-binary-cache
fix nar endpoint for binary cache hosting
2024-09-20 13:24:47 +02:00
hacker1024
1ef6b5e7b4 Use Nix::Store and Nix::Utils in NARInfo.pm
These are required for the `signString` and `readFile` subroutines used when signing NARs.

(cherry picked from commit b94a7b6d5c)
2024-09-20 08:04:23 -03:00
Jörg Thalheim
44248d3cf4 Merge pull request #1412 from NixOS/hydra-compress-logs
set a default for hydra-compress-logs service
2024-09-20 09:21:34 +02:00
Michael Bishop
cc1b6d394e fix the binary cache calling isValidPath, and 2 other files with the same issue 2024-09-20 04:08:22 -03:00
zowoq
b472f55563 set a default for hydra-compress-logs service
follow up from 99ca560d58
2024-09-20 09:04:15 +02:00
Jörg Thalheim
c61bdd2c28 Merge pull request #1410 from NixOS/compiler-warnings
hydra-queue-runner: fix compilation warning
2024-09-20 09:00:55 +02:00
Jörg Thalheim
0231453cc5 hydra-eval-jobs: fix build against nix 2.24 2024-09-20 08:49:46 +02:00
Jörg Thalheim
ae787e5799 bump nix to 2.24 2024-09-20 08:49:32 +02:00
Jörg Thalheim
2dad87ad89 hydra-queue-runner: fix compilation warning
instead of converting to double, we can convert to float right away.
2024-09-20 07:50:24 +02:00
Jörg Thalheim
b6f44b5cd0 Merge pull request #1402 from NixOS/like-sub
tests: use `like` for testing regexes
2024-09-15 23:50:13 +02:00
Janne Heß
c8b7a0fea9 Merge pull request #1403 from NixOS/docs
Devdocs: mention nix develop and nproc
2024-09-03 15:03:01 +02:00
Jörg Thalheim
2d79b0a4da Merge pull request #1406 from NixOS/fix/remove-url-literal
default.nix: Drop URL literal
2024-08-27 21:41:42 +02:00
Martin Weinelt
f730433789 Create eval-jobset role and guard /api/push route 2024-08-27 19:49:05 +02:00
Janne Heß
916531dc9c api: Require POST for /api/push 2024-08-27 17:52:13 +02:00
Janne Heß
0ead8dc65c default.nix: Drop URL literal 2024-08-27 17:44:36 +02:00
Jörg Thalheim
b1a0501520 Merge pull request #1405 from hacker1024/patch-2
Use Nix::Store and Nix::Utils in NARInfo.pm
2024-08-27 17:09:37 +02:00
hacker1024
b94a7b6d5c Use Nix::Store and Nix::Utils in NARInfo.pm
These are required for the `signString` and `readFile` subroutines used when signing NARs.
2024-08-25 17:25:08 +10:00
Jörg Thalheim
9ee3c6aea2 Merge pull request #1400 from SuperSandro2000/feat/buildlogs-zstd
CompressLog: Add zstd compression
2024-08-21 09:43:39 +02:00
Jörg Thalheim
02a514234b hacking.md: make build parallel 2024-08-21 08:42:22 +02:00
Jörg Thalheim
54a9729a0f hacking.md: mention nix develop 2024-08-21 08:42:22 +02:00
Jörg Thalheim
250780aaf2 tests: use like for testing regexes
This gives us better diagnostics when the test fails.
2024-08-21 08:34:25 +02:00
Jörg Thalheim
4bb2f08be1 Merge pull request #1396 from nh2/hash-length-12
renderInputDiff: Increase git hash length 8 -> 12
2024-08-20 09:55:04 +02:00
Jörg Thalheim
c23973785f Merge pull request #1399 from Mindavi/bugfix/too-strict-timeouts
Looser timeouts, disable broken test, less verbose output
2024-08-20 09:54:40 +02:00
Sandro Jäckel
b2b2d6e26c Expand docs with new compression options 2024-08-18 17:59:36 +02:00
Sandro Jäckel
99ca560d58 Use configured compression in hydra-compress-logs service 2024-08-18 17:59:36 +02:00
Janne Heß
2c886f51d3 CompressLog: Add zstd compression 2024-08-09 18:52:03 +02:00
Janne Heß
7de7122479 Merge pull request #1398 from marius851000/document_foreman_user
Document the default Hydra user and port in hacking.md
2024-08-01 09:58:30 +02:00
Rick van Schijndel
54002f0fcf t/evaluator/evaluate-oom-job.t: always skip, the test always fails
We should look into how to resolve this, but I tried some things and nothing really worked.
Let's put it skipped for now until someone comes along to improve it.
2024-07-31 17:15:02 +02:00
Rick van Schijndel
a6b14369ee t/test.pl: increase event-timeout, set qvf
Only log issues/failures when something's actually up.
It has irked me for a long time that so much output came
out of running the tests, this seems to silence it.
It does hide some warnings, but I think it makes the output
so much more readable that it's worth the tradeoff.

Helps for highly parallel running of jobs, sometimes they'd not give output for a while.
Setting this timeout higher appears to help.
Not completely sure if this is the right place to do it, but it works fine for me.
2024-07-31 17:15:02 +02:00
Rick van Schijndel
578a3d2292 t: increase timeouts for slow commands with high load
We've seen many fails on ofborg, at lot of them ultimately appear to come down to
a timeout being hit, resulting in something like this:

Failure executing slapadd -F /<path>/slap.d -b dc=example -l /<path>/load.ldif.

Hopefully this resolves it for most cases.
I've done some endurance testing and this helps a lot.
some other commands also regularly time-out with high load:

- hydra-init
- hydra-create-user
- nix-store --delete

This should address most issues with tests randomly failing.

Used the following script for endurance testing:

```

import os
import subprocess

run_counter = 0
fail_counter = 0

while True:
    try:
        run_counter += 1
        print(f"Starting run {run_counter}")
        env = os.environ
        env["YATH_JOB_COUNT"] = "20"
        result = subprocess.run(["perl", "t/test.pl"], env=env)
        if (result.returncode != 0):
            fail_counter += 1
        print(f"Finish run {run_counter}, total fail count: {fail_counter}")
    except KeyboardInterrupt:
        print(f"Finished {run_counter} runs with {fail_counter} fails")
        break
```

In case someone else wants to do it on their system :).
Note that YATH_JOB_COUNT may need to be changed loosely based on your
cores.
I only have 4 cores (8 threads), so for others higher numbers might
yield better results in hashing out unstable tests.
2024-07-31 17:13:28 +02:00
marius david
ada51d70fc Document the default user and port in hacking.md 2024-07-23 22:39:22 +02:00
Niklas Hambüchen
bc19e7cd65 renderInputDiff: Increase git hash length 8 -> 12
See investigation on lengths required to be conflict-free in practice:

https://github.com/NixOS/hydra/pull/1258#issuecomment-1321891677
2024-07-20 23:45:12 +02:00
John Ericson
d7986226f0 Merge pull request #1227 from SuperSandro2000/gitea-push-hook
Add gitea push hook
2024-07-09 14:31:10 -04:00
John Ericson
2feddd8511 flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/2c42e7b8d9ea32e59c01334852599b548b214d31' (2024-05-23)
  → 'github:NixOS/nix/ef5c846e257e1e284ad47ed6be4308d190fe6531' (2024-05-29)
2024-05-29 17:05:41 -04:00
John Ericson
cd925e876f Merge branch 'master' into nix-next 2024-05-29 17:05:04 -04:00
John Ericson
b3e0d9a8b7 Merge pull request #1387 from NixOS/pipe-buffer-size
queue-runner: try larger pipe buffer sizes
2024-05-23 11:50:15 -04:00
Pierre Bourdon
5728011da1 queue-runner: try larger pipe buffer sizes
(cherry picked from commit 18466e8326)
2024-05-23 11:42:35 -04:00
John Ericson
91bb72e323 Merge pull request #1386 from NixOS/machine-dedup
Dedup with nix: use `nix::Machine::parseConfig`
2024-05-23 11:21:41 -04:00
John Ericson
09a1e64ed2 Dedup with nix: use nix::Machine::parseConfig
Companion to https://github.com/NixOS/nix/pull/10763
2024-05-23 09:59:46 -04:00
John Ericson
bede2a141a flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/5845fd59c34198ad52a7f7bcb6d3ea7176ca437b' (2024-05-22)
  → 'github:NixOS/nix/2c42e7b8d9ea32e59c01334852599b548b214d31' (2024-05-23)
2024-05-23 09:59:32 -04:00
John Ericson
b75bf5c882 Merge pull request #1385 from NixOS/machine-dedup
Utilize `nix::Machine` more fully
2024-05-23 00:00:58 -04:00
John Ericson
d55bea2a1e Utilize nix::Machine more fully
With https://github.com/NixOS/nix/pull/9839, the `storeUri` field is
much better structured, so we can use it while still opening the SSH
connection ourselves.
2024-05-22 22:02:46 -04:00
John Ericson
346badc66f flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/a57abbd143f8ed44e823c3244e93507f64020878' (2024-05-20)
  → 'github:NixOS/nix/5845fd59c34198ad52a7f7bcb6d3ea7176ca437b' (2024-05-22)
2024-05-22 22:00:38 -04:00
John Ericson
a940450875 Merge branch 'master' into nix-next 2024-05-22 22:00:25 -04:00
John Ericson
879ceb5cdc flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/60824fa97c588a0faf68ea61260a47e388b0a4e5' (2024-04-11)
  → 'github:NixOS/nix/1ebc34e9c54b740ea4f4466443047d709dccf5b2' (2024-05-16)
2024-05-21 18:23:35 -04:00
John Ericson
898ca2f600 Merge branch 'nix-2.20' into nix-2.21 2024-05-21 18:23:04 -04:00
John Ericson
559376e907 Merge pull request #1377 from SuperSandro2000/fix-doi-1375
Fix doi resolution after #1375
2024-05-21 18:11:21 -04:00
John Ericson
21044bc4d9 flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/8f42912c80c0a03f62f6a3d28a3af05a9762565d' (2024-01-30)
  → 'github:NixOS/nix/ab48ea416a203e9ccefb70aa634e27477e4c1ac4' (2024-05-15)
2024-05-21 18:01:30 -04:00
John Ericson
af120e7195 Merge pull request #1384 from NixOS/more-serve-proto-factor-out
Dedup more protocol code
2024-05-20 21:49:06 -04:00
John Ericson
71c4e2dc5b Dedup more protocol code
Use https://github.com/NixOS/nix/pull/10749
2024-05-20 18:19:59 -04:00
John Ericson
e4552ddf91 flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/beb3c2bc7ab781c1b8907b647c6e72b72fa9f56b' (2024-05-17)
  → 'github:NixOS/nix/a57abbd143f8ed44e823c3244e93507f64020878' (2024-05-20)
2024-05-20 18:11:37 -04:00
John Ericson
e4f2c84f8d flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/0930058189f350a3729cd5aef2ffc8dae2ad436e' (2024-05-08)
  → 'github:NixOS/nix/beb3c2bc7ab781c1b8907b647c6e72b72fa9f56b' (2024-05-17)
2024-05-17 20:02:54 -04:00
John Ericson
e10fc2bd13 Merge branch 'master' into nix-next 2024-05-17 19:59:41 -04:00
Janne Heß
998df1657e Merge pull request #1382 from Mic92/patch-1
README: update wiki link
2024-05-08 21:37:18 +02:00
Jörg Thalheim
f99cdaf5fe README: update wiki link 2024-05-08 21:31:32 +02:00
John Ericson
5e910fa2ce flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/00ca2b05b8fbbef09be5d1e4820857605d4c31b6' (2024-05-03)
  → 'github:NixOS/nix/0930058189f350a3729cd5aef2ffc8dae2ad436e' (2024-05-08)
2024-05-08 11:25:14 -04:00
John Ericson
4b767aa9a2 Merge branch 'master' into nix-next 2024-05-08 11:25:04 -04:00
John Ericson
3bf00e31c0 Merge pull request #1381 from NixOS/factor-out-tests
Try again to ensure hydra module is usable
2024-05-03 12:50:02 -04:00
John Ericson
2926aa1d64 Merge branch 'factor-out-tests' into nix-next 2024-05-03 12:44:51 -04:00
John Ericson
e149da7b9b Try again to ensure hydra module is usable
Nixpkgs only contains a `hydra_unstable`, not `hydra`, package, so
adjust the default accordingly, and then override it to our package in
the separate module which does that.
2024-05-03 12:41:17 -04:00
John Ericson
555ea44a7a Merge branch 'master' into nix-next 2024-05-03 12:35:06 -04:00
John Ericson
e81c36ac92 Merge pull request #1380 from NixOS/factor-out-tests
Factor out NixOS tests, and clean up
2024-05-03 12:33:50 -04:00
John Ericson
743795b2b0 Factor out NixOS tests, and clean up
Due to newer nixpkgs, there were a number of things that could be
cleaned up in the process.
2024-05-03 12:26:06 -04:00
John Ericson
50378aef22 Merge pull request #1379 from NixOS/remove-unneeded-override
Remove `PrometheusTiny` from overlay
2024-05-03 12:06:29 -04:00
John Ericson
92155f9a07 Remove PrometheusTiny from overlay
It's in Nixpkgs for a good while now.
2024-05-03 11:41:48 -04:00
John Ericson
29ce5c603c Merge pull request #1378 from NixOS/nix-2.22
Update to Nix 2.22
2024-05-03 11:14:49 -04:00
John Ericson
410077a26e Merge branch 'nix-2.22' into nix-next 2024-05-03 10:49:28 -04:00
John Ericson
4bd687e3e6 Update to Nix 2.22
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/60824fa97c588a0faf68ea61260a47e388b0a4e5' (2024-04-11)
  → 'github:NixOS/nix/1c8150ac312b5f9ba1b3f6768ff43b09867e5883' (2024-04-23)
• Added input 'nix/flake-parts':
    'github:hercules-ci/flake-parts/9126214d0a59633752a136528f5f3b9aa8565b7d' (2024-04-01)
• Added input 'nix/flake-parts/nixpkgs-lib':
    follows 'nix/nixpkgs'
• Added input 'nix/pre-commit-hooks':
    'github:cachix/pre-commit-hooks.nix/40e6053ecb65fcbf12863338a6dcefb3f55f1bf8' (2024-04-12)
• Added input 'nix/pre-commit-hooks/flake-compat':
    follows 'nix'
• Added input 'nix/pre-commit-hooks/flake-utils':
    'github:numtide/flake-utils/5aed5285a952e0b949eb3ba02c12fa4fcfef535f' (2022-11-02)
• Added input 'nix/pre-commit-hooks/gitignore':
    follows 'nix'
• Added input 'nix/pre-commit-hooks/nixpkgs':
    follows 'nix/nixpkgs'
• Added input 'nix/pre-commit-hooks/nixpkgs-stable':
    follows 'nix/nixpkgs'
2024-05-03 10:47:43 -04:00
Sandro Jäckel
1b8154e67f Fix doi resolution after #1375
This fixes:

> Caught exception in Hydra::Controller::Root->realisations "Undefined subroutine &Hydra::Controller::Root::queryRawRealisation called at /nix/store/v842xb35ph8ka1yi1xanjhk4xh1pn5nm-hydra-2024-04-22/libexec/hydra/lib/Hydra/Controller/Root.pm line 371."
2024-05-03 14:31:34 +02:00
Pierre Bourdon
b72528be50 web: serveFile: also serve a CSP putting served HTML in its own origin 2024-04-22 16:28:50 +02:00
John Ericson
8b48579593 Merge pull request #1374 from Mindavi/bugfix/rendering-issue-content-addressed
ca-derivations: fix rendering issue
2024-04-18 13:08:30 -04:00
John Ericson
39a4e4791e Switch (back) to Nix master
Re-creating `nix-next` after using it in #1375.

Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/60824fa97c588a0faf68ea61260a47e388b0a4e5' (2024-04-11)
  → 'github:NixOS/nix/aa438b8fbaebbbdb922655127053c4e8ea3e55bb' (2024-04-12)
2024-04-12 17:30:57 -04:00
John Ericson
ef7bf1e67b Merge pull request #1375 from NixOS/nix-2.21
Nix 2.21
2024-04-12 17:28:37 -04:00
John Ericson
ab1f64aa4d flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/c4ebb82da4eade975e874da600dc50e9dec610cb' (2024-02-12)
  → 'github:NixOS/nix/60824fa97c588a0faf68ea61260a47e388b0a4e5' (2024-04-11)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/a1982c92d8980a0114372973cbdfe0a307f1bdea' (2024-01-12)
  → 'github:NixOS/nixpkgs/1d6a23f11e44d0fb64b3237569b87658a9eb5643' (2024-04-11)
• Removed input 'nixpkgs-for-fileset'
2024-04-12 12:26:11 -04:00
Rick van Schijndel
3f913a771d t: content-addressed: add a comment about a misleading testcase 2024-04-03 22:55:42 +02:00
Rick van Schijndel
71986632ce hydra-server: findLog: fix issue with ca-derivations enabled
When content addressed derivations are built on the hydra server,
one may run into an issue where some builds suddenly don't load anymore.

This seems to be caused by outPaths that are NULL (which is
allowed for ca-derivations). Filter them out to prevent querying the
database for them, which is not supported by the database abstraction
layer that's currently in use.

On my instance this appears to resolve the issue.
I feel like I might be doing this at the wrong abstraction layer, but on
the other hand -- it seems to resolve it and it also doesn't really look
like it will hurt anything.

The test added in a previous commit uncovers this issue, and this commit
resolves it. So I'm happy with this patch for now.

The issue I was seeing on my server:

hydra-server[2549]: [error] Couldn't render template "undef error - DBIx::Class::SQLMaker::ClassicExtensions::puke(): Fatal: NULL-within-IN not implemented: The upcoming SQL::Abstract::Classic 2.0 will emit the logically correct SQL instead of raising this exception. at /nix/store/<hash>-hydra-unstable-2024-03-08_nix_2_20/libexec/hydra/lib/Hydra/Helper/Nix.pm line 190

See also short discussion here: https://github.com/NixOS/nixpkgs/pull/297392#issuecomment-2035366263
2024-04-03 22:47:22 +02:00
Rick van Schijndel
1665aed5e3 t: content-addressed: add test for caDependingOnFailingCA
This uncovers an issue with the front-end.
2024-04-03 22:45:53 +02:00
John Ericson
b676b08fac Merge pull request #1368 from Ma27/login-submit-btn
Use `submit` event in login form
2024-03-26 11:23:51 -04:00
John Ericson
d614163e9c Merge pull request #1370 from Ma27/reconnect-db
hydra-queue-runner: drop broken connections from pool
2024-03-26 11:21:35 -04:00
Maximilian Bosch
99afff03b0 hydra-queue-runner: drop broken connections from pool
Closes #1336

When restarting postgresql, the connections are still reused in
`hydra-queue-runner` causing errors like this

    main thread: Lost connection to the database server.
    queue monitor: Lost connection to the database server.

and no more builds being processed.

`hydra-evaluator` doesn't have that issue since it crashes right away.
We could let it retry indefinitely as well (see below), but I don't
want to change too much.

If the DB is still unreachable 10s later, the process will stop with a
non-zero exit code because of a missing DB connection. This however
isn't such a big deal because it will be immediately restarted
afterwards. With the current configuration, Hydra will never give up,
but restart (and retry) infinitely. To me that seems reasonable, i.e. to
retry DB connections on a long-running process. If this doesn't work
out, the monitoring should fire anyways because the queue fills up, but
I'm open to discuss that.

Please note that this isn't reproducible with the DB and the queue
runner on the same machine when using `services.hydra-dev`, because of
the `Requires=` dependency `hydra-queue-runner.service` ->
`hydra-init.service` -> `postgresql.service` that causes the queue
runner to be restarted on `systemctl restart postgresql`.

Internally, Hydra uses Nix's pool data structure: it basically has N
slots (here DB connections) and whenever a new one is requested, an idle
slot is provided or a new one is created (when N slots are active, it'll
be waited until one slot is free). The issue in the code here is however
that whenever an error is encountered, the slot is released, however the
same broken connection will be reused the next time. By using
`Pool::Handle::markBad`, Nix will drop a broken slot. This is now being
done when `pqxx::broken_connection` was caught.
2024-03-15 14:09:31 +01:00
ajs124
8f56209bd6 Merge pull request #1361 from Ma27/fix-gitea-test
flake: fix gitea integration test
2024-03-08 15:28:07 +01:00
Maximilian Bosch
806c375c33 Don't send gitea status update when build is started
This was the source of a flaky test because sometimes hydra-notify was
quick enough to send out `buildStarted` and sometimes it apparently
wasn't which was quickly spottable with `nix build --rebuild`.

Removing that status update doesn't make a difference functionally,
gitea doesn't differentiate between "queued" and "running", so we send
the same status ("pending") out on both events, so we'd even safe one
avoidable request.
2024-03-08 11:07:38 +01:00
Maximilian Bosch
669617ab54 Use submit event in login form
It's a pet peeve from me when logging into my personal Hydra that I
always have to press the button rather than hitting Return after entering
my password.

Reason for that is that the form doesn't have a "submit" button, so far
it was always listened to the "click" event. Submit does that and you
can hit Return alternatively.
2024-03-07 18:49:52 +01:00
Janne Heß
c45c06509a Merge pull request #1364 from K900/urlencode-logs
urlencode drv names when fetching logs
2024-03-01 10:11:08 +01:00
K900
9db5d0a88d urlencode drv names when fetching logs
Otherwise names with special characters like + break things.
2024-02-26 22:48:16 +03:00
John Ericson
973cb644d3 Merge pull request #1359 from Ma27/nix-perl-bindings
Update perl bindings for nix#9863
2024-02-12 12:55:50 -05:00
Maximilian Bosch
e499509595 Switch to new Nix bindings, update Nix for that
Implements support for Nix's new Perl bindings[1]. The current state
basically does `openStore()`, but always uses `auto` and doesn't support
stores at other URIs.

Even though the stores are cached inside the Perl implementation, I
decided to instantiate those once in the Nix helper module. That way
store openings aren't cluttered across the entire codebase. Also, there
are two stores used later on - MACHINE_LOCAL_STORE for `auto`,
BINARY_CACHE_STORE for the one from `store_uri` in `hydra.conf` - and
using consistent names should make the intent clearer then.

This doesn't contain any behavioral changes, i.e. the build product
availability issue from #1352 isn't fixed. This patch only contains the
migration to the new API.

[1] https://github.com/NixOS/nix/pull/9863
2024-02-12 18:50:56 +01:00
Maximilian Bosch
ceff5c5cfe flake: fix gitea integration test
This is an integration test that confirms that jobset definitions from
git repositories are correctly built and status updates pushed to the
gitea instance. The following things needed to be fixed:

* We're still on 23.05 where gitea is marked as insecure. Not going to
  update nixpkgs right now, but going for the quick fix.
* Since gitea 1.19 tokens have scopes that describe what's possible.
  Not specifying the scope in the DB appears to imply that no
  permissions are granted.
* Apparently we have three status updates now (for three status hooks,
  queued/started/finished). No idea why that was broken before, but the
  behavior still looks correct.
2024-02-12 18:30:03 +01:00
John Ericson
878c0f240e Switch (back) to Nix master
Re-creating `nix-next` after using it in #1354.

Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/8df68a213fc52a57b02a57005b0e06cc8de40ce3' (2024-01-25)
  → 'github:NixOS/nix/75ebb90a70f6320c1c7a1fca87a0a8adb0716143' (2024-01-30)
2024-01-30 14:09:38 -05:00
John Ericson
c1bd50a80d Merge pull request #1354 from NixOS/nix-2.20
Nix 2.20
2024-01-30 14:07:49 -05:00
John Ericson
14aabc1cc9 Update to released Nix 2.20
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/8df68a213fc52a57b02a57005b0e06cc8de40ce3' (2024-01-25)
  → 'github:NixOS/nix/8f42912c80c0a03f62f6a3d28a3af05a9762565d' (2024-01-30)
2024-01-30 13:33:20 -05:00
John Ericson
7b826ec5ad Merge branch 'nix-next' into nix-2.20 2024-01-30 13:26:45 -05:00
John Ericson
838648c0ce Merge pull request #1349 from NixOS/ca-no-new-col
Allow building content-addressed derivations with hydra, minimally
2024-01-26 17:54:02 -05:00
John Ericson
6ac4292912 Merge pull request #1351 from Ma27/hacking-fixes
Small fixes for the development environment
2024-01-26 17:22:42 -05:00
John Ericson
b503280256 Add migration to drop non-null constraints 2024-01-26 11:53:58 -05:00
Maximilian Bosch
b4c91b5a6a package: move foreman to nativeCheckInputs
In 1bd195a513 strictDeps was set for the
Hydra package. As a result, `checkInputs` aren't available anymore in
the local dev-shell which is the sole purpose of foreman, to start
services and a database for development.
2024-01-26 17:30:07 +01:00
Maximilian Bosch
8477009310 doc/manual: fix instructions in contribution guidelines
In 5db374cb50 the `bootstrap` script was
removed, however it's still referenced in the contribution guidelines.
Change that to `autoreconfPhase` as intended by the commit.
2024-01-26 17:28:07 +01:00
John Ericson
c62eaf248f Remove now-unneeded workaround 2024-01-26 01:20:07 -05:00
John Ericson
13b5f007ef Merge branch 'master' into ca-no-new-col 2024-01-26 01:19:45 -05:00
John Ericson
7f5889559e Merge pull request #1350 from NixOS/remove-old-workaround
Remove now-unneeded workaround
2024-01-26 01:13:37 -05:00
John Ericson
5ee0e443e4 Remove now-unneeded workaround 2024-01-26 01:08:11 -05:00
John Ericson
323b556dc8 Minimal CA support
This verison has a worse UI, but also chnages the schema less: One
non-null constraint is removed, but no new columns are added.

Co-Authored-By: Andrea Ciceri <andrea.ciceri@autistici.org>
Co-Authored-By: regnat <rg@regnat.ovh>
2024-01-26 00:34:58 -05:00
John Ericson
458b9e4242 Merge pull request #1348 from NixOS/ca-prep
More CA derivations prep
2024-01-25 21:53:40 -05:00
John Ericson
fcde5908d8 More CA derivations prep
Again, with care not to change the schema in any way.
2024-01-25 21:32:22 -05:00
John Ericson
083ef46c12 Merge pull request #1344 from delroth/google-popup
web: disable Sign in with Google popup
2024-01-25 16:36:16 -05:00
John Ericson
7a53b866f6 Merge branch 'master' into nix-next
• Updated input 'nix' (merge):
    'github:NixOS/nix/212ba69e6f995992f8b4e4c0656d19c0156c8714'
    'github:NixOS/nix/2c4bb93ba5a97e7078896ebc36385ce172960e4e' (2024-01-25)
  → 'github:NixOS/nix/8df68a213fc52a57b02a57005b0e06cc8de40ce3' (2024-01-25)
2024-01-25 16:26:07 -05:00
John Ericson
8a02bb7c36 Merge pull request #1347 from NixOS/simplify-req-features
Simplify `StoreConfig::getDefaultSystemFeatures` call
2024-01-25 16:17:25 -05:00
John Ericson
c64eed7d07 Simplify StoreConfig::getDefaultSystemFeatures call
That method is now static.
2024-01-25 15:58:07 -05:00
John Ericson
aed130cd17 flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/03e96b9dc011a16a0f6db9c7cb021ff93f8dcf88' (2024-01-19)
  → 'github:NixOS/nix/2c4bb93ba5a97e7078896ebc36385ce172960e4e' (2024-01-25)
2024-01-25 15:57:39 -05:00
John Ericson
7a6c401d42 Merge pull request #1346 from obsidiansystems/flake-reorg
Clean up the flake/build in a a few ways
2024-01-25 15:55:47 -05:00
John Ericson
b5ed0787f7 Replace "not Perl" and "Perl again" with something more self-explanatory 2024-01-25 14:55:10 -05:00
John Ericson
c5f37eca91 Reorganize hydra modules 2024-01-25 14:55:07 -05:00
John Ericson
73b6c1fb11 Filter out (mosts test) when !doCheck 2024-01-25 14:55:07 -05:00
John Ericson
4bbc7b8f75 Use the Nixpkgs fileset library to filter source
Now I can change Nix files without causing rebuilds.
2024-01-25 14:55:07 -05:00
John Ericson
d6d6d1b649 flake.nix: Temporarily add a second Nixpkgs for lib.fileset
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/b38e5a665e9d0aa7975beb0ed12e42d13a392e74' (2023-12-13)
  → 'github:NixOS/nix/03e96b9dc011a16a0f6db9c7cb021ff93f8dcf88' (2024-01-19)
• Added input 'nixpkgs-for-fileset':
    'github:NixOS/nixpkgs/a77ab169a83a4175169d78684ddd2e54486ac651' (2024-01-24)
2024-01-25 14:55:07 -05:00
John Ericson
1bd195a513 Clean up deps
- `strictDeps`

- Ensure it builds with and without `doCheck`
2024-01-25 14:55:07 -05:00
John Ericson
1471aacadc Split out a package.nix
Just like we did with Nix.
2024-01-25 14:55:06 -05:00
John Ericson
62ddeb0ff0 Merge pull request #1345 from SuperSandro2000/patch-2
Remove automake, libtool
2024-01-25 14:47:07 -05:00
Sandro
a876e46894 Remove automake, libtool
Those are already part of autoreconfHook
2024-01-25 17:12:40 +01:00
Pierre Bourdon
6df06b089e web: disable Sign in with Google popup 2024-01-25 09:27:46 +01:00
John Ericson
cc50fdff6f Merge pull request #1343 from obsidiansystems/default-machine-file-features
Use `StoreConfig::getDefaultSystemFeatures` for default machine config
2024-01-24 21:44:32 -05:00
John Ericson
b1fa6b3aac Use StoreConfig::getDefaultSystemFeatures for default machine config
We have to oddly make a `StoreConfig` subclass to get it, but
https://github.com/NixOS/nix/pull/9848 will fix that.

The purpose of this is to ensure that, absent an explicit config,
`localhost` includes `ca-derivations` and `recursive-nix` if those
experimental features are enabled.

Very much the complement of #1342, the previous PR.
2024-01-24 21:37:13 -05:00
John Ericson
f6a2b7562a Merge pull request #1342 from obsidiansystems/dedup-required-system-features
Use `nix::ParsedDerivation::getRequiredSystemFeatures()`
2024-01-24 21:13:49 -05:00
John Ericson
07cb5d1b7c Use nix::ParsedDerivation::getRequiredSystemFeatures()
A slight dedup, and also ensures that floating CA derivations require a
`ca-derivations` experimental feature. This fixes the scheduling issue
that @SuperSandro2000 found.
2024-01-24 21:04:14 -05:00
John Ericson
449eb2d873 Use more nix::Machine fields
The upstream fields were made to match Hydra, so we can get rid of the
extra fields temporary added in
70e5469303.
2024-01-24 20:14:31 -05:00
John Ericson
2bdbf51d7d flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/b6aee9a93f6646bbffd919d362a5c75c37bb9caa' (2024-01-23)
  → 'github:NixOS/nix/212ba69e6f995992f8b4e4c0656d19c0156c8714' (2024-01-24)
2024-01-24 18:46:56 -05:00
John Ericson
9e7ac58042 Merge branch 'master' into nix-next 2024-01-24 18:36:03 -05:00
John Ericson
d45e14fd43 Merge pull request #1316 from NixOS/ca-derivations-prep
Prepare for CA derivation support with lower impact changes
2024-01-24 18:12:42 -05:00
John Ericson
9a86da0e7b Merge branch 'master' into nix-next 2024-01-23 15:49:14 -05:00
John Ericson
d02e20a4c1 Merge pull request #1341 from NixOS/machine-dedup
Use Nix's `Machine` type in a minimal way
2024-01-23 15:38:19 -05:00
John Ericson
70e5469303 Use Nix's Machine type in a mimimal way
This is *just* using the fields from that type, and only where the types
coincide. (There are two fields with different types, `speedFactor` most
interestingly.) No code is reused, so we can be sure that no behavior is
changed.

Once the types are reconciled on the Nix side, then we can start
carefully actually reusing code.

Progress on #1164
2024-01-23 12:18:57 -05:00
John Ericson
2e6ee28f9b Machine -> ::Machine so we don't conflict with Nix's 2024-01-23 11:03:19 -05:00
John Ericson
20b0ad3ba2 Merge pull request #1339 from NixOS/use-nix-ssh
Use Nix's `SSHMaster`
2024-01-23 10:35:02 -05:00
John Ericson
7386caaecf Use Nix's SSHMaster 2024-01-23 10:24:02 -05:00
John Ericson
84c46b6b68 Update to newer Nix
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/74534829f23b668fb9b2f2a14ff6afa4d5e71d4a' (2024-01-22)
  → 'github:NixOS/nix/b6aee9a93f6646bbffd919d362a5c75c37bb9caa' (2024-01-23)
2024-01-23 10:21:48 -05:00
John Ericson
f1d9230f25 Merge remote-tracking branch 'upstream/master' into nix-next 2024-01-23 01:18:13 -05:00
John Ericson
f5c0efb11e Merge pull request #1340 from NixOS/start-using-nix-ssh
Replace `Child` with `SSHMaster::Connection`
2024-01-23 01:17:26 -05:00
John Ericson
4e8fbaa3d6 Replace Child with SSHMaster::Connection
Nix defines basically an identical struct for the same purpose, so let's
just use that.
2024-01-23 01:11:46 -05:00
John Ericson
34c51fcea9 Merge pull request #1165 from obsidiansystems/factor-out-proto
Begin factoring out the protocol code
2024-01-22 14:49:07 -05:00
John Ericson
4ac31c89df Use nix::serv_proto::BasicConnection in build_remote.cc
- Use the type itself

  This lays the foundation for being able to dedup the protocol code.

- Use `BasicConnection::handshake`, replacing ours.

- Use `BasicConnection::queryValidPaths`

- Use `BasicConnection::putBuildDerivationRequest`
2024-01-22 14:20:39 -05:00
John Ericson
db7aa01b8d Update to newer Nix master
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/b7e016ab2464ad2e7e2e856ad0f173157135aae0' (2023-12-10)
  → 'github:NixOS/nix/74534829f23b668fb9b2f2a14ff6afa4d5e71d4a' (2024-01-22)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/e9f06adb793d1cca5384907b3b8a4071d5d7cb19' (2023-12-03)
  → 'github:NixOS/nixpkgs/a1982c92d8980a0114372973cbdfe0a307f1bdea' (2024-01-12)
• Removed input 'nix/lowdown-src'
2024-01-22 14:14:59 -05:00
John Ericson
89cfe26533 Merge remote-tracking branch 'upstream/master' into nix-next 2024-01-22 13:01:40 -05:00
John Ericson
588a0c5269 Merge remote-tracking branch 'upstream/master' into ca-derivations-prep 2023-12-23 19:19:54 -05:00
John Ericson
02e453fc8c Merge pull request #1329 from NixOS/small-std-optional-cleanup
Clean up `std::optional` dereferencing in the queue runner
2023-12-23 19:18:41 -05:00
John Ericson
75f26f1fc4 Clean up std::optional dereferencing in the queue runner
Instead of doing this partial operation a number of times, assert (with
a comment, get a reference to the thing inside, and use that just once.
(This refactor was done twice, "just once" for each time.)
2023-12-23 19:10:58 -05:00
John Ericson
3c89067f52 Merge pull request #1328 from JackKelly-Bellroy/doc-store-uri
Document the `store_uri` parameter by way of example
2023-12-23 03:57:10 -05:00
Jack Kelly
abd858d3dc Document the store_uri parameter by way of example 2023-12-19 07:54:40 +10:00
John Ericson
163dbf7f54 Merge pull request #1327 from NixOS/latest-2.19
flake.lock: Update Nix
2023-12-14 00:57:19 -05:00
John Ericson
642156372f Merge branch 'latest-2.19' into ca-derivations-prep 2023-12-14 00:33:22 -05:00
John Ericson
7517c134c5 flake.lock: Update Nix
Newer 2.19-maintenance has some `restricted-eval` fixes that benefit
Hydra.

Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/50f8f1c8bc019a4c0fd098b9ac674b94cfc6af0d' (2023-12-11)
  → 'github:NixOS/nix/b38e5a665e9d0aa7975beb0ed12e42d13a392e74' (2023-12-13)
2023-12-14 00:32:15 -05:00
John Ericson
6e67884ff1 One more queryDerivationOutputMap should use the eval store param 2023-12-11 14:05:18 -05:00
John Ericson
a6b6c5a539 Revert query -- those columns don't exist yet! 2023-12-11 12:58:54 -05:00
John Ericson
ebfefb9161 Sync up with some changes done to the main CA branch 2023-12-11 12:46:36 -05:00
John Ericson
8783dd53f6 Merge remote-tracking branch 'upstream/master' into ca-derivations-prep 2023-12-11 12:42:43 -05:00
John Ericson
f3a760ad9c Merge pull request #1324 from obsidiansystems/serve-proto-build-options-serializer
Use `ServeProto::Serialise<ServeProto::BuildOptions>`
2023-12-11 10:45:33 -05:00
John Ericson
8c10331ee8 Fix totalNarSize summation
I accidentally removed it in d0d3b0a298.
2023-12-10 14:05:26 -05:00
John Ericson
20f5a2120c Use ServeProto::Serialise<ServeProto::BuildOptions> 2023-12-10 13:24:17 -05:00
John Ericson
b56d2383c1 Do not attempt to speak a newer version of the protocol
Both sides need to agree on a version (with `std::min`) for anything to
work. Somehow... we've never done this.

With this comment, the next commit succeeds. Without this commit, the
next commit fails. This is because the next commit exposes serializers
which do different things for proto version 2.7, and we're currently
requesting 2.6.

Opened https://github.com/NixOS/nix/issues/9584 to track this issue
2023-12-10 13:24:17 -05:00
John Ericson
2bd67562b5 Merge pull request #1323 from obsidiansystems/serve-proto-build-options
Use `ServeProto::BuildOption`
2023-12-10 13:23:43 -05:00
John Ericson
69a5b00e60 Use ServeProto::BuildOption
More deduplication with Nix.
2023-12-10 13:01:00 -05:00
John Ericson
1d80b72ffb flake.lock: Update Nix master
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/c8458bd731eb1c74159bebe459ea00165e056b65' (2023-12-09)
  → 'github:NixOS/nix/b7e016ab2464ad2e7e2e856ad0f173157135aae0' (2023-12-10)
2023-12-10 13:00:47 -05:00
John Ericson
105fd18fee Merge pull request #1322 from NixOS/use-UnkeyedValidPathInfo-serializer
Use `ServeProto::Serialise<UnkeyedValidPathInfo>` for `QueryValidPaths`
2023-12-10 11:52:56 -05:00
John Ericson
f6f817926a std::move the into the path info map 2023-12-09 12:12:00 -05:00
John Ericson
d0d3b0a298 Use ServeProto::Serialise<UnkeyedValidPathInfo> for QueryValidPaths
Companion to already-merged https://github.com/NixOS/nix/pull/9560
2023-12-09 12:08:04 -05:00
John Ericson
3f932a6731 build-remote: Use std::map<StorePath, UnkeyedValidPathInfo>
It is less denormalized
2023-12-09 11:59:09 -05:00
John Ericson
aaa0e128c1 flake.lock: Update Nix master
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/c3827ff6348a4d5199eaddf8dbc2ca2e2ef46ec5' (2023-12-07)
  → 'github:NixOS/nix/c8458bd731eb1c74159bebe459ea00165e056b65' (2023-12-09)
2023-12-09 11:59:02 -05:00
John Ericson
4515b5aa17 Merge pull request #1321 from NixOS/master
Mere `master` into `nix-next`
2023-12-09 11:53:58 -05:00
John Ericson
411e4d0c24 Let tests themselves intentionally leak temp dir (#1320)
* Let tests themselves intentionally leak temp dir

By default Yath will clean up temporary files, so the result is the
same. But `--keep-dirs` can be passed to `yath test` telling Yath to
*not* clean them up instead. This is very useful for debugging.

* Update t/lib/HydraTestContext.pm

Co-authored-by: Cole Helbling <cole.e.helbling@outlook.com>
2023-12-08 16:30:31 +00:00
John Ericson
831021808c Merge pull request #1318 from obsidiansystems/use-build-result-serialiser
Use factored-out `BuildResult` serializer
2023-12-08 11:25:05 -05:00
John Ericson
2ee0068fdc Do not copy for both stores for now
It has a performance cost, and as the comment says we should be doing
the better solution. We want to land this preparatory change on prod
while the rest is still on staging, so we should just skip it for now.

Skipping it will not affect regular fixed-output and input-addressed
derivations, which are the only ones prod would deal with upon getting
this code.

The main CA derivations support branch will revert this commit so it
still works.
2023-12-07 15:05:03 -05:00
John Ericson
31ea6458ca Merge remote-tracking branch 'upstream/master' into ca-derivations-prep 2023-12-07 15:01:35 -05:00
John Ericson
20c8263e3c Update to Nix master
The point of this branch is to always track Nix master, so we are
proactively ready to upgrade to the next Nix release when it is ready.

Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/50f8f1c8bc019a4c0fd098b9ac674b94cfc6af0d' (2023-11-27)
  → 'github:NixOS/nix/c3827ff6348a4d5199eaddf8dbc2ca2e2ef46ec5' (2023-12-07)
• Added input 'nix/libgit2':
    'github:libgit2/libgit2/45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5' (2023-10-18)
2023-12-07 13:11:31 -05:00
John Ericson
91bbd5366f Merge pull request #1319 from NixOS/nixpkgs-newer-23.05
flake.lock: Update Nixpkgs
2023-12-07 13:10:08 -05:00
John Ericson
a45a27851b flake.lock: Update Nixpkgs
This will be required for upgrading Nix beyond 2.19.

Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/ef0bc3976340dab9a4e087a0bcff661a8b2e87f3' (2023-06-21)
  → 'github:NixOS/nixpkgs/e9f06adb793d1cca5384907b3b8a4071d5d7cb19' (2023-12-03)
2023-12-07 12:21:18 -05:00
John Ericson
6a54ab24e2 Use factored-out BuildResult serializer
For the record, here is the Nix 2.19 version:
https://github.com/NixOS/nix/blob/2.19-maintenance/src/libstore/serve-protocol.cc,
which is what we would initially use.

It is a more complete version of what Hydra has today except for one
thing: it always unconditionally sets the start/stop times.

I think that is correct at the other end seems to unconditionally
measure them, but just to be extra careful, I reproduced the old
behavior of falling back on Hydra's own measurements if `startTime` is
0.

The only difference is that the fallback `stopTime` is now measured from
after the entire `BuildResult` is transferred over the wire, but I think
that should be negligible if it is measurable at all. (And remember,
this is fallback case I already suspect is dead code.)
2023-12-07 02:00:22 -05:00
John Ericson
58707438ba Merge pull request #1317 from obsidiansystems/substitute-flag
`copyClosureTo`: Use `SubstituteFlag` instead of `bool`
2023-12-07 00:23:54 -05:00
John Ericson
86cd5e9076 copyClosureTo: Use SubstituteFlag instead of bool
This matches Nix (in the same serialization logic in
`src/libstore/legacy-ssh-store.cc`) and adds clarity.
2023-12-07 00:18:50 -05:00
John Ericson
11f8030b0f Add comment from GitHub about adding to store as code comment 2023-12-06 17:59:25 -05:00
John Ericson
3df8feb3a2 Add TODO about setting null instead of empty string in JSON
An empty string is a sneaky way to avoid hard failures --- things that
expect strings still get strings, but it does conversely open the door
up to soft failures (spooky-action-at-a-distance ones because the string
did not have the expected invariants).

"Fail fast" with null will ultimately make the system more robust, but
force us to fix more things up front, and I don't want to change this
without also fixing those things up front, especially as this commit is
for now just part of the the preparatory PR for which this is dead code.
2023-12-05 11:31:06 -05:00
John Ericson
069b7775c5 hydra-eval-jobs: Ensure we have output path if ca-derivations is disabled
Brought up by @thufschmitt in
https://github.com/NixOS/hydra/pull/1316#discussion_r1415111329 . This
makes this closer to what was originally there --- which just dispatched
off the experimental feature rather than the presence/absense of the
output, too.
2023-12-05 11:26:26 -05:00
John Ericson
e3443cd22a Put back nicer copyClosure instead of manual closure + copy
It looks like we accidentally got the old code back, probably after a merge
conflict resolution.
2023-12-04 17:41:11 -05:00
John Ericson
8046ec2668 Remove unused outputHashes variable
This looks like a stray copy paste.
2023-12-04 16:21:56 -05:00
John Ericson
9ba4417940 Prepare for CA derivation support with lower impact changes
This is just C++ changes without any Perl / Frontend / SQL Schema
changes.

The idea is that it should be possible to redeploy Hydra with these
chnages with (a) no schema migration and also (b) no regressions. We
should be able to much more safely deploy these to a staging server and
then production `hydra.nixos.org`.

Extracted from #875

Co-Authored-By: Théophane Hufschmitt <theophane.hufschmitt@tweag.io>
Co-Authored-By: Alexander Sosedkin <monk@unboiled.info>
Co-Authored-By: Andrea Ciceri <andrea.ciceri@autistici.org>
Co-Authored-By: Charlotte 🦝 Delenk Mlotte@chir.rs>
Co-Authored-By: Sandro Jäckel <sandro.jaeckel@gmail.com>
2023-12-04 16:14:47 -05:00
John Ericson
a5d44b60ea Merge pull request #1313 from obsidiansystems/split-buildRemote
Split the `buildRemote` function, take 2
2023-12-04 11:37:36 -05:00
John Ericson
363604846a Again, use const in for loop
As requested by @teh. Was lost in merge with master, now added back.
2023-12-04 11:31:05 -05:00
John Ericson
162b538912 Remove unused thisArrow variable 2023-12-04 11:27:39 -05:00
John Ericson
104baef503 Document the connection initialization process 2023-12-04 09:42:04 -05:00
John Ericson
3c5636162a Merge remote-tracking branch 'upstream/master' into split-buildRemote 2023-12-04 09:38:43 -05:00
Janne Heß
874fcae1e8 Merge pull request #1301 from delroth/queue-runner-perf
queue-runner: only re-sort runnables by prio once per dispatch cycle
2023-12-04 15:27:14 +01:00
Eelco Dolstra
4dc8fe0b08 Merge pull request #1312 from obsidiansystems/clean-up-deps
Cleanup deps
2023-12-04 15:15:09 +01:00
John Ericson
67eeabd518 Merge remote-tracking branch 'upstream/master' into split-buildRemote 2023-12-04 09:12:58 -05:00
John Ericson
622c25e3c4 Sedding prior to merge 2023-12-04 08:56:06 -05:00
Eelco Dolstra
f216bce0e6 Merge pull request #1314 from obsidiansystems/2.19
Upgrade to Nix 2.19
2023-12-01 17:07:51 +01:00
Eelco Dolstra
4d1c850512 Merge pull request #1308 from chayleaf/2.18
support nix 2.18
2023-12-01 15:10:29 +01:00
John Ericson
c922e73c11 Update to Nix 2.19
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/f5f4de6a550327b4b1a06123c2e450f1b92c73b6' (2023-10-02)
  → 'github:NixOS/nix/50f8f1c8bc019a4c0fd098b9ac674b94cfc6af0d' (2023-11-27)
2023-11-30 15:26:46 -05:00
John Ericson
e172461e55 Use const in for loop
As requested by @teh
2023-11-30 12:19:20 -05:00
John Ericson
0917145622 Make new functions not in header static 2023-11-30 12:19:05 -05:00
John Ericson
2bda7ca642 Further use Machine::Connection to deduplicate 2023-11-30 11:31:58 -05:00
John Ericson
831a2d9bd5 Merge remote-tracking branch 'upstream/master' into split-buildRemote 2023-11-30 11:27:40 -05:00
John Ericson
5db374cb50 Cleanup deps
- `nativeBuildInputs` vs `buildInputs`

- narrow down `with`s for clarity

- use `autoreconfHook` not `bootstrap` script

These sorts of changes have also been done in the Nix repo.
2023-11-30 10:48:17 -05:00
chayleaf
e9da80fff6 support nix 2.18 2023-11-21 18:41:52 +07:00
Janne Heß
8f48e4ddec Merge pull request #1268 from knedlsepp/fix-mime
Fix MIME types when serving .js and .css to fix rendering of HTML reports
2023-11-17 22:16:27 +01:00
Janne Heß
33f8a36736 Merge pull request #1304 from stigtsp/crypt-passphrase-argon2-output-len
Set output length of C::P::Argon2 hashes to 16
2023-10-20 16:03:18 +02:00
Stig Palmquist
6a5fb9efae Set output length of C::P::Argon2 hashes to 16
Since the default lengths in Crypt::Passphrase::Argon2 changed from 16
to 32 in in 0.009, some tests that expected the passphrase to be
unchanged started failing.
2023-10-20 00:09:28 +02:00
Janne Heß
c1a5ff3959 Merge pull request #1258 from nh2/patch-1
`renderInputDiff`: Increase git hash length 6 -> 8
2023-09-09 17:17:43 +02:00
Janne Heß
8520ab1391 Merge pull request #1300 from sternenseemann/doc-eval-builds
Document all_builds (/eval/{eval-id}/builds) endpoint
2023-09-09 17:11:52 +02:00
Janne Heß
8a413ce71a Merge pull request #1293 from arianvp/patch-1
Fix docs for  /eval/{id}  endpoint
2023-09-09 17:10:56 +02:00
Pierre Bourdon
b7c864c515 queue-runner: only re-sort runnables by prio once per dispatch cycle
The previous implementation was O(N²lg(N)) due to sorting the full
runnables priority list once per runnable being scheduled. While not
confirmed, this is suspected to cause performance issues and
bottlenecking with the queue runner when the runnable list gets large
enough.

This commit changes the dispatcher to instead only sort runnables per
priority once per dispatch cycle. This has the drawback of being less
reactive to runnable priority changes: the previous code would react
immediately, while this might end up using "old" priorities until the
next dispatch cycle. However, dispatch cycles are not supposed to take
very long (seconds, not minutes/hours), so this is not expected to have
much or any practical impact.

Ideally runnables would be maintained in a sorted data structure instead
of the current approach of copying + sorting in the scheduler. This
would however be a much more invasive change to implement, and might
have to wait until we can confirm where the queue runner bottlenecks
actually lie.
2023-09-08 23:38:30 +02:00
sternenseemann
e2195c46d1 hydra-api.yaml: document all_builds (/eval/{eval-id}/builds) 2023-08-30 15:08:11 +02:00
sternenseemann
113836ebae hydra-api.yaml: name JobsetEval parameter eval-id
This is more accurate since the id space is not shared between build and
eval ids.
2023-08-30 15:06:48 +02:00
Eelco Dolstra
00d30874da Merge pull request #1296 from DeterminateSystems/nix-2.17
Support Nix 2.17
2023-08-23 17:53:14 +02:00
Eelco Dolstra
35ccc9ebb2 Fix indentation
Co-authored-by: John Ericson <git@JohnEricson.me>
2023-08-23 17:04:45 +02:00
Linus Heckemann
9f0427385f Apply LTO fix suggested by Ericson2314 2023-08-20 14:55:56 +02:00
Linus Heckemann
b23431a657 Support Nix 2.17 2023-08-04 15:53:48 +02:00
Eelco Dolstra
60e2c377d3 Merge pull request #1295 from arianvp/patch-3
Fix documentation of defaultpath in api docs
2023-08-03 17:09:21 +02:00
Arian van Putten
a78664f1b5 Fix documentation of defaultpath in api docs 2023-07-20 14:43:03 +02:00
Arian van Putten
46246dcae3 Fix docs for /eval/{id} endpoint
You  need to pass it an eval-id, not a build-id pretty sure
2023-07-19 15:13:25 +02:00
Janne Heß
d135b123cd Merge pull request #1292 from Ma27/fix-queue-runner-stats
hydra-queue-runner: fix stats
2023-07-17 09:56:05 +02:00
Janne Heß
526e8bd744 Merge pull request #1291 from NixOS/update-nix-nixpkgs 2023-06-25 20:53:50 +02:00
Maximilian Bosch
5c35d1be20 hydra-queue-runner: fix stats 2023-06-25 17:28:15 +02:00
Eelco Dolstra
ce001bb142 Relax time interval checks
I saw one of these failing randomly.
2023-06-23 15:09:09 +02:00
Eelco Dolstra
9f69bb5c2c Fix compilation against Nix 2.16 2023-06-23 15:06:55 +02:00
Eelco Dolstra
a0c8440a5c Update to Nix 2.16 and NixOS 23.05
Flake lock file updates:

• Updated input 'nix':
    'github:nixos/nix/4acc684ef7b3117c6d6ac12837398a0008a53d85' (2023-02-22)
  → 'github:NixOS/nix/84050709ea18f3285a85d729f40c8f8eddf5008e' (2023-06-06)
• Added input 'nix/flake-compat':
    'github:edolstra/flake-compat/35bb57c0c8d8b62bbfd284272c928ceb64ddbde9' (2023-01-17)
• Updated input 'nixpkgs':
    follows 'nix/nixpkgs'
  → 'github:NixOS/nixpkgs/ef0bc3976340dab9a4e087a0bcff661a8b2e87f3' (2023-06-21)
2023-06-23 15:06:46 +02:00
Janne Heß
13ef4e3c5d Merge pull request #1286 from JulienMalka/fix-hydra-eval-jobs-dot
hydra-eval-jobs: fix jobs containing a dot being dropped
2023-05-08 14:48:33 +02:00
Julien Malka
b4099df91e hydra-eval-jobs: fix jobs containing a dot being dropped 2023-04-25 10:37:41 +02:00
Eelco Dolstra
082495e34e Merge pull request #1275 from Ma27/nix-2.13
Nix 2.13 + nixpkgs input update
2023-03-27 13:30:13 +02:00
Graham Christensen
399b61ff67 Merge pull request #1277 from Mindavi/systemd/network-online
systemd: hydra-queue-runner: wait for network-online
2023-03-24 09:56:29 -04:00
Graham Christensen
3da6ef0d6d Merge pull request #1281 from NixOS/rv-google-signin
Use new Google for Web signin
2023-03-24 09:55:22 -04:00
Rob Vermaas
f88bef15ed Use new Google for Web signin, the old way will be deprecated Mar 31st 2023 2023-03-14 09:04:12 +01:00
Rick van Schijndel
a084e204ae systemd: hydra-queue-runner: wait for network.target too
Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
2023-03-07 21:56:20 +01:00
Graham Christensen
ecfa817d30 Merge pull request #1279 from DeterminateSystems/drop-unnecessary-index
Drop unused IndexBuildOutputsOnPath index
2023-03-06 11:06:31 -05:00
Cole Helbling
8d53c3ca11 test: use ubuntu-latest 2023-03-06 07:56:05 -08:00
Cole Helbling
810d2e6b51 Drop unused IndexBuildOutputsOnPath index
Also it's larger than the actual table it's indexing lol.

    -[ RECORD 30 ]----------+-----------------------------------------
    table_name              | buildoutputs
    index_name              | indexbuildoutputsonpath
    index_scans_count       | 0
    index_size              | 31 GB
    table_reads_index_count | 2128699937
    table_reads_seq_count   | 0
    table_reads_count       | 2128699937
    table_writes_count      | 22442976
    table_size              | 28 GB
2023-03-06 07:56:05 -08:00
Maximilian Bosch
f44d3d6ec9 Update Nix to 2.13.3
Includes the following required fixes:

* perl-bindings are correctly initialized: 77d8066e83
* /etc/ must be unwritable in build sandbox: 4acc684ef7
2023-03-04 12:07:34 +01:00
Rick van Schijndel
65c1249227 systemd: hydra-queue-runner: wait for network-online
This prevents eval errors when a machine is just started and the network isn't yet online.
I'm running hydra on a laptop and the network takes a bit of time to come online (WLAN),
so it's nice if the evaluator starts only when the network actually goes online.

Otherwise an error like this can happen on the first eval(s):

```
error fetching latest change from git repo at `https://github.com/nixos/nixpkgs.git':
fatal: unable to access 'https://github.com/nixos/nixpkgs.git/': Could not resolve host: github.com
```
2023-02-16 19:24:53 +01:00
Linus Heckemann
73dff15039 tests: ports are numbers 2023-02-04 20:12:30 +01:00
Linus Heckemann
ddd3ac3a4d name tests 2023-02-04 20:12:30 +01:00
Maximilian Bosch
c7716817a9 Update Nix to 2.13 2023-02-04 20:11:53 +01:00
Linus Heckemann
5b35e13898 hydra-queue-runner: use initializer lists for constructing JSON
And also fix the parts that were broken
2023-02-04 20:08:27 +01:00
Linus Heckemann
96e36201eb hydra-queue-runner: adapt to nlohmann::json 2023-02-04 20:08:09 +01:00
Brad Bondurant
c6263c280c use project name in sysbuild query 2023-01-04 15:45:14 -05:00
Josef Kemetmüller
ad99d3366f Fix MIME types when serving .js and .css
To correctly render HTML reports we make sure to return the following MIME
types instead of "text/plain"

- *.css: "text/css"
- *.js: "application/javascript"

Fixes: #1267
2022-12-29 22:26:59 +01:00
Graham Christensen
f48f00ee6d Merge pull request #1256 from cransom/hydra-evaluator-broken-connection
exit with error if database connectivity lost
2022-12-22 19:28:51 -05:00
Eelco Dolstra
d1fac69c21 Merge pull request #1264 from SuperSandro2000/patch-2
Fix example config
2022-12-05 17:48:46 +01:00
Graham Christensen
01802efc17 Merge pull request #1263 from Ma27/fix-my-jobs-tab
Fix "My Jobs" tab in user dashboard
2022-12-05 01:55:49 +01:00
Sandro
7f816e3237 Fix link 2022-12-05 00:35:05 +01:00
Sandro
213879484d Fix example config 2022-12-05 00:22:35 +01:00
Eelco Dolstra
14d4624dc2 Merge pull request #1215 from knedlsepp/fix-hydra-with-latest-git
scmdiff: Hardcode `--git-dir`
2022-11-24 12:04:23 +01:00
Maximilian Bosch
fd765bc97a Fix "My Jobs" tab in user dashboard
Nowadays `Builds` doesn't reference `Project` directly anymore. This
means that simply resolving both `jobset` and `project` with a single
JOIN from `Builds` doesn't work anymore. Instead we need to resolve the
relation to `jobset` first and then the relation to `project`.

For similar fixes see e.g. c7c4759600.
2022-11-22 20:54:51 +01:00
Eelco Dolstra
d4d20f6484 Merge pull request #1262 from lheckemann/aarch64
Enable aarch64 support
2022-11-21 11:01:38 +01:00
Linus Heckemann
a8b89420bc Enable aarch64 support 2022-11-17 23:04:52 +01:00
Niklas Hambüchen
d1d171ee90 renderInputDiff: Increase git hash length 6 -> 8
Nixpkgs has so many commits that length 6 is often ambiguous,
making the use of the shown values with git difficult.
2022-11-02 17:30:32 +01:00
Casey Ransom
70ad3a924a exit with error if database connectivity lost
There's currently no automatic recovery for disconnected databases in
the evaluator. This means if the database is ever temporarily
unavailable, hydra-evaluator will sit and spin with no work
accomplished.

If this condition is caught, the daemon will exit and systemd will be
responsible for resuming the service.
2022-10-26 16:13:40 -04:00
John Ericson
3526d61ff2 Merge remote-tracking branch 'upstream/master' into split-buildRemote 2022-10-25 11:24:54 -04:00
Théophane Hufschmitt
143c31734f Move all the build remote utils to their namespace
Just don't pollute the global one
2022-10-25 10:04:29 +02:00
Janne Heß
312cb42275 Merge pull request #1234 from helsinki-systems/feat/squiggly-line
Add a squiggly line to the Hydra link on hover
2022-10-21 22:57:20 +02:00
Janne Heß
a67d3b47d2 Merge pull request #1255 from MaxHearnden/patch-1
Fix insecure advice in the manual
2022-10-21 10:00:52 +02:00
MaxHearnden
c737bed42f Fix insecure advice in the manual
Bring the manual in line with the configuration documentation
2022-10-19 16:24:01 +01:00
MaxHearnden
4a0c5a2570 Only guess domain when gitea_url is not set
allows for gitea integration when not using a uri e.g. gitea@example.com:example/example so long as gitea_http_url is set
2022-10-13 15:15:45 +01:00
ajs124
8f05b797e9 Merge pull request #1251 from Mic92/coreutils
fix deprecated chown syntax
2022-09-30 15:59:06 +02:00
Janne Heß
7e459e8c5a Merge pull request #1250 from Mic92/fix-ssh-prefix
hydra: fix localhost detection when protocol prefix are used
2022-09-30 10:06:29 +02:00
Jörg Thalheim
940c0d7d97 fix deprecated chown syntax 2022-09-29 21:22:13 +02:00
Jörg Thalheim
94d19e1972 hydra: fix localhost detection when protocol prefix are used 2022-09-29 20:46:13 +02:00
Eelco Dolstra
a8876a8956 Merge pull request #1249 from Mic92/docs
docs/hacking: update nixos module option for nix-daemon
2022-09-28 17:02:49 +02:00
Jörg Thalheim
2ff67cbacc docs/hacking: update nixos module option for nix-daemon 2022-09-27 22:44:43 +02:00
Janne Heß
53335323ae Merge pull request #1246 from Ma27/job-prometheus-metric-improvements
Job: expose `closuresize` and `size` (output size in the UI) as prometheus metrics
2022-09-22 16:21:42 +02:00
Maximilian Bosch
d3fe4ffbf6 Job: expose closuresize and size (output size in the UI) as prometheus metrics 2022-09-22 10:47:22 +02:00
Graham Christensen
d6cbf227cb Merge pull request #1243 from K900/maybe-fix-trees
Run the JS code to make build trees collapsible at the right time
2022-09-08 09:55:14 -04:00
Janne Heß
4c67562c0a Merge pull request #1237 from NixOS/update-nix
Update to Nix 2.11.0 and Nixpkgs 22.05
2022-09-08 12:08:48 +02:00
Eelco Dolstra
44e1efff7f Send the right nix-serve client version
We were using protocol version 6 but requesting version 4. The only
reason that this worked was because of a broken version check in
'nix-store --serve'. That was fixed in
c2d7456926,
which had the side-effect of breaking hydra-queue-runner.
2022-09-08 11:51:13 +02:00
Eelco Dolstra
b16470c544 nix flake info -> nix flake metadata
This gets rid of a deprecation warning.
2022-09-06 19:23:20 +02:00
Eelco Dolstra
1dbc100837 flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/b9cf655150b52d071c85a337cb5db96e735fa64a' (2022-07-11)
  → 'github:NixOS/nix/11e45768b34fdafdcf019ddbd337afa16127ff0f' (2022-08-27)
• Updated input 'nix/nixpkgs':
    'github:NixOS/nixpkgs/2fa57ed190fd6c7c746319444f34b5917666e5c1' (2022-05-31)
  → 'github:NixOS/nixpkgs/365e1b3a859281cf11b94f87231adeabbdd878a2' (2022-07-13)
2022-09-06 16:19:05 +02:00
Eelco Dolstra
d61702f86d Merge remote-tracking branch 'origin/master' into update-nix 2022-09-06 16:14:23 +02:00
ajs124
222a8047e4 Merge pull request #1244 from NixOS/drop/hipchat
Drop the HipChat plugin
2022-08-20 19:33:22 +02:00
Janne Heß
81228cae50 Merge pull request #1239 from AmandaCameron/patch-3
Update hydra-module.nix to use newer nixos options
2022-08-20 19:25:46 +02:00
Janne Heß
371402c3c1 Drop the HipChat plugin
https://en.wikipedia.org/wiki/HipChat says:
> Following this, HipChat and Stride customers were migrated to the
> Slack group collaboration platform in a transition that was completed by
> February 2019.
2022-08-20 19:16:43 +02:00
Janne Heß
9addaeb17f Add a squiggly line to the Hydra link on hover
The effect is the same as the one on links in mail bodys on
https://lists.apache.org/
2022-08-17 11:44:19 +02:00
K900
2b8a8fdd9c Make the tree a little less dense 2022-08-12 09:46:32 +03:00
K900
93bbd6925b Also restore the "expand all" and "collapse all" buttons 2022-08-12 09:46:17 +03:00
K900
74caaa696e Run the JS code to make build trees collapsible at the right time 2022-08-11 13:30:19 +03:00
Janne Heß
2b1c1e65d5 Merge pull request #1242 from Ma27/fix-ldap-docs
doc/configuration: fix ldap role mapping example
2022-08-08 13:56:34 +02:00
Maximilian Bosch
f6d45b0f0c doc/configuration: fix ldap role mapping example
To group is called `cancel-build`, not `cancel-builds` (note the
trailing `s`).
2022-08-08 13:35:56 +02:00
Eelco Dolstra
c511315b6b Merge pull request #1240 from 2xsaiko/outgoing/download-mime
Use libmagic for better output MIME detection
2022-08-05 11:15:20 +02:00
Marco Rebhan
a58e2f1a64 Use libmagic for better output MIME detection 2022-08-04 22:34:58 +02:00
Amanda Cameron
9656f16509 Update hydra-module.nix to use newer nixos options
nix.trustedUsers is deprecated as of 22.05, and since the nix.extraOptions config is just doing something similar, I moved that to the new nix.settings as well
2022-07-22 10:35:38 -04:00
Janne Heß
e2756042b8 Merge pull request #965 from helsinki-systems/css_more_content
Fit more content on screen
2022-07-13 23:47:04 +02:00
Eelco Dolstra
481ca71d6e Use new flake output naming convention 2022-07-12 15:03:27 +02:00
Eelco Dolstra
3e001a8f05 Remove newNixpkgs and a lot of packages that are in Nixpkgs 22.05 2022-07-12 14:58:57 +02:00
Eelco Dolstra
d5ba1bba50 Fix deprecation warning 2022-07-12 14:46:48 +02:00
Eelco Dolstra
c72bed5cb4 Fix tests
Use $NIX_REMOTE instead of the legacy environment variables.
2022-07-12 14:45:30 +02:00
Eelco Dolstra
e06c480fd6 flake.lock: Update
Flake lock file updates:

• Updated input 'newNixpkgs':
    'github:NixOS/nixpkgs/6e3ee8957637a60f5072e33d78e05c0f65c54366' (2022-03-15)
  → 'github:NixOS/nixpkgs/de5b3dd17034e6106e75746e81618e5bd408de8a' (2022-07-10)
• Updated input 'nix':
    'github:NixOS/nix/624e38aa43f304fbb78b4779172809add042b513' (2022-05-31)
  → 'github:NixOS/nix/b9cf655150b52d071c85a337cb5db96e735fa64a' (2022-07-11)
• Updated input 'nix/nixpkgs':
    'github:NixOS/nixpkgs/530a53dcbc9437363471167a5e4762c5fcfa34a1' (2022-02-19)
  → 'github:NixOS/nixpkgs/2fa57ed190fd6c7c746319444f34b5917666e5c1' (2022-05-31)
2022-07-12 14:45:30 +02:00
Eelco Dolstra
8dd1daac8a Update to Nix 2.10 2022-07-12 14:45:30 +02:00
Janne Heß
389ed2e110 Merge pull request #1235 from NixOS/drop/url-literal
Remove yet another URL literal
2022-07-12 10:23:07 +02:00
Janne Heß
38e033e7ce Remove yet another URL literal 2022-07-10 13:31:21 +02:00
Janne Heß
bf50ae0d36 Merge pull request #1224 from SuperSandro2000/dependabot/github_actions/actions/checkout-3
build(deps): bump actions/checkout from 2 to 3
2022-07-06 23:14:00 +02:00
Janne Heß
d58bfe0909 Merge pull request #1199 from NixOS/dependabot/github_actions/cachix/install-nix-action-17
build(deps): bump cachix/install-nix-action from 16 to 17
2022-07-06 23:12:57 +02:00
Sandro
a81c6a3a80 Match URIs that don't end in .git
Co-authored-by: Charlotte <lotte@chir.rs>
2022-07-01 22:21:32 +02:00
Janne Heß
e05118171b Merge pull request #1229 from helsinki-systems/fix/nix-cat-store
replace nix cat-store with nix store cat
2022-07-01 13:28:27 +02:00
Janne Heß
f2f82b3eee Merge pull request #1230 from helsinki-systems/fix/declarative-dynamic-runcommand
AddBuilds: fix declarative jobsets with dynamic runcommand enabled
2022-06-30 17:25:09 +02:00
ajs124
bb1f04ed86 AddBuilds: fix declarative jobsets with dynamic runcommand enabled
$project->{enable_dynamic_run_command} is undefined
2022-06-30 01:49:30 +02:00
ajs124
bab671124d replace nix cat-store with nix store cat
the former was deprecated in favor of the latter
2022-06-30 00:24:09 +02:00
Sandro Jäckel
750978a192 Add gitea push hook 2022-06-18 13:22:42 +02:00
Janne Heß
44841fc827 Merge pull request #1223 from SuperSandro2000/patch-1
Remove url literal
2022-06-17 14:33:28 +02:00
Sandro
183f58ca9f Remove url literal 2022-06-16 22:48:39 +02:00
Eelco Dolstra
fb26435fe9 Merge pull request #1222 from Ma27/nix-2.9
flake: Update Nix to 2.9.1
2022-06-16 15:06:11 +02:00
Maximilian Bosch
5c01800fbe flake: Update Nix to 2.9.1
NOTE: I'm well-aware that we have to be careful with this to avoid new
regressions on hydra.nixos.org, so this should only be merged after
extensive testing from more people.

Motivation: I updated Nix in my deployment to 2.9.1 and decided to also
update Hydra in one go (and compile it against the newer Nix). Given
that this also updates the C++ code in `hydra-{queue-runner,eval-jobs}`
this patch might become useful in the future though.
2022-06-16 14:54:57 +02:00
Janne Heß
cf9f38e43f Merge pull request #1211 from Ma27/fix-notifications-with-latest-git
Fix email notifications for jobsets w/git-inputs
2022-05-31 18:22:55 +02:00
Josef Kemetmüller
b6ea85a601 scmdiff: Hardcode --git-dir
The newest version of git refuses to work on repositories not owned by
the current user. This leads to issues with the /api/scmdiff endpoint:

May 27 11:16:05 myhydra hydra-server[923698]: fatal: unsafe repository ('/var/lib/hydra/scm/git/57ea036ec7ecd85c8dd085e02ecc6f12dd5c079a6203d16aea49f586cadfb2be' is owned by someone else)
May 27 11:16:05 myhydra hydra-server[923698]: To add an exception for this directory, call:
May 27 11:16:05 myhydra hydra-server[923698]:         git config --global --add safe.directory /var/lib/hydra/scm/git/57ea036ec7ecd85c8dd085e02ecc6f12dd5c079a6203d16aea49f586cadfb2be
May 27 11:16:05 myhydra hydra-server[923701]: warning: Not a git repository. Use --no-index to compare two paths outside a working tree
May 27 11:16:05 myhydra hydra-server[923701]: usage: git diff --no-index [<options>] <path> <path>

I used the same solution that was used in NixOS/nix#6440.

Fixes #1214
2022-05-27 12:12:44 +02:00
Maximilian Bosch
a8b590014b Fix email notifications for jobsets w/git-inputs
I started to wonder quite recently why Hydra doesn't send email
notifications anymore to me. I saw the following issue in the log of
`hydra-notify.service`:

    May 22 11:57:29 hydra 9bik0bxyxbrklhx6lqwifd6af8kj84va-hydra-notify[1887289]: fatal: unsafe repository ('/var/lib/hydra/scm/git/3e70c16c266ef70dc4198705a688acccf71e932878f178277c9ac47d133cc663' is owned by someone else)
    May 22 11:57:29 hydra 9bik0bxyxbrklhx6lqwifd6af8kj84va-hydra-notify[1887289]: To add an exception for this directory, call:
    May 22 11:57:29 hydra 9bik0bxyxbrklhx6lqwifd6af8kj84va-hydra-notify[1887289]:         git config --global --add safe.directory /var/lib/hydra/scm/git/3e70c16c266ef70dc4198705a688acccf71e932878f178277c9ac47d133cc663
    May 22 11:57:29 hydra 9bik0bxyxbrklhx6lqwifd6af8kj84va-hydra-notify[1886654]: error running build_finished hooks: command `git log --pretty=format:%H%x09%an%x09%ae%x09%at b0c30a7557685d25a8ab3f34fdb775e66db0bc4c..eaf28389fcebc2beca13a802f79b2cca6e9ca309 --git-dir=.git' failed with e>

This is also a problem because of Git's fix for CVE-2022-24765[1], so I
applied the same fix as for Nix[2], by using `--git-dir` which skips the
code-path for the ownership-check[3].

[1] https://lore.kernel.org/git/xmqqv8veb5i6.fsf@gitster.g/
[2] https://github.com/NixOS/nix/pull/6440
[3] To quote `git(1)`:
    > Specifying the location of the ".git" directory using this option
    > (or GIT_DIR environment variable) turns off the repository
    > discovery that tries to find a directory with ".git" subdirectory
2022-05-22 14:14:14 +02:00
Janne Heß
27023b514a Merge pull request #1210 from ulrikstrid/ulrikstrid-fix-github-pr
GithubPulls: Don't fail on missing `Link`
2022-05-18 17:48:50 +02:00
Ulrik Strid
3c71be5b5b GithubPulls: Don't fail on missing Link 2022-05-18 08:14:00 +02:00
Ivor Wanders
cba85a6a19 Add a link to the raw log. 2022-05-04 13:32:47 -04:00
Graham Christensen
7c133a98f8 Merge pull request #1203 from DeterminateSystems/ds-33/wait-child-on-eof
hydra-eval-jobs: Report forked worker process status information on exception
2022-05-02 15:35:12 -04:00
Kayla Firestack
065039beba feat(t/evaluator/evaluate-oom): comment intentions 2022-05-02 15:26:26 -04:00
Kayla Firestack
87f610e7c1 fix(t/evaluator/evaluate-oom): use test_context to get path to ./t/jobs instead of relative paths 2022-05-02 15:14:46 -04:00
Kayla Firestack
013a1dcabc fix(t/evaluator/evaluate-oom): check that the exit value of the systemd-run check is zero. Rework skip messages 2022-05-02 15:13:59 -04:00
Kayla Firestack
e917d9e546 fix(t/evaluator/evaluate-oom): convert systemd-run presence check to eval, fix indentaion, show relationships between flags and commands with indentation 2022-05-02 14:40:13 -04:00
Kayla Firestack
01ec004108 feat(t/evaluator/evaluate-oom-job): skip test if systemd-run is not present 2022-05-02 14:08:50 -04:00
Kayla Firestack
2c909c038f feat(t/evaluator/hydra-eval-jobs): add basic evaluation test for hydra-eval-jobs 2022-05-02 13:50:57 -04:00
Kayla Firestack
90769ab5ad feat(t/jobs): add test job to cause an OOM 2022-05-02 13:49:32 -04:00
Kayla Firestack
2cdd7974de fix(hydra-eval-jobs): fix typo 2022-04-29 13:06:16 -04:00
Kayla Firestack
62cdbc4138 feat(hydra-eval-jobs.cc): add check_pid_status_nonblocking to catch handler 2022-04-21 10:55:51 -04:00
Kayla Firestack
cb4fa0000f fix(hydra-eval-jobs.cc): add function to report pid status 2022-04-21 10:55:51 -04:00
Graham Christensen
5c90edd19f Merge pull request #1103 from DeterminateSystems/runcommand/dynamic
Dynamic RunCommand
2022-04-19 10:09:47 -04:00
dependabot[bot]
a179f0be61 build(deps): bump cachix/install-nix-action from 16 to 17
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 16 to 17.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v16...v17)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-11 15:26:03 +00:00
Graham Christensen
c44d9d9e91 Merge pull request #1194 from fricklerhandwerk/contributing
add contributor's guide with architecture notes
2022-04-07 20:35:06 -04:00
Graham Christensen
05ce23aaa2 Merge pull request #1197 from DeterminateSystems/civetweb-ipv6-smile
flake: add ipv6 support to civetweb
2022-04-07 14:37:32 -04:00
Cole Helbling
be6077d2bb doc/manual: demonstrate ipv6 metrics address for queue-runner 2022-04-07 11:29:18 -07:00
Cole Helbling
3f303b479c flake: add ipv6 support to civetweb 2022-04-07 11:29:18 -07:00
Graham Christensen
6d9fac2577 Merge pull request #1196 from DeterminateSystems/fixup-metrics-addr-option-name
doc/manual: fixup configuration option name
2022-04-07 14:29:14 -04:00
Cole Helbling
ae690d6602 doc/manual: fixup configuration option name
Oops.
2022-04-07 10:40:50 -07:00
Graham Christensen
e1965250b5 Merge pull request #1173 from DeterminateSystems/queue-runner-exporter
hydra-queue-runner metrics
2022-04-07 12:27:33 -04:00
Cole Helbling
f8dc48f171 hydra-queue-runner: fixup: remove extraneous newline 2022-04-06 17:53:11 -07:00
Graham Christensen
59ac96a99c Track the number of steps created 2022-04-06 20:23:02 -04:00
Graham Christensen
1c12c5882f hydra queue runner: instrument the process of loading new builds with prom 2022-04-06 20:18:29 -04:00
Graham Christensen
5de08d412e queue metrics: refactor the metrics into a struct 2022-04-06 20:00:30 -04:00
Graham Christensen
46f52b4c4e bring back the working version Cole made 2022-04-06 15:49:38 -04:00
Cole Helbling
5bff730f2c WIP: I love it when they delete the assignment operator :) 2022-04-06 11:41:40 -07:00
Cole Helbling
15e8fa8aff doc/manual: document queue-runner prometheus exporter configuration 2022-04-06 11:41:40 -07:00
Cole Helbling
edf3c348f2 hydra-queue-runner: make entire address configurable 2022-04-06 10:59:45 -07:00
Cole Helbling
33bc60b83c hydra-queue-runner: move exporter back to State::run
It's (arguably) better than risking pinning the thread at 100% due to
the busy `while` loop.
2022-04-06 10:49:14 -07:00
fricklerhandwerk
0803634a41 add architecture notes
meeting notes from @edolstra giving a one-hour tour of the code
2022-04-06 09:01:10 +02:00
Eelco Dolstra
8cbf065468 Merge pull request #1195 from NixOS/update-nix
Update to Nix 2.8.0pre20220404_e496241
2022-04-05 20:12:56 +02:00
Eelco Dolstra
71a036ed00 Update to Nix master
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/ec90fc4d1f42db3c5e3c74dc186487d10a28c221' (2022-04-05)
  → 'github:NixOS/nix/5fe4fe823c193cbb7bfa05a468de91eeab09058d' (2022-04-05)
• Updated input 'nix/nixpkgs':
    'github:NixOS/nixpkgs/82891b5e2c2359d7e58d08849e4c89511ab94234' (2021-09-28)
  → 'github:NixOS/nixpkgs/530a53dcbc9437363471167a5e4762c5fcfa34a1' (2022-02-19)
2022-04-05 17:31:30 +02:00
Cole Helbling
8c5636fe18 hydra-queue-runner: use port 9198 by default
Co-authored-by: Graham Christensen <graham@grahamc.com>
2022-04-02 17:32:14 -07:00
Graham Christensen
3c181463f0 Merge pull request #1191 from ncfavier/nixos-search
Prepare for nixos-search integration
2022-03-31 16:27:43 -04:00
Naïm Favier
5e3374cb86 Prepare for nixos-search integration 2022-03-31 12:55:15 +02:00
Graham Christensen
84f54cb011 Merge pull request #1189 from NixOS/fix-hang
openConnection(): Don't throw exceptions in forked child
2022-03-30 17:16:02 -04:00
Eelco Dolstra
bcaad1c934 openConnection(): Don't throw exceptions in forked child
On hydra.nixos.org the queue runner had child processes that were
stuck handling an exception:

  Thread 1 (Thread 0x7f501f7fe640 (LWP 1413473) "bld~v54h5zkhmb3"):
  #0  futex_wait (private=0, expected=2, futex_word=0x7f50c27969b0 <_rtld_local+2480>) at ../sysdeps/nptl/futex-internal.h:146
  #1  __lll_lock_wait (futex=0x7f50c27969b0 <_rtld_local+2480>, private=0) at lowlevellock.c:52
  #2  0x00007f50c21eaee4 in __GI___pthread_mutex_lock (mutex=0x7f50c27969b0 <_rtld_local+2480>) at ../nptl/pthread_mutex_lock.c:115
  #3  0x00007f50c1854bef in __GI___dl_iterate_phdr (callback=0x7f50c190c020 <_Unwind_IteratePhdrCallback>, data=0x7f501f7fb040) at dl-iteratephdr.c:40
  #4  0x00007f50c190d2d1 in _Unwind_Find_FDE () from /nix/store/65hafbsx91127farbmyyv4r5ifgjdg43-glibc-2.33-117/lib/libgcc_s.so.1
  #5  0x00007f50c19099b3 in uw_frame_state_for () from /nix/store/65hafbsx91127farbmyyv4r5ifgjdg43-glibc-2.33-117/lib/libgcc_s.so.1
  #6  0x00007f50c190ab90 in uw_init_context_1 () from /nix/store/65hafbsx91127farbmyyv4r5ifgjdg43-glibc-2.33-117/lib/libgcc_s.so.1
  #7  0x00007f50c190b08e in _Unwind_RaiseException () from /nix/store/65hafbsx91127farbmyyv4r5ifgjdg43-glibc-2.33-117/lib/libgcc_s.so.1
  #8  0x00007f50c1b02ab7 in __cxa_throw () from /nix/store/dd8swlwhpdhn6bv219562vyxhi8278hs-gcc-10.3.0-lib/lib/libstdc++.so.6
  #9  0x00007f50c1d01abe in nix::parseURL (url="root@cb893012.packethost.net") at src/libutil/url.cc:53
  #10 0x0000000000484f55 in extraStoreArgs (machine="root@cb893012.packethost.net") at build-remote.cc:35
  #11 operator() (__closure=0x7f4fe9fe0420) at build-remote.cc:79
  ...

Maybe the fork happened while another thread was holding some global
stack unwinding lock
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71744). Anyway, since
the hanging child inherits all file descriptors to SSH clients,
shutting down remote builds (via 'child.to = -1' in
State::buildRemote()) doesn't work and 'child.pid.wait()' hangs
forever.

So let's not do any significant work between fork and exec.
2022-03-30 22:39:48 +02:00
Graham Christensen
bbb0998699 Merge pull request #1188 from DeterminateSystems/nix-2.7
Nix 2.7
2022-03-29 15:49:37 -04:00
ajs124
089da272c7 fix build against nix 2.7.0
fix build after such commits as df552ff53e68dff8ca360adbdbea214ece1d08ee
and e862833ec662c1bffbe31b9a229147de391e801a
2022-03-29 15:38:24 -04:00
ajs124
c64c5f0a7e hydra-queue-runner: rename build-result.hh to hydra-build-result.hh 2022-03-29 15:34:29 -04:00
Graham Christensen
4368ff5d5b flake.lock: Add
Flake lock file updates:

• Added input 'nix':
    'github:NixOS/nix/ffe155abd36366a870482625543f9bf924a58281' (2022-03-07)
• Added input 'nix/lowdown-src':
    'github:kristapsdz/lowdown/d2c2b44ff6c27b936ec27358a2653caaef8f73b8' (2021-10-06)
• Added input 'nix/nixpkgs':
    'github:NixOS/nixpkgs/82891b5e2c2359d7e58d08849e4c89511ab94234' (2021-09-28)
• Added input 'nix/nixpkgs-regression':
    'github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2' (2022-01-24)
• Added input 'nixpkgs':
    follows 'nix/nixpkgs'
2022-03-29 15:33:08 -04:00
Graham Christensen
98da457e16 nix: 2.7.0 2022-03-29 15:31:11 -04:00
Graham Christensen
20a8437094 flake.nix: set nix to 2.6.0 2022-03-29 15:29:33 -04:00
Graham Christensen
fd3690a0c1 flake.lock: Update
Flake lock file updates:

• Updated input 'nix':
    'github:NixOS/nix/a6ba313a0aac3b6e2fef434cb42d190a0849238e' (2021-08-10)
  → 'github:NixOS/nix/a1cd7e58606a41fcf62bf8637804cf8306f17f62' (2022-01-24)
• Updated input 'nix/lowdown-src':
    'github:kristapsdz/lowdown/148f9b2f586c41b7e36e73009db43ea68c7a1a4d' (2021-04-03)
  → 'github:kristapsdz/lowdown/d2c2b44ff6c27b936ec27358a2653caaef8f73b8' (2021-10-06)
• Updated input 'nix/nixpkgs':
    'github:NixOS/nixpkgs/f77036342e2b690c61c97202bf48f2ce13acc022' (2021-06-28)
  → 'github:NixOS/nixpkgs/82891b5e2c2359d7e58d08849e4c89511ab94234' (2021-09-28)
• Added input 'nix/nixpkgs-regression':
    'github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2' (2022-01-24)
2022-03-29 15:29:23 -04:00
Graham Christensen
3b048ed136 Revert "Revert "Use copyClosure instead of computeFSClosure + copyPaths""
This reverts commit 8e3ada2afc.
2022-03-29 15:28:47 -04:00
Cole Helbling
9c1f36c47c t/lib/HydraTestContext: set queue runner port to 0
This makes the exposer choose a random, available port.
2022-03-29 11:41:23 -07:00
Cole Helbling
4789eba92c hydra-queue-runer: split metrics functionality into its own function 2022-03-29 10:55:28 -07:00
Cole Helbling
928b3b8268 hydra-queue-runner: fix priority of flag over config file 2022-03-29 10:42:07 -07:00
Cole Helbling
5ddb9a98ca fixup! hydra-queue-runner: log message before and after exporter is started 2022-03-29 08:47:41 -07:00
Cole Helbling
905a7a7beb hydra-queue-runner: read metrics port from queue_runner_metrics_port config 2022-03-29 08:46:43 -07:00
Cole Helbling
9cdc5aceed hydra-queue-runner: log message before and after exporter is started
This way, if something goes wrong between the two, it's easier to narrow
down where the issue lies.
2022-03-29 08:41:19 -07:00
Théophane Hufschmitt
6e571e26ff Build the resolved derivation and not the original one 2022-03-29 17:05:30 +02:00
Théophane Hufschmitt
92b627ac1b Remove an accidental re-indenting of a comment
Co-authored-by: Eelco Dolstra <edolstra@gmail.com>
2022-03-29 17:04:19 +02:00
Théophane Hufschmitt
b430d41afd Use the BuildOptions more eagerly 2022-03-29 17:04:19 +02:00
Théophane Hufschmitt
fd0ae78eba Factor out the copying from the build store 2022-03-29 17:04:19 +02:00
Théophane Hufschmitt
a778a89f04 Factor out the queryPathInfos part of the build 2022-03-29 17:04:19 +02:00
Théophane Hufschmitt
365776f5d7 Factor out the building part 2022-03-29 17:04:19 +02:00
Théophane Hufschmitt
9f1b911625 Factor more stuff out 2022-03-29 17:04:17 +02:00
Théophane Hufschmitt
2f494b7834 Factor out the creation of the log file 2022-03-29 16:52:59 +02:00
Théophane Hufschmitt
5db8642224 Factor out a struct representing a connection to a machine 2022-03-29 16:52:59 +02:00
Graham Christensen
78ef4ae9a5 Merge pull request #1187 from DeterminateSystems/revert-to-nix-2.4pre20210810_a6ba313
Revert "Build against Nix 2.5.1" - build against nix-2.4pre20210810_a…
2022-03-29 09:35:15 -04:00
Graham Christensen
dc709422a6 Revert "Build against Nix 2.5.1" - build against nix-2.4pre20210810_a6ba313
This reverts commit 921e27d6c0.
2022-03-29 09:24:51 -04:00
Graham Christensen
47c7170c52 Merge pull request #1185 from DeterminateSystems/revert-from-nix-2.6
Revert to Nix 2.5.1
2022-03-28 14:45:15 -04:00
Cole Helbling
921e27d6c0 Build against Nix 2.5.1 2022-03-28 11:36:14 -07:00
Cole Helbling
2ba83a5cba t/jobs/empty-dir-builder: provide output for nix log 2022-03-28 09:54:02 -07:00
Cole Helbling
127a644595 Revert "Update Nix to 2.6"
This reverts commit 5ae26aa760.
2022-03-28 09:54:02 -07:00
Cole Helbling
8e3ada2afc Revert "Use copyClosure instead of computeFSClosure + copyPaths"
This reverts commit f14c583ce5.
2022-03-28 09:54:02 -07:00
Eelco Dolstra
962bf36939 Merge pull request #1162 from obsidiansystems/less-ref
Make `copyClosureTo` take a regular C++ ref to the store
2022-03-23 16:25:59 +01:00
Eelco Dolstra
3390415905 Merge pull request #1125 from obsidiansystems/simplify--copyClosure
Use `copyClosure` instead of `computeFSClosure` + `copyPaths`
2022-03-23 12:49:22 +01:00
Cole Helbling
8503a7917b fixup! hydra-queue-runner: make registry member of State, configurable metrics port 2022-03-22 13:38:13 -07:00
Graham Christensen
01fb23ddf6 Merge pull request #1178 from DeterminateSystems/hydra-update-gc-roots/network-traffic
hydra-update-gc-roots: allow cached refs to the build's jobset
2022-03-21 09:05:54 -04:00
Graham Christensen
e5393c2cf8 fixup: make id non-ambiguous 2022-03-19 23:56:47 -04:00
Graham Christensen
137be3452e Reduce the jobset cols on the remaining two queries 2022-03-19 23:56:47 -04:00
Graham Christensen
f353a7ac41 update-gc-roots: try subselecting the jobset table 2022-03-19 23:56:47 -04:00
Graham Christensen
145667cb53 hydra-update-gc-roots: allow cached refs to the build's jobset
Re-executing this search_related on every access turned out to
create very problematic performance. If a jobset had a lot of
error output stored in the jobset, and there were many hundreds
or thousands of active jobs, this could easily cause >1Gbps of
network traffic.
2022-03-19 23:56:47 -04:00
Graham Christensen
22026da4f8 Merge pull request #1176 from DeterminateSystems/broken-constituent
Broken constituents: emit useful log messages on evaluation errors on constituents
2022-03-19 14:55:17 -04:00
Graham Christensen
a582e4c485 HydraTestContext: add \n's to various dies 2022-03-19 14:46:53 -04:00
Graham Christensen
074a2f96bf hydra-eval-jobset: emit a useful error if constituents errored 2022-03-19 14:37:12 -04:00
Graham Christensen
0c51de6334 hydra-evaluate-jobset: assert it logs errored constituents properly 2022-03-19 14:35:30 -04:00
Graham Christensen
25f6bae847 HydraTestContext: make it easy to create a jobset without evaluating 2022-03-19 14:34:43 -04:00
Cole Helbling
b0c17112c9 flake: update to nixos-unstable-small
https://github.com/NixOS/nixpkgs/pull/163695 was merged, so no longer
need to use my commit!
2022-03-18 11:10:57 -07:00
Cole Helbling
c0f826b92d hydra-queue-runner: get the listening port from the exposer itself
Otherwise, when the port is randomly chosen (e.g. by specifying no port,
or a port of 0), it will just show that the port is 0 and not the port
that is actually serving the metrics.
2022-03-14 08:41:45 -07:00
Cole Helbling
52a29d43e6 hydra-queue-runner: make registry member of State, configurable metrics port
Thanks to the updated prometheus-cpp library, specifying a port of 0
will cause it to pick a random (available) port -- ideal for tests.
2022-03-11 11:58:10 -08:00
Cole Helbling
6e6475d860 flake: replace aliases with their proper names
Newer Nixpkgs have added a throw for these aliases.
2022-03-11 11:58:10 -08:00
Cole Helbling
a0cb73579d flake: update newNixpkgs for newer prometheus-cpp 2022-03-11 11:58:10 -08:00
Cole Helbling
3bf31bd6a6 hydra-queue-runner: add simple "up" exporter
There are probably better ways to achieve this (and will likely need to
be refactored a bit to support further metrics).
2022-03-10 12:36:58 -08:00
Cole Helbling
5bbaa18a8f flake: fix foreman execution
[vin@scadrial:~/workspace/vcs/hydra]$ foreman -h
    Warning: the running version of Bundler (2.1.4) is older than the version that created the lockfile (2.2.20). We suggest you to upgrade to the version that created the lockfile by running `gem install bundler:2.2.20`.
    Traceback (most recent call last):
    	2: from /nix/store/ycshcdssxcj9sjf6yzb1ydw4fcglf66y-foreman-0.87.2/bin/foreman:20:in `<main>'
    	1: from /nix/store/ggqacj06n6qfm1iww0bih9ph0j89wcna-bundler-2.1.4/lib/ruby/gems/2.7.0/gems/bundler-2.1.4/lib/bundler/rubygems_integration.rb:413:in `block in replace_bin_path'
    /nix/store/ggqacj06n6qfm1iww0bih9ph0j89wcna-bundler-2.1.4/lib/ruby/gems/2.7.0/gems/bundler-2.1.4/lib/bundler/rubygems_integration.rb:374:in `block in replace_bin_path': can't find executable foreman for gem foreman. foreman is not currently included in the bundle, perhaps you meant to add it to your Gemfile? (Gem::Exception)
2022-03-10 12:26:13 -08:00
Graham Christensen
28b682b85b Merge pull request #1170 from NixOS/dependabot/github_actions/actions/checkout-3
build(deps): bump actions/checkout from 2 to 3
2022-03-09 21:13:47 -05:00
dependabot[bot]
f1f2fc7427 build(deps): bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-07 19:07:06 +00:00
dependabot[bot]
b9ec3a41d6 build(deps): bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-07 15:01:23 +00:00
Graham Christensen
a2546121f0 Merge pull request #1163 from DeterminateSystems/constituents
Constituents: Add a GC root for indirect aggregates
2022-02-21 20:42:42 -05:00
Graham Christensen
9316544abf src/hydra-eval-jobs/hydra-eval-jobs.cc: .get<std::string> for drvPath
Co-authored-by: Kayla Fire <firestack@users.noreply.github.com>
2022-02-21 12:41:21 -05:00
Graham Christensen
290e0653ad hydra-eval-jobs: GC root aggregate jobs 2022-02-20 12:28:40 -05:00
Graham Christensen
e0921eba0a Create a basic test which verifies we can't delete the derivation of aggregate jobs 2022-02-20 12:28:40 -05:00
Graham Christensen
be46f02164 tests: relocate evaluator tests 2022-02-20 12:28:40 -05:00
Graham Christensen
5d169e3a2e Add a test validating direct and indirect constituents 2022-02-20 12:28:40 -05:00
John Ericson
445bba337b Make copyClosureTo take a regular C++ ref to the store
This is syntactically lighter wait, and demonstates there are no weird
dynamic lifetimes involved, just regular passing reference to callee
which it only borrows for the duration of the call.
2022-02-20 17:22:43 +00:00
John Ericson
f14c583ce5 Use copyClosure instead of computeFSClosure + copyPaths
It is more terse, and in the future it is possible `copyClosure` will
become more sophisticated.
2022-02-19 11:59:17 -05:00
Graham Christensen
dfb3eccfaa Merge pull request #1140 from Ma27/nix-update
Update Nix to 2.6
2022-02-19 08:38:34 -05:00
Graham Christensen
4c41ca08e1 Merge pull request #1155 from helsinki-systems/fix/graph-readability
build-graphs: Fix readability in dark mode
2022-02-14 11:27:37 -05:00
Graham Christensen
1124230d9f Merge pull request #1151 from DeterminateSystems/ldap-tests-inc-mapping
ldap: support configurable roles with backwards compatibility
2022-02-14 09:30:54 -05:00
ajs124
1c84676527 Fit more content on screen 2022-02-13 18:33:37 +01:00
Janne Heß
54675a0d94 Fix local store detection and related issues
- Add localStore into the stash because it's used in templates
- Hide the Channels button for non-local stores because the link 404s
  anyway
- Fix a style issue when having popovers in dark mode
2022-02-13 14:24:36 +01:00
Janne Heß
6d146deaf0 build-graphs: Fix readability in dark mode 2022-02-13 14:00:17 +01:00
Graham Christensen
01aedc92ed Merge pull request #9 from DeterminateSystems/runcommand/dynamic-notice-on-page
dynamic runcommand: print a notice on the build page if it is disabled
2022-02-11 16:01:02 -05:00
Graham Christensen
4c1daacdf1 Merge pull request #8 from DeterminateSystems/runcommand/dynamic-guarding
Runcommand/dynamic guarding
2022-02-11 15:05:15 -05:00
Graham Christensen
27ddde1e9e dynamic runcommand: print a notice on the build page if it is disabled 2022-02-11 15:04:54 -05:00
Cole Helbling
8c3122cacd hydra-api: add enable_dynamic_run_command to Project PUT 2022-02-11 14:35:52 -05:00
Cole Helbling
a22a8fa62d AddBuilds: reject declarative jobsets with dynamic runcommand enabled if disabled elsewhere 2022-02-11 14:35:52 -05:00
Cole Helbling
928ba9e854 Controller/{Jobset,Project}: error when enabling dynamic runcommand but it's disabled elsewhere 2022-02-11 14:35:52 -05:00
Cole Helbling
d680c209fe edit-project.tt: disable when disabled by server
Also add a tooltip describing why it's disabled, to make it easier to
chase down.
2022-02-11 14:35:52 -05:00
Cole Helbling
6053e5fd4b edit-jobset.tt: disable when disabled by project and server
Also add a tooltip describing why it's disabled, to make it easier to
chase down.
2022-02-11 14:35:52 -05:00
Cole Helbling
dfd3a67424 project.tt: more info on why Dynamic RunCommand is disabled 2022-02-11 14:35:52 -05:00
Cole Helbling
3f4f183792 jobset.tt: more info on why Dynamic RunCommand is disabled 2022-02-11 14:35:52 -05:00
Cole Helbling
3b895aec54 DynamicRunCommand: needs to be enabled by server, project, and jobset 2022-02-11 14:35:52 -05:00
Graham Christensen
78e9872251 ldap.t: write the password to an external .conf file 2022-02-11 11:27:10 -05:00
Graham Christensen
848fb3b265 ldap-legacy.t: specify the root password manually 2022-02-11 11:26:56 -05:00
Graham Christensen
0bd4a75918 HydraTestContext: support running a sub before running hydra-init. 2022-02-11 11:26:27 -05:00
Graham Christensen
05ca71069f ldap config: document putting the password in a separate file 2022-02-11 11:24:45 -05:00
Graham Christensen
e13d80f5cf LDAPContext: take a root_password argument or generate one 2022-02-11 11:02:04 -05:00
Graham Christensen
86bb16d07b LDAPContext: sort $self hash keys 2022-02-11 11:01:25 -05:00
Graham Christensen
6637c03985 fixup normalization error regex 2022-02-11 10:59:24 -05:00
Graham Christensen
71c06f2ce7 LDAP normalization errors: note that the error came while normalizing the roles. 2022-02-11 10:55:27 -05:00
Graham Christensen
d6dea39912 ldap_role_map.t: fixup indentation 2022-02-11 10:53:08 -05:00
Graham Christensen
185100adb8 docs: fixup 2022-02-11 10:50:58 -05:00
Graham Christensen
f07fb7d279 LDAP support: include BC support for the YAML based loading
Includes a refactoring of the configuration loader.
2022-02-11 10:49:38 -05:00
Janne Heß
61d74a7194 Redo LDAP config in the main configuration and add role mappings 2022-02-11 10:49:38 -05:00
Graham Christensen
76b4b43ac5 Move ldap.t to a legacy-ldap.t, make ldap.t use the new format config. 2022-02-11 10:49:38 -05:00
Graham Christensen
d0bc0d0eda Merge pull request #1152 from DeterminateSystems/parallel-tests
Parallel tests, fix a hydra-queue-runner race condition
2022-02-10 12:11:20 -05:00
Graham Christensen
74a29e8ea9 Merge pull request #1150 from DeterminateSystems/ldap-tests
LDAP: Test without a VM
2022-02-10 12:05:19 -05:00
Graham Christensen
4f9aea9434 t/Hydra/Plugin/gitea.t: explain why we loop a few times
Co-authored-by: Cole Helbling <cole.e.helbling@outlook.com>
2022-02-10 12:02:29 -05:00
Graham Christensen
a1579007f4 Update t/test.pl: fixup the list of env vars yath looks at for job count 2022-02-10 11:53:10 -05:00
Graham Christensen
b1b1b4b74b t/lib/LDAPContext.pm: error message nit
Co-authored-by: Cole Helbling <cole.e.helbling@outlook.com>
2022-02-10 11:31:49 -05:00
Graham Christensen
33f4c4c13d build-locally-with-substitutable-path.t: give nix-store --delete a bit more time to run
Under high load, like 64-128 tests at once, this can take more than a second.
2022-02-10 11:13:31 -05:00
Graham Christensen
e709a17508 gitea.t: try opening the file a few times 2022-02-10 11:01:09 -05:00
Graham Christensen
4acaf9c8b0 hydra-queue-runner: don't dispatch until the machines parser has completed one run
Periodically, I have seen tests fail because of out of order queue runner behavior:

    checking the queue for builds > 0...
    loading build 1 (tests:basic:empty_dir)
    aborting unsupported build step '...-empty-dir.drv' (type 'x86_64-linux')
    marking build 1 as failed
    adding new machine ‘localhost’

This patch should prevent the dispatcher from running before any machines are
made available.
2022-02-10 10:54:30 -05:00
Graham Christensen
09652475bd Set the YATH_JOB_COUNt to NIX_BUILD_CORES if no parallelism variables are set 2022-02-10 10:00:32 -05:00
Graham Christensen
5506962537 Test::Postgresql: update to a tagged fork to improve paralellism 2022-02-10 09:37:48 -05:00
Graham Christensen
4837a68d8d LDAPContext: don't background slapd 2022-02-10 09:28:53 -05:00
Graham Christensen
8bce8109e3 flake.nix: drop the LDAP server test 2022-02-09 20:56:10 -05:00
Graham Christensen
80c6525029 LDAP: Create a test which does not use a VM 2022-02-09 20:56:10 -05:00
Graham Christensen
e4adec36f3 Set an env var in the build environment to point to the root of openldap 2022-02-09 20:56:10 -05:00
Graham Christensen
60adee7f94 hydra check inputs: add openldap 2022-02-09 20:56:10 -05:00
Graham Christensen
9ae7c8bddc Hydra::Helper::Exec add an expectOkay which dies with stdout / stderr on exit 2022-02-09 20:56:10 -05:00
Graham Christensen
5184e895df Merge pull request #1148 from DeterminateSystems/hydra-helper-exec
captureStdoutStderr*: move to Hydra::Helper::Exec which helps avoid some environment variable fixation problems
2022-02-09 14:42:07 -05:00
Graham Christensen
a374ef7d81 Merge pull request #1149 from DeterminateSystems/flake-format
flake.nix: format with nixpkgs-fmt
2022-02-09 14:40:48 -05:00
Graham Christensen
845e6d4760 captureStdoutStderr*: move to Hydra::Helper::Exec which helps avoid some environment variable fixation problems 2022-02-09 14:28:50 -05:00
Graham Christensen
68c6c3d556 flake.nix: format with nixpkgs-fmt 2022-02-09 10:43:40 -05:00
Graham Christensen
1abe7f4d80 Merge pull request #1145 from DeterminateSystems/eval-status
`eval_*` events: change the API to include IDs and use \t separators
2022-02-09 10:23:15 -05:00
Graham Christensen
517dce285a eval_added event: change interface to traceID\tjobsetID\tevaluationID
I was not going to break the interface until I noticed
the current implementation uses the string literal \t.
2022-02-08 09:51:35 -05:00
Graham Christensen
d512e6220f eval_failed event: change interface to traceID\tjobsetID
I was not going to break the interface until I noticed the other eval_* events used literal \ts
2022-02-08 09:51:35 -05:00
Graham Christensen
2597fa8c11 eval_cached event: change interface to traceID\tjobsetID\tevaluationID
I was not going to break the interface until I noticed
the current implementation uses the string literal \t.
2022-02-08 09:51:35 -05:00
Graham Christensen
be531c6c57 notifications.t: create a helper to parse the actual messages from the evaluator using the Event code 2022-02-08 09:51:35 -05:00
Graham Christensen
c30f084f32 eval_started event: change interface to traceID\tjobsetID
I was not going to break the interface until I noticed
the current implementation uses the string literal \t.
2022-02-08 09:51:35 -05:00
Graham Christensen
3864ca820a Merge pull request #1144 from DeterminateSystems/eval-event-cleanup
Eval event cleanup
2022-02-08 09:50:33 -05:00
Graham Christensen
c0eb873379 notifications: document eval_* 2022-02-07 18:08:01 -05:00
Graham Christensen
f648e91487 StepFinished.t: fixup use 2022-02-07 16:08:40 -05:00
Graham Christensen
7107ce2bc7 t/Event/* -> t/Hydra/Event/ 2022-02-07 16:08:40 -05:00
Graham Christensen
8a18326f2b Sort notification classes / events 2022-02-07 16:08:27 -05:00
Graham Christensen
7b7c03a521 Merge pull request #1141 from amerocu/amerocu/fix-dev-env
missing develop dependencies
2022-02-06 14:35:27 -05:00
Maximilian Bosch
5ae26aa760 Update Nix to 2.6 2022-02-06 15:05:15 +01:00
Marco Turchetto
73f2cc184f missing develop dependencies 2022-02-05 20:28:44 +01:00
Graham Christensen
d8b56f022d RunCommand: print a warning if the hook isn't run because the project / jobset doens't have it enabled 2022-02-01 10:58:54 -05:00
Graham Christensen
3aa2393091 Jobsets: add a supportsDynamicRunCommand which also checks the project's dynamic runcommand support 2022-02-01 10:58:54 -05:00
Graham Christensen
daa6864a58 Project result: add a supportsDynamicRunCommand helper 2022-02-01 10:58:54 -05:00
Graham Christensen
38514ae494 fanout tests: capture warnings and test their relevance 2022-02-01 10:58:54 -05:00
Graham Christensen
bc1630bd27 fixup! RunCommand: Add a WIP execution of dynamic commands 2022-02-01 10:58:54 -05:00
Graham Christensen
2635607b6e whoops: add a test on the enable_dynamic_run_command field 2022-02-01 10:58:54 -05:00
Graham Christensen
8a96f07f58 Project: enable enabling dynamic runcommand per project 2022-02-01 10:58:54 -05:00
Graham Christensen
1affb1cfb1 jobset API: expose and check the enable_dynamic_run_command 2022-02-01 10:58:54 -05:00
Graham Christensen
726ea80e99 HTTP/Jobset: support setting / reading enable_dynamic_run_command 2022-02-01 10:58:54 -05:00
Graham Christensen
1802bd0113 Declarative Jobs: add support for the enable_dynamic_run_command flag 2022-02-01 10:58:54 -05:00
Graham Christensen
0810f5debc finish making the dynamic hooks only run on project & jobset agreement 2022-02-01 10:58:54 -05:00
Graham Christensen
aef11685a0 regenerate schema files after adding the flag to the projects 2022-02-01 10:58:54 -05:00
Graham Christensen
0c96172c28 RunCommand: only run dynamic runcommand hooks if the project AND jobset agree they should be enabled 2022-02-01 10:58:54 -05:00
Graham Christensen
85a53694c8 sql: add enable_dynamic_run_command to the Project as well 2022-02-01 10:58:54 -05:00
Graham Christensen
a9bfabd672 sql: add a migration for enable_dynamic_run_command 2022-02-01 10:58:23 -05:00
Graham Christensen
3cce0c5ef6 Only run dynamic runcommand hooks if the jobset enables them 2022-02-01 10:57:30 -05:00
Graham Christensen
97a1d2d1d4 Jobsets: add enable_dynamic_run_command 2022-02-01 10:57:30 -05:00
Graham Christensen
216d8bee35 DynamicRunCommand: don't run if the build failed 2022-02-01 10:57:30 -05:00
Graham Christensen
1a30a0c2f1 Dynamic RunCommand: validate that the job's out exists, is a file (or points to a file) which is executable. 2022-02-01 10:57:30 -05:00
Graham Christensen
c2be27e82b fanout.t: switch to makeAndEvaluateJobset 2022-02-01 10:57:30 -05:00
Graham Christensen
e7f68045f4 DynamicRunCommand: pull out the function determining if a build is
eligible for execution under dynamic run commands.
2022-02-01 10:57:30 -05:00
Graham Christensen
e56c49333f RunCommand: Add a WIP execution of dynamic commands
This in-progress feature will run a dynamically generated set of
buildFinished hooks, which must be nested under the `runCommandHook.*`
attribute set. This implementation is not very good, with some to-dos:

1. Only run if the build succeeded
2. Verify the output is named $out and that it is an executable file
   (or a symlink to a file)
3. Require the jobset itself have a flag enabling the feature, since
   this feature can be a bit dangerous if various people of different
   trust levels can create the jobs.
2022-02-01 10:57:30 -05:00
Graham Christensen
ea311a0eb4 RunCommand: enable the plugin if dynamicruncommand is set 2022-02-01 10:57:30 -05:00
Graham Christensen
6ffc93c01a RunCommand: write documentation for dynamic commands 2022-02-01 10:57:30 -05:00
Graham Christensen
4ea646130c RunCommand: split out documentation, fixup the matcher syntax 2022-02-01 10:57:30 -05:00
Graham Christensen
85b842e0ac Merge pull request #1137 from DeterminateSystems/runcommand-logs
Store and display the output of RunCommands
2022-01-31 16:26:31 -05:00
Cole Helbling
b57345ba1f hydra.sql: add IndexRunCommandLogsOnBuildID index 2022-01-31 12:56:34 -08:00
Cole Helbling
d0b6329aa8 sql/upgrade-81: remove unnecessary comment 2022-01-31 12:55:36 -08:00
Cole Helbling
9c4e6f78e7 hydra-module: don't bzip2 runcommand-logs 2022-01-31 12:55:36 -08:00
Cole Helbling
8c67e32480 RunCommand: ensure we reset the umask 2022-01-31 12:55:36 -08:00
Cole Helbling
34e4c119f4 build.tt: don't duplicate RunCommandLog buttons 2022-01-31 11:40:16 -08:00
Cole Helbling
61189ecca9 Helper/Nix: constructRunCommandLogPath: verify uuid is valid
This shouldn't be possible normally, but it is possible to:

    $db->resultset('RunCommandLogs')->new({ uuid => "../etc/passwd" });

if you have access to the `$db`.
2022-01-31 08:58:33 -08:00
Cole Helbling
e381751564 Helper/Nix: constructRunCommandLogPath: return undef in case of an error
This allows us to give a web request to an invalid UUID a 404.
2022-01-31 08:58:33 -08:00
Cole Helbling
2c6487b8d7 t/Helper: test constructRunCommandLogPath 2022-01-31 08:58:33 -08:00
Cole Helbling
8bf3cdbc67 t/Helper: switch to using test_context() 2022-01-31 08:58:33 -08:00
Cole Helbling
8eab7b8543 Helper/Nix: constructRunCommandLogPath: take RunCommandLog as input
This way we ensure that it actually exists in the database, rather than
blindly trusting user-generated input.
2022-01-31 08:58:33 -08:00
Cole Helbling
61914d56c6 runcommand-log.tt: escape the command 2022-01-31 08:58:33 -08:00
Cole Helbling
71bbb042db build.tt: link to the pretty, raw, and tail versions of the log
Also split it out to a new div -- there are now 3 lines per
RunCommandLog -- the first saying when it started, the second saying how
long it ran for (or has been running), and the third with the buttons
for the pretty, raw, and tail versions of the log.
2022-01-31 08:58:33 -08:00
Cole Helbling
3594ba942a Controller/Build: use showLog in view_runcommandlog
This also adds the `runcommandlog` object to the stash so that we can
access its uuid as well as command run in order to display more useful
and specific information on the webpage.
2022-01-31 08:58:33 -08:00
Cole Helbling
1d0076408b Controller/Build: pass log_uri to showLog in place of drvPath
This way, we can reuse the `showLog` sub for other things, such as
`view_runcommandlog` (which doesn't have a drvPath attached).
2022-01-31 08:58:33 -08:00
Cole Helbling
ff390e89a6 Controller/Build: remove unused parameter from showLog 2022-01-31 08:58:33 -08:00
Cole Helbling
38896db6b6 t/RunCommand: init http.t
Test that we can indeed visit the pages of a valid runcommand log and
not of an invalid one.
2022-01-31 08:58:33 -08:00
Cole Helbling
47c1f89d5a t/RunCommand: fixup basic.t to use uuid 2022-01-31 08:58:33 -08:00
Cole Helbling
fc3cf4ecb2 RunCommandLogs: identify and access via uuid
Using a sha1 of the command combined with the build ID is not a
particularly good or unique identifier:

* A build could fail, be restarted, and then succeed -- assuming no
configuration changes, the sha1 hash of the command as well as the build
ID will be the same. This would lead to an overwritten log file.

* Allowing user input to influence filenames is not the best of ideas.
2022-01-31 08:58:33 -08:00
Graham Christensen
dcb0c1425c RunCommandLogs: set a UUID automatically 2022-01-31 08:58:33 -08:00
Graham Christensen
89e8676d80 UUID4Tiny: init 2022-01-31 08:58:33 -08:00
Graham Christensen
cf49a05ff5 RunCommandLogs: add a uuid to each log entry 2022-01-31 08:58:33 -08:00
Graham Christensen
94ed9ed7ff Merge pull request #1136 from DeterminateSystems/github-status-cached-evals
GithubStatus: try pushing statuses for cached buildqueued/buildfinished events
2022-01-31 09:11:37 -05:00
Graham Christensen
3ae4b19d12 flake: update to postgres 13 for UUID commands 2022-01-28 13:07:11 -08:00
Cole Helbling
244300c1ad RunCommand: remove unused and problematic imports
Since breaking the filename construction out to a helper function,
Hydra::Model::DB is no longer used. Importing Hydra::Helper::Nix,
however, has the potential to break tests, so just use the functions we
need without importing the entire module.
2022-01-28 13:07:11 -08:00
Cole Helbling
fdf6f4d3da RunCommand: use IPC::Run3::run3 instead
run3 just seems to do better handling for what we want to do, and
requires less deep-reaching changes to this plugin to get it to play
nice, as IPC::Run::run would.
2022-01-28 13:07:11 -08:00
Cole Helbling
3e722f1d0a t/RunCommand: remove duplicate use 2022-01-28 13:07:11 -08:00
Cole Helbling
c8f3943d03 hydra-module: log files don't have a .drv extension 2022-01-28 13:07:11 -08:00
Cole Helbling
3432cd7636 build.tt: split runcommand logic across multiple lines
Helps with readability.
2022-01-28 13:07:11 -08:00
Cole Helbling
988e79c6e5 t/RunCommand: test that the log file exists on the filesystem 2022-01-28 13:07:11 -08:00
Cole Helbling
1554750acc RunCommand: use make_path over mkdir
This will make all necessary parent directories a la `mkdir -p`.
2022-01-28 13:03:15 -08:00
Cole Helbling
bf3c46ed43 RunCommand: use IPC::Run to spawn the command
This allows `logPath`s with spaces and other characters that might
otherwise cause problems inside a `system()` call.
2022-01-28 13:03:15 -08:00
Cole Helbling
bb16f4fb10 RunCommand: set umask when creating log paths
This uses the somewhat restrictive umask of 0027 so that people outside
the user or group cannot read the files. This also helps to inhibit
TOCTOU where someone else has a handle to our file before we chmod it
and after we close it.
2022-01-28 13:03:15 -08:00
Cole Helbling
5d3912962b RunCommand: use helper functions to ensure filenames and paths are the same
Otherwise, it's possible someone updates the format in one place but not
the others, leading to broken or incorrect functionality.
2022-01-28 13:03:15 -08:00
Cole Helbling
4a441b54ce hydra-module: /var/lib/hydra -> ${baseDir} 2022-01-28 13:03:15 -08:00
Cole Helbling
14090fbb86 runcommand-log.tt: init 2022-01-28 13:03:15 -08:00
Janne Heß
796ce165d4 RunCommand: Allow displaying command output 2022-01-28 13:03:15 -08:00
Janne Heß
4cb5e6cd94 RunCommand: Capture the output of the commands 2022-01-28 13:00:17 -08:00
Graham Christensen
ef362e92d1 GithubStatus: try pushing statuses for cached buildqueued/buildfinished events 2022-01-25 12:42:28 -05:00
Graham Christensen
001539c3d2 Merge pull request #1127 from NixOS/grahamc-patch-1
Create a bug report issue template
2022-01-25 09:57:17 -05:00
Graham Christensen
0a5f625746 Update bug_report.md 2022-01-24 20:36:08 -05:00
Graham Christensen
f6e86efc9f Merge pull request #1091 from Ma27/ssh-remote-store-location
hydra-queue-runner: support store URIs declaring an alternate store location
2022-01-24 14:10:54 -05:00
Graham Christensen
3a4ea6e563 Merge pull request #1124 from obsidiansystems/simplify--closure-of-path-set
simplify, `computeFSClosure` can take a set now
2022-01-24 14:09:35 -05:00
Graham Christensen
bb68b56f61 Merge pull request #1133 from helsinki-systems/doc/config-format
doc: Document the file format of the config
2022-01-21 20:49:18 -05:00
Graham Christensen
c280692f91 Merge pull request #1126 from DeterminateSystems/build-localhost-paths
build-remote: copy missing paths from the binary cache to localhost
2022-01-21 16:16:33 -05:00
Graham Christensen
44cd890ae3 Merge pull request #1130 from DeterminateSystems/prompt-password
hydra-create-user: support prompting for password
2022-01-21 15:38:39 -05:00
Graham Christensen
ba96a13407 Record metrics when getting the closure to localhost 2022-01-21 15:38:05 -05:00
Graham Christensen
7e9e82398d build-remote: copy missing paths from the binary cache to localhost
In a Hydra instance I saw:

    possibly transient failure building ‘/nix/store/X.drv’ on ‘localhost’:
      dependency '/nix/store/Y' of '/nix/store/Y.drv' does not exist,
      and substitution is disabled

This is confusing because the Hydra in question does have substitution enabled.

This instance uses:

  keep-outputs = true
  keep-derivations = true

and an S3 binary cache which is not configured as a substituter in the nix.conf.

It appears this instance encountered a situation where store path Y was built
and present in the binary cache, and Y.drv was GC rooted on the instance,
however Y was not on the host.

When Hydra would try to build this path locally, it would look in the binary
cache to see if it was cached:

    (nix)
    439      bool valid = isValidPathUncached(storePath);
    440
    441      if (diskCache && !valid)
    442          // FIXME: handle valid = true case.
    443          diskCache->upsertNarInfo(getUri(), hashPart, 0);
    444
    445      return valid;

Since it was cached, the store path was considered Valid.

The queue monitor would then not put this input in for substitution, because
the path is valid:

    (hydra)
    470          if (!destStore->isValidPath(*i.second.path(*localStore, step->drv->name, i.first))) {
    471              valid = false;
    472              missing.insert_or_assign(i.first, i.second);
    473          }

Hydra appears to correctly handle the case of missing paths that need
to be substituted from the binary cache already, but since most
Hydra instances use `keep-outputs` *and* all paths in the binary cache
originate from that machine, it is not common for a path to be cached
and not GC rooted locally.

I'll run Hydra with this patch for a while and see if we run in to the
problem again.

A big thanks to John Ericson who helped debug this particular issue.
2022-01-21 15:26:45 -05:00
Graham Christensen
952f629b7c Test the queue runner in the scenario where a dependency is available in the cache but GC'd locally, where we're building locally 2022-01-21 15:26:45 -05:00
Graham Christensen
5c3e48fd0d CliRunners: decode UTF8 before printing stderr/stdout
Fixes yath output. It used to say:

    step â is now runnable

Now it says:

    step ‘/run...2ipqz6hbc41m4c5w5bkq-dependent-job.drv’ is now runnable
2022-01-21 15:24:33 -05:00
Graham Christensen
e4407f8c93 HydraTestContext: expose the nix state dir 2022-01-21 15:12:10 -05:00
Janne Heß
56308dbb05 doc: Document the file format of the config 2022-01-21 20:48:50 +01:00
Graham Christensen
da1af1ce68 Docs: use hydra-create-user --password-prompt 2022-01-21 13:05:12 -05:00
Graham Christensen
e351054f61 Merge pull request #1129 from DeterminateSystems/fixup-argon2
Fixup argon2 instructions in hydra-create-user
2022-01-21 13:01:37 -05:00
Graham Christensen
61325853a6 Merge pull request #1132 from DeterminateSystems/ldap-role-match
LDAP support: require the prefix 'hydra_' to match documentation
2022-01-21 12:58:35 -05:00
Graham Christensen
0eeced7f08 hydra-create-user: Warn that creating users with a plaintext password is deprecated 2022-01-21 12:56:15 -05:00
Graham Christensen
98928a4125 fixups 2022-01-21 12:52:06 -05:00
Graham Christensen
a888a57baf tests.ldap: verify the hydra_ prefix is required 2022-01-21 12:46:02 -05:00
Graham Christensen
76fbde6d6b Set noecho when reading passwords 2022-01-21 11:11:09 -05:00
Graham Christensen
8ba4ae461e Merge pull request #1131 from kenranunderscore/fix-invalid-yaml
Fix invalid YAML in documentation
2022-01-21 11:03:28 -05:00
Graham Christensen
b8f72d7ff2 LDAP support: require the prefix 'hydra_' to match documentation 2022-01-21 10:48:04 -05:00
Graham Christensen
bb893d0bd5 hydra-create-user: support prompting for passwords
I'm not sure this is a good implementation as-is. It does work,
but the password gets echo'd to the screen. I tried to use IO::Prompt
but IO::Prompt really seems to want to read the password from ARGV.
2022-01-21 10:40:56 -05:00
Graham Christensen
3a6c25489c Hydra::Helper::Nix: expose a captureStdoutStderrWithStdin, make it available in tests 2022-01-21 10:40:06 -05:00
Graham Christensen
d4fe7e55dd Hydra::Helper::Nix: sort exported functions 2022-01-21 10:40:06 -05:00
Graham Christensen
4945306a2b hydra-create-user: make docs about using --password-hash better 2022-01-21 10:39:22 -05:00
Johannes Maier
4476aba5f7 Fix invalid YAML in documentation 2022-01-21 16:38:59 +01:00
Graham Christensen
12d0d0c176 hydra-create-user: use test_context over test_init 2022-01-21 10:37:48 -05:00
Graham Christensen
bb9864bad7 hydra-create-user.t: rename the various users based on their password type 2022-01-21 09:12:47 -05:00
Graham Christensen
46b8f7cce8 Create a bug report issue template 2022-01-20 20:10:28 -05:00
John Ericson
e7a1ae87aa simplify, computeFSClosure can take a set now 2022-01-20 14:53:01 -05:00
Graham Christensen
ed1b532b74 Merge pull request #1093 from DeterminateSystems/builds-jobset-project
Builds: drop the jobset and project columns
2022-01-17 10:11:55 -05:00
Graham Christensen
8c50cd06e4 machines: ensure the jobset name is present 2022-01-15 17:11:08 -05:00
Graham Christensen
c8dc6a9419 Plugins: get project and jobset information from the project and jobset tables 2022-01-15 15:58:02 -05:00
Graham Christensen
9dc40e0816 evaluator: don't save project, jobset on builds 2022-01-15 15:58:02 -05:00
Graham Christensen
c539deea99 builds: add a build->project func to get the project via the jobset 2022-01-15 15:58:02 -05:00
Graham Christensen
f120909547 builds: drop project, jobset columns
Indexes were haphazardly dropped.
2022-01-15 15:58:02 -05:00
Graham Christensen
1caff3a250 Merge pull request #1117 from DeterminateSystems/project-jobset/queue-runner
queue-runner: track jobsets by ID
2022-01-15 15:57:14 -05:00
Graham Christensen
9671d4d135 Merge pull request #1119 from DeterminateSystems/project-jobset/update-gc-roots
Project jobset: update-gc-roots
2022-01-15 15:57:06 -05:00
Graham Christensen
f1a608ac35 Merge pull request #1118 from DeterminateSystems/project-jobset/declarativejobsets
Project jobset: Update DeclarativeJobsets to not use the project or jobsets columns on Bulids
2022-01-15 15:56:48 -05:00
Graham Christensen
7544d4ff47 hydra-update-gc-roots: get project and jobset information from the project and jobset tables 2022-01-15 14:26:45 -05:00
Graham Christensen
52dda56b99 hydra-update-gc-roots: add a very basic test validating successful execution 2022-01-15 14:20:11 -05:00
Graham Christensen
72c3110002 queue-runner: track jobsets by ID 2022-01-15 14:06:00 -05:00
Graham Christensen
17c6bd4fd8 DeclarativeJobsets: get the jobset name from the jobset table 2022-01-15 13:46:32 -05:00
Graham Christensen
b2cdde0901 DeclarativeJobsets: test basic functionality 2022-01-15 13:46:32 -05:00
Graham Christensen
eef633c1cc tests: create a declarative project spec and the autoconfig machinery 2022-01-15 13:46:32 -05:00
Graham Christensen
9d3b14dd43 Merge pull request #1116 from DeterminateSystems/project-jobset/input-type-build
Project jobset: update input type "build"
2022-01-15 12:48:20 -05:00
Graham Christensen
8c3c573953 hydra-eval-jobset: fixup old reference to project / jobset columns 2022-01-15 12:32:16 -05:00
Graham Christensen
2abcd84931 Merge pull request #1115 from DeterminateSystems/project-jobset/builds-json-repr
Project jobset: update builds json repr
2022-01-15 12:09:45 -05:00
Graham Christensen
d91593e93a Merge pull request #1114 from DeterminateSystems/project-jobset/delete-project
Projects: delete: delete all builds first
2022-01-14 23:04:55 -05:00
Graham Christensen
6bb9adc1a5 Builds: get the project and jobset names from the their tables 2022-01-14 22:45:26 -05:00
Graham Christensen
cb68629417 test a Build's json representation 2022-01-14 21:19:48 -05:00
Graham Christensen
f4c4b496d8 Projects: delete: delete all builds first
Deleting jobsets first would fail because buildmetrics has an FK
to the jobset. However, the jobset / project relationship is not
marked as CASCADE.

Deleting all the builds automatically cascades to delete
buildmetrics, so deleting the relevant builds first, then deleting
the jobset solves it.
2022-01-14 20:37:55 -05:00
Graham Christensen
0044622198 Projects: test deleting 2022-01-14 20:36:52 -05:00
Graham Christensen
9cc3e4264d Merge pull request #1113 from DeterminateSystems/project-jobset/steps
Project jobset: update /steps
2022-01-14 17:00:52 -05:00
Graham Christensen
31c6c26121 common.tt: fixup refs 2022-01-14 16:49:58 -05:00
Graham Christensen
8ae2daece7 root: test /steps and /evals 2022-01-14 16:49:58 -05:00
Graham Christensen
3a03784af6 Merge pull request #1112 from DeterminateSystems/project-jobset/search
Project jobset: update search
2022-01-14 16:49:43 -05:00
Graham Christensen
c7c4759600 search: fix references to jobset / project info 2022-01-14 16:38:25 -05:00
Graham Christensen
0b33550871 search.tt: fixup project and jobset reference 2022-01-14 16:38:25 -05:00
Graham Christensen
e0e8840d8f Test /search 2022-01-14 16:38:25 -05:00
Graham Christensen
42a871e413 Merge pull request #1111 from DeterminateSystems/project-jobset/queue-summary-machines
Project jobset columns: fixup /queue-summary and /machines
2022-01-14 15:34:43 -05:00
Graham Christensen
cc8104fa46 Merge pull request #1110 from DeterminateSystems/project-jobset/api-buildToHash
Project jobset: api: update endpoints to stop using build.{project,jobset}
2022-01-14 15:27:13 -05:00
Graham Christensen
8a663f2cf8 machines: fixup refs 2022-01-14 15:23:19 -05:00
Graham Christensen
bdccad573c machines: test 2022-01-14 15:23:19 -05:00
Graham Christensen
c945529f05 queue summary: fix refs 2022-01-14 15:23:19 -05:00
Graham Christensen
da516f70a4 queue summary: test 2022-01-14 15:23:19 -05:00
Graham Christensen
a81e358016 API: test api/push-github 2022-01-14 14:57:32 -05:00
Graham Christensen
20db82b001 API test /api/push 2022-01-14 14:57:24 -05:00
Graham Christensen
fe095a56c5 API: test /nrbuilds and fix jobset / project references 2022-01-14 14:57:15 -05:00
Graham Christensen
86473f4b3c API: fixup filtering latestbuilds by project and jobset 2022-01-14 14:57:10 -05:00
Graham Christensen
e5c8a35423 API: test fetching the queue and latestbuilds 2022-01-14 14:57:03 -05:00
Graham Christensen
1f49a5af66 Fixup project name, jobset name, in buildToHash 2022-01-14 14:57:00 -05:00
Graham Christensen
95eb14591f Merge pull request #1109 from DeterminateSystems/project-jobset/buildListColumns
buildListColumns: drop the project and jobset columns from the query
2022-01-14 13:02:32 -05:00
Graham Christensen
8383679bf6 test /queue and /status, both of which use buildListColumns 2022-01-14 12:48:51 -05:00
Graham Christensen
59d0259220 test /eval/ID/channel works
Uses buildListColumns
2022-01-14 12:48:51 -05:00
Graham Christensen
2de40f86ec test /job/PROJECT/JOBSET/JOB works
Uses buildListColumns
2022-01-14 12:48:51 -05:00
Graham Christensen
4a07622195 test /job/PROJECT/JOBSET/JOB/prometheus works
Uses buildListColumns
2022-01-14 12:48:51 -05:00
Graham Christensen
b37ca88fd5 test /job/PROJECT/JOBSET/JOB/shield works
Uses buildListColumns
2022-01-14 12:48:51 -05:00
Graham Christensen
97596c3e93 buildListColumns: remove project, jobset. 2022-01-14 12:48:48 -05:00
Graham Christensen
dc4a4aa038 Merge pull request #1108 from DeterminateSystems/builds-project-jobset/Project-Build
Builds table: replace some project and jobset references in the Projects and Builds controllers
2022-01-14 12:05:35 -05:00
Graham Christensen
796cae0fd0 Test Job's builds and channel pages 2022-01-14 11:52:07 -05:00
Graham Christensen
a2adb8cfb6 Test Jobset's builds and channel pages 2022-01-14 11:28:39 -05:00
Graham Christensen
2803f06e6e CatalystUtils::buildListColumns: add jobset_id 2022-01-14 11:28:39 -05:00
Graham Christensen
23d7046522 t/Controller/Build/constituents.t: assert the response is valid JSON, dump if it isn't 2022-01-14 11:28:39 -05:00
Graham Christensen
12ff981d24 Builds: LatestSucceeded*: remove project, jobset references 2022-01-14 11:28:39 -05:00
Graham Christensen
5c5ecdb9fc Helper::Nix::isLocalStore: a file store is local 2022-01-14 11:28:39 -05:00
Graham Christensen
9291cba89f Project: tests we can get the channel for the latest builds 2022-01-14 11:28:39 -05:00
Graham Christensen
e019028ce9 common.tt: access project and jobset names from respective tables 2022-01-14 11:28:39 -05:00
Graham Christensen
4086f3bafd Result::Projects: give a builds method to access all of a project's builds 2022-01-14 11:28:39 -05:00
Graham Christensen
dcefb88373 test /project/NAME/all returns a 200 2022-01-14 11:28:39 -05:00
Graham Christensen
29f9e30b10 Merge pull request #1107 from DeterminateSystems/runcommand/project-jobset-name
RunCommand: update the source of project and jobset names
2022-01-14 09:26:07 -05:00
Graham Christensen
526a21ef7e Merge pull request #1105 from DeterminateSystems/hydra-eval-jobset-notifications-sub-send_cached_finished_queued
hydra-eval-jobset: send cached_build_finished, cached_build_queued
2022-01-14 09:25:51 -05:00
Graham Christensen
6d5b234ba2 hydra-eval-jobset/notification.t: comment which jobs produced which messages
I tried to write the test in such a way to assert the content matched
what we expected, but since the ordering of them is not known, it
is quite tricky to write.
2022-01-14 09:13:17 -05:00
Graham Christensen
42edd3a9d8 hydra-notify: respond to cached_build_queued 2022-01-14 09:13:17 -05:00
Graham Christensen
6b7f1da11e hydra-notify: operate on cached_build_finished events 2022-01-14 09:13:17 -05:00
Graham Christensen
5b35a597b4 RunCommand: update project / jobset name refs 2022-01-13 20:44:51 -05:00
Maximilian Bosch
a18b487403 hydra-queue-runner: support store URIs declaring an alternate store location
When having a builder like this in `/etc/nix/machines`

    ssh://mfbuild?remote-store=/home/bosch/store

Hydra cannot build there since it tries to pass the entire value to
`ssh(1)` which doesn't work. Also, an alternate store-location is e.g.
used if the user isn't a trusted user on the remote system and thus
cannot use `/nix/store`.

If such a URI is given, Hydra will now add a `--store /home/bosch/store`
to the `ssh`-command to select the appropriate location remotely.
2022-01-12 15:56:05 +01:00
Graham Christensen
96b2200895 hydra-notify: sort subscriptions 2022-01-11 13:28:04 -05:00
Graham Christensen
4da80e736e hydra-eval-jobset: send notifications when cached queued / finished builds are submitted 2022-01-11 13:28:04 -05:00
Graham Christensen
769f56f793 Merge pull request #1101 from DeterminateSystems/hydra-eval-jobset-notifications
hydra-eval-jobset: test emitted notifications
2022-01-11 13:23:44 -05:00
Graham Christensen
87a0782e71 Merge pull request #1104 from DeterminateSystems/builds-refs/showjobname
Builds refs: showjobname: use project / jobset from relations, not the bulids table
2022-01-11 13:14:20 -05:00
Graham Christensen
2e195c524d evalSucceds/evalFails: log that the success or failure was not expected 2022-01-11 13:10:43 -05:00
Graham Christensen
f30ca3c423 showJobName: use jobset/project columns 2022-01-11 11:51:31 -05:00
Graham Christensen
2b163aa78b CatalystUtils::showJobName: write a basic test that shows it works 2022-01-11 11:48:02 -05:00
Graham Christensen
ceb6ea252a CatalystUtils.pm: don't use Hydra::Helper::Nix
Using it causes database information to get fixated early, before tests can set a
new database. We only used it in one case, and that is an absolute reference anyway. The
tests for channel generation are passing, and that uses
[requireLocalStore, so this should be fine.
2022-01-11 11:47:42 -05:00
Graham Christensen
0ada412979 hydra-eval-jobset: write a test validating the events that comes out 2022-01-11 10:17:14 -05:00
Graham Christensen
ae38cc5d04 test_context: support an override on jobsdir when creating a jobset 2022-01-11 10:17:14 -05:00
Graham Christensen
8d4c448e92 t: create a evalFails helper 2022-01-11 10:17:14 -05:00
Graham Christensen
40e556aee5 tests: evalSucceeds: don't print stdout/stderr unless it fails 2022-01-11 10:17:14 -05:00
Graham Christensen
a5b8221a43 Merge pull request #1102 from DeterminateSystems/nest-new-tests
Relocate new tests in to the Hydra subdir
2022-01-11 10:16:45 -05:00
Graham Christensen
ca6ba409de Relocate new tests in to the Hydra subdir 2022-01-11 09:54:51 -05:00
Graham Christensen
b41818e067 Merge pull request #1100 from DeterminateSystems/nest-tests
Tests: restructure to more closely mirror the sources
2022-01-11 09:53:16 -05:00
Graham Christensen
ff26ce0d06 Merge pull request #1092 from DeterminateSystems/restart-failed-no-eval
Allow restarting failed builds even with no eval to compare to
2022-01-10 21:26:08 -05:00
Graham Christensen
a5d1d36fa6 Tests: restructure to more closely mirror the sources
t/ had lots of directories and files mirroring src/lib/Hydra. This moves
those files under t/Hydra
2022-01-10 15:34:52 -05:00
Cole Helbling
9b12a88d81 BuildDiff: ensure buildstatus is defined
buildstatus won't be defined if e.g. a build is queued but none have
failed.
2022-01-10 12:11:06 -08:00
Cole Helbling
92bd0fae7d t/BuildDiff: test jobs without previous history 2022-01-10 12:11:06 -08:00
Cole Helbling
b98dbe01c3 BuildDiff: slight cleanup
Remove debugging Data::Dumper import, make comment describing function
inputs more readable.
2022-01-10 12:11:06 -08:00
Cole Helbling
ef6a2c96e7 JobsetEval: add the result of buildDiff to $c->stash 2022-01-10 12:11:06 -08:00
Cole Helbling
98375e9086 BuildDiff: bring back the sort 2022-01-10 12:11:05 -08:00
Cole Helbling
1ca786561f t/JobsetEval: test GETing the eval page 2022-01-10 12:11:05 -08:00
Cole Helbling
157a02bff7 t/BuildDiff: slightly refactor empty test to be more readable 2022-01-10 12:11:05 -08:00
Cole Helbling
220ccc68df t/BuildDiff: test diffing two jobs 2022-01-10 12:11:05 -08:00
Cole Helbling
ceb81e7d78 BuildDiff: actual list reference to $builds2 2022-01-10 12:11:05 -08:00
Cole Helbling
458214381d BuildDiff: document what the inputs mean
They were tripping me up, so it helped to know exactly what they were at
the ~point they're used.
2022-01-10 12:11:05 -08:00
Cole Helbling
ff12218d02 BuildDiff: cleanup imports and make slightly more readable 2022-01-10 12:11:05 -08:00
Cole Helbling
ec98bdaaaa BuildDiff: move cmdBuilds from Controller/JobsetEval 2022-01-10 12:11:05 -08:00
Cole Helbling
0c51f3ca7d BuildDiff: make actual hash ref 2022-01-10 12:11:05 -08:00
Cole Helbling
0eb952d72d t/BuildDiff: init 2022-01-10 12:11:05 -08:00
Cole Helbling
1349887974 BuildDiff: split out from JobsetEval GET impl 2022-01-10 12:11:05 -08:00
Cole Helbling
aba0422865 JobsetEval: allow restarting failed builds even with no eval to compare to 2022-01-10 12:10:56 -08:00
Graham Christensen
98c88a4dbf Merge pull request #1097 from DeterminateSystems/api-test-warnings
Api test warnings: clean up
2022-01-10 14:03:38 -05:00
Graham Christensen
265908c1cd Merge pull request #1099 from helsinki-systems/feat/dark-theme
Provide a dark theme when the user prefers it
2022-01-10 14:01:36 -05:00
Janne Heß
680cd43e40 Provide a dark theme when the user prefers it 2022-01-10 19:33:51 +01:00
Graham Christensen
e254b62f13 Merge pull request #1096 from DeterminateSystems/pathinput-revision-hash
PathInput: make the hash part of the revision
2022-01-10 13:32:58 -05:00
Graham Christensen
d68032dd13 Merge pull request #1098 from helsinki-systems/fix/hydra-eval-jobset
hydra-eval-jobset: Fix two minor bugs
2022-01-10 13:20:56 -05:00
Janne Heß
a69693a832 hydra-eval-jobset: Fix two minor bugs
I'm honestly too lazy to create two commits for fixing these one-line
issues so here's one.

The first hunk fixes the name of the projectName input. This is relevant
now because it gets logged and the log message looks stupid when there
is an input without a name.

The second hunk fixes a warning when using declarative non-flake
jobsets. The implementation may look weird but it's just the same as the
logical implication operator of nix.
2022-01-10 18:28:41 +01:00
Graham Christensen
3874db4fb7 PathInput: make the hash part of the revision 2022-01-10 11:23:22 -05:00
Graham Christensen
d8025fcf04 api-test.t: don't print request content
It adds noise to the logs
2022-01-10 11:02:01 -05:00
Graham Christensen
6b2f0a9fe1 api-test.t: set a default method 2022-01-10 11:02:01 -05:00
Graham Christensen
832fa8c73d Controller/Jobset: make some warnings about undef's go away 2022-01-10 10:33:33 -05:00
Graham Christensen
0484f13a1a Merge pull request #1095 from DeterminateSystems/tests/prefix-names-with-t
HydraTestContext: prefix names with t
2022-01-10 10:01:45 -05:00
Cole Helbling
35f55279c1 HydraTestContext: prefix names with t
This is necessary because jobset and project names are not allowed to
begin with a digit, and yet the generated jobset and project names would
do just that.

Not the most elegant solution, but it works.
2022-01-10 09:39:42 -05:00
Graham Christensen
e72d2225e9 Merge pull request #1094 from helsinki-systems/feat/print-whats-evaluated
hydra-eval-jobset: Print the jobset that is evaluated
2022-01-10 09:29:46 -05:00
Graham Christensen
bf9ac72fe1 Merge pull request #1062 from DeterminateSystems/runcommand-logs
RunCommand: store a log of execution and render it on the Build page
2022-01-10 09:27:28 -05:00
Janne Heß
22f9045a03 Merge branch 'master' into feat/print-whats-evaluated 2022-01-10 13:45:57 +01:00
Janne Heß
f3d77c3e6b hydra-eval-jobset: Print the jobset that is evaluated
This is useful for systems that use concurrent evals
2022-01-10 13:44:07 +01:00
Graham Christensen
1505a56a70 build.tt: only show RunCommandLogs tab if there are any to show 2022-01-07 15:14:02 -05:00
Graham Christensen
06360bfbb6 RunCommandLogs.t: use test_context to get a specific build
Fixes a build error: Can't use global @_ in 'my' at Schema/Result/RunCommandLogs.t line 20, near ', @_'
2022-01-07 15:05:33 -05:00
Graham Christensen
2f382ba067 Add migration 79: RunCommand logs 2022-01-07 15:05:33 -05:00
Graham Christensen
fe149613b3 Builds page: show RunCommand logs 2022-01-07 15:05:33 -05:00
Graham Christensen
a7aeb766aa RunCommandLogs: add a helper for if it failed with an exec error 2022-01-07 15:05:33 -05:00
Graham Christensen
d849856dcd RunCommandLogs: add helpers for if it is running/failed/signaled 2022-01-07 15:05:33 -05:00
Graham Christensen
c81acbf93e RunCommandLogs: test recording a signaled process without a core dump 2022-01-07 15:05:33 -05:00
Graham Christensen
d003fec8a5 RunCommandLogs: add a did_succeed helper 2022-01-07 15:05:33 -05:00
Graham Christensen
5bb3e2be78 Record the errno if exec fails 2022-01-07 15:05:33 -05:00
Graham Christensen
4ce8239cea RunCommand: create run logs for each execution 2022-01-07 15:05:33 -05:00
Graham Christensen
52843195db RunCommandLogs: init table 2022-01-07 15:05:33 -05:00
Graham Christensen
f4e86a3236 Merge pull request #1089 from DeterminateSystems/config/tracker
Fetch the tracker HTML from the config file, remove HYDRA_TRACKER
2022-01-06 15:48:47 -05:00
Graham Christensen
9708f6bf6f Fetch the tracker HTML from the config file, remove HYDRA_TRACKER
The indentation in the hydra.conf makes it possible to include multi-line
strings without it being likely that the contents of the tracker
is mis-parsed or interrupts tho config parser.

It isn't impossible / foolproof probably, but it shouldn't be likely.
2022-01-05 15:27:21 -05:00
Graham Christensen
76962bfcb0 Merge pull request #1083 from DeterminateSystems/faster-notifications
Faster notifications and buildQueued support
2021-12-23 09:23:00 -05:00
Graham Christensen
189d4fdabe build_queued: document in the notifications docs 2021-12-21 20:57:53 -05:00
Graham Christensen
2db422f7b0 Event: interested -> interestedIn 2021-12-21 20:57:53 -05:00
Graham Christensen
e84bbc7f90 hydra-eval-jobset: notify build_queued 2021-12-21 20:57:53 -05:00
Graham Christensen
a14501c616 Tasks: only execute the event if the plugin is interested in it 2021-12-21 20:57:53 -05:00
Graham Christensen
633fc36d6a TaskDispatcher: pre-declare the notify_no_such_plugin metric 2021-12-21 20:57:53 -05:00
Graham Christensen
d195e545f5 hydra-notify: listen for build_queued events 2021-12-21 20:57:53 -05:00
Graham Christensen
eb5f6c8490 Merge pull request #1084 from DeterminateSystems/measure-per-event-duration
hydra-notify: track the duration of handling an event
2021-12-21 20:00:30 -05:00
Graham Christensen
cf514baaf2 hydra-notify: track the duration of handling an event
Currently we only track how long individual plugins take.
With #1083 we stop executing a lot of plugins, but we
don't have a way to measure its practical impact on the
execution time of handling events.
2021-12-21 19:46:19 -05:00
Graham Christensen
e1e5fafdff Merge pull request #1079 from DeterminateSystems/dev-server
foreman: run the dev server with --restart and --debug
2021-12-17 10:03:08 -05:00
Graham Christensen
aaec4bb626 foreman: run the dev server with --restart and --debug
Debug enables info and debug log levels and provides quite a lot of useful dev-time information.

Restart automatically restarts the app when the .pm files change.
2021-12-16 10:20:25 -05:00
Graham Christensen
cf6f78c365 Merge pull request #1078 from DeterminateSystems/fixup-queue-runner-status
queue-runner-status: fixup from perlcritic-level-2
2021-12-15 18:44:07 -05:00
Graham Christensen
f2f8d571f3 queue-runner-status: fixup from perlcritic-level-2
>
> from_json was legacy / deprecated. This was the only use.
2021-12-15 17:24:23 -05:00
Graham Christensen
42f0dee441 Merge pull request #1076 from DeterminateSystems/HydraTestContext
HydraTestContext: init a context object for helpers
2021-12-14 21:22:43 -05:00
Graham Christensen
fbce3b6ed1 default-machine-file: use makeAndEvaluateJobset 2021-12-14 20:52:40 -05:00
Graham Christensen
06f824ca48 notifications.t: use system() with lists 2021-12-14 20:48:19 -05:00
Graham Christensen
5836bc9a11 HydraTestContext::makeAndEvaluateJobset: make a random user 2021-12-14 20:48:07 -05:00
Graham Christensen
c2384a04d8 notifications.t: move to makeAndEvaluateJobset 2021-12-14 20:41:21 -05:00
Graham Christensen
008321d972 build-products: switch to makeAndEvaluateJobset 2021-12-14 20:32:13 -05:00
Graham Christensen
7333d444c6 evaluate-basic.t: move to makeAndEvaluateJobset 2021-12-14 20:25:54 -05:00
Graham Christensen
adfe74b76a HydraTestContext: give a helper for creating a project, jobset, evaluating jobs, and optionally building them.
In return, get a hash of all the build records.
2021-12-14 20:25:42 -05:00
Graham Christensen
3238496b3d t/Setup: move subs calling hydra-* programs to a CliPrograms module
Makes it so HydraTestContext can call them without an import loop
2021-12-14 20:25:02 -05:00
Graham Christensen
1fa141229f HydraTestContext: explicitly stop the db
This might, hopefully, I don't know, possibly force the
database to live a little while longer and *reduce* but not
eliminate errors around stopping the database before we lose all
our DB::PG handles to it.
2021-12-14 19:51:12 -05:00
Graham Christensen
eca09bc980 Attempt to fix errors during test teardown 2021-12-14 16:31:41 -05:00
Graham Christensen
a466d53d18 Merge pull request #1075 from DeterminateSystems/perlcritic-level-1
Perlcritic level 1
2021-12-14 12:09:30 -05:00
Graham Christensen
cff387a027 Merge pull request #1045 from DeterminateSystems/perlcritic-level-2
Perlcritic: level 2
2021-12-14 11:29:19 -05:00
Graham Christensen
e43f487157 perlcritic: return undef in list context too 2021-12-14 10:24:53 -05:00
Graham Christensen
d0a1cf5785 perlcritic: level 1 2021-12-14 10:24:34 -05:00
Graham Christensen
aa7b37838a PerlCritic: MoreUtils -> SomeUtils 2021-12-14 10:16:25 -05:00
Graham Christensen
a658b80863 perlcritic: Readonly -> ReadonlyX 2021-12-14 10:16:25 -05:00
Graham Christensen
fc49a7129d JSON -> JSON::MaybeXS 2021-12-14 10:16:25 -05:00
Graham Christensen
30a7f068b7 AttributeSet helper: skip wantarray 2021-12-14 10:16:25 -05:00
Graham Christensen
d2f03ca050 fixup foreach 2021-12-14 10:16:25 -05:00
Graham Christensen
327d79bc1d pin 2021-12-14 10:16:25 -05:00
Graham Christensen
4dfe787bc2 perlcritic: each() called at line 752, column 35. The each function may cause undefined behavior when operating on the hash while iterating. Use a foreach loop over the hash's keys or values instead. 2021-12-14 10:16:25 -05:00
Graham Christensen
7dcf6a01c6 JSON -> JSON::MaybeXS 2021-12-13 15:37:56 -05:00
Graham Christensen
d16c57e5f1 perlcritic: level 2 2021-12-13 15:35:07 -05:00
Graham Christensen
ed58ad0c2b Merge pull request #1073 from DeterminateSystems/runcommand-tests
Runcommand: Expand the test coverage
2021-12-09 09:44:20 -05:00
Graham Christensen
26b197ea62 RunCommand: calculate all the commands to run against before starting 2021-12-08 20:29:32 -05:00
Graham Christensen
b7962c3882 RunCommand: Move the json validation testing to its own test 2021-12-08 20:29:27 -05:00
Graham Christensen
2ce0ab9f51 RunCommand: move JSON generation to its own function 2021-12-08 20:09:48 -05:00
Graham Christensen
bb91f96381 RunCommand: test isEnabled, configSectionMatches, and eventMatches 2021-12-08 20:03:43 -05:00
Graham Christensen
9dfa34682d RunCommand tests: move in to a subdirectory 2021-12-08 20:03:43 -05:00
Graham Christensen
7a5b8a38d9 builds page: capitalize tabs (#1072)
Make tabs Title Case
2021-12-08 20:02:14 -05:00
Graham Christensen
2cbeca5c44 Merge pull request #1071 from DeterminateSystems/log-fetches-evals
hydra-eval-jobset: log fetches and evaluations
2021-12-08 16:00:29 -05:00
Graham Christensen
264092169c hydra-eval-jobset: log fetches and evaluations 2021-12-08 09:25:27 -05:00
Graham Christensen
7227395a72 Merge pull request #1068 from DeterminateSystems/fix-some-warnings
Fix some warnings
2021-12-03 15:38:46 -05:00
Cole Helbling
47cabac4bf hydra-eval-jobset: fix use of uninitialized value
This happens with flake jobsets for obvious reasons (namely, that nixexprinput
and nixexprpath may be undefined for a flake jobset).

12:38:59 hydra-evaluator.1    | Use of uninitialized value $args[0] in join or string at /home/vin/workspace/vcs/hydra/src/script/hydra-eval-jobset line 648.
12:38:59 hydra-evaluator.1    | Use of uninitialized value $args[1] in join or string at /home/vin/workspace/vcs/hydra/src/script/hydra-eval-jobset line 648.
2021-12-03 12:12:53 -08:00
Cole Helbling
5659d2982c Hydra/Controller/Root: remove deprecated LocalRegex
11:38:20 hydra-server.1       | DEPRECATION WARNING: The Regex dispatch type is deprecated.
11:38:20 hydra-server.1       |   It is recommended that you convert Regex and LocalRegex
11:38:20 hydra-server.1       |   methods to Chained methods. at /nix/store/aa6gw57fnahd4824pbhmvcs0jlypmynq-hydra-perl-deps/lib/perl5/site_perl/5.32.1/Catalyst/DispatchType/Regex.pm line 210.
2021-12-03 12:12:53 -08:00
Cole Helbling
ecb1454cf1 t/Controller/Root: test narinfo path 2021-12-03 12:12:53 -08:00
Graham Christensen
085b02e092 t/Helper/CatalystUtils.t: test trim functionality 2021-12-03 11:58:19 -08:00
Graham Christensen
fc82877695 Merge pull request #1069 from DeterminateSystems/fixup-my-under
TT.t: fixup $_, since _ is a special variable, not a throwaway
2021-12-01 14:04:38 -05:00
Graham Christensen
4d5dfec8c7 TT.t: fixup $_, since _ is a special variable, not a throwaway 2021-12-01 13:46:58 -05:00
Cole Helbling
d56815cae6 Hydra/Helper/CatalystUtils: default trim arg to empty string
12:34:12 hydra-server.1       | Use of uninitialized value $s in substitution (s///) at /home/vin/workspace/vcs/hydra/src/script/../lib/Hydra/Helper/CatalystUtils.pm line 283, <$fh> line 1.
2021-11-30 13:10:31 -08:00
Cole Helbling
78233b8083 Hydra: Unicode::Encoding is auto-applied
11:28:20 hydra-server.1       | [warn] Unicode::Encoding plugin is auto-applied, please remove this from your appclass and make sure to define "encoding" config
2021-11-30 12:42:05 -08:00
Cole Helbling
f26b3e1779 Hydra/Event: fix scalar context warning
12:10:15 hydra-notify.1       | %channels_to_events{...} in scalar context better written as $channels_to_events{...} at /home/vin/workspace/vcs/hydra/src/lib/Hydra/Event.pm line 20.
2021-11-30 12:42:01 -08:00
Graham Christensen
e5be4a9022 Merge pull request #1065 from DeterminateSystems/project-jobset-links
project:jobset:job: make clickable links in titles
2021-11-22 20:39:26 -05:00
Graham Christensen
ce6805f02b fixup: TT.t: move the :'s to the next line 2021-11-22 20:20:06 -05:00
Graham Christensen
b06457c75c Titles of pages: make project:jobset:job names clickable
But don't make the final element clickable when we're looking at that
thing.
2021-11-22 20:20:06 -05:00
Graham Christensen
f1343b3a4c layout.tt: support a title with HTML in it
By default, title is escaped. To support links in titles, support
providing the title with HTML in it.
2021-11-22 13:38:53 -05:00
Graham Christensen
03323f6ef1 TT: add helpers for linking to jobs, jobsets, and projects, and for generating colon separated names. 2021-11-22 13:38:53 -05:00
Graham Christensen
72590a4f8d Merge pull request #1064 from NixOS/dependabot/github_actions/cachix/install-nix-action-16
build(deps): bump cachix/install-nix-action from 15 to 16
2021-11-22 10:35:20 -05:00
dependabot[bot]
4372548885 build(deps): bump cachix/install-nix-action from 15 to 16
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 15 to 16.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v15...v16)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-22 15:00:54 +00:00
Graham Christensen
aab4a0e8ab Merge pull request #1061 from DeterminateSystems/update-dbix-overwrite
update-dbix: overwrite modifications
2021-11-19 15:15:03 -05:00
Graham Christensen
bb040aa029 Merge pull request #1060 from DeterminateSystems/runcommand-t-fixups
Runcommand.t: minor cleanup
2021-11-19 15:14:52 -05:00
Graham Christensen
ecb4697930 update-dbix: overwrite modifications
Prevents authors from mistakenly corrupting the hashes
2021-11-19 15:02:07 -05:00
Graham Christensen
27f48c6f7f Merge pull request #1058 from NixOS/dependabot/github_actions/cachix/install-nix-action-15
build(deps): bump cachix/install-nix-action from 14 to 15
2021-11-19 14:57:31 -05:00
Graham Christensen
5917de4948 t/plugins/runcommand.t: output the filename if it fails to open 2021-11-17 15:05:28 -05:00
Graham Christensen
e5a4147f0a runcommand.t: stop dumping the json 2021-11-17 15:05:28 -05:00
Graham Christensen
f1350d2de7 Merge pull request #1057 from amerocu/missing-nc
add missing develop dependency
2021-11-16 12:40:43 -05:00
dependabot[bot]
735c3f6f35 build(deps): bump cachix/install-nix-action from 14 to 15
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 14 to 15.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v14...v15)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-15 15:00:52 +00:00
Marco Turchetto
68a9aac251 add missing develop dependency 2021-11-10 17:51:01 +01:00
Eelco Dolstra
2dc6d58845 Merge pull request #1052 from Mic92/docs
Document github integration further.
2021-11-02 15:29:07 +01:00
Eelco Dolstra
492476bbfe Merge pull request #1054 from rybak/docs-typos
docs: fix typos
2021-11-02 15:28:36 +01:00
Andrei Rybak
a462a9f488 docs: fix typos
Fix various typos in Markdown documentation files.
2021-11-02 14:39:58 +01:00
Jörg Thalheim
1593e0212e docs: document github webhooks 2021-10-30 09:42:32 +02:00
Jörg Thalheim
70f1db2762 docs: improve github refs documentation 2021-10-30 09:40:37 +02:00
Jörg Thalheim
cdddbb89f3 docs: improve github status plugin documentation 2021-10-30 09:40:36 +02:00
Eelco Dolstra
9ae676072c Merge pull request #1051 from DeterminateSystems/restart-cancel-resultset-p2
Validate and fix canceling builds
2021-10-27 18:22:20 +02:00
Graham Christensen
c1630e6d80 Admin/clear-queue-non-current: test behavior 2021-10-27 11:43:58 -04:00
Graham Christensen
d19890a4e1 JobsetEval/cancel: test & fix 2021-10-27 11:43:36 -04:00
Graham Christensen
ef9a9fa481 Merge pull request #1025 from lukegb/hydra-better-errors
Produce better errors for failing jobsets
2021-10-26 12:35:45 -04:00
Graham Christensen
dc2bec3272 Merge pull request #1050 from DeterminateSystems/restart-cancel-resultset
Restart/Cancel: Pass a resultset
2021-10-26 11:49:28 -04:00
Graham Christensen
a62c2a4d71 JobsetEval/restart-*: Write tests for the behavior 2021-10-26 10:45:33 -04:00
Graham Christensen
383b395b00 Test canceling builds. 2021-10-26 09:44:58 -04:00
Luke Granger-Brown
67ebce8493 Output evaluation errors without crashing if aggregate job is broken.
At the moment, aggregate jobs can easily break and cause the entire
evaluation to fail, which is not ideal. For Nixpkgs, we do have some
important aggregate jobs (like `tested`), but for debugging and building
purposes it's still useful to get a partial result even if the channel
won't actually advance.

This commit changes the behaviour of hydra-eval-jobs such that it
aggregates any errors found during the construction of an aggregate, and
will instead annotate the job with the evaluation failure such that it
shows up in a "cleaner" way.

There are really two types of failure that we care about: one is where
the attribute just ends up missing altogether in the final output, and
also where the attribute is in the output but fails to evaluate. Both
are handled here.

Note that this does mean that the same error message may be output
multiple times, but this aids debuggability because it'll be much
clearer what's blocking the job from being created.
2021-10-26 10:14:34 +01:00
Luke Granger-Brown
f2b51a017b Test Setup: fix evalSucceeds to actually output evaluation errors
At the moment, the jobset object is unlikely to actually retrieve the
evaluation error output, because it isn't refreshed after
hydra-eval-jobsets is run.

Explicitly calling DBIx::Class::Row->discard_changes causes any updated
data to be refreshed, at the cost of losing any not-yet committed
changes to the row.
2021-10-26 10:13:58 +01:00
Graham Christensen
d52e397503 Builds controller: add a test for restarting builds, fix restarting builds 2021-10-25 22:22:08 -04:00
Graham Christensen
ffedbe5996 restart/cancelBuilds: always pass resultsets explicitly 2021-10-25 22:21:48 -04:00
Graham Christensen
592fef9d82 Merge pull request #1049 from DeterminateSystems/drop-systemtypes
SystemTypes: drop database table.
2021-10-24 21:46:57 -04:00
Graham Christensen
802a5dfe68 Merge pull request #1048 from DeterminateSystems/fixup-1003
Hydra::Helper::Nix::getMachines: add a test
2021-10-24 21:38:38 -04:00
Graham Christensen
ff888032eb SystemTypes: drop database table. It was originally removed in #65, but put back in fcd511c4de, and now totally unused. 2021-10-24 21:38:04 -04:00
Graham Christensen
5fbf1470bd (perl) machines file: support machine lines with multiple spaces between fields 2021-10-24 21:30:53 -04:00
Graham Christensen
b817124337 Hydra::Helper::Nix::getMachines: add a test
Fix parsing breakage from #1003: assigning the lines to $lines broke chomp and the filters.

This test validates the parsing works as expected, and also fixes
a minor bug where '-' in features isn't pruned, like in the C++
repo.
2021-10-23 22:53:55 -04:00
Graham Christensen
7fbf5cbd42 Merge pull request #1047 from NixOS/revert-825-fix/unhelpful-errors-in-aggregates
Revert "Fix unhelpful error messages in aggregate jobs."
2021-10-23 22:23:40 -04:00
Graham Christensen
8cf158b7a9 Revert "Fix unhelpful error messages in aggregate jobs." 2021-10-23 22:23:29 -04:00
Graham Christensen
3516950d3c Merge pull request #825 from samueldr/fix/unhelpful-errors-in-aggregates
Fix unhelpful error messages in aggregate jobs.
2021-10-23 20:34:50 -04:00
Graham Christensen
30e50010f5 Merge pull request #1044 from DeterminateSystems/perlcritic-level-3
Perlcritic level 3
2021-10-20 17:06:26 -04:00
Graham Christensen
5285d0b6cb gittea test: prune trailing space 2021-10-20 13:09:39 -04:00
Graham Christensen
d98d74fa4f perlcritic: doesn't like prototypes 2021-10-20 13:09:39 -04:00
Graham Christensen
c317ab0dbe shell: add pixz so NAR serving works from foreman 2021-10-20 13:09:39 -04:00
Graham Christensen
7095d00608 perlcritic: make all open() calls three-argument
Two-argument calls end up parsing the second argument to guess what
should happen, three-arg parses ... less?
2021-10-20 13:09:39 -04:00
Graham Christensen
43c056bb7b t/TaskDispatcher.t: array / arrayref consistency
Also fixes a test which was comparing the length of two lists
instead of the values inside the lists. Dang, Perl.
2021-10-20 11:38:27 -04:00
Graham Christensen
a5fa3fccc3 perlcritic: level 3 2021-10-20 10:51:17 -04:00
Graham Christensen
f0d0358ee4 Merge pull request #1043 from DeterminateSystems/perl-warnings
Fixup Perl warnings around undefined variables
2021-10-20 10:48:05 -04:00
Graham Christensen
a887b3d346 fixup! EmailNotification: address Use of uninitialized value in numeric eq (==) 2021-10-20 10:40:08 -04:00
Graham Christensen
a36d23c1dd fixup! BitBucketStatus: address Use of uninitialized value in numeric eq (==) 2021-10-20 10:40:08 -04:00
Graham Christensen
d5282de131 Merge pull request #1042 from DeterminateSystems/declarative-jobsets-no-jq
GitHubPulls: output sorted json without using jq
2021-10-20 10:33:46 -04:00
Graham Christensen
3c38629fad GitHubPulls: output sorted json without using jq 2021-10-20 10:05:31 -04:00
Graham Christensen
30d36da057 CoverityScan: fixup tarballshandle introduced in 21e1ff0da1 2021-10-19 22:04:57 -04:00
Graham Christensen
093e235bf0 GithubRefs: fixup "my" variable $type masks earlier declaration in same scope 2021-10-19 22:02:41 -04:00
Graham Christensen
0f8d02894a hydra-eval-jobset: Scalar value @declInputs[0] better written as $declInputs[0] at hydra-eval-jobset line 570. 2021-10-19 21:52:39 -04:00
Graham Christensen
31cf249aed S3Backup: check for bzip2 and xz Nix Config support (Use of uninitialized value ::Config::xz in concatenation) 2021-10-19 21:52:39 -04:00
Graham Christensen
bf692c9e8c BitBucketStatus: address Use of uninitialized value in numeric eq (==) 2021-10-19 21:52:39 -04:00
Graham Christensen
4fd90ec784 EmailNotification: address Use of uninitialized value in numeric eq (==) 2021-10-19 21:52:39 -04:00
Graham Christensen
01112e9bd3 GitInput: deal with undefined deepClone 2021-10-19 21:52:39 -04:00
Eelco Dolstra
2ee584e7ae Merge pull request #1040 from NixOS/update-api
Update hydra-api.yaml
2021-10-12 16:46:16 +02:00
Eelco Dolstra
2e43a9644f Update hydra-api.yaml 2021-10-12 14:31:46 +02:00
Eelco Dolstra
8755321ec7 Merge pull request #1039 from NixOS/return-flake
/eval: Return more columns
2021-10-12 14:09:52 +02:00
Eelco Dolstra
888ba467fd /eval: Return more columns
Fixes #1038.
2021-10-12 12:41:37 +02:00
Graham Christensen
0be3bed757 Merge pull request #1033 from Mic92/plugins
add basic documentation for all plugins
2021-10-08 09:17:41 -04:00
Jörg Thalheim
243291f9bd add basic documentation for all plugins
Co-authored-by: Pablo Ovelleiro Corral <mail@pablo.tools>
Co-authored-by: Graham Christensen <graham@grahamc.com>
2021-10-03 13:56:44 +02:00
Graham Christensen
dcee1a35ad Merge pull request #1035 from DeterminateSystems/fixup-perlcritic-after-constituents
constituents test: add use warnings
2021-09-30 09:41:27 -04:00
Graham Christensen
3990bd12e9 constituents test: add use warnings
This is causing CI to fail after #1026 merged. #1026 had a green
bill of health, but #1003 increased perlcritic to level 4. #1003
was not part of #1026 so it was not checked at perlcritic level 4.
2021-09-30 09:13:01 -04:00
Graham Christensen
4c8279044b Merge pull request #1026 from DeterminateSystems/constituents
add api endpoint: /build/<id>/constituents
2021-09-28 09:21:21 -04:00
Eelco Dolstra
19e668b7cd Merge pull request #981 from jonringer/pure_eval
Allow for evaluator_pure_eval to be configured
2021-09-27 20:25:01 +02:00
Eelco Dolstra
2745226ada Merge pull request #1003 from DeterminateSystems/perlcritic-level-4
perlcritic: level 4
2021-09-27 20:23:55 +02:00
Eelco Dolstra
37af3e69eb Merge pull request #1030 from NixOS/ublock
Fix 'Error loading tab: 0 error' with uBlock Origin
2021-09-27 20:21:39 +02:00
Eelco Dolstra
b622337186 Merge pull request #1029 from NixOS/fix-make
Fix building $(srcdir)/static
2021-09-27 17:45:01 +02:00
Eelco Dolstra
66375fd2d9 Fix 'Error loading tab: 0 error' with uBlock Origin
/metrics-tab matches a rule in one of uBlock Origin's default
blocklists, so let's name it something else.
2021-09-27 17:42:56 +02:00
Eelco Dolstra
9bb3e30a46 Fix building $(srcdir)/static
Fixes

  mv: cannot move './static/bootstrap-4.3.1-dist' to './static/bootstrap/bootstrap-4.3.1-dist': Directory not empty

when 'make' is called more than once.
2021-09-27 17:01:25 +02:00
Graham Christensen
b550145967 Merge pull request #1017 from Ma27/compare-full
jobset-eval: pass `full` parameter to "Compare to..."
2021-09-24 22:00:05 -04:00
Graham Christensen
8d7116522f Merge pull request #1024 from Ma27/hydra-home-creation
hydra-module: don't use `createHome = true;` to create Hydra's base-dir
2021-09-24 21:59:26 -04:00
Graham Christensen
c60c8d10ea add api endpoint: /build/<id>/constituents
Returns a list of constituent builds
2021-09-24 16:30:44 -04:00
Graham Christensen
99161c7c53 Merge pull request #1012 from helsinki-systems/fix/ldap-test
fix ldap nixos test
2021-09-24 14:27:26 -04:00
Graham Christensen
047fbbdd6b Merge pull request #1021 from NixOS/dependabot/github_actions/cachix/install-nix-action-14
build(deps): bump cachix/install-nix-action from 13 to 14
2021-09-24 14:26:52 -04:00
Jörg Thalheim
e985a277b3 migrate to new openldap module syntax 2021-09-23 20:32:09 +02:00
Maximilian Bosch
dd2ce84fe5 hydra-module: don't use createHome = true; to create Hydra's base-dir
In NixOS, the user generation script was changed to set the permissions `0700`
to a home-directory that's specified in the `users.users`-submodule with
`createHome` being set to `true`[1].

However, the home-directory of `hydra` is also the base directory of other services using
other users (e.g. `hydra-queue-runner`). With permissions being `0700`, processes with
such a user cannot traverse into `/var/lib/hydra` and thus not into subdirectories.

I guess that this issue was kind of hidden because `hydra-init.service` ensures
proper permissions[2]. However, if `hydra-init.service` is not restarted on a
system-activation, the permissions of `/var/lib/hydra` will be set back to `0700`
by the activation script that runs on each activation.

This has lead to errors like this in `hydra-queue-runner` on my Hydra:

```
Sep 20 09:11:30 hydra hydra-queue-runner[306]: error (ignored): error: cannot unlink '/var/lib/hydra/build-logs/7h/dssz03gazrkqzfmlr5cprd0dvkg4db-squashfs.img.drv': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: error (ignored): error: cannot unlink '/var/lib/hydra/build-logs/b9/350vd8jpv1f86i312c9pkdcd2z56aw-squashfs.img.drv': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: error (ignored): error: cannot unlink '/var/lib/hydra/build-logs/kz/vlq4v9a1rylcp4fsqqav3lcjgskky4-squashfs.img.drv': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: error (ignored): error: cannot unlink '/var/lib/hydra/build-logs/xd/hkjnbbr9jp7364pkn8zpk9v8xapj2c-nix-2.4pre20210917_37cc50f.drv': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: error (ignored): error: cannot unlink '/var/lib/hydra/build-logs/zn/9df7225fl8p7iavqqfvlyay4rf0msw-nix-2.4pre20210917_37cc50f.drv': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: possibly transient failure building ‘/nix/store/7hdssz03gazrkqzfmlr5cprd0dvkg4db-squashfs.img.drv’ on ‘roflmayr’: error: creating directory '/var/lib/hydra/build-logs': Permission denied
Sep 20 09:11:30 hydra hydra-queue-runner[306]: will retry ‘/nix/store/7hdssz03gazrkqzfmlr5cprd0dvkg4db-squashfs.img.drv’ after 543s
```

Because of that, I decided to remove the `createHome = true;` setting and instead used
`systemd-tmpfiles`[3] which can not only ensure that certain directories
exist, but also proper permissions.

With this change, we can also get rid of the manual setup in
`hydra-init.service` since `systemd-tmpfiles` will be executed by
`switch-to-configuration` before *any* systemd service gets started. On
startup, `systemd-tmpfiles-setup.service` is invoked within
`sysinit.target` being reached, so when `hydra-init.service` gets called
in `multi-user.target`, the structure already exists.

[1] fa0d499dbf
[2] 3cec908738/hydra-module.nix (L260-L262)
[3] https://www.freedesktop.org/software/systemd/man/systemd-tmpfiles.html
2021-09-22 00:08:15 +02:00
dependabot[bot]
ac0529cacb build(deps): bump cachix/install-nix-action from 13 to 14
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 13 to 14.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v13...v14)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-13 15:00:47 +00:00
Maximilian Bosch
255d4a91bc jobset-eval: pass full parameter to "Compare to..."
When I take a look at *all* failing builds (by clicking at `[...] more
jobs omitted`) and I try to compare the failures to another jobset, I'd
like to still view *all* failing builds in the compare-view.

This wasn't the case before since the `full=`-param was ignored by the
compare-buttons.
2021-09-08 23:23:29 +02:00
Graham Christensen
741590c923 perlcritic: explicitly assign the result of readdir/file reads 2021-09-07 21:55:55 -04:00
Graham Christensen
85bb1c7ef9 (perlcritic) JSON::Any -> JSON::MaybeXS 2021-09-07 21:55:55 -04:00
Graham Christensen
c603ae35f0 perlcritic: Don't conditionally declare variables 2021-09-07 21:35:01 -04:00
Graham Christensen
3cec908738 Merge pull request #1016 from DeterminateSystems/fixup/1011
ResultSet::TaskRetries: add missing method, get_retryable_task
2021-09-07 11:20:29 -04:00
Graham Christensen
b1879132af ResultSet::TaskRetries: add missing method, get_retryable_task
Yet again, manual testing is proving to be insufficient. I'm pretty
sure I wrote this code but lost it in a rebase, or perhaps the switch
to result classes.

At any rate, this implements the actual "fetch a retry row and run it"
for the hydra-notify daemon.

Tested by hand.
2021-09-07 11:12:10 -04:00
Graham Christensen
d6aa3f8d15 Merge pull request #1011 from DeterminateSystems/retryable-notifications
Retryable notifications
2021-09-07 10:04:32 -04:00
Graham Christensen
21e1ff0da1 perlcritic: don't open files as bare words 2021-09-06 22:20:17 -04:00
Graham Christensen
efd1d78b97 Hydra::Helper::Nix: getHydraNotifyPrometheusConfig fixup strict warning around double-declaring cfg 2021-09-06 22:13:33 -04:00
Graham Christensen
c880888f1e File::Slurp -> File::Slurper 2021-09-06 22:13:33 -04:00
Your Name
c54629b732 Helper/Nix.pm: perlcritic statsd in scalar context 2021-09-06 22:13:33 -04:00
Your Name
55b7802b61 t/lib/Setup.pm: nix_config: default to empty string 2021-09-06 22:13:33 -04:00
Your Name
4677a7c894 perlcritic: use strict, use warnings 2021-09-06 22:13:33 -04:00
Your Name
d3feb8b9a5 perlcritic: ratchet to severity 4 2021-09-06 21:35:35 -04:00
Graham Christensen
dd06ab7a99 Merge pull request #1004 from DeterminateSystems/avoid-a-b
Avoid $a, $b
2021-09-06 21:35:17 -04:00
Graham Christensen
ca4b8d449f BitBucketStatus: tbuild -> build (typo) 2021-09-06 21:12:13 -04:00
Graham Christensen
d9df26ac5a POD: improve wording, punctuation, caps
Co-authored-by: Cole Helbling <cole.helbling@determinate.systems>
2021-09-03 09:13:34 -04:00
Graham Christensen
ea3ae0693e Hook up the retryable tasks with hydra-notify 2021-09-02 10:06:26 -04:00
Graham Christensen
c0e86faa78 hydra-notify: call TaskRetries->save_task if a task fails 2021-09-02 10:06:26 -04:00
Graham Christensen
b0055a23df TaskDispatcher: Support re-queueing tasks, and dropping tasks after 100 failures. 2021-09-02 10:06:26 -04:00
Graham Christensen
d0b0fc21b3 ResultSet::TaskRetries: teach about saving tasks 2021-09-02 10:06:26 -04:00
Graham Christensen
147fa4d029 Result::TaskRetries: Teach about requeue 2021-09-02 10:06:26 -04:00
Graham Christensen
42c2d2f387 Hydra::Math: add an exponential_backoff function 2021-09-02 10:06:26 -04:00
Graham Christensen
29738364fb ResultSet::TaskRetries: add get_seconds_to_next_retry
Get the number of seconds before the next retriable task is ready.

This number is specifically intended to be used as a timeout, where
`undef` means never time out.
2021-09-02 10:06:26 -04:00
Graham Christensen
c4134c8e84 TaskRetries: init table 2021-09-02 10:06:26 -04:00
Graham Christensen
1f2adf61aa hydra-notify: extract runPluginsForEvent to a TaskDispatcher 2021-09-02 10:06:26 -04:00
Graham Christensen
bec44614f4 Merge pull request #1014 from Ma27/fix-gitea-test
gitea-plugin: fix test
2021-08-30 09:43:59 -04:00
ajs124
59cb44261d fix ldap nixos test
passwords were replaced with salted sha1 instead of sha256, because I
don't want to have to figure out how to make slapd load this module

We could also just do {CLEARTEXT} for the purpose of this test
2021-08-29 01:47:34 +02:00
Maximilian Bosch
e36353532c gitea-plugin: fix test
The test seems to be broken for a while[1]. The cause for this is that
in gitea 1.14 the `create-user` command got renamed to `user create`.

[1] https://hydra.nixos.org/build/151092299
2021-08-29 00:08:59 +02:00
Graham Christensen
a0a9d4c1c3 Merge pull request #1009 from DeterminateSystems/dbix-docs
hydra.sql: explain update-dbix.pl map
2021-08-27 10:22:53 -04:00
Graham Christensen
fa57fb8f25 hydra.sql: explain update-dbix.pl map 2021-08-26 22:10:19 -04:00
Graham Christensen
f81905fce4 Merge pull request #1007 from DeterminateSystems/resultset-class-namespaces
DBIx::Class: migrate to use_namespaces
2021-08-26 16:30:07 -04:00
Graham Christensen
397d13a300 DBIx::Class: migrate to use_namespaces
This gives us a place to put helper functions that act on entire
tables, not just individual records.

This should be a backwards compatible change, except in places we're
manually using result class names.
2021-08-26 12:37:19 -04:00
Graham Christensen
da55838703 Merge pull request #1001 from DeterminateSystems/hydra-notify-prometheus
hydra-notify: export prometheus metrics
2021-08-25 11:50:43 -04:00
Your Name
24467a7bde Nix::getHydraNotifyPrometheusConfig: print errors if the configuration provided is invalid. 2021-08-24 11:35:38 -04:00
Your Name
4ebdcc290e fixup! hydra-notify: pre-declare metrics 2021-08-24 10:57:23 -04:00
Your Name
45e8fa5319 hydra-notify: support sending diagnostic dumps to STDERR on request 2021-08-24 10:56:13 -04:00
Your Name
de2282bcf4 hydra-notify: print out log lines indicating it is or is not launching the exporter 2021-08-24 10:56:13 -04:00
Your Name
5c1228e141 hydra-notify: pre-declare metrics 2021-08-24 10:56:13 -04:00
Your Name
f4ad80527a hydra-notify: Enable the prometheus exporter in development environments by default 2021-08-24 10:56:13 -04:00
Your Name
6d7ee27d25 hydra-notify: make the prometheus endpoint configurable, default-off 2021-08-24 10:56:13 -04:00
Your Name
5d0ad5f649 hydra-notify: initial scratch take of prometheus events 2021-08-24 10:56:12 -04:00
Graham Christensen
e9ba0b56f6 BuildFinished : $b -> $build (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
5e10648a98 CoverityScan: $b -> $build (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
c929f5cac0 SlackNotification: $build -> $topbuild, $b -> $build (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
b4f9807290 GithubStatus: $build -> $topbuild, $b -> $build (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
5c9d8794b1 GiteaStatus: $build -> $topbuild, $b -> $build (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
3920bf1df3 BitBucketStatus: $build -> $topbuild, $b -> $build (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
bcf37ab705 GitlabStatus: $build -> $topbuild, $b -> $build (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
b4a19fd3c8 HIpChatNotification: $build -> $topbuild, $b -> $build (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
0d4ce15c62 EmailNotification: $build -> $topbuild, $b -> $build (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
0f88014631 CircleCiNotification: $b -> $build (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
b6714cdce3 JobsetEval: $a, $b to $left, $right (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
d0fb3cbf8f Job: $b -> $build (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
1cda08351f CatalystUtils: rename $b to $builds (perlcritic) 2021-08-20 21:52:32 -04:00
Graham Christensen
4aa6a7b6ee Merge pull request #1002 from DeterminateSystems/perlcritic
Check the perl with perlcritic
2021-08-20 14:28:35 -04:00
Your Name
4632132d02 fixup perlcritic: indirect new
> Subroutine new called using indirect syntax at line 14, column 14.  See page 349 of PBP.  (Severity: 5)
2021-08-20 11:39:19 -04:00
Your Name
241985fb2d Start checking PRs with perlcritic 2021-08-20 11:06:43 -04:00
Your Name
098e48d055 Flake: add perlcritic deps 2021-08-19 16:17:49 -04:00
Your Name
194eda28b7 flake.nix sort hydra-perl-deps inputs 2021-08-18 15:10:55 -04:00
Graham Christensen
ff7ecf50d9 Merge pull request #1000 from DeterminateSystems/fixup/pr-998'
#998: Batch of fixups
2021-08-16 16:18:24 -04:00
Your Name
6e65c3b320 hydra-notify: fixup printing of build IDs
Used to print:

    sending notifications for build Hydra::Model::DB::Builds=HASH(0x124cf960)->id...

Now it prints:

    sending notifications for build 123...
2021-08-16 16:09:05 -04:00
Your Name
2c50227082 hydra-notify: properly call new_event 2021-08-16 15:52:25 -04:00
Your Name
e572a5e576 hydra-notify: use Hydra::Event 2021-08-16 15:52:14 -04:00
Your Name
d311a0d002 hydraJobs.tests.notifications: fixup file reference 2021-08-16 15:51:51 -04:00
Graham Christensen
fda3ed1d4e Merge pull request #999 from DeterminateSystems/fixup/pr-998
lib/makefile: include Event/*.pm
2021-08-16 14:13:18 -04:00
Your Name
cfd3034af8 lib/makefile: include Event/*.pm 2021-08-16 14:04:48 -04:00
Graham Christensen
2433dd96ee Merge pull request #998 from DeterminateSystems/notify-events
hydra-notify: abstract event handling, make testable
2021-08-16 13:22:42 -04:00
Graham Christensen
fa6d7abc13 hydra-notify: move BuildFinished processing to an Event 2021-08-13 16:51:29 -04:00
Graham Christensen
4a1389e36e hydra-notify: move StepFinished processing to an Event 2021-08-13 16:51:29 -04:00
Graham Christensen
4fdb20d3bd hydra-notify: move BuildStarted processing to an Event 2021-08-13 16:51:29 -04:00
Graham Christensen
10e85e3422 hydra-notify: Create a helper for running each plugin on an event 2021-08-13 16:51:29 -04:00
Graham Christensen
d02c6794f4 Event: teach how to execute a plugin 2021-08-13 16:51:29 -04:00
Graham Christensen
4e86e55008 Event.pm: add a new_event helper to parse and construct an Event
An Event will be part of many Tasks
2021-08-13 16:51:29 -04:00
Graham Christensen
64a3e75c10 Event: init structure and parse existing messages 2021-08-13 16:51:29 -04:00
Graham Christensen
a14c8ad5f8 Merge pull request #995 from DeterminateSystems/declarative-jobsets-plugin
Declarative jobsets: move event handling to a plugin
2021-08-12 15:56:13 -04:00
Graham Christensen
0f958f3425 Merge pull request #997 from DeterminateSystems/abstract-listener
Abstract over postgres' LISTEN/NOTIFY
2021-08-12 14:00:34 -04:00
Graham Christensen
f30addb9d7 Merge pull request #996 from DeterminateSystems/cleanup-build-finished
hydra-notify: move buildFinished query in to the function impl
2021-08-12 13:57:13 -04:00
Graham Christensen
5027003285 Abstract over postgres' LISTEN/NOTIFY
This lets us test the event loop if we wanted, and lets us
test the listening behavior in isolation.
2021-08-12 13:54:05 -04:00
Graham Christensen
593af41808 Declarative jobsets: move event handling to a plugin
Declarative jobsets were sort of tucked in to the event hanlder
itself. It turned out that it could have been implemented as a
plugin without much trouble.
2021-08-12 12:48:18 -04:00
Graham Christensen
9c5f317453 hydra-notify: move buildFinished query in to the function impl
This is more consistent with the other event handlers, of dealing
with IDs and not objects.
2021-08-12 12:30:35 -04:00
Eelco Dolstra
9bce425c33 Merge pull request #994 from NixOS/update-nix
Update nix
2021-08-10 14:35:30 +02:00
Eelco Dolstra
5edb58b314 Fix build 2021-08-10 13:47:16 +02:00
Eelco Dolstra
f1d5c254b5 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/d9864be4b757468d33bc49edddce5e4f04ef4b90' -> 'github:NixOS/nix/a6ba313a0aac3b6e2fef434cb42d190a0849238e'
* Added 'nix/lowdown-src': 'github:kristapsdz/lowdown/148f9b2f586c41b7e36e73009db43ea68c7a1a4d'
* Updated 'nix/nixpkgs': 'github:NixOS/nixpkgs/0e499fde7af3c28d63e9b13636716b86c3162b93' -> 'github:NixOS/nixpkgs/f77036342e2b690c61c97202bf48f2ce13acc022'
2021-08-10 13:41:04 +02:00
Graham Christensen
429be3ed44 Merge pull request #988 from DeterminateSystems/editorconfig
Initialize a basic editorconfig
2021-08-06 15:14:11 -04:00
Graham Christensen
3ceac80cdc Initialize a basic editorconfig
Based on NixOS/nixpkgs' editorconfig + some for Perl.
2021-08-06 14:59:40 -04:00
Graham Christensen
ba1ea8d9c4 Merge pull request #989 from DeterminateSystems/docs/connect-local-db
docs: note how to connect to the database
2021-08-06 14:56:20 -04:00
Graham Christensen
c7c322545d Merge pull request #992 from DeterminateSystems/sql/fixup-comment
hydra.sql: Update comment on regeneration
2021-08-06 14:54:12 -04:00
Graham Christensen
d1670b0526 Merge pull request #991 from DeterminateSystems/sql/fixup-generator-syntax
update-dbix.pl: correct indentation
2021-08-06 14:53:38 -04:00
Graham Christensen
512b0663e8 Merge pull request #990 from DeterminateSystems/docs/notifications
docs/notifications: fixup sending a notification
2021-08-06 14:52:55 -04:00
Graham Christensen
4169f22231 update-dbix.pl: correct indentation 2021-08-06 14:40:57 -04:00
Graham Christensen
5bd8dc171b hydra.sql: Update comment on regeneration
We no longer need to generate the hydra-postgres.sql document,
that is a relic from when sqlite was also supported.
2021-08-06 14:40:34 -04:00
Graham Christensen
5900e4d0b3 docs/notifications: fixup sending a notification 2021-08-06 14:35:38 -04:00
Graham Christensen
23ac4a665c docs: note how to connect to the database 2021-08-06 14:34:59 -04:00
Graham Christensen
4e94551602 Merge pull request #985 from kreisys/hydra-server-config-includes
Make hydra-server honor apache-style includes in hydra.conf like all the other components
2021-07-29 12:44:52 -04:00
Shay Bergmann
d64caea870 Remove clause suggesting absolute paths don't work 2021-07-26 19:51:29 +00:00
Shay Bergmann
f36bffa008 Use absolute path in example as it seems to be working now
might have something to do with `-IncludeRelative`...
2021-07-26 19:29:28 +00:00
Shay Bergmann
638f5a1ac9 Note in README how to run a single test 2021-07-26 17:16:41 +00:00
Shay Bergmann
ba557972c7 Add test to verify includes work 2021-07-26 17:16:40 +00:00
Shay Bergmann
503b0e0b6f Remove unnecessary comment 2021-07-26 17:16:40 +00:00
Shay Bergmann
173ecb5d92 Apply requested changes to Config.pm 2021-07-26 17:16:40 +00:00
Shay Bergmann
4f95774ca3 Factor out common options 2021-07-26 03:43:09 +00:00
Shay Bergmann
3c621ec386 ... add some needed gitignores... 2021-07-26 03:42:08 +00:00
Shay Bergmann
45077a120d ... fix embarrassing typo... 2021-07-23 22:10:00 +00:00
Shay Bergmann
e98bd0ec8d Comment around dupe to avoid drift 2021-07-22 23:27:21 -04:00
Shay Bergmann
774194d681 Update docs 2021-07-22 23:12:25 -04:00
Shay Bergmann
54c8028ec0 Make hydra-server honor config file includes 2021-07-22 17:25:30 -04:00
Graham Christensen
2f0dc294af Merge pull request #984 from DeterminateSystems/test-Jobset-constraints
Jobset: test `type`-related constraints
2021-07-20 13:45:33 -04:00
Cole Helbling
e6a8412a12 Jobset: test type-related constraints
Prior to https://github.com/NixOS/hydra/pull/856, the `type`-related constraints
were a bit too loose, allowing some variations that should have been seen as
invalid. This commit adds a test (inspired by
https://github.com/NixOS/hydra/pull/856#issuecomment-772820929) to ensure these
constraints stay unviolated.
2021-07-20 10:38:22 -07:00
Graham Christensen
2bb1ba22d3 Merge pull request #983 from Taneb/libpqxx-deprecations
Fix build with libpqxx 7
2021-07-05 20:15:27 -04:00
Nathan van Doorn
b63dfb7ad4 Rename version to version.txt
<version> is a standard header with C++20 which could cause issues if a library checks it exists then imports it

Because we have the root of this repo in the include path, it'd see that <version> exists (with, e.g., __has_include), and then try to include it as a header

But because it's just a file that says 0.1, this would fail

This happens with libpqxx 7
2021-07-05 19:47:58 +01:00
Nathan van Doorn
5c47343b40 Fix deprecation warnings with libpqxx usage 2021-07-05 19:45:25 +01:00
Graham Christensen
e02f34722f Merge pull request #887 from helsinki-systems/feat/eval-overview-duration
Show evaluation time in the evaluations overview
2021-06-29 10:59:02 -04:00
Janne Heß
94b88b34ae Show evaluation time in the evaluations overview
Parts of this code have been authored by @grahamc
2021-06-29 16:53:10 +02:00
Jonathan Ringer
24959a3ca6 Allow for evaluator_pure_eval to be configured 2021-06-28 16:24:40 -07:00
Graham Christensen
6f9db20cd8 Merge pull request #976 from ztzg/x-16304/deep-clone-inputs
GitInput: Include deepClone option in the cache key
2021-06-28 15:38:38 -04:00
Graham Christensen
04fdb8e6e6 Merge pull request #980 from DeterminateSystems/fixup-drv-meta-maintainers
Docs: fixup `maintainers` derivation meta field example
2021-06-28 15:14:19 -04:00
Cole Helbling
5e72d42575 Docs: fixup maintainers derivation meta field example 2021-06-28 11:16:25 -07:00
Eelco Dolstra
082140bdb2 Merge pull request #979 from DeterminateSystems/hydra-timeout
Docs: document derivation attributes
2021-06-28 18:42:19 +02:00
Graham Christensen
59018323ae Docs: document derivation attributes 2021-06-28 10:00:05 -04:00
Damien Diederen
df7dab1291 GitInput: Include deepClone option in the cache key
Without this commit, two jobsets using the same repository as input,
but different `deepClone` options, end up incorrectly sharing the same
"checkout" for a given (`uri`, `branch`, `revision`) tuple.  The
presence or absence of `.git` is determined by the jobset execution
order.

This patch adds the missing `isDeepClone` boolean to the cache key.

The database upgrade script empties the `CachedGitInputs` table, as we
don't know if existing checkouts are deep clones.  Unfortunately, this
generally forces rebuilds even for correct `deepClone` checkouts, as
the binary contents of `.git` are not deterministic.

Fixes #510
2021-06-19 17:37:40 +02:00
Graham Christensen
b6921c2006 Merge pull request #974 from AmandaCameron/patch-1
flake: stdenv.lib -> lib
2021-06-17 17:11:51 -04:00
Amanda Cameron
b0f8a207fe flake: stdenv.lib -> lib
Nixpkgs on unstable has removed `stdenv.lib` as they've been warning for a while now. This removes the extra references to it in the flake.nix

I'm not entirely sure if this is right, but I figured it was trivial enough to give a quick try using the GH Editor while I was waiting for a job to finish
2021-06-17 16:50:38 -04:00
Graham Christensen
ac1ef9361e Merge pull request #913 from grahamc/notif-docs
Notifications: write up some docs
2021-06-17 13:27:21 -04:00
Graham Christensen
6eb701fcf2 notifications: Document an example scenario where builds_finished is triggered twice. 2021-06-17 13:20:13 -04:00
Graham Christensen
e8afde5079 Write up some documentation on notifications 2021-06-17 13:15:34 -04:00
Graham Christensen
4375268276 Merge pull request #973 from DeterminateSystems/build-evals
/build/ID/evals: fix after #860
2021-06-16 13:36:20 -04:00
Graham Christensen
09ad52ab60 Document getEvals a bit
Also drop the $self parameter.

Co-authored-by: gustavderdrache
2021-06-16 13:15:01 -04:00
Graham Christensen
5d95abf540 getBuilds: clarify the names of evals vs. the query builder 2021-06-16 11:53:04 -04:00
Graham Christensen
cb8929b7ed Tighten up 'should exit with return code' 2021-06-16 11:48:49 -04:00
Graham Christensen
bf5c76feb6 getEvals: order by the eval table's ID
I broke this when I added `me.` in f1e75c8bff

I added me. to disambiguate `id`, but:

* eval.id works on the per-build page
* me.id works on the other pages
* Just id works everywhere if I drop:

    , prefetch => { evaluationerror => [ ] },

  but this causes a query per row to collect the evaluationerror
  records later, this becomes significantly slow on non-trivial
  datasets.

Using evals->current_source_alias will use the correct alias
whether it is me or eval or something else.
2021-06-16 11:24:30 -04:00
Graham Christensen
2ac47e8013 Test that each page listing evals works
PR #860 caused a regression that broke some loads.
2021-06-16 11:22:40 -04:00
Graham Christensen
75855c202f Merge pull request #972 from DeterminateSystems/prom
Prometheus Metrics for the Webserver
2021-06-11 09:16:15 -04:00
Graham Christensen
5700c351e8 Init a docs section for monitoring, document queue-runner-status and the prometheus metrics 2021-06-10 20:13:08 -04:00
Graham Christensen
71453dd341 Expose Prometheus metrics at /metrics
Exposes metrics:

* http_request_duration_seconds_bucket
* http_request_size_bytes_bucket
* http_response_size_bytes_bucket
* http_requests_total

with labels of action and controller to help identify popular
endpoints and their performance characteristics.
2021-06-10 20:02:42 -04:00
Graham Christensen
db6bad108b Use PrometheusTinyShared 2021-06-10 17:47:11 -04:00
Graham Christensen
1652631b21 Prometheus: init Tiny, TinyShared 2021-06-10 17:47:11 -04:00
Graham Christensen
c6670b805f init: HashSharedMem for Prometheus 2021-06-10 17:47:11 -04:00
Graham Christensen
b1fcc0c25b init DataRandom perl package for Prometheus stats 2021-06-10 17:47:11 -04:00
Graham Christensen
e04dc14d94 Merge pull request #969 from DeterminateSystems/builds-index-jobset-id
Builds: index on jobset_id, largely join by jobset_id
2021-06-01 17:59:39 -04:00
Graham Christensen
382ba590ad Drop unused query from GET Build. 2021-06-01 11:47:05 -04:00
Graham Christensen
a9e4ede006 SQL: create better indexes for builds based on the jobset id
These are primarily used by the jobsetOverview renders.
2021-06-01 11:23:22 -04:00
Graham Christensen
719d0a6134 jobset overview: join jobsets to builds by jobset id 2021-06-01 11:19:33 -04:00
Graham Christensen
508d99d611 Join to builds via jobset_id when easy 2021-06-01 11:16:47 -04:00
Graham Christensen
5b6b8261fc Merge pull request #968 from DeterminateSystems/unnecessary-declarative-field
Projects: don't respond with unnecessary declarative field
2021-05-24 19:21:00 -04:00
Cole Helbling
45ced33ab6 Projects: don't respond with unnecessary declarative field
If the project isn't declarative, who cares about it in the response? After
setting the `declfile` to an empty string, everything related to declarative-
ness is wiped out, anyways.
2021-05-24 15:26:34 -07:00
Eelco Dolstra
cdba2b86c0 Merge pull request #967 from Ma27/hydra-system-users
Set `isSystemUser = true;` for each statically declared user
2021-05-24 16:09:15 +02:00
Maximilian Bosch
302f5e0de9 Set isSystemUser = true; for each statically declared user
This is needed to evaluate the module on 21.05.
2021-05-24 14:47:30 +02:00
Graham Christensen
3dc745de68 Merge pull request #964 from DeterminateSystems/fix-cascade
Jobsets: remove defunct Jobs relationship
2021-05-09 21:17:12 -04:00
Cole Helbling
7ba58ca3ea Jobsets: remove defunct Jobs relationship
It appears the Jobs table was removed in
8adb433e3b, but the Jobsets schema was never
updated to reflect this. This relationship was added in
efa1f1d4fb, roughly 3 months prior.

Previously, one would see a message similar to the following logged when
deleting a jobset:

    17:38:23 hydra-server.1       | DBIx::Class::Relationship::CascadeActions::delete(): Skipping cascade delete on relationship 'jobs' - related resultsource 'Hydra::Schema::Jobs' is not registered with this schema at /home/vin/workspace/vcs/hydra/src/script/../lib/Hydra/Controller/Jobset.pm line 106
2021-05-09 17:52:48 -07:00
Graham Christensen
67b6f0d7ed Merge pull request #962 from DeterminateSystems/del-.jobsets
Project: delete the `.jobsets` jobset if project is no longer declarative
2021-05-06 11:57:34 -04:00
Cole Helbling
588a3a774f Project: add test for declarative->normal project transition
Also split into subtests.
2021-05-06 08:47:29 -07:00
Cole Helbling
6107040bf5 Project: clear decltype and declvalue when project is no longer declarative 2021-05-06 08:47:18 -07:00
Cole Helbling
bd9c52dbd0 Project: delete the .jobsets jobset if project is no longer declarative
"No longer declarative" as defined by the "Edit project" page is an empty spec
file.
2021-05-05 14:03:51 -07:00
Graham Christensen
bc8619af3f Merge pull request #961 from DeterminateSystems/fix-959
lazy tabs: trigger the load event
2021-05-05 14:51:33 -04:00
Graham Christensen
6c1151b14a lazy tabs: trigger the load event
Something in the upgrade of Bootstrap and JQuery broke lazy tab loading.
I don't understand what is providing the tab behavior, how it should
work, or what the correct fix is.

I can tell you that this patch fixes the issue: when loading a tab
with a URL fragment deep-linking to a lazily loaded tab... it now
loads.

Close #959
2021-05-05 14:42:12 -04:00
Eelco Dolstra
886e6f85e4 Merge pull request #924 from hackworthltd/fix-flake-github-status
Fix GitHub status update for private flakes.
2021-05-03 16:24:51 +02:00
Graham Christensen
6e537671df Merge pull request #954 from DeterminateSystems/projects-json-schema
Projects: use JSON in Schema
2021-05-02 21:35:04 -04:00
Cole Helbling
f3947acfc4 Projects: use JSON in Schema 2021-05-02 18:25:37 -07:00
Graham Christensen
5520f4b7b6 Merge pull request #952 from DeterminateSystems/decl-api
Project: add declfile, decltype, declvalue to API
2021-05-02 20:51:27 -04:00
Cole Helbling
ad13d13436 Project: add declfile, decltype, declvalue to API
This makes it possible to create declarative projects via a PUT request, and
also exposes the currently-configured values to GET requests.
2021-05-02 17:45:14 -07:00
Graham Christensen
e9a06113c9 Merge pull request #951 from DeterminateSystems/delete-project
Fix deleting projects
2021-05-01 13:01:39 -04:00
Cole Helbling
7c9ed6b919 Project: fix DELETE route
This appears to have been broken in ac3e8a4a59,
which removed the `jobsetevals` column from the Projects schema, but didn't
update the Controller accordingly.

Fixes the test added in the previous commit.
2021-04-30 10:43:21 -07:00
Cole Helbling
d0682c804d api-test: test deleting a project
As of this commit, this test will fail, because the underlying cause hasn't been
fixed.
2021-04-30 10:42:38 -07:00
Graham Christensen
6047b1dd04 Merge pull request #948 from DeterminateSystems/known-inputs
Jobset: list known inputs in invalid input type response
2021-04-29 21:45:16 -04:00
Cole Helbling
14aff5678c hydra-api: don't restrict input types
Plugins can add their own input types; we don't want to restrict this.
2021-04-29 18:19:44 -07:00
Cole Helbling
03d5a858a7 Jobset: list known inputs in invalid input type response 2021-04-29 18:19:44 -07:00
Graham Christensen
18d271655c Merge pull request #945 from DeterminateSystems/fixup-ToJSON
Jobsets,JobsetInputs: use JSON
2021-04-29 08:38:45 -04:00
Graham Christensen
8492db033e Jobsets,JobsetInputs: use JSON 2021-04-29 08:32:47 -04:00
Graham Christensen
ec288e6d88 Merge pull request #941 from DeterminateSystems/align-api
ToJSON: allow custom as_json function; JobsetInputs, Jobsets: update schema to align with the API
2021-04-29 07:57:39 -04:00
Cole Helbling
f1dd5d202e Jobsets: update schema to align with the API
To further align with the API, we return custom JSON in order to display a
`visible` field rather than `hidden` -- a `PUT` request expects `visible`, while
a `GET` request returns `hidden`.

This also allows us to rename the `jobsetinputs` field to `inputs` for the same
reason: `PUT` expects `inputs`, while `GET` returns `jobsetinputs`.
2021-04-29 07:50:23 -04:00
Cole Helbling
d23f431889 JobsetInputs: update schema to align with the API
`PUT /jobsets/{project-id}/{jobset-id}` expects a JSON object `inputs` which
maps a name to a name, a type, a value, and a boolean that enables emailing
responsible parties. However, `GET /jobsets/{project-id}/{jobset-id}` responds
with an object that doesn't contain a value, but does contain a jobsetinputalts
(which is old and should be unused).

This commit aligns the two by removing the old and unused `jobsetinputalts` from
the response and replaces it with `value`.
2021-04-29 07:50:23 -04:00
Cole Helbling
fff0db10e3 ToJSON: allow custom as_json function
This allows us to modify what the API responds with, which in turn lets us unify
the OpenAPI specification and the actual API's responses.
2021-04-29 07:50:23 -04:00
Graham Christensen
29028258e3 Merge pull request #940 from regnat/test-with-remote-dest-store
Run the tests with a remote dest store
2021-04-29 07:27:42 -04:00
Graham Christensen
e1a761194f Merge pull request #943 from regnat/include-localhost-features
Cleanup the localhost-features test
2021-04-29 07:26:50 -04:00
regnat
bf3e1cf77b Disable the remote dest store for the channel test
Looks like feature is only works when the destination store is the local
store
2021-04-29 07:24:20 +02:00
regnat
9c787e5e94 Document the use_external_destination_store test_init param 2021-04-29 07:24:20 +02:00
Théophane Hufschmitt
7af63658f1 tests: Make the external destination store optional
Co-authored-by: Graham Christensen <graham@grahamc.com>
2021-04-29 07:24:20 +02:00
regnat
305c27d3fb Move the default-machine-file test under queue-runner
Just a bit of housekeeping to keep the testsuite clean
2021-04-29 06:55:23 +02:00
regnat
f61a13d2db Only add the Nix system feature to the test that requires it 2021-04-29 06:54:25 +02:00
Graham Christensen
7017d41117 Merge pull request #942 from DeterminateSystems/port-api-test-master
Port api-test to yath
2021-04-28 19:48:33 -04:00
Graham Christensen
a44e5b73a8 api-test: clean up, use subtests 2021-04-28 19:41:49 -04:00
Graham Christensen
015d8298cb flake.nix: drop the API test 2021-04-28 18:32:23 -04:00
Graham Christensen
5c5b53961e fixup: api-test.t expected to pass inputs as inputs 2021-04-28 18:30:53 -04:00
Graham Christensen
fdb6e7dd97 fixup: return the user entity on login 2021-04-28 18:30:35 -04:00
Graham Christensen
a34f23f7e6 api-test: use is for nicer errors 2021-04-28 18:28:35 -04:00
Graham Christensen
20df86c275 api-test.t: make it work under yath
1. Configure the in-memory Hydra instance with a null path input cache
time to avoid caching slowing the test down.
2. Use the Catalyst::Test helpers so we talk to the application and skip
needing to actually run a webserver.
3. Change path references to use a tempdir, since this is running while
other tests are also running.
4. Change the login flow to save a cookie and pass it manually. A bit
weird, but it avoids a dependency on heavier browser-mimicking
libraries.
2021-04-28 18:28:35 -04:00
Graham Christensen
38c7f88b7c rename api-test.pl to .t so it runs under yath 2021-04-28 18:28:35 -04:00
Graham Christensen
dd6cd33e98 move the api-test.nix in to the jobsdir 2021-04-28 18:28:35 -04:00
Graham Christensen
823da22e4f Merge pull request #937 from DeterminateSystems/flesh-out-api
hydra-api: flesh out Jobset, JobsetInput schemas; implement DELETE /jobset/{project-id}/{jobset-id}
2021-04-28 13:43:04 -04:00
Cole Helbling
948b3cf073 Jobset: add HTTP API test 2021-04-28 10:37:06 -07:00
Graham Christensen
725c9c2f81 login: redirect to the current-user page 2021-04-28 08:32:10 -07:00
Graham Christensen
d589db2ed9 login: missing parameters are 400s 2021-04-28 08:31:59 -07:00
Eelco Dolstra
8d6a5aac84 Merge pull request #939 from regnat/include-localhost-features
Include localhost's features in the default machine file
2021-04-28 12:25:21 +02:00
regnat
0d3977866e Run the tests with a remote dest store
Set `dest_store` in the test hydra config, so that the testsuite ensures
that the distinction between the local store and the destination store
is properly taken into account.

Fix #938
2021-04-28 12:22:54 +02:00
regnat
abff212d06 Use system-features from the Nix conf in the default machine file
Fix #936
2021-04-28 11:43:04 +02:00
regnat
d58b3274f9 test: Don't generate a Nix conf in the makefile
The config is overriden by the `test_init` perl function, so it’s at
best misleading to create a first one there
2021-04-28 11:41:37 +02:00
Cole Helbling
42ef3b7b72 hydra-api: update Project and Jobset examples with the new schema
For future reference, this was generated by sending the request and piping it to
`yq -y` so that it would spit out YAML.
2021-04-27 23:09:33 -07:00
Cole Helbling
bcd3bbb680 hydra-api: implement DELETE /jobset/{project-id}/{jobset-id} 2021-04-27 16:16:42 -07:00
Cole Helbling
72fec31dbb hydra-api: flesh out JobsetInput schema 2021-04-27 16:16:42 -07:00
Cole Helbling
2600810551 hydra-api: flesh out Jobset schema
* made all columns available via the API (except for forceeval)
* renamed flakeref to flake to unify the API with the database schema
* renamed inputs to jobsetinputs to unify the API with the database schema
2021-04-27 16:16:42 -07:00
Graham Christensen
0c8d016a38 Merge pull request #935 from DeterminateSystems/delete-project
hydra-api: implement DELETE /project/{id}
2021-04-27 11:15:15 -04:00
Cole Helbling
ddccf6a60e hydra-api: implement DELETE /project/{id} 2021-04-27 08:10:09 -07:00
Graham Christensen
ada497db4f Merge pull request #934 from DeterminateSystems/missing-name
hydra-api: add missing `name` property
2021-04-26 22:02:14 -04:00
Cole Helbling
9128802727 hydra-api: add missing name property
The Hydra website allows you to change the name of a Project, so it only makes
sense for the API to expose this functionality as well.
2021-04-26 18:55:10 -07:00
Graham Christensen
fa5811eabf Merge pull request #933 from cole-h/boolean-json
Serialize `enabled` and `hidden` columns as boolean
2021-04-26 19:44:59 -04:00
Cole Helbling
50fab154a4 ToJSON: serialize string_columns to JSON
If the column is undefined, then it should be an empty string according to your
API spec.
2021-04-26 16:39:13 -07:00
Graham Christensen
f0ede5f8b8 t: Test Projects JSON serialization and deserialization 2021-04-26 16:39:13 -07:00
Graham Christensen
f2b9649bf2 Projects: serialize enabled and hidden as boolean 2021-04-26 16:03:32 -07:00
Graham Christensen
4aea02e1e1 ToJSON: serialize boolean_columns to JSON boolean 2021-04-26 16:03:32 -07:00
Graham Christensen
683b8c41c1 Merge pull request #932 from cole-h/project
Add homepage to Projects schema
2021-04-26 18:57:02 -04:00
Graham Christensen
8e3b3c95f8 Merge pull request #931 from cole-h/put-project
hydra-api: hidden -> visible
2021-04-26 18:48:29 -04:00
Cole Helbling
c757867b9e Add homepage to Projects schema 2021-04-26 15:46:30 -07:00
Cole Helbling
221cc0663d hydra-api: hidden -> visible
The PUT API doesn't accept `hidden` (even though the GET API responds with it).
2021-04-26 15:28:20 -07:00
Graham Christensen
2dfcd411da Merge pull request #928 from cole-h/put-project
hydra-api: add missing properties to PUT /project/{id}
2021-04-26 15:06:05 -04:00
Cole Helbling
36da978489 hydra-api: add missing properties to PUT /project/{id} 2021-04-26 12:01:11 -07:00
Graham Christensen
453b8479be Merge pull request #927 from cole-h/nonexistent-user-400
Return HTTP 400 when creating Project with nonexistent user
2021-04-26 14:40:15 -04:00
Cole Helbling
47e19ba22c Return HTTP 400 when creating Project with nonexistent user 2021-04-26 11:32:39 -07:00
Graham Christensen
bc292db45b Merge pull request #923 from Ma27/mail-auth
Add AuthenSASL to perl deps; improve email docs
2021-04-26 13:11:21 -04:00
Maximilian Bosch
963085a04a Add AuthenSASL to perl deps; improve email docs
The addition of AuthenSASL seems to be necessary to properly
authenticate against an SMTP server. Without this I got errors
such as

    error with Hydra::Plugin::EmailNotification=HASH(0x6ad0128)->buildFinished: SMTP auth requires MIME::Base64 and Authen::SASL
2021-04-26 18:33:57 +02:00
Graham Christensen
18c02afe77 Merge pull request #921 from Ma27/email-notification-create-jobset
Make it possible to enable email notifications when creating a jobset
2021-04-26 11:22:17 -04:00
Drew Hess
523d6df5b8 Fix GitHub status update for private flakes.
Also, if the parse fails, don't try to update the GitHub status, as
this will eventually cause rate-limiting.
2021-04-26 01:38:24 +01:00
Maximilian Bosch
21ed005c84 Make it possible to enable email notifications when creating a jobset
The checkbox is only enabled if `email_notification = 1` is set in
`hydra.conf`. However, when creating jobset (in contrast to the edit
form), the checkbox is always disabled because the `emailNotification`
parameter in Catalyst's stash was missing.
2021-04-24 19:48:43 +02:00
Eelco Dolstra
85e299d3d7 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/906adadacd2d1c98346a2f42c0b42a32d2806d94' -> 'github:NixOS/nix/d9864be4b757468d33bc49edddce5e4f04ef4b90'
2021-04-22 10:44:21 +02:00
Eelco Dolstra
a53f6657ee Remove gc-check-reachability setting
It no longer exists on nix master.
2021-04-20 13:35:39 +02:00
Graham Christensen
1bb1ba6928 Merge pull request #916 from grahamc/argon2-nested
Rehash existing sha1 passwords with Argon2
2021-04-17 08:46:52 -04:00
Graham Christensen
05636de7d2 hydra-init: upgrade passwords to Argon2 on startup 2021-04-16 12:32:13 -04:00
Graham Christensen
79b0ddc27d hydra-create-user: re-hash sha1 as Argon2 2021-04-16 12:32:13 -04:00
Graham Christensen
d10d8964f2 Users: add a validation step which lets the user's password be a Argon2 hashed sha1 hash.
OWASP suggests expiring all passwords and requiring users to update their password.
However, we don't have a way to do this. They suggest this mechanism
as a good alternative:
https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#upgrading-legacy-hashes
2021-04-16 12:32:13 -04:00
Eelco Dolstra
fa924ea697 Merge pull request #915 from grahamc/hydra-auth
Hydra auth: support Argon2, transparently upgrade hashes
2021-04-15 17:40:32 +02:00
Graham Christensen
9225be0897 Drop remaining sha1_hex references
Co-authored-by: Graham Christensen <graham@grahamc.com>
2021-04-15 11:35:18 -04:00
Graham Christensen
1d956be61e hydra-create-user: support Argon2
Co-authored-by: Graham Christensen <graham@grahamc.com>
2021-04-15 11:35:16 -04:00
Graham Christensen
beb5be4302 Users: password changes via the web UI now use Argon2
Co-authored-by: Graham Christensen <graham@grahamc.com>
2021-04-15 11:35:13 -04:00
Graham Christensen
1da70030b7 Users: transparently upgrade passwords to Argon2
Passwords that are sha1 will be transparently upgraded to argon2,
and future comparisons will use Argon2

Co-authored-by: Graham Christensen <graham@grahamc.com>
2021-04-15 11:35:11 -04:00
Graham Christensen
29620df85e Passwords: check in constant time
The default password comparison logic does not use
constant time validation. Switching to constant time
offers a meager improvement by removing a timing
oracle.

A prepatory step in moving to Argon2id password storage, since we'll need this change anyway after
for validating existing passwords.

Co-authored-by: Graham Christensen <graham@grahamc.com>
2021-04-15 11:34:56 -04:00
Graham Christensen
d4d8f1ba1b Plugin::Authentication config: modernize
Some time in the last decade the plugin switched to preferring
a flatter namespace for realm config.

Co-authored-by: Graham Christensen <graham@grahamc.com>
2021-04-15 11:34:47 -04:00
Eelco Dolstra
0bee194ce9 Merge pull request #914 from Ma27/fix-remote-builds
Fix `std::bad_alloc` errors for remote builds
2021-04-15 17:05:54 +02:00
Maximilian Bosch
2808227eb7 Fix std::bad_alloc errors for remote builds
In Nix the protocol was slightly altered[1] to also contain more
information about realisations. This however wasn't read from the pipe
that was used to read from the store.

After the `cmdBuildDerivation` command which caused this issue, Hydra
will issue a `cmdQueryPathInfos` that tries to read from the remote
store as well. However, there's still left over to read from the
previous command and thus Nix fails to properly allocate the expected
string.

[1] See rev a2b69660a9b326b95d48bd222993c5225bbd5b5f

Fixes #898
2021-04-15 15:16:52 +02:00
Graham Christensen
b9bcedbfdb Merge pull request #596 from kquick/local_inp_url
Update prompt for Local path input to indicate a URL is also valid.
2021-04-14 20:01:58 +00:00
Graham Christensen
d2512e327c Merge pull request #912 from grahamc/test-notifications
Notifications: Test behavior of the queue runner
2021-04-14 18:35:44 +00:00
Graham Christensen
cf4434bc9f queue runner: test notifications
Especially, test the difference in behavior of substituted and unsubstituted builds.
2021-04-14 14:19:10 -04:00
Graham Christensen
e45f852277 tests: allow specifying some nix config 2021-04-14 14:19:10 -04:00
Graham Christensen
c7ac123dc5 Setup.pm: specify NIX_ env vars for running yath
Otherwise yath will try to use global configuration.
2021-04-14 14:19:10 -04:00
Graham Christensen
74d34c0f80 t/Setup.pm: sort NIX_ env vars 2021-04-14 14:19:09 -04:00
Graham Christensen
8aa59dcc1b Drop references to NIX_MANFIESTS_DIR and NIX_BUILD_HOOK
Neither of these have been supported in ~years.
2021-04-14 14:19:09 -04:00
Graham Christensen
ffc4be6743 Merge pull request #910 from grahamc/ui-fixups
UI fixups
2021-04-12 17:42:01 +00:00
Graham Christensen
afd064d19d Merge pull request #867 from ck3d/fix-proxy-login
Fix login if Hydra runs behind HTTP proxy with sub-path location
2021-04-12 17:36:55 +00:00
Graham Christensen
82953389e4 Make new jobsets enabled by default in the UI
If the jobset is brand new, none of the options matched. This
makes all new jobsets default to Enabled.
2021-04-12 12:01:24 -04:00
Graham Christensen
0fe4cba5b7 edit-jobset: make the "add a new input" button span the whole way
Previously it would only cross 4 of the 5 columns.
2021-04-12 12:01:24 -04:00
Graham Christensen
f9e30d2550 Merge pull request #905 from grahamc/danger-user
User Roles: make checkboxes
2021-04-09 14:20:47 +00:00
Graham Christensen
e674fb6139 edit user: make the role changer checkboxes
Also, it makes the role changer a bit of a dangerzone visually for
admins.
2021-04-09 14:07:10 +00:00
Graham Christensen
258b39f1e5 Merge pull request #677 from twhitehead/javascripts-update
Javascript libraries update
2021-04-09 14:05:47 +00:00
Eelco Dolstra
20c1efeb5b Merge pull request #904 from Ma27/gitea-integration
Add `GiteaStatus`-Plugin
2021-04-08 17:57:38 +02:00
Eelco Dolstra
4338d904f0 Merge pull request #907 from NixOS/dependabot/github_actions/cachix/install-nix-action-v13
build(deps): bump cachix/install-nix-action from v12 to v13
2021-04-08 17:56:24 +02:00
Eelco Dolstra
2020ea1335 Merge pull request #909 from regnat/nix-master
Fix build with latest master
2021-04-08 17:56:09 +02:00
Tyson Whitehead
e51a6a4bca Cards are now required to decorate pre blocks 2021-04-08 11:32:30 -04:00
Tyson Whitehead
7d3bd08c9b Fix tab link spacing issue by dropping old sticky navbar css hack 2021-04-08 11:32:29 -04:00
Samuel Dionne-Riel
def05105bb Add top spacing to tab contents 2021-04-08 11:32:26 -04:00
Samuel Dionne-Riel
d85b846357 Fix spacing with search inputs
And more importantly, crucially, fix the "appended" button so the round
corners are on the right (heh) side.
2021-04-08 11:32:08 -04:00
Samuel Dionne-Riel
20e3c51ba9 Style unstyled alerts 2021-04-08 11:32:02 -04:00
Graham Christensen
db2c9fe96a layout.tt: make the header constrained to the center 2021-04-08 11:31:56 -04:00
Graham Christensen
9c903e9991 renderEvals: fixup colspan on Jobs and More 2021-04-08 11:31:47 -04:00
Graham Christensen
c8dd5b57c4 src/root/Makefile: fixup extraction of the fontawesome and bootstrap archives 2021-04-08 11:31:39 -04:00
Tyson Whitehead
abe082c1d6 Couple of upstream/bootstrap items missed in rebase 2021-04-08 11:31:34 -04:00
Tyson Whitehead
b5e18ce62c Fix the empty popovers 2021-04-08 11:31:34 -04:00
Tyson Whitehead
2902684c61 Update jobset comparison button 2021-04-08 11:31:34 -04:00
Tyson Whitehead
3f77bd240f Bring deep-embedding (tab anchors) javascript up-to-date 2021-04-08 11:31:34 -04:00
Tyson Whitehead
b6f5b6eb38 Labels are now badges 2021-04-08 11:31:34 -04:00
Tyson Whitehead
70df5e6312 Update button styles as btn-mini is no more 2021-04-08 11:31:34 -04:00
Graham Christensen
1e34cd3d3d fixups to the rebase 2021-04-08 11:30:49 -04:00
regnat
26ffd4a93e Fix build with latest master 2021-04-08 17:11:15 +02:00
Graham Christensen
225634349e Merge pull request #908 from grahamc/manual-hacking
Manual: mention in hacking docs
2021-04-05 18:01:51 +00:00
Graham Christensen
5f91353824 doc/manual/src/installation.md: give a conf syntax type
Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
2021-04-05 16:42:15 +00:00
Graham Christensen
c69912b287 start-manual.sh: Drop explicit pwd's 2021-04-05 16:10:09 +00:00
Graham Christensen
c442f1aa14 Procfile: sort alphabetically 2021-04-05 16:10:09 +00:00
Graham Christensen
7bb9850656 doc: hacking: fixup nix-shell dependency comment 2021-04-05 16:10:09 +00:00
Graham Christensen
9788c52eff doc: hacking: remove duplicate 'by default' 2021-04-05 16:10:09 +00:00
Graham Christensen
b03fa96186 doc: hacking: Quote perl5lib 2021-04-05 16:10:09 +00:00
Graham Christensen
2e47970a97 doc: switch shell session code blocks to console type. 2021-04-05 16:10:09 +00:00
Graham Christensen
16902f3866 start-hydra: create a db for the current username
Otherwise the logs are spammed with database not existing errors:

15:46:07 postgres.1 | 2021-04-05 15:46:07.631 UTC [30742] FATAL:  database grahamc does not exist
15:46:08 postgres.1 | 2021-04-05 15:46:08.641 UTC [30759] FATAL:  database grahamc does not exist
15:46:09 postgres.1 | 2021-04-05 15:46:09.650 UTC [30765] FATAL:  database grahamc does not exist
2021-04-05 15:47:25 +00:00
Graham Christensen
0ddf3d43f2 manual: document working on docs 2021-04-05 15:40:09 +00:00
Graham Christensen
d764eabfcc docs: mention foreman under hacking 2021-04-05 15:40:09 +00:00
dependabot[bot]
67d909322a build(deps): bump cachix/install-nix-action from v12 to v13
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from v12 to v13.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v12...8d6d5e949675fbadb765c6b1a975047fa5f09b27)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-05 05:21:35 +00:00
Maximilian Bosch
3bc5252c80 Get rid of now obsolte LD_PRELOAD hack 2021-04-03 09:56:15 +02:00
Maximilian Bosch
2beb1f5405 Replace TestHTTPMockServer with python script
This seems to work fine in a `nix build`-sandbox as it doesn't depend on
`getprotobyname`.
2021-04-03 01:07:07 +02:00
Maximilian Bosch
d16bf5b8cd Implement yath-test for the new Gitea plugin 2021-04-02 19:11:25 +02:00
Graham Christensen
0693cc713e Merge pull request #899 from grahamc/horses
Projects, jobsets: order jobsets with disabled, hidden rows at the end
2021-03-31 16:54:24 +00:00
Graham Christensen
cc9c91fe12 jobsets: put hidden and enabled jobsets at the end
Allows for generally correct zebra striping
2021-03-31 14:33:20 +00:00
Graham Christensen
a46f655c56 root project listing: show hidden projects at the end
Makes the zebra striping correct.
2021-03-31 14:33:20 +00:00
Maximilian Bosch
f9f5ab2fb1 Make gitea public URL configurable
Otherwise, it will be obtained from the jobset input that contains the
URL to the git repo to build.
2021-03-30 23:01:36 +02:00
Maximilian Bosch
eecea56131 Implement VM-test for gitea plugin 2021-03-30 22:35:39 +02:00
Maximilian Bosch
56997d8e8b Fix error codes for GiteaStatus plugin
* `failure` if a build error occurred, on e.g. an aborted build send
  `error`.
2021-03-30 14:13:46 +02:00
Maximilian Bosch
fef142f13a Implement simple status notifications for Git repos hosted on gitea 2021-03-30 14:10:21 +02:00
Graham Christensen
9bb04ed97a Merge pull request #893 from grahamc/fake-channel-nested
Test the fake derivations channel, asserting nested packages are properly represented.
2021-03-24 17:56:55 -04:00
Tyson Whitehead
eb8a0f279a Add fontawesome as required by newer bootstrap 2021-03-24 17:10:28 -04:00
Tyson Whitehead
cd0ff484f7 Add popper.js as required by newer bootstrap 2021-03-24 17:10:28 -04:00
Tyson Whitehead
4d881b59ad Update bootbox to latest 5.2.0 2021-03-24 17:10:27 -04:00
Tyson Whitehead
230a0387d2 Update boostrap to latest 4.3.1
Co-authored-by: Graham Christensen <graham@grahamc.com>
... but just fixing up merge conflicts from the introduction of flakes
and the removal of the Jobs table.
2021-03-24 17:10:27 -04:00
Tyson Whitehead
627af61abe Update jquery to latest 3.4.1 (considered by some as more secure) 2021-03-24 17:10:27 -04:00
Graham Christensen
e14175fc36 Merge pull request #895 from Mic92/fix-hydra-send-stats
hydra-send-stats: fix imports
2021-03-20 11:52:34 -04:00
Graham Christensen
425c7ff17f hydra-send-stats: add a --once option for testing 2021-03-20 09:16:08 -04:00
Jörg Thalheim
6bb180a0f2 hydra-send-stats: fix imports 2021-03-20 09:16:04 -04:00
Graham Christensen
6f662a606a hydra-send-stats: add a failing test asserting it can run 2021-03-20 09:14:14 -04:00
Graham Christensen
6b7ca554f9 Update src/lib/Hydra/Helper/Escape.pm: fewer ()s
Co-authored-by: Stig <stig@stig.io>
2021-03-18 16:27:21 -04:00
Graham Christensen
019aef3d41 Test the fake derivations channel, asserting nested packages are properly represented.
This is a breaking change. Previously, packages named `packageset.foo`
would be exposed in the fake derivation channel as `packageset-foo`.

Presumably this was done to avoid needing to track attribute sets, and
to avoid the complexity. I think this now correctly handles the
complexity and properly mirrors the input expressions layout.
2021-03-18 11:33:37 -04:00
Graham Christensen
88e0198a8e Create a helper for dealing with nested attribute sets 2021-03-18 11:33:36 -04:00
Graham Christensen
d62a2c1657 NixExprs: extract the escape function and test it 2021-03-18 11:24:17 -04:00
Eelco Dolstra
aeb3d2f44c Merge pull request #892 from grahamc/hydra-queue-runner-build-one
hydra-queue-runner: --build-one: correctly handle a cached build
2021-03-16 21:28:32 +01:00
Graham Christensen
87d46ad5d6 hydra-queue-runner: --build-one: correctly handle a cached build
Previously, the build ID would never flow through channels which
exited.

This patch tracks the buildOne state as part of State and exits avoids
waiting forever for new work.

The code around buildOnly is a bit rough, making this a bit weird to
implement but since it is only used for testing the value of improving
it on its own is a bit questionable.
2021-03-16 16:13:38 -04:00
Graham Christensen
cab187a19d Merge pull request #891 from grahamc/bug-889
Fixup #717 "Add the project name to declarative inputs"
2021-03-16 09:58:53 -04:00
Janne Heß
3c86083d21 Fixup #717 "Add the project name to declarative inputs"
```
Mar 10 16:22:35 hydra-b hydra-evaluator[41419]: DBIx::Class::Storage::DBI::_dbh_execute(): DBI Exception: DBD::Pg::st execute failed: ERROR:  null value in column "type" violates not-null constraint
Mar 10 16:22:35 hydra-b hydra-evaluator[41419]: DETAIL:  Failing row contains (62358, projectName, 0, null, null, null, hackworthltd, null, , null). [for Statement "INSERT INTO jobsetevalinputs ( altnr, dependency, eval, name, path, revision, sha256hash, type, uri, value) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" with ParamValues: 1='0', 2=undef, 3='62358', 4='projectName', 5='', 6=undef, 7=undef, 8=undef, 9=undef, 10='hackworthltd'] at /nix/store/cmqblv437mp57yz5lwvkzcqca4ldf3r5-hydra-0.1.20210308.ebf1cd2/bin/.hydra-eval-jobset-wrapped line 793
Mar 10 16:22:35 hydra-b hydra-evaluator[25828]: evaluation of jobset ‘hackworthltd:.jobsets (jobset#1)’ failed with exit code 1
```

Use the abstraction for creating inputs for simulating the project
name input.

Co-authored-by: Graham Christensen <graham@grahamc.com>
2021-03-16 09:52:36 -04:00
Shea Levy
930f05c38e Bump Nix version 2021-03-10 12:53:03 -05:00
Graham Christensen
b9fb66401b Merge pull request #880 from grahamc/runcommand-finished-bool
RunCommand: emit the `finished` field as a boolean
2021-03-09 09:58:43 -05:00
Graham Christensen
2179b4b4b0 RunCommand: emit the finished field as a boolean 2021-03-08 12:11:20 -05:00
Graham Christensen
ebf1cd22ef Merge pull request #717 from helsinki-systems/projectname
Add the project name to declarative inputs
2021-03-08 11:42:38 -05:00
Janne Heß
9e018d5443 Add the project name to declarative inputs
This allows for more generic declarative configurations which can be
shared between projects.
2021-03-08 17:36:52 +01:00
Graham Christensen
a2717b3d7e Merge pull request #886 from grahamc/269
statsd: add a chance to set hostname and port in hydra.conf
2021-03-08 11:23:43 -05:00
Matej Cotman
a551fba346 statsd: add a chance to set hostname and port in hydra.conf
Co-authored-by: Graham Christensen <graham@grahamc.com>
2021-03-08 10:03:16 -05:00
Graham Christensen
1f4183e05f Merge pull request #885 from mcsaucy/patch-1
Make nix-build args copy-pastable via `set -x`
2021-03-07 08:14:49 -05:00
Josh McSavaney
e0d3a1c1a5 Make nix-build args copy-pastable via set -x
A reproduce script includes a logline that may resemble:

> using these flags: --arg nixpkgs { outPath = /tmp/build-137689173/nixpkgs/source; rev = "fdc872fa200a32456f12cc849d33b1fdbd6a933c"; shortRev = "fdc872f"; revCount = 273100; } -I nixpkgs=/tmp/build-137689173/nixpkgs/source --arg officialRelease false --option extra-binary-caches https://hydra.nixos.org/ --option system x86_64-linux /tmp/build-137689173/nixpkgs/source/pkgs/top-level/release.nix -A 

These are passed along to nix-build and that's fine and dandy, but you can't just copy-paste this as is, as the `{}` introduces a syntax error and the value accompanying `-A` is `''`.

A very naive approach is to just `printf "%q"` the individual args, which makes them safe to copy-paste. Unfortunately, this looks awful due to the liberal usage of slashes:

```
$ printf "%q" '{ outPath = /tmp/build-137689173/nixpkgs/source; rev = "fdc872fa200a32456f12cc849d33b1fdbd6a933c"; shortRev = "fdc872f"; revCount = 273100; }'
\{\ outPath\ =\ /tmp/build-137689173/nixpkgs/source\;\ rev\ =\ \"fdc872fa200a32456f12cc849d33b1fdbd6a933c\"\;\ shortRev\ =\ \"fdc872f\"\;\ revCount\ =\ 273100\;\ \}
```

Alternatively, if we just use `set -x` before we execute nix-build, we'll get the whole invocation in a friendly, copy-pastable format that nicely displays `{}`-enclosed content and preserves the empty arg following `-A`:

```
running nix-build...
using this invocation: 
+ nix-build --arg nixpkgs '{ outPath = /tmp/build-138165173/nixpkgs/source; rev = "e0e4484f2c028d2269f5ebad0660a51bbe46caa4"; shortRev = "e0e4484"; revCount = 274008; }' -I nixpkgs=/tmp/build-138165173/nixpkgs/source --arg officialRelease false --option extra-binary-caches https://hydra.nixos.org/ --option system x86_64-linux /tmp/build-138165173/nixpkgs/source/pkgs/top-level/release.nix -A ''
```
2021-03-06 23:25:26 -05:00
Graham Christensen
de2f30f035 Merge pull request #883 from cole-h/bare-yath-test
Trivially run tests with `yath test`
2021-03-05 14:04:16 -05:00
Cole Helbling
2befb2c1e1 doc: document how to run tests
Both `make check` and `make && yath test` are now documented ways to
run the test suite.
2021-03-05 09:49:06 -08:00
Cole Helbling
025be052b7 tests: move to t, allow yath test from root
By moving the tests subdirectory to t, we gain the ability to run `yath
test` with no arguments from inside `nix develop` in the root of the
the repo.

(`nix develop` is necessary in order to set the proper env vars for
`yath` to find our test libraries.)
2021-03-05 09:49:06 -08:00
Graham Christensen
a8ec1b1afa Merge pull request #884 from cole-h/perl-cleanup
tests: replace the flat list of contexts with a hash
2021-03-05 12:45:21 -05:00
Cole Helbling
014778344c tests: remove unnecessary Cwd imports 2021-03-04 23:48:48 -08:00
Cole Helbling
9a3af13c51 tests: add jobsdir and testdir to ctx hash
This allows us to calculate those directories only once, and just pass
them around as necessary.
2021-03-04 23:19:48 -08:00
Graham Christensen
f08d0be1bd tests: replace the flat list of contexts with a hash
This way we can return more values without breaking callers.
2021-03-04 23:11:54 -08:00
Graham Christensen
26cfe624d5 Merge pull request #882 from cole-h/split-inputtype-test
tests/input-types: split out scminputs into individual tests
2021-03-04 17:13:22 -05:00
Cole Helbling
387fe8005a tests/input-types: split out scminputs into individual tests
This makes the test faster (by removing it and replacing it with a
`TestScmInput` module that exports the `testScmInput` subroutine). Now,
all the input tests can be run in parallel.

Some of the `tests/jobs/*-update.sh` scripts were "broken" (e.g. tests
failed for various reasons on my machine), so I fixed those up as well.

Co-authored-by: gustavderdrache <gustavderdrache@gmail.com>
2021-03-04 13:58:48 -08:00
Graham Christensen
572a0c0abd Merge pull request #881 from cole-h/hydra-dbi
module: append `application_name` to HYDRA_DBI
2021-03-04 10:07:01 -05:00
Cole Helbling
fe70160008 module: append application_name to HYDRA_DBI
This will make it easier to track specifically where queries are being
made from (assuming a `log_line_prefix` that includes `%a` in the
postgres configuration).
2021-03-03 16:02:52 -08:00
Graham Christensen
68ac64dbd9 Merge pull request #832 from wizeman/fix-hash-mismatch
Fix persistent hash mismatch errors when importing
2021-03-02 16:04:23 -05:00
Eelco Dolstra
3cd312fc4c Merge pull request #879 from grahamc/runcommand-meta
RunCommand: pass homepage, description, license, system, and nixname
2021-02-25 09:59:19 +01:00
Graham Christensen
a756614fa1 RunCommand: pass homepage, description, license, system, and nixname 2021-02-24 16:13:09 -05:00
Eelco Dolstra
6fb9a2bbf5 Merge pull request #878 from grahamc/test-runcommand
Test RunCommand's behavior
2021-02-24 21:42:14 +01:00
Graham Christensen
3fda37f65a RunCommand: Test 2021-02-24 13:43:25 -05:00
Graham Christensen
b2520267a9 Test setup: support arbitrary hydra config 2021-02-24 11:44:16 -05:00
Graham Christensen
8d3633594b Merge pull request #876 from grahamc/per-test-db
Create an ephemeral PostgreSQL database and Nix store per test, split up tests.
2021-02-24 07:59:18 -05:00
Graham Christensen
cccdc70162 input-types.t: don't litter ./tests/ 2021-02-24 07:01:32 -05:00
Graham Christensen
611d7b71f2 input-types: use is() for test comparisons 2021-02-24 07:01:32 -05:00
Graham Christensen
371826f931 Tests: build-products: use is for good errors on failures 2021-02-24 07:01:32 -05:00
Graham Christensen
0df9c68422 Relocate the final evalutation tests to a build-products specific test. 2021-02-24 07:01:31 -05:00
Graham Christensen
2776ae6c78 Move tests for SCM inputs in to its own .t 2021-02-24 07:01:31 -05:00
Graham Christensen
c8df544046 evaluate-dependent-jobsets: clean up test to be more clear 2021-02-24 07:01:31 -05:00
Graham Christensen
0b693ad8e8 Use is in evaluate-dependent-jobsets 2021-02-24 07:01:31 -05:00
Graham Christensen
9590bababc Split out dependent tests in to its own .t 2021-02-24 07:01:25 -05:00
Graham Christensen
e4cda87b5a db.hh: use hasPrefix for prefix comparisons
Co-authored-by: Eelco Dolstra <edolstra@gmail.com>
2021-02-24 07:00:26 -05:00
Graham Christensen
62b2880dfc Give each test its own Nix directories
Otherwise we risk tripping over confusing statuses where a build is
"done" and "Cached", but we were expecting to run it.
2021-02-23 21:43:54 -05:00
Graham Christensen
fe1f2f0806 Create an ephemeral PostgreSQL database per test 2021-02-23 21:12:06 -05:00
Graham Christensen
b15d8edab1 tests: delete set-up.pl / tear-down.pl
We'll set these up on a per-test basis.
2021-02-23 21:12:06 -05:00
Graham Christensen
9ddc6e355f flake: add TestPostgreSQL for per-test DBs 2021-02-23 21:12:02 -05:00
Graham Christensen
bfcc50f978 Merge pull request #877 from immae/mdbook
Convert documentation to markdown / mdbook
2021-02-23 20:16:33 -05:00
Ismaël Bouya
bd64b2481d Remove old files 2021-02-24 01:07:11 +01:00
Ismaël Bouya
9d916877fb Add markdown files for documentation
projects.xml and declarative-projects.xml were merged with xmllint, and
then I ran that to convert files
for i in *.xml; do pandoc -s -f docbook -t markdown $i -o ${i/xml/md}; done
2021-02-24 01:07:00 +01:00
Graham Christensen
e16388e34a Merge pull request #872 from grahamc/yath
Use `yath` for testing Hydra
2021-02-23 17:33:26 -05:00
Graham Christensen
3ebcaef127 README: update with instructions on running tests 2021-02-23 17:26:56 -05:00
Eelco Dolstra
e072c1d741 Merge pull request #874 from regnat/remove-sendDerivation
Remove the `sendDerivation` logic from the builder
2021-02-23 13:07:03 +01:00
regnat
f602ed0d86 Remove the sendDerivation logic from the builder
The queue runner used to special-case `localhost` as a remote builder:
Rather than using the normal remote-build (using the
`cmdBuildDerivation` command), it was using the (generally less
efficient, except when running against localhost) `cmdBuildPaths`
command because the latter didn't require a privileged Nix user (so made
testing easier − allowing to run hydra in a container in particular).

However:
1. this means that the build loop can follow two discint code paths depending
   on the setup, the irony being that the most commonly used one in production
   (the “non-localhost” case) isn't the one used in the testsuite (because all
   the tests run against a local store);
2. It turns out that the “localhost” version is buggy in relatively obvious
   ways − in particular a failure in a fixed-output derivation or a hash
   mismatch isn't reported properly;
3. If the “run in a container” use-case is indeed that important, it can be
   (partially) restored using a chroot store (which wouldn't behave excactly
   the same way of course, but would be more than good-enough for testing)
2021-02-23 09:50:15 +01:00
Eelco Dolstra
107d60027f hydra-eval-jobs: Fix unexpected EOF when a top-level attr fails 2021-02-22 16:29:07 +01:00
Eelco Dolstra
a7d8ee98da Fix build 2021-02-22 15:10:24 +01:00
Eelco Dolstra
34b438ab6e flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/8a2ce0f455da32bc20978e68c0aad9efb4560abc' -> 'github:NixOS/nix/548437c2347159c4c79352283dd12ce58324f1d6'
* Removed 'nix/lowdown-src'
2021-02-22 15:03:20 +01:00
Graham Christensen
45d9a22d73 flake.nix: add perlPackages until they're available from nixpkgs
These packages were added to Nixpkgs in https://github.com/NixOS/nixpkgs/pull/113702.
2021-02-19 17:06:49 -05:00
Graham Christensen
2240035e20 Run tests with yath
This will let us run tests in parallel, and creates a more Perl-standard
test development experience.
2021-02-19 17:04:19 -05:00
Eelco Dolstra
a39b479280 Merge pull request #866 from Infinisil/github-status-flakes
Fix Github status plugin for flakes
2021-02-16 17:00:46 +01:00
Andreas Rammhold
c35791fcc2 Add Queue Runner Status to the topbar
I've been searching for this waaay too often in the past and I simply do not see a reason not to include it in the topbar by default.
2021-02-09 14:10:08 +01:00
Christian Kögler
150213cbb3 Fix login if Hydra runs behind HTTP proxy with sub-path location 2021-02-07 19:18:29 +01:00
Silvan Mosberger
58dd7f9ed3 Fix Github status plugin for flakes
If the root flake is a github: one, github status notifications are sent
to it. The githubstatus->inputs configuration isn't used for flakes.
2021-02-06 00:02:30 +01:00
Graham Christensen
d8a5892795 Merge pull request #856 from immae/fix_check_jobsets
Fix check in jobsets
2021-02-03 16:25:18 -05:00
Ismaël Bouya
339a09f2e4 Fix check in jobsets
The current check happening in jobsets is incorrect.
The wanted constraint is stated as follow :
- If type is 0 (legacy), then the flake field should be null, and
  both nixExprInput and nixExprPath should be non-null
- If type is 1 (flake), then the flake field should be non-null, and
  both nixExprInput and nixExprPath should be null

The current version will not catch (i.e. it will accept) situations
where you have for instance :
type = 1, nixExprPath null, nixExprInput non-null, flake non-null

This commit fixes that.

I split(ted) that into two constraints, to make it more readable and
easier to extend if a new type appears in the future.

The complete query could be instead :
( type = 0
  AND nixExprInput IS NOT NULL AND nixExprPath IS NOT NULL AND flake IS NULL )
OR ( type = 1
  AND nixExprInput IS NULL AND nixExprPath IS NULL AND flake IS NOT NULL )

(but an "OR" cannot be split, hence the other formulation)
2021-02-03 22:14:53 +01:00
Graham Christensen
bc12fe19f9 Merge pull request #855 from grahamc/jobsetevals-fixups
JobsetEvals: fixup permission references
2021-02-02 11:04:18 -05:00
Graham Christensen
6de9c6540c Merge pull request #858 from Infinisil/fix-declarative-flakes
Fix transition from declarative non-flake to flake jobset
2021-02-02 11:04:05 -05:00
Graham Christensen
ac80843e31 Merge pull request #860 from grahamc/eval-error-table
Move evaluation errors from evaluations to EvaluationErrors, a new table
2021-02-02 10:37:04 -05:00
Graham Christensen
f1e75c8bff Move evaluation errors from evaluations to EvaluationErrors, a new table
DBIx likes to eagerly select all columns without a way to really tell
it so. Therefore, this splits this one large column in to its own
table.

I'd also like to make "jobsets" use this table too, but that is on hold
to stop the bleeding caused by the extreme amount of traffic this is
causing.
2021-02-01 21:33:14 -05:00
Silvan Mosberger
1d45b63516 Fix transition from declarative non-flake to flake jobset
The database has these constraints:

    check ((type = 0) = (nixExprInput is not null and nixExprPath is not null)),
    check ((type = 1) = (flake is not null)),

which prevented switching to flakes in a declarative jobspec, since the
nixexpr{path,input} fields were not nulled in such an update

Co-Authored-By: Graham Christensen <graham@grahamc.com>
2021-02-01 18:57:40 +01:00
Graham Christensen
8d7bfe1706 JobsetEvals: fixup permission references
Going from an eval to a project now requires hopping through the jobset
2021-02-01 10:31:05 -05:00
Graham Christensen
aaf16d542c Merge pull request #854 from NixOS/limit-query-time
search: limit queries to 20s
2021-01-30 11:55:22 -05:00
Graham Christensen
91e63fb7da search: limit queries to 20s
Even 20s is really long, but it cuts off queries which are today
running for 500+s.
2021-01-30 11:51:20 -05:00
Graham Christensen
72e237fb2f Merge pull request #853 from NixOS/search-limit-reqs
search: limit results to 50, default to 10
2021-01-30 08:57:05 -05:00
Graham Christensen
4f308b1f2f search: limit results to 50, default to 10
This search query is pretty heavy. Defaulting to 500 has caused
Hydra's web UI to appear to be down. Since 500 can take it down, users
probably shouldn't be allowed t ask for that many.
2021-01-30 08:37:57 -05:00
Graham Christensen
6d047c286f Merge pull request #850 from grahamc/jobset-evals-by-id
Jobset -> JobsetEvals by JobsetEvals.jobset_id
2021-01-28 09:25:18 -05:00
Graham Christensen
5fcc2018db hydra-evaluator: clean up names, clean up & / * spacing 2021-01-28 09:15:19 -05:00
Graham Christensen
091d58c128 hydra-dev-server: autoflush stderr/stdout 2021-01-26 13:51:39 -05:00
Graham Christensen
54b8cb188e perl: jobsetevals -> jobset via by jobset_id
Frankly, this was suspiciously little work.
2021-01-26 13:51:39 -05:00
Graham Christensen
54341cd9f6 hydra-evaluator: deal in jobset IDs 2021-01-26 13:51:31 -05:00
Graham Christensen
cb01859718 hydra-evaluator: JobsetName -> JobsetIdentity 2021-01-26 11:50:38 -05:00
Graham Christensen
705a45df2b hydra-evaluator: reformat readJobsets query 2021-01-26 11:50:37 -05:00
Graham Christensen
ac3e8a4a59 jobsetevals: refer to jobset by ID 2021-01-26 11:50:37 -05:00
Graham Christensen
99e3c83358 JobsetEvals: noop: re-run the generator to update the order of fields 2021-01-26 11:50:36 -05:00
Graham Christensen
bf674a9653 hydra.sql: embed some in-line docs about schema changes 2021-01-26 11:50:36 -05:00
Graham Christensen
dc5a0d59c5 sql: Stop loading SQL if an error occurs
Otherwise we may go ahead and create DBIx classes for a half-loaded schema.
2021-01-26 11:50:32 -05:00
Eelco Dolstra
d0b3f2dac4 Merge pull request #848 from grahamc/normalize-nixexprinputpath
Normalize nixexpr{input,path} from builds to jobsetevals.
2021-01-25 15:22:01 +01:00
Graham Christensen
9516b256f1 Normalize nixexpr{input,path} from builds to jobsetevals.
Duplicating this data on every record of the builds table cost
approximately 4G of duplication.

Note that the database migration included took about 4h45m on an
untuned server which uses very slow rotational disks in a RAID5 setup,
with not a lot of RAM. I imagine in production it might take an hour
or two, but not 4. If this should become a chunked migration, I can do
that.

Note: Because of the question about chunked migrations, I have NOT
YET tested this migration thoroughly enough for merge.
2021-01-22 09:10:18 -05:00
Eelco Dolstra
53c2fc2216 Merge pull request #847 from grahamc/jobsetevals-evaluation-errors
JobsetEvals: record evaluation errors
2021-01-22 15:08:22 +01:00
Graham Christensen
bd99052a6f tests: create database with the utf-8 locale
Otherwise tests may fail with wide character errors.
2021-01-21 17:08:05 -05:00
Graham Christensen
c64c4aac4f jobset page: render error labels per eval 2021-01-21 17:08:02 -05:00
Graham Christensen
805dd6e7ee Evaluation page: render evaluation errors 2021-01-21 13:11:05 -05:00
Graham Christensen
086eed5147 hydra-eval-jobs: write evaluation errorMsg to the jobseteval table 2021-01-21 13:10:41 -05:00
Graham Christensen
fb6b10a86c gitignore: artifacts 2021-01-21 13:10:41 -05:00
Graham Christensen
d9989b7fa1 Schema: add errorMsg, errorTime to JobsetEvals 2021-01-21 13:10:41 -05:00
Eelco Dolstra
6bb876cb35 Merge pull request #846 from grahamc/buildoutputs-index-hash-path
BuildOutputs: index path with HASH
2021-01-18 20:01:44 +01:00
Graham Christensen
bc4b96d053 BuildOutputs: index path with HASH
Looking at AWS' Performance Insights for a Hydra instance, I found
the hydra-queue-runner's query:

    select id, buildStatus, releaseName, closureSize, size
    from Builds b
    join BuildOutputs o on b.id = o.build
    where
      finished = ?
      and (buildStatus = ? or buildStatus = ?)
      and path = $1

was the slowest query by at least 10x. Running an explain on this
showed why:

hydra=> explain select id, buildStatus, releaseName, closureSize, size
    from Builds b join BuildOutputs o on b.id = o.build where
    finished = 1 and (buildStatus = 0 or buildStatus = 6) and
    path = '/nix/store/s93khs2dncf2cy273mbyr4fb4ns3db20-MIDIVisualizer-5.1';

                                                     QUERY PLAN
    ------------------------------------------------------------------------
     Gather  (cost=1000.43..33718.98 rows=2 width=56)
       Workers Planned: 2
       ->  Nested Loop  (cost=0.43..32718.78 rows=1 width=56)
             ->  Parallel Seq Scan on buildoutputs o  (cost=0.00..32710.32
                                                       rows=1
                                                        width=4)
                   Filter: (path = '/nix/store/s93kh...snip...'::text)
             ->  Index Scan using indexbuildsonjobsetidfinishedid on builds b
                                            (cost=0.43..8.45 rows=1 width=56)
                   Index Cond: ((id = o.build) AND (finished = 1))
                   Filter: ((buildstatus = 0) OR (buildstatus = 6))
    (8 rows)

A paralell sequential scan is definitely better than a sequential scan, but the
cost ranging from 0 to 32710 is not great. Looking at the table, I saw the `path`
column is completely unindex:

    hydra=> \d buildoutputs
                Table "public.buildoutputs"
    Column |  Type   | Collation | Nullable | Default
    --------+---------+-----------+----------+---------
    build  | integer |           | not null |
    name   | text    |           | not null |
    path   | text    |           | not null |
    Indexes:
        "buildoutputs_pkey" PRIMARY KEY, btree (build, name)
    Foreign-key constraints:
        "buildoutputs_build_fkey" FOREIGN KEY (build) REFERENCES builds(id)
            ON DELETE CASCADE

Since we always do exact matches on the path and don't care about ordering,
and since the path column is very high cardinality a `hash` index is a
good candidate. Note that I did test a btree index and it performed
similarly well, but slightly worse.

After creating the index (this took about 10 seconds) on a test database:

    create index IndexBuildOutputsPath on BuildOutputs using hash(path);

We get a *significantly* reduced cost:

    hydra=> explain select id, buildStatus, releaseName, closureSize, size
    hydra->     from Builds b join BuildOutputs o on b.id = o.build where
    hydra->     finished = 1 and (buildStatus = 0 or buildStatus = 6) and
    hydra->     path = '/nix/store/s93khs2dncf2cy273mbyr4fb4ns3db20-MIDIVisualizer-5.1';
                                                QUERY PLAN
    -------------------------------------------------------------------------------------------------------
    Nested Loop  (cost=0.43..41.41 rows=2 width=56)
    ->  Index Scan using buildoutputs_path_hash on buildoutputs o  (cost=0.00..16.05 rows=3 width=4)
            Index Cond: (path = '/nix/store/s93khs2dncf2cy273mbyr4fb4ns3db20-MIDIVisualizer-5.1'::text)
    ->  Index Scan using indexbuildsonjobsetidfinishedid on builds b  (cost=0.43..8.45 rows=1 width=56)
            Index Cond: ((id = o.build) AND (finished = 1))
            Filter: ((buildstatus = 0) OR (buildstatus = 6))
    (6 rows)

For direct comparison, the overall query plan was changed:

    From: Gather      (cost=1000.43..33718.98 rows=2 width=56)
    To:   Nested Loop (cost=   0.43.....41.41 rows=2 width=56)

and the query plan for buildoutputs changed from a maximum cost of
32,710 down to 16.

In practical terms, the query's planning and execution time was reduced:

Before (ms) | Try 1   | Try 2   | Try 3
------------+---------+---------+--------
Planning    |   0.898 |   0.416 |   0.383
Execution   | 138.644 | 172.331 | 375.585

After (ms)  | Try 1   | Try 2   | Try 3
------------+---------+---------+--------
Planning    |   0.298 |   0.290 |   0.296
Execution   | 219.625 |   0.035 |   0.034
2021-01-18 11:28:05 -05:00
Eelco Dolstra
be0aa7eb85 Merge pull request #841 from pingiun/github-login
Implement GitHub logins
2021-01-05 14:51:51 +01:00
Jelle Besseling
43d662f63a Don't use enable_github_login option after all
Instead the github_client_id option is used to detect if github logins
should be enabled.
2021-01-04 18:09:49 +01:00
Jelle Besseling
c49ca66689 Die when no email is found 2021-01-04 18:09:05 +01:00
Jelle Besseling
20d8134936 Update src/lib/Hydra/Controller/User.pm
Co-authored-by: Eelco Dolstra <edolstra@gmail.com>
2021-01-04 17:48:43 +01:00
Jelle Besseling
19f9d8249f Update src/lib/Hydra/Controller/User.pm
Co-authored-by: Eelco Dolstra <edolstra@gmail.com>
2021-01-04 17:48:37 +01:00
Eelco Dolstra
20d09518f8 Merge pull request #839 from pingiun/shield-io
Add endpoint to generate a shields.io badge
2021-01-04 14:09:09 +01:00
Eelco Dolstra
525a229dac Convert validate-openapi to a Hydra job 2021-01-03 18:47:05 +01:00
Eelco Dolstra
ce7b23ae09 Disable broken validate-openapi test 2021-01-03 18:40:08 +01:00
Eelco Dolstra
c4062c2772 Merge pull request #842 from pingiun/also-trigger-flakes
Also trigger flake based jobsets with push-github endpoint
2021-01-03 18:28:29 +01:00
Eelco Dolstra
b59a5850a8 Merge branch 'receiveContents' of https://github.com/orivej/hydra 2021-01-03 18:26:04 +01:00
Eelco Dolstra
2a695a621d Merge branch 'update-for-nix2020' of https://github.com/matthewbauer/hydra 2021-01-03 18:24:35 +01:00
Eelco Dolstra
896e72169f flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/79aa7d95183cbe6c0d786965f0dbff414fd1aa67' -> 'github:NixOS/nix/8a2ce0f455da32bc20978e68c0aad9efb4560abc'
2021-01-03 18:17:05 +01:00
Eelco Dolstra
bc10fd9d75 Merge pull request #831 from NixOS/dependabot/github_actions/cachix/install-nix-action-v12
Bump cachix/install-nix-action from v10 to v12
2021-01-03 18:12:07 +01:00
Jelle Besseling
5f4eddbe57 Use email scope 2020-12-31 13:40:33 +01:00
Jelle Besseling
e88355b3d4 Use email api call 2020-12-31 13:40:32 +01:00
Matthew Bauer
d38ef4492e Update for Nix Value::type API changes
This updates hydra to be compatible with Nix https://github.com/NixOS/nix/pull/4355.

Along with https://github.com/NixOS/hydra/pull/840 needed for https://github.com/NixOS/nixpkgs/pull/107909

/cc @edolstra
2020-12-29 17:25:51 -06:00
Jelle Besseling
1b3000e132 Allow push-github endpoint to also trigger flakes 2020-12-28 15:27:09 +01:00
Jelle Besseling
bbd4891133 Implement GitHub logins
Requires the following configuration options
enable_github_login = 1
github_client_id
github_client_secret
Or github_client_secret_file which points to a file with the secret
2020-12-28 14:37:03 +01:00
Orivej Desh
34a856c7ab Update for receiveContents taking string_view
nix change: https://github.com/NixOS/nix/commit/faa31f40
2020-12-26 11:23:26 +00:00
Jelle Besseling
f64230b45e Add endpoint to generate a shields.io badge 2020-12-25 15:05:34 +01:00
Eelco Dolstra
bde8d81876 Merge pull request #811 from helsinki-systems/fix/override-constraint
Stop violating not null constraint
2020-11-22 00:02:26 +01:00
Janne Heß
bd0ab9a5fb Stop violating not null constraint
Fixes this error:

ERROR: failed to process declarative jobset test:inputs,
DBIx::Class::Storage::DBI::_dbh_execute(): DBI Exception: DBD::Pg::st
execute failed: ERROR:  null value in column "emailoverride" violates
not-null constraint
2020-11-21 22:04:40 +01:00
Eelco Dolstra
b40db4c4f8 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/5e6eabe1551f3fa2a463fced39a4a48b504ed1ab' -> 'github:NixOS/nix/79aa7d95183cbe6c0d786965f0dbff414fd1aa67'
2020-11-19 17:23:39 +01:00
Ricardo M. Correia
f47749a62d Fix persistent hash mismatch errors when importing
This would start happening if the network connection between the Hydra
server and the remote build server breaks after sucessfully importing
at least one output of a derivation, but before having finished
importing all outputs.

Fixes #816.
2020-11-10 04:50:35 +01:00
dependabot[bot]
2dcdc06e3a Bump cachix/install-nix-action from v10 to v12
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from v10 to v12.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v10...07da2520eebede906fbeefa9dd0a2b635323909d)

Signed-off-by: dependabot[bot] <support@github.com>
2020-11-09 05:34:56 +00:00
Eelco Dolstra
0bdeb63a15 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/e0ca98c2071b815578470e280df8fdb750c7e23b' -> 'github:NixOS/nix/5e6eabe1551f3fa2a463fced39a4a48b504ed1ab'
2020-11-03 14:57:06 +01:00
Eelco Dolstra
73dfef364b Copy deriver field to the binary cache
Fixes https://github.com/NixOS/nixos-org-configurations/issues/129.
2020-11-02 17:08:02 +01:00
Eelco Dolstra
d50f9a242f Merge pull request #826 from Taneb/patch-2
Remove Debug prints from GitLabStatus.pm
2020-11-02 12:13:42 +01:00
Nathan van Doorn
2742fde8c2 Remove Debug prints from GitLabStatus.pm
These make the hydra-queue-runner logs very noisy even when not using the GitlabStatus plugin.
Also, they shouldn't be necessary except when developing the plugin itself and should have been removed before release.
2020-11-02 10:14:54 +00:00
Eelco Dolstra
87317812a8 Fix some broken indices
These indices basically did nothing since they put "id" first.

In particular this makes /job/.../all much faster.
2020-10-28 14:30:44 +01:00
Eelco Dolstra
2922f45b4f Ignore 'nix develop' outputs directory 2020-10-28 13:41:34 +01:00
Eelco Dolstra
8bb23905c3 Build: Remove unused prevBuild
This speeds up loading the page a lot in the case where there is no
previous evaluation (for some reason).
2020-10-28 13:29:31 +01:00
Eelco Dolstra
d9dc7ca18b getPreviousBuild: Get previous build in the job, not jobset
Broken since 8adb433e3.
2020-10-28 13:29:02 +01:00
Eelco Dolstra
a1b5418114 Remove dead link 2020-10-27 12:35:36 +01:00
Samuel Dionne-Riel
b5140c1da1 hydra-eval-jobs: Transmit original Nix error when handling aggregate jobs
It might happen that a job from the aggregate returned an error!

This is what the vague "[json.exception.type_error.302] type must be string, but is null"
was all about in this instance; there was no `drvPath` to stringify!

So we now actively watch for errors and copy them to the aggregate job.
2020-10-25 20:13:07 -04:00
Samuel Dionne-Riel
68e689cace hydra-eval-jobs: Identify unexpected errors in handling aggregate jobs
The vague "[json.exception.type_error.302] type must be string, but is null"
is **absolutely** unhelpful in the way Hydra currently handles it on
evaluation.

This is handling *unexpected* errors only; the following commit will
handle the specific instance of the previously mentioned error.
2020-10-25 19:27:15 -04:00
Eelco Dolstra
be709d450b Fix sysbuild
596f4cf4b9
2020-10-22 13:27:52 +02:00
Eelco Dolstra
79d34ed7c9 Follow nix/nixpkgs 2020-10-20 12:21:06 +02:00
Eelco Dolstra
94d696df0e flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/20a7d8d23a19530207378fc74ddd558232240f43' -> 'github:NixOS/nix/e0ca98c2071b815578470e280df8fdb750c7e23b'
* Updated 'nix/nixpkgs': 'github:NixOS/nixpkgs/3a10a004bb5802d5f23c58886722e4239705e733' -> 'github:NixOS/nixpkgs/ad0d20345219790533ebe06571f82ed6b034db31'
* Updated 'nixpkgs': 'github:NixOS/nixpkgs/5659cb448e9b615d642c5fe52779c2223e72f7eb' -> follows 'nix/nixpkgs'
2020-10-20 12:20:33 +02:00
Eelco Dolstra
90a2f8eb2b Merge branch 'master' of github.com:NixOS/hydra into master 2020-10-20 12:19:53 +02:00
Eelco Dolstra
338d946620 Remove nix from hydra-perl-deps
Also add nix to passthru. This makes it easier to override nix in 'nix
develop', e.g.

  $ nix develop \
    --redirect .#hydraJobs.build.x86_64-linux.nix ~/Dev/nix/outputs/out \
    --redirect .#hydraJobs.build.x86_64-linux.nix.dev ~/Dev/nix/outputs/dev
2020-10-20 12:15:18 +02:00
Eelco Dolstra
4e05acc471 Fix localhost builds 2020-10-20 12:11:46 +02:00
Eelco Dolstra
6cd2bb6954 Fix build 2020-10-18 21:01:06 +02:00
Eelco Dolstra
deb9b68afd flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/8b4a542d1767e0df7b3c0902b766f34352cb0958' -> 'github:NixOS/nix/20a7d8d23a19530207378fc74ddd558232240f43'
* Updated 'nix/nixpkgs': 'github:NixOS/nixpkgs/70717a337f7ae4e486ba71a500367cad697e5f09' -> 'github:NixOS/nixpkgs/3a10a004bb5802d5f23c58886722e4239705e733'
2020-10-18 20:55:30 +02:00
Eelco Dolstra
bea7c2581f Merge branch 'update-nix-unstable' of https://github.com/Ma27/hydra 2020-10-18 20:40:57 +02:00
Eelco Dolstra
869671e556 Merge pull request #823 from andir/ldap
ldap: Use hashed passwords in the test
2020-10-13 12:37:16 +02:00
Andreas Rammhold
458b0ceb85 ldap: Use hashed passwords in the test
We should lead with good example and when users copy code from this repo
it should not incentivize them to use plain text passwords.
2020-10-12 17:18:37 +02:00
Andreas Rammhold
656b0c27b3 Update to NixOS 20.09
This allows us to make use of the openldap modules for hashed passwords.
In 20.03 the openldap expression didn't yet build those modules.
2020-10-12 17:18:01 +02:00
Maximilian Bosch
9cc76f6d69 Fix build with latest Nix
Recently a few internal APIs have changed[1]. The `outputPaths` function
has been removed and a lot of data structures are modeled with
`std::optional` which broke compilation.

This patch updates the code in `hydra-queue-runner` accordingly to make
sure that Hydra compiles again.

[1] https://github.com/NixOS/nix/pull/3883
2020-09-26 23:37:39 +02:00
Maximilian Bosch
2394140843 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/2a8017092025a7c108ca1a829a8b4f0bcf7ee2c0' -> 'github:NixOS/nix/8b4a542d1767e0df7b3c0902b766f34352cb0958'
* Updated 'nix/lowdown-src': 'github:edolstra/lowdown/c7a4e715af1e233080842db82d15b261cb74cb28' -> 'github:kristapsdz/lowdown/1705b4a26fbf065d9574dce47a94e8c7c79e052f'
* Updated 'nixpkgs': 'github:NixOS/nixpkgs/252bfe0107587d40092057f338e9ffcf7bbd90cb' -> 'github:NixOS/nixpkgs/5659cb448e9b615d642c5fe52779c2223e72f7eb'
2020-09-26 23:36:37 +02:00
Eelco Dolstra
46a8d6d531 Merge branch 'fix/addPermRoot' of https://github.com/helsinki-systems/hydra 2020-09-15 13:22:53 +02:00
Eelco Dolstra
d33ac5799c flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/eb75282b8dc855983368c79cc4c2943c298518f7' -> 'github:NixOS/nix/2a8017092025a7c108ca1a829a8b4f0bcf7ee2c0'
* Added 'nix/lowdown-src': 'github:edolstra/lowdown/c7a4e715af1e233080842db82d15b261cb74cb28'
2020-09-15 13:14:47 +02:00
Eelco Dolstra
b8a4ed0c77 Merge pull request #815 from helsinki-systems/fix/non-static-decl
Fix non-static declarative jobsets
2020-09-14 15:52:05 +02:00
Eelco Dolstra
2c76e9848a Merge pull request #812 from helsinki-systems/no-accesslog
Disable access log
2020-09-14 15:38:13 +02:00
Eelco Dolstra
a6c4e4b067 Merge pull request #807 from plutotulp/bugfix-revcount-as-integer
reproduce bash script must supply revCount as int
2020-09-14 15:34:03 +02:00
Eelco Dolstra
733bbc131d Merge pull request #808 from andir/ldap
ldap: only try the LDAP realm when it is configured
2020-09-14 15:33:33 +02:00
ajs124
2c61779816 fix build after nix commit 82b77a77262c414044fffc7ad8b955ad91827995 2020-09-14 15:30:59 +02:00
Eelco Dolstra
e630440a07 Merge pull request #813 from helsinki-systems/fix/manual-xml
manual: Fix XML
2020-09-14 14:55:43 +02:00
Janne Heß
24acb9d6bb Fix non-static declarative jobsets
With the current implementation, if ANY hash was found inside the decl
spec, the spec would be treated as static. This is problematic since
`inputs` is a hash and hence any configuration would be handled as a
static one.
This fixes the code to match the documentation and only switch to static
processing when ALL values are hashes.
2020-09-13 18:21:38 +02:00
Janne Heß
3f4d9f8446 manual: Fix XML 2020-09-13 17:52:18 +02:00
Janne Heß
971dcc46a2 Disable access log
This is annoying and mostly redundant to nginx.
2020-09-13 17:51:21 +02:00
Andreas Rammhold
6a07712e1d LDAP: only try LDAP authentication when the realm is configured 2020-09-12 19:57:24 +02:00
Andreas Rammhold
ee60f4ccd9 tests: fix invalid YAML
Somwhere while polishing the initial PR I forgot to add that colo.
2020-09-12 19:57:24 +02:00
Erlend Pedersen
1d11b29e73 reproduce bash script must supply revCount as int
The reproduce script would fail for me, because it passed revCount as
a string to nix-build, which would then fail to subtract from it.
2020-09-12 14:04:43 +02:00
Graham Christensen
8f683aa7f8 Merge pull request #805 from andir/ldap
LDAP support continued (with missing packages & tests)
2020-09-11 12:10:23 -04:00
Andreas Rammhold
b5d7ed2e99 LDAP: add brief section in the documentation 2020-09-11 15:21:40 +02:00
Andreas Rammhold
f229da352e LDAP add test for roles and multiple users 2020-09-10 17:09:32 +02:00
Andreas Rammhold
cfc01e2518 LDAP: add VM test to flake.nix
In this newly added test an OpenLDAP server will provide one user
(called `user`) and it will be attempted to login as that said user.
Also logging in with any other password must fail.
2020-09-10 17:09:32 +02:00
Andreas Rammhold
b8c19337b6 LDAP: add the required packages to the perlPackage via the overlay
Nixpkgs doesn't currently provide these required packages. In order to
use this feature without waiting for a newer release of NixOS/Nixpkgs
thes have been packages inline.
2020-09-10 16:47:33 +02:00
edef
c00b42dced don't try to load HYDRA_LDAP_CONFIG if none is provided 2020-09-09 13:02:51 +02:00
edef
b9ff7b2671 include perlPackages.YAML in buildInputs 2020-09-09 13:02:49 +02:00
ajs124
28646e1c5f Initial attempt at adding LDAP login support 2020-09-09 13:00:34 +02:00
Eelco Dolstra
e707990e2d Merge pull request #804 from grahamc/fully-static-jobsets
declarative projects: support fully static, declarative configuration
2020-09-02 21:09:01 +02:00
Eelco Dolstra
dd0145a7f4 Merge pull request #802 from grahamc/run-command-hacking
Development-time improvements
2020-09-02 21:05:57 +02:00
Graham Christensen
7f16c0d243 declarative projects: support fully static, declarative configuration 2020-09-02 12:35:41 -04:00
Graham Christensen
648eb980dd hydra-notify: autoflush stdout too 2020-09-02 12:35:18 -04:00
Graham Christensen
65a34499f0 foreman/queue runner: run locally to avoid trust issues 2020-09-02 12:35:18 -04:00
Graham Christensen
128aa0afc9 foreman: allow using substitutes by default 2020-09-02 12:35:18 -04:00
Graham Christensen
42d09aace1 readme: note the default user/pass 2020-09-02 12:35:18 -04:00
Graham Christensen
cbc386efe7 Merge pull request #803 from cransom/fix-imagebase
Remove image dependency on hydra.nixos.org
2020-09-01 15:37:18 -04:00
Casey Ransom
03be8ae7a1 Remove image dependency on hydra.nixos.org
Also standardize the slack image size on 256 pixels.
2020-09-01 15:13:12 -04:00
Eelco Dolstra
405c52b589 Fix build 2020-08-27 17:46:36 +02:00
Eelco Dolstra
e463f44bfc flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/edfd676e059578fb574ce78d1a2cc66d018d3b16' -> 'github:NixOS/nix/eb75282b8dc855983368c79cc4c2943c298518f7'
2020-08-27 17:28:34 +02:00
Eelco Dolstra
1113c2895a Fix build 2020-08-07 21:42:09 +02:00
Eelco Dolstra
529a003de5 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/4e7f1c7f11fb22d7954b2dacbe87c61548fab82d' -> 'github:NixOS/nix/edfd676e059578fb574ce78d1a2cc66d018d3b16'
2020-08-07 21:20:39 +02:00
Eelco Dolstra
f8e15bc311 Revive putBytes 2020-08-04 18:25:21 +02:00
Eelco Dolstra
56495289cd flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/ed52cf632bf9db90311014600ca0f042ef57ca20' -> 'github:NixOS/nix/4e7f1c7f11fb22d7954b2dacbe87c61548fab82d'
2020-08-04 16:02:38 +02:00
Eelco Dolstra
4b5813051b unsigned long long -> uint64_t 2020-08-04 11:38:22 +02:00
Eelco Dolstra
7d3ba616a9 Fix build 2020-08-04 11:33:29 +02:00
Eelco Dolstra
7b8a3acbf0 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/d7c0f094cbcfe1ae4ccc3d54baec00b66ccb1ed0' -> 'github:NixOS/nix/ed52cf632bf9db90311014600ca0f042ef57ca20'
2020-08-04 10:54:40 +02:00
Eelco Dolstra
77c33c1d71 Restore NoCheckSigs
https://github.com/NixOS/nixpkgs/pull/93945#issuecomment-668244478
2020-08-04 10:53:06 +02:00
Eelco Dolstra
858eb41fab Merge pull request #795 from NixOS/no-nar-accessors
Stream NARs from the remote to the destination store
2020-07-28 15:03:57 +02:00
Eelco Dolstra
8722927c08 Copy paths in the right order 2020-07-28 13:46:57 +02:00
Eelco Dolstra
58a8b1c91c Keep the SHA-1 column in existing installations 2020-07-28 11:47:44 +02:00
Kevin Quick
3e73a2f709 Fix issue #614: restart queue/evaluator on sufficient disk space avai… (#777)
* Fix issue #614: restart queue/evaluator on sufficient disk space available.

* Only try to stop the service if it is currently running.

* Use named variables and added restarting message.
2020-07-27 15:46:57 -04:00
Eelco Dolstra
a0e24f446b Remove unused getMemSize() function 2020-07-27 20:40:57 +02:00
Eelco Dolstra
5b4df3ad5a Get data needed by getBuildOutput() from the incoming NAR in a streaming fashion 2020-07-27 20:38:59 +02:00
Eelco Dolstra
d4e4be4fd1 Remove SHA-1 hash from BuildProducts
SHA-1 is deprecated and it will be expensive to compute with the
streaming NAR handler.
2020-07-27 18:24:10 +02:00
Eelco Dolstra
7622cbfe37 buildRemote(): Copy paths to the destination store in O(1) memory 2020-07-27 18:11:04 +02:00
Eelco Dolstra
cbcf6359b4 Remove TokenServer in preparation of making NAR copying O(1) memory 2020-07-27 14:57:22 +02:00
Eelco Dolstra
e5f6fc2e4e Quick hack to fix compilation 2020-07-27 14:53:43 +02:00
Eelco Dolstra
90f03158f3 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/1ab9da915422405452118ebb17b88cdfc90b1e10' -> 'github:NixOS/nix/d7c0f094cbcfe1ae4ccc3d54baec00b66ccb1ed0'
2020-07-27 14:02:36 +02:00
dependabot[bot]
63188667b8 Bump cachix/install-nix-action from v8 to v10 (#791)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from v8 to v10.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v8...63cf434de4e4292c6960639d56c5dd550e789d77)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-14 20:50:41 +02:00
Bas van Dijk
48678df8b6 updateDeclarativeJobset: only set the emailresponsible column when defined (#788) 2020-07-08 19:08:11 -04:00
Eelco Dolstra
7985757a1d Fix build 2020-07-08 12:50:02 +02:00
Eelco Dolstra
6c9e407bee flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/334e26bfc2ce82912602e8a0f9f9c7e0fb5c3221' -> 'github:NixOS/nix/1ab9da915422405452118ebb17b88cdfc90b1e10'
* Updated 'nixpkgs': 'github:NixOS/nixpkgs/a84b797b28eb104db758b5cb2b61ba8face6744b' -> 'github:NixOS/nixpkgs/c9d124e39dbeefc53c7b3e09fbfc2c26bcbd4845'
2020-07-08 12:27:26 +02:00
Eelco Dolstra
b0163e9eae Fix project creation by non-admin users 2020-07-08 12:26:46 +02:00
Eelco Dolstra
d0deebc4fc Merge pull request #790 from Mic92/dependabot
automatically update github actions
2020-06-30 11:35:23 +02:00
Jörg Thalheim
2d2b0d11dc automatically update github actions
Same as https://github.com/NixOS/nix/pull/3757
2020-06-30 08:34:01 +01:00
Eelco Dolstra
bb32aafa4a Fix build 2020-06-23 13:56:44 +02:00
Eelco Dolstra
1726adbad7 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/2e4bd782115c5842781db31f6e06c162f8afe780' -> 'github:NixOS/nix/334e26bfc2ce82912602e8a0f9f9c7e0fb5c3221'
2020-06-23 11:47:15 +02:00
Eelco Dolstra
2dd06329eb Simplify default.nix and shell.nix 2020-06-17 19:19:55 +02:00
Eelco Dolstra
03e8a7fef4 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/14a3a62bfca6c572b9a415cfa80cdbd7ad4326b3' -> 'github:NixOS/nix/2e4bd782115c5842781db31f6e06c162f8afe780'
* Updated 'nix/nixpkgs': 'github:NixOS/nixpkgs/b88ff468e9850410070d4e0ccd68c7011f15b2be' -> 'github:NixOS/nixpkgs/70717a337f7ae4e486ba71a500367cad697e5f09'
* Updated 'nixpkgs': 'github:NixOS/nixpkgs/29eddfc36d720dcc4822581175217543b387b1e8' -> 'github:NixOS/nixpkgs/a84b797b28eb104db758b5cb2b61ba8face6744b'
2020-06-17 19:19:41 +02:00
Eelco Dolstra
1831866a52 Merge pull request #692 from knl/emit-hostname-with-influxdb-metrics
Add host tag to InfluxDB metrics
2020-06-10 10:57:17 +02:00
Kevin Quick
23fa93c5f8 Better update of timeout for the PathInput handler. 2020-06-09 09:00:02 -07:00
Kevin Quick
66730993fc Reconcile with changes from pullreq #775 2020-06-09 08:55:46 -07:00
Kevin Quick
25d1e8900a Allow PathInput to take an optional frequency parameter.
The previous version hard-coded the cache check frequency to 30
seconds.  This meant that the path was checked very frequently (max of
30 seconds and the evaluation period of the job), which could be
problematic for URL PathInput specifications, and especially ones that
are automatically updated frequently without *each* update necessarily
being interesting (an example: the haskell hackage index file.)
2020-06-09 08:48:22 -07:00
Eelco Dolstra
6168e7fa44 Merge pull request #781 from knl/remove-SSL_CERT_FILE
Remove SSL_CERT_FILE
2020-06-06 12:32:26 +02:00
Nikola Knezevic
e5c757e219 Remove SSL_CERT_FILE
This was slated to be removed with Nix 16.03. We're now in 20.03, so
it's good to clean that up a bit.
2020-06-05 18:53:16 +02:00
Eelco Dolstra
56b1660c4d Merge pull request #775 from knl/path-input-cache-validity-fix
Make PathInput plugin cache validity configurable
2020-06-05 17:22:07 +02:00
Eelco Dolstra
5f1faf4cb4 Merge pull request #779 from knl/there-is-no-hydra-postgresql.sql-anymore
Remove references to hydra-postgresql.sql
2020-06-05 17:21:40 +02:00
Eelco Dolstra
c0b4686b32 Merge pull request #780 from knl/remove-dead-method
Remove dead method from Nix.pm
2020-06-05 17:21:15 +02:00
Nikola Knezevic
e34d40d4f8 Remove dead method from Nix.pm
This method has been moved to hydra-eval-jobset a long time ago.
2020-06-05 15:01:36 +02:00
Nikola Knezevic
3acdd21569 Remove references to hydra-postgresql.sql
As of https://github.com/NixOS/hydra/pull/737 (removal of sqlite
dependency), the only supported database is Postgresql.

This change removes all references to hydra-postgresql.sql file. This
file is generated using a cpp on hydra.sql, but doesn't differ from
hydra.sql at all.
2020-06-05 13:42:56 +02:00
Nikola Knezevic
fceaed2b24 Make PathInput plugin cache validity configurable
PathInput plugin keeps a cache of path evaluations. This cache is simple, and
path is not checked more than once every N seconds, where N=30. The caching is
there to avoid expensive calls to `nix-store --add`.

This change makes the validity period configurable. The main use case is
`api-test.pl` which was implemented wrong for a while, as the invocation of
`hydra-eval-jobset` would return the previous evaluation, claiming there are no
changes. The test has been fixed to check better for a new evaluation.
2020-06-04 12:26:47 +02:00
Eelco Dolstra
0b300e80ad Merge pull request #773 from Ma27/fix-hydra-send-stats
Fix syntax error in `hydra-send-stats`
2020-06-02 16:25:25 +02:00
Maximilian Bosch
d4822a5f4b Fix syntax error in hydra-send-stats 2020-06-02 15:30:42 +02:00
Eelco Dolstra
750e2e618a Merge pull request #770 from NixOS/remove-jobs
Remove the Jobs table
2020-06-01 10:25:41 +02:00
Eelco Dolstra
d5844897da Merge pull request #771 from knl/fix-unprocessed-notificationpendingsince
Fix: Set notificationpendingsince for dependent builds
2020-05-28 11:15:24 +02:00
Nikola Knezevic
7d52946982 Set notificationpendingsince for dependent builds
`build_finished` Postgres event will never be fired for the dependent builds.

For example, on our Hydra, the following query always returns increasing
numbers, even though all notifications have been delivered:

```
hydra=> select count(1) from builds where notificationpendingsince is not null;
 count
-------
  4583
(1 row)
```

Thus, we have to iterate over all dependent builds and mark their
`notificationpendingsince` as `null`, otherwise they will pile up until
the next restart of hydra-notify, when they will get delivered.
2020-05-28 10:45:41 +02:00
Nikola Knezevic
7148923d30 Make --no-allow-import-from-derivation configurable in hydra-eval-jobset
When deploying Hydra different than hydra.nixos.org one may encounter a problem
as building any job that uses IFD fails with:

May 22 19:41:07 hydra hydra-evaluator[6960]: error: "attempted to realize '/nix/store/1jm02mfiv58rpy8zrx95cpqxzsp64ssh-source.drv' during evaluation but 'allow-import-from-derivation' is false"
May 22 19:41:07 hydra hydra-evaluator[6960]: error: "attempted to realize '/nix/store/av3jr8ix4qcadq2wm3y3hplvxwzlhl4y-source.drv' during evaluation but 'allow-import-from-derivation' is false"
May 22 19:41:07 hydra hydra-evaluator[6960]: error: "attempted to realize
'/nix/store/2jm02mfiv58rpy8zrx95cpqxzsp64ssh-source.drv' during evaluation but
'allow-import-from-derivation' is false"

The recent change enforced passing `--no-allow-import-from-derivation`
to `hydra-eval-job` unconditionally. This change makes it configurable and
defaults to **NOT PASSING IT** -- most of the deployments allow IFDs.

The configuration option is called `allow_import_from_derivation` and
defaults to `true`. It is interpreted as a boolean, with only true option being
`true`.
2020-05-28 10:15:46 +02:00
Eelco Dolstra
8adb433e3b Remove the Jobs table
This table has been superfluous for a long time.
2020-05-27 20:09:36 +02:00
Eelco Dolstra
af9f635a5a Use PostgreSQL 11
This is what we use for hydra.nixos.org.
2020-05-27 17:34:14 +02:00
Eelco Dolstra
a1e08d8819 Merge pull request #768 from knl/improve-handling-of-perl-block-eval-errors
Improve handling of Perl's block eval errors
2020-05-27 12:20:25 +02:00
Nikola Knezevic
f79810bac1 Improve handling of Perl's block eval errors
Taken from `Perl::Critic`:

A common idiom in perl for dealing with possible errors is to use `eval`
followed by a check of `$@`/`$EVAL_ERROR`:

    eval {
        ...
    };
    if ($EVAL_ERROR) {
        ...
    }

There's a problem with this: the value of `$EVAL_ERROR` (`$@`) can change
between the end of the `eval` and the `if` statement. The issue are object
destructors:

    package Foo;

    ...

    sub DESTROY {
        ...
        eval { ... };
        ...
    }

    package main;

    eval {
        my $foo = Foo->new();
        ...
    };
    if ($EVAL_ERROR) {
        ...
    }

Assuming there are no other references to `$foo` created, when the
`eval` block in `main` is exited, `Foo::DESTROY()` will be invoked,
regardless of whether the `eval` finished normally or not. If the `eval`
in `main` fails, but the `eval` in `Foo::DESTROY()` succeeds, then
`$EVAL_ERROR` will be empty by the time that the `if` is executed.
Additional issues arise if you depend upon the exact contents of
`$EVAL_ERROR` and both `eval`s fail, because the messages from both will
be concatenated.

Even if there isn't an `eval` directly in the `DESTROY()` method code,
it may invoke code that does use `eval` or otherwise affects
`$EVAL_ERROR`.

The solution is to ensure that, upon normal exit, an `eval` returns a
true value and to test that value:

    # Constructors are no problem.
    my $object = eval { Class->new() };

    # To cover the possiblity that an operation may correctly return a
    # false value, end the block with &quot;1&quot;:
    if ( eval { something(); 1 } ) {
        ...
    }

    eval {
        ...
        1;
    }
        or do {
            # Error handling here
        };

Unfortunately, you can't use the `defined` function to test the result;
`eval` returns an empty string on failure.

Various modules have been written to take some of the pain out of
properly localizing and checking `$@`/`$EVAL_ERROR`. For example:

    use Try::Tiny;
    try {
        ...
    } catch {
        # Error handling here;
        # The exception is in $_/$ARG, not $@/$EVAL_ERROR.
    };  # Note semicolon.

"But we don't use DESTROY() anywhere in our code!" you say. That may be
the case, but do any of the third-party modules you use have them? What
about any you may use in the future or updated versions of the ones you
already use?
2020-05-26 11:19:43 +02:00
Eelco Dolstra
471b036eef Merge pull request #765 from cransom/foreman-hydra-notify
Add hydra-notify to devshell
2020-05-25 16:36:43 +02:00
Casey Ransom
8a169ffa56 Add hydra-notify to devshell
I came across https://github.com/NixOS/hydra/issues/751 and realized
that hydra-notify is responsible for creating the additional jobsets in
a declarative file. My declarative testing works in dev now.
2020-05-20 15:38:31 -04:00
Bas van Dijk
3c6b724f92 Merge pull request #764 from knl/render-jobset.tt-correctly
Render the jobset page correctly when there are fetch errors
2020-05-20 17:58:07 +02:00
Nikola Knezevic
0f21e4067b Render the jobset page correctly when there are fetch errors
The original code would return standard "Please come back later" page when there
are only fetch errors on a newly setup declarative project. The problem is that
there are two types of errors: standard errors and fetch errors. Each is
acompanied by a corresponding field for time of occurence. Standard errors use
'errortime', while fetch errors have 'lastchecktime' set to the time of the
error. Unfortunately, jobset.tt file was only using 'errortime' for displaying
the time. This would result in the following errors in logs:

    Couldn't render template "date error - bad time/date string:  expects 'h:m:s d:m:y'  got: ''

This change includes using 'lastchecktime' when rendering the error times.
2020-05-20 17:47:18 +02:00
Bas van Dijk
03f14f46d7 Merge pull request #762 from knl/fix-declarative-jobset-missing-type-value
Fix declarative jobset missing type value
2020-05-18 11:04:00 +02:00
Nikola Knezevic
e9922c460e Add missing SQL upgrade script for NOT NULL on type
`type` column in `Jobsets` is defined as NOT NULL. However, the original upgrade
script adding this column ommited the constraint.
2020-05-18 10:59:55 +02:00
Nikola Knezevic
575113396d Handle missing values in declarative jobsets
The current implementation will pass all values to `create_or_update` method. The
missing values will end up as `undef` (or `NULL`) when assigned to `%update`.
Thus, for columns that are NOT NULL, when, for example, flakes are not used,
will result in a horrible:

    DBIx::Class::Storage::DBI::_dbh_execute(): DBI Exception: DBD::Pg::st execute failed:
    ERROR:  null value in column "type" violates not-null constraint

    DETAIL:  Failing row contains (.jobsets, 118, hydra, hydra jobsets, src, hydra/jobsets.nix, null,
    null, null, 1589536378, 1, 0, 0, , 3, 30, 100, null, null, 1589536379, null, null). [for Statement
    "UPDATE jobsets SET checkinterval = ?, description = ?, enableemail = ?, nixexprinput = ?,
    nixexprpath = ?, type = ? WHERE ( ( name = ? AND project = ? ) )" with ParamValues: 1='30',
    2='hydra jobsets', 3='0', 4='src', 5='hydra/jobsets.nix', 6=undef, 7='.jobsets', 8='hydra'] at
    /nix/store/lsf81ip9ybxihk5praf2n0nh14a6i9j0-hydra-0.1.19700101.DIRTY/libexec/hydra/lib/Hydra/Helper/AddBuilds.pm line 50

This change just omits adding such values to `%update`, which results in
PostgreSQL assigning the default values.
2020-05-15 20:33:54 +02:00
Eelco Dolstra
c4104fe1fa Merge pull request #759 from gilligan/devshell
Devshell
2020-05-15 14:21:40 +02:00
Tobias Pflug
006233d7f3 README.md update
- drop any mention of runHydra
- link foreman and mention Procfile
2020-05-15 13:59:36 +02:00
Tobias Pflug
31262f14fb Address PR comments:
- scripts -> foreman
- drop runHydra
- drop devShell
- move postgresql to buildInputs
2020-05-15 13:48:21 +02:00
Tobias Pflug
fc0eb02ffe Run hydra-dev-server
Execute hydra-dev-server instead of hydra-server

Co-authored-by: Graham Christensen <graham@grahamc.com>
2020-05-15 12:37:16 +02:00
Tobias Pflug
1bcb8d0be9 Use pg_isready for readiness check
Co-authored-by: Graham Christensen <graham@grahamc.com>
2020-05-15 12:37:16 +02:00
Tobias Pflug
d9d58b7055 Use pg_ctl for readiness check
Using `pg_ctl status` is more reliable than relying checking an
open port via netcat.
2020-05-15 12:37:16 +02:00
Tobias Pflug
45ac8e0cbc README.md: info about runHydra/foreman
Add sections about using `runHydra` and `foreman`
2020-05-15 12:37:16 +02:00
Tobias Pflug
0add1cc6d8 Default to devShell in shell.nix 2020-05-15 12:37:16 +02:00
Tobias Pflug
07a4465260 Use custom ports for postgres/hydra
Use custom ports so hydra and postgres can run in environments where
the default ports are in use already.
2020-05-15 12:37:16 +02:00
Andreas Rammhold
eb06a435ab Add devShell for faster feedback
This adds a `devShell` which unlike `runHydra` doesn't start hydra
automatically and doesn't receive hydra as build input. It is better
suited for interactive development cycles:

```
$ nix-shell -A devShell
$ ./bootstrap
$ configurePhase
$ make
$ # hack hack hack
$ foreman start
  # test test test
  <C-c>
$ # hack hack hack
```
2020-05-15 12:37:16 +02:00
Andreas Rammhold
d1237c315d Add runHydra shell
runHyda automatically starts hydra and postgres:

```
$ nix-shell -A runHydra
```

The shell receives hydra from the working copy as buildInput.
Running hydra, queue-runner, evaluator and postgres is managed
by foreman (https://github.com/ddollar/foreman) and configured
in `Procfile`.
2020-05-15 12:37:16 +02:00
Eelco Dolstra
a614199449 Merge pull request #760 from knl/patch-1
Correct the link to hydra-api.yml file
2020-05-14 16:38:13 +02:00
Nikola Knežević
090c05be5d Correct the link to hydra-api.yml file
The correct filename is `hydra-api.yml` not `hydra.yml`.
2020-05-14 14:15:30 +02:00
Eelco Dolstra
16ecd4f59d Merge pull request #757 from grahamc/fixup-migration-p2
schema/Builds: use jobset_id instead of jobset name matches
2020-05-13 16:43:02 +02:00
Graham Christensen
548fd8eadd schema/Builds: use jobset_id instead of jobset name matches
This was clearly an error in the original part-2 of the diff, and
specifically breaks when two projects have a jobset of the same name.
2020-05-13 10:12:56 -04:00
Bas van Dijk
301e4e088e Merge pull request #756 from basvandijk/only-convert-integer-option-values-to-ints
GitInput: only convert integer option values to int
2020-05-13 12:09:20 +02:00
Bas van Dijk
38122544ed GitInput: only convert integer option values to int
The previous code converted option values to ints when the value
contained a digit somewhere. This is too eager since it also converts
strings like `release-0.2` to an int which should not happen.

We now only convert to int when the value is an integer.
2020-05-13 11:41:52 +02:00
Eelco Dolstra
15a45f1a8a Fix build 2020-05-12 16:14:20 +02:00
Eelco Dolstra
ace051e8d9 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/3aaceeb7e2d3fb8a07a1aa5a21df1dca6bbaa0ef' -> 'github:NixOS/nix/14a3a62bfca6c572b9a415cfa80cdbd7ad4326b3'
2020-05-12 16:03:29 +02:00
Eelco Dolstra
e379628db0 hydra-eval-jobset: Pass --no-allow-import-from-derivation
https://github.com/NixOS/nixpkgs/issues/87592
2020-05-12 15:17:50 +02:00
Eelco Dolstra
cb06f0af47 flake.nix: Remove edition field 2020-05-12 14:03:06 +02:00
Bas van Dijk
c2bc84ddb7 Merge pull request #755 from knl/migrate-tests-to-the-python-DSL
Convert all tests to the Python DSL
2020-05-11 22:11:58 +02:00
Nikola Knezevic
3efa8223c9 Convert all tests to the Python DSL
Since Perl-based NixOS tests will be deprecated in nixpkgs 20.09, this
change migrates all tests to the new Python-based NixOS tests.
2020-05-11 22:05:30 +02:00
Tobias Pflug
41d70395e4 Add hydra OpenAPI description (#750)
* Add swagger config

* Add hydra api info to the README

* hydra.yaml: added some more descriptions

* Add /login

* Add 404/403 responses

* hydra.yaml -> hydra-api.yaml

* Address PR comments

- drop releases/releasename
- document dependency
- document defaultpath

* Fix syntax

* Add project creation

Add `PUT /project/{id}`

* Add /search

* Add "/api/jobsets" endpoint

* Add /api/push endpoint

* Add jobset PUT definition

* Add eval endpoint

* Remove duplicated key

* Fix typo

* Fix structural errors

* fix another error

* Link to hydra-api.yaml from master

* Add openapi yaml validation step to CI
2020-05-11 10:04:46 -04:00
Bas van Dijk
f32a2a48d7 Merge pull request #740 from knl/add-githubrefs-plugin
Add GithubRefs plugin
2020-05-08 13:21:45 +02:00
Eelco Dolstra
88ef3e68a2 Merge pull request #752 from NixOS/remove-releases
Remove the "releases" feature
2020-05-06 18:20:45 +02:00
Eelco Dolstra
96a514c169 Remove the "releases" feature
We haven't used this in many years (it was really only used for nix
and patchelf releases).
2020-05-06 12:39:21 +02:00
Eelco Dolstra
ace30b4184 Merge pull request #749 from lopsided98/localhost-no-remote
Don't distribute localhost builds to other builders
2020-05-04 16:36:53 +02:00
Eelco Dolstra
65819a225d Merge pull request #748 from gilligan/flake-compat-comment
Add comment about edolstra/flake-compat
2020-05-04 16:36:00 +02:00
Ben Wolsieffer
f020f7efef hydra-queue-runner: don't try to distribute builds on localhost 2020-05-03 00:05:52 -04:00
Tobias Pflug
9d80a6de66 Add comment about edolstra/flake-compat
Add a comment to default.nix and shell.nix briefly outlining what
flake-compat/default.nix does.
2020-05-02 18:56:30 +02:00
Graham Christensen
c82f51751d Merge pull request #747 from gilligan/extend-readme
Extend Setup Information
2020-05-02 10:21:51 -04:00
Tobias Pflug
c8c308c0e2 Extend Setup Information
Add information on how to create a minimal setup: project/jobset.
2020-05-02 16:04:20 +02:00
Graham Christensen
fd38524843 Merge pull request #746 from gilligan/add-ci-badge
Add CI badge to README.md
2020-05-02 08:36:38 -04:00
Tobias Pflug
32c35ed6e6 Add CI badge to README.md 2020-05-02 14:29:19 +02:00
Graham Christensen
9f2a7f86b3 Merge pull request #745 from gilligan/remove-png
Remove .png
2020-05-02 08:24:35 -04:00
Tobias Pflug
8400b005f3 Remove .png
File was added to the repo by accident
2020-05-02 14:19:14 +02:00
Graham Christensen
4dcae3100e Merge pull request #744 from gilligan/revamp-readme
Update README
2020-05-01 18:02:25 -04:00
Tobias Pflug
d949726a6e Update README.md
Co-authored-by: Graham Christensen <graham@grahamc.com>
2020-05-01 23:57:22 +02:00
Tobias Pflug
cc7827f57a Update README
Revamp the whole text providing info on

- installation / setup via nixos module
- building via nix-build
- development environment via nix-shell
2020-05-01 23:28:36 +02:00
Eelco Dolstra
028bab462d Merge pull request #738 from ehmry/sotest
Add SoTest plugin
2020-04-28 13:40:50 +02:00
Emery Hemingway
e93c36aab1 SoTest: read credentials from file 2020-04-26 12:12:04 +05:30
Nikola Knezevic
f03e7ef800 Add GithubRefs plugin
This plugin is a counterpart to GithubPulls plugin. Instead of fetching pull
requests, it will fetch all references (branches and tags) that start with a
particular prefix.

The plugin is a copy of GithubPulls plugin with appropriate changes to call the
right API and parse the config matching the need.
2020-04-23 10:45:37 +02:00
Emery Hemingway
a63e349476 Add SoTest plugin
https://opensource.sotest.io/
https://docs.sotest.io/
2020-04-21 15:25:44 +05:30
Eelco Dolstra
87837f1d82 Merge pull request #737 from Ma27/rm-sqlite
Get rid of dependency to SQLite
2020-04-16 00:55:38 +02:00
Maximilian Bosch
16a8b4d086 Re-add DBDSQLite since it's needed by the Perl-bindings of Nix 2020-04-16 00:42:40 +02:00
Maximilian Bosch
721c764951 Remove Hydra::Helper::nix::txn_do from the Perl code
To quote the function's comment:

  Awful hack to handle timeouts in SQLite: just retry the transaction.
  DBD::SQLite *has* a 30 second retry window, but apparently it
  doesn't work.

Since SQLite is now dropped entirely, this wrapper can be removed
completely.
2020-04-16 00:42:40 +02:00
Maximilian Bosch
efcbc08686 Get rid of dependency to SQLite
SQLite isn't properly supported by Hydra for a few years now[1], but
Hydra still depends on it. Apart from a slightly bigger closure this can
cause confusion by users since Hydra picks up SQLite rather than
PostgreSQL by default if HYDRA_DBI isn't configured properly[2]

[1] 78974abb69
[2] https://logs.nix.samueldr.com/nixos-dev/2020-04-10#3297342;
2020-04-16 00:42:40 +02:00
Eelco Dolstra
a42cf35a1c Only run the 'build' test 2020-04-16 00:33:02 +02:00
Eelco Dolstra
b9ec1193d8 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/3e7aab81ce6787e01ea4ced5af1fc6a84e523762' -> 'github:NixOS/nix/3aaceeb7e2d3fb8a07a1aa5a21df1dca6bbaa0ef'
* Updated 'nixpkgs': 'github:NixOS/nixpkgs/b0c285807d6a9f1b7562ec417c24fa1a30ecc31a' -> 'github:NixOS/nixpkgs/29eddfc36d720dcc4822581175217543b387b1e8'
2020-04-09 17:52:02 +02:00
Eelco Dolstra
fe1c21091f Merge pull request #735 from Mic92/github-workflow
add github ci tests
2020-04-09 16:06:34 +02:00
Jörg Thalheim
828f686e83 add github ci tests
To avoid breakages as in: https://github.com/NixOS/hydra/pull/731
2020-04-09 14:55:21 +01:00
Eelco Dolstra
400a0fbd14 lastModified -> lastModifiedDate 2020-04-09 15:44:53 +02:00
Graham Christensen
7b705758ec Merge pull request #732 from Ma27/fix-build
Fix build against latest Nix
2020-04-09 09:02:45 -04:00
Bas van Dijk
d816503814 Merge pull request #733 from basvandijk/fix-build_finished-notifications
Separate the build IDs in the build_finished payload with tabs
2020-04-08 12:27:58 +02:00
Bas van Dijk
6e358189ad Separate the build IDs in the build_finished payload with tabs
hydra-notify splits the payload on tabs so we shouldn't separate the
IDs with spaces.
2020-04-08 12:05:25 +02:00
Maximilian Bosch
2f9d422172 Fix build against latest Nix 2020-04-07 13:55:38 +02:00
Eelco Dolstra
4cabb37ebd Merge pull request #730 from NixOS/flake
Flake support
2020-04-07 11:18:38 +02:00
Eelco Dolstra
62e6c65e68 Merge pull request #703 from kquick/libpqxx_undeprecate
Update libpqxx usage to move away from deprecated API interactions.
2020-04-01 22:04:46 +02:00
Kevin Quick
a055796ef5 Merge branch 'master' into libpqxx_undeprecate 2020-04-01 11:54:41 -07:00
Eelco Dolstra
2d092a6fbc Merge pull request #702 from kquick/fix_api_push
Handle case where jobset has no defined errormsg for api/jobsets
2020-04-01 13:09:05 +02:00
Eelco Dolstra
8564089186 Merge pull request #707 from basvandijk/fix-aggregate-status
Fix printing aggregate status
2020-04-01 13:04:53 +02:00
Eelco Dolstra
6c0bb909df Merge pull request #704 from basvandijk/sleep-after-catch-exception
hydra-queue-runner: sleep 5s after handling an exception
2020-04-01 13:04:31 +02:00
Eelco Dolstra
9668bc01da Merge pull request #726 from knl/document-slack-notifications-plugin
Document SlackNotifications plugin
2020-04-01 13:04:00 +02:00
Eelco Dolstra
681d84da0f Merge remote-tracking branch 'origin/master' into flake 2020-03-31 22:36:36 +02:00
Eelco Dolstra
53e1294825 Fix Mercurial tests
In Nixpkgs 20.03, Mercurial fails if PYTHONPATH is set:

  $ hg
  Traceback (most recent call last):
    File "/nix/store/q7s856v6nw4dffdrm9k3w38qs35i8kr3-mercurial-5.2.2/bin/..hg-wrapped-wrapped", line 37, in <module>
      dispatch.run()
    File "/nix/store/bffdy7q3wi3qinflnvbdkigqj39zzynd-python3-3.7.6/lib/python3.7/importlib/util.py", line 245, in __getattribute__
      self.__spec__.loader.exec_module(self)
    File "<frozen importlib._bootstrap_external>", line 728, in exec_module
    File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
    File "/nix/store/q7s856v6nw4dffdrm9k3w38qs35i8kr3-mercurial-5.2.2/lib/python3.7/site-packages/mercurial/dispatch.py", line 10, in <module>
      import difflib
    File "/nix/store/bffdy7q3wi3qinflnvbdkigqj39zzynd-python3-3.7.6/lib/python3.7/difflib.py", line 1084, in <module>
      import re
    File "/nix/store/bffdy7q3wi3qinflnvbdkigqj39zzynd-python3-3.7.6/lib/python3.7/re.py", line 143, in <module>
      class RegexFlag(enum.IntFlag):
  AttributeError: module 'enum' has no attribute 'IntFlag'

(cherry picked from commit 4009d4295e)
2020-03-31 22:19:19 +02:00
Eelco Dolstra
9727892b61 Don't spam the journal with hydra-queue-runner status dumps
(cherry picked from commit 15ae932488)
2020-03-31 22:19:07 +02:00
Eelco Dolstra
ccd046ca3d Keep track of the number of unsupported steps
(cherry picked from commit 45ffe578b6)
2020-03-31 22:19:03 +02:00
Eelco Dolstra
4417f9f260 Abort unsupported build steps
If we don't see machine that supports a build step for
'max_unsupported_time' seconds, the step is aborted. The default is 0,
which is appropriate for Hydra installations that don't provision
missing machines dynamically.

(cherry picked from commit f5cdbfe21d)
2020-03-31 22:19:01 +02:00
Eelco Dolstra
68a59f34a0 Remove tabs
(cherry picked from commit 5b731004da)
2020-03-31 22:18:58 +02:00
Eelco Dolstra
8b5900ac33 Remove outdated email address
(cherry picked from commit 22a65d0269)
2020-03-31 22:18:46 +02:00
Eelco Dolstra
d1f367f657 Add default.nix, shell.nix for compatibility 2020-03-31 16:07:46 +02:00
Eelco Dolstra
4009d4295e Fix Mercurial tests
In Nixpkgs 20.03, Mercurial fails if PYTHONPATH is set:

  $ hg
  Traceback (most recent call last):
    File "/nix/store/q7s856v6nw4dffdrm9k3w38qs35i8kr3-mercurial-5.2.2/bin/..hg-wrapped-wrapped", line 37, in <module>
      dispatch.run()
    File "/nix/store/bffdy7q3wi3qinflnvbdkigqj39zzynd-python3-3.7.6/lib/python3.7/importlib/util.py", line 245, in __getattribute__
      self.__spec__.loader.exec_module(self)
    File "<frozen importlib._bootstrap_external>", line 728, in exec_module
    File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
    File "/nix/store/q7s856v6nw4dffdrm9k3w38qs35i8kr3-mercurial-5.2.2/lib/python3.7/site-packages/mercurial/dispatch.py", line 10, in <module>
      import difflib
    File "/nix/store/bffdy7q3wi3qinflnvbdkigqj39zzynd-python3-3.7.6/lib/python3.7/difflib.py", line 1084, in <module>
      import re
    File "/nix/store/bffdy7q3wi3qinflnvbdkigqj39zzynd-python3-3.7.6/lib/python3.7/re.py", line 143, in <module>
      class RegexFlag(enum.IntFlag):
  AttributeError: module 'enum' has no attribute 'IntFlag'
2020-03-31 13:33:11 +02:00
Eelco Dolstra
f6119f2b19 perlDeps: Use lib.closePropagation
Apparentely, buildEnv in 20.03 no longer respects
propagated-build-inputs.

Note that the use of a library function (closePropagation) seems
fundamentally wrong to me - propagated-build-inputs should be used at
runtime, not at evaluation time.
2020-03-31 13:21:01 +02:00
Eelco Dolstra
22a65d0269 Remove outdated email address 2020-03-31 12:58:24 +02:00
Eelco Dolstra
810075cd3d Update to 20.03 2020-03-31 12:55:35 +02:00
Eelco Dolstra
05bf278971 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/4ad5826a182f8eeb4cbc61e27d2128b08050b0d4' -> 'github:NixOS/nix/3e7aab81ce6787e01ea4ced5af1fc6a84e523762'
* Updated 'nix/nixpkgs': 'github:edolstra/nixpkgs/43e283790fbe330b723ac44b584824cf6d85c1ee' -> 'github:NixOS/nixpkgs/b88ff468e9850410070d4e0ccd68c7011f15b2be'
* Updated 'nixpkgs': 'github:edolstra/nixpkgs/d959778e0934c4c93896d509a65de798909c7cdd' -> 'github:NixOS/nixpkgs/b0c285807d6a9f1b7562ec417c24fa1a30ecc31a'
2020-03-31 12:55:07 +02:00
Samuel Dionne-Riel
7889aef792 hydra-eval-jobs: Mirror eval errors in STDERR
Otherwise, errors will not be shown to end-users, which makes debugging
long evals pretty much impossible.

(cherry picked from commit 76299b9174)
2020-03-31 12:48:33 +02:00
Eelco Dolstra
082dbdb922 Merge pull request #729 from samueldr/fix/error-transmission
hydra-eval-jobs: Mirror eval errors in STDERR
2020-03-31 09:04:32 +02:00
Samuel Dionne-Riel
76299b9174 hydra-eval-jobs: Mirror eval errors in STDERR
Otherwise, errors will not be shown to end-users, which makes debugging
long evals pretty much impossible.
2020-03-30 16:11:44 -04:00
Eelco Dolstra
a7540b141d Merge pull request #727 from NixOS/fail-unsupported
Abort unsupported build steps
2020-03-27 09:45:11 +01:00
Eelco Dolstra
15ae932488 Don't spam the journal with hydra-queue-runner status dumps 2020-03-26 15:30:37 +01:00
Eelco Dolstra
45ffe578b6 Keep track of the number of unsupported steps 2020-03-26 15:27:13 +01:00
Eelco Dolstra
f5cdbfe21d Abort unsupported build steps
If we don't see machine that supports a build step for
'max_unsupported_time' seconds, the step is aborted. The default is 0,
which is appropriate for Hydra installations that don't provision
missing machines dynamically.
2020-03-26 15:00:04 +01:00
Eelco Dolstra
5b731004da Remove tabs 2020-03-26 14:59:52 +01:00
Nikola Knezevic
1bee6e3d8a Add debug logging
This will help us track potential problems with the plugin.
2020-03-26 13:27:44 +01:00
Nikola Knezevic
986fde8888 Refactor code
Extract the conditions before the loop, as they do not change due to channel
definition.
2020-03-26 13:27:44 +01:00
Nikola Knezevic
956f009672 Add documentation for SlackNotification plugin 2020-03-26 13:27:44 +01:00
Eelco Dolstra
d0688b93e1 Merge remote-tracking branch 'origin/master' into flake 2020-03-26 11:44:11 +01:00
Graham Christensen
12cc46cdb3 fixup: hydra-init: correct reference to hydra-backill-ids 2020-03-24 11:22:14 -04:00
Eelco Dolstra
c85ee736a4 Merge pull request #724 from Ma27/different-icons-for-timeout-and-loglimit
Use the stopsign as icon for timeouts and exceeded log-limits
2020-03-23 09:39:04 +01:00
Maximilian Bosch
73694087a0 Use the stopsign as icon for timeouts and exceeded log-limits
When I browse failed builds in a jobset-eval on Hydra, I regularly
mistake actual build-failures with temporary issues like timeouts (that
probably disappear at the next eval).

To prevent this kind of issue, I figured that using the stopsign-svg for
builds with timeouts or exceeded log-limits is a reasonable choice for
the following reasons:

* A user can now distinguish between actual build-errors (like
  compilation-failures or oversized outputs) and (usually) temporary issues
  (like a bloated log or a timeout).

* The stopsign is also used for aborted jobs that are shown in a
  different tab and can't be confused with timeouts for that reason.
2020-03-21 21:08:33 +01:00
Eelco Dolstra
5ae8b54d25 README.md: Link to the latest manual
(cherry picked from commit 455611b0b4e97290a858687142805babc9929673)
2020-03-13 21:33:22 +01:00
Eelco Dolstra
be0ec2d223 Remove style.css
https://github.com/NixOS/nix/issues/3392
2020-03-13 16:17:48 +01:00
Nikola Knezevic
01ae944c80 Add host tag to InfluxDB metrics
This should help us discern machines in environments with multiple Hydra deployments.
2020-03-12 14:23:07 +01:00
Eelco Dolstra
101a9b3797 Run 'make check'
This got lost when I converted from releaseTools.nixBuild to
stdenv.mkDerivation. Doh!
2020-03-04 15:42:51 +01:00
Eelco Dolstra
4b5bb4e760 Merge remote-tracking branch 'origin/master' into flake 2020-03-04 15:28:23 +01:00
Eelco Dolstra
123bee1db5 Restore job type checking 2020-03-04 15:16:26 +01:00
Eelco Dolstra
69a6f3448a Fix calling job functions
Fixes #718.
2020-03-04 15:16:04 +01:00
Eelco Dolstra
3cc1deb125 Merge pull request #721 from grahamc/one-by-one
hydra-evaluator: add a 'ONE_AT_A_TIME' evaluator style
2020-03-04 08:44:43 +01:00
Eelco Dolstra
e6e4aa54c0 Merge pull request #722 from grahamc/fix-declarative-jobsets
Fix declarative jobsets due to `nix` command being hidden
2020-03-04 08:41:13 +01:00
Graham Christensen
994430b94b treewide: allow nix command 2020-03-03 22:52:20 -05:00
Graham Christensen
117b9ecef1 Nix.pm: readNixFile: pass «--experimental-features nix-command»
Declarative jobsets were broken by the Nix update, causing
nix cat-file to break silently.

This commit restores declarative jobsets, based on top of a commit
making it easier to see what broke.
2020-03-03 22:36:21 -05:00
Graham Christensen
113a312f67 handleDeclarativeJobsetBuild: handle errors from readNixFile 2020-03-03 22:32:13 -05:00
Graham Christensen
5fae9d96a2 hydra-evaluator: add a 'ONE_AT_A_TIME' evaluator style
In the past, jobsets which are automatically evaluated are evaluated
regularly, on a schedule. This schedule means a new evaluation is
created every checkInterval seconds (assuming something changed.)

This model works well for architectures where our build farm can
easily keep up with demand.

This commit adds a new type of evaluation, called ONE_AT_A_TIME, which
only schedules a new evaluation if the previous evaluation of the
jobset has no unfinished builds.

This model of evaluation lets us have 'low-tier' architectures.

For example, we could now have a jobset for ARMv7l builds, where
the buildfarm only has a single, underpowered ARMv7l builder.
Configuring that jobset as ONE_AT_A_TIME will create an evaluation
and then won't schedule another evaluation until every job of
the existing evaluation is complete.

This way, the cache will have a complete collection of pre-built
software for some commits, but the underpowered architecture will
never become backlogged in ancient revisions.
2020-03-03 19:28:44 -05:00
Graham Christensen
eaa65f51f4 hydra-evaluator: make the logic of the scheduler easier to read 2020-03-03 18:17:21 -05:00
Eelco Dolstra
eb5873ae53 Fix build 2020-02-20 11:19:45 +01:00
Eelco Dolstra
c642f787ee hydra-eval-jobs: Parallelize
(cherry picked from commit be8eb9d00d)
2020-02-20 10:28:58 +01:00
Eelco Dolstra
adf61e5cf8 Fix build
(cherry picked from commit 639c660abf)
2020-02-20 10:26:45 +01:00
Eelco Dolstra
5308e514ad Fix nlohmann_json dependency 2020-02-20 10:26:18 +01:00
Eelco Dolstra
e4f5156c41 Build against nix-master
(cherry picked from commit e7f2139e25)
2020-02-20 10:24:04 +01:00
Eelco Dolstra
b790a00729 Disable deprecation warnings
(cherry picked from commit 950e8bef6c)
2020-02-20 10:22:21 +01:00
Eelco Dolstra
2a50daa377 Update aggregate handling
(cherry picked from commit cf961ac893)
2020-02-20 10:13:39 +01:00
Eelco Dolstra
15187b059b Remove hydra-eval-guile-jobs
This hasn't been used in a long time (Guix uses its own CI system),
and it probably doesn't work anymore.

(cherry picked from commit 23c9ca3e94)
2020-02-20 09:58:12 +01:00
Eelco Dolstra
be8eb9d00d hydra-eval-jobs: Parallelize 2020-02-19 21:10:22 +01:00
Eelco Dolstra
c53cfb5234 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/6529490cc10018d5191e50c482ac1180b96b1a3c' -> 'github:NixOS/nix/4ad5826a182f8eeb4cbc61e27d2128b08050b0d4'
2020-02-19 20:37:14 +01:00
Eelco Dolstra
6f1d68bda4 Revert "hydra-eval-jobs -> nix eval-hydra-jobs"
This reverts commit 345512a6d0.
2020-02-19 20:36:52 +01:00
Eelco Dolstra
cf961ac893 Update aggregate handling 2020-02-17 16:33:25 +01:00
Eelco Dolstra
4824b0fd9b flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/144bb3ef7ddca6502ea3e1878f7fc0a3f9013aba' -> 'github:NixOS/nix/6529490cc10018d5191e50c482ac1180b96b1a3c'
2020-02-17 16:23:39 +01:00
Eelco Dolstra
4b9cdc4933 Remove boehmgc dependency
This is now propagated by Nix.
2020-02-15 21:56:35 +01:00
Eelco Dolstra
b0a5365602 flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/eb19ff3b82240326fc0e999e09f81b6c8ed98640' -> 'github:NixOS/nix/144bb3ef7ddca6502ea3e1878f7fc0a3f9013aba'
2020-02-15 21:55:33 +01:00
Eelco Dolstra
68bdf834ee Fix hydra-evaluator --unlock 2020-02-15 16:40:16 +01:00
Eelco Dolstra
345512a6d0 hydra-eval-jobs -> nix eval-hydra-jobs 2020-02-15 15:59:34 +01:00
Eelco Dolstra
23c9ca3e94 Remove hydra-eval-guile-jobs
This hasn't been used in a long time (Guix uses its own CI system),
and it probably doesn't work anymore.
2020-02-15 15:59:34 +01:00
Eelco Dolstra
639c660abf Fix build 2020-02-15 14:54:35 +01:00
Eelco Dolstra
93ed7f81cb flake.lock: Update
Flake input changes:

* Updated 'nix': 'github:NixOS/nix/d2032edb2f86e955a8a7724a27c0c3225f386500' -> 'github:NixOS/nix/eb19ff3b82240326fc0e999e09f81b6c8ed98640'
2020-02-14 23:26:56 +01:00
Graham Christensen
ae1b9face3 Merge remote-tracking branch 'origin/master' into flake 2020-02-11 12:52:46 -05:00
Graham Christensen
027668f0db hydra.sql: add an index for slow queries in production
These queries used to use (jobset, project) based indexes,
and the addition of jobset_id makes most of those indexes
unusable now.
2020-02-11 12:52:28 -05:00
Graham Christensen
53896ff19b Merge remote-tracking branch 'origin/master' into flake 2020-02-11 08:36:40 -05:00
Graham Christensen
834793468f fixup: d'oh, make the migrations from #710 part-2 sequential 2020-02-11 08:36:14 -05:00
Eelco Dolstra
881b7449fd Merge remote-tracking branch 'origin/master' into flake 2020-02-11 14:23:16 +01:00
Eelco Dolstra
0dbf0a361e Merge pull request #714 from grahamc/jobset-id-pgsql-part-2
Jobset id pgsql part 2
2020-02-11 13:51:17 +01:00
Graham Christensen
2637a7ad76 Builds: index literally what latest-finished queries 2020-02-11 07:06:21 -05:00
Graham Christensen
f0f41eaaff LatestSucceededForJob{,set}: Filter with jobset_id 2020-02-11 07:06:20 -05:00
Graham Christensen
66fbbd9692 Jobs.builds: Fetch via Jobs.jobset_id 2020-02-11 07:06:20 -05:00
Graham Christensen
7c71f9df28 Jobsets.builds: Fetch via Jobsets.id 2020-02-11 07:06:20 -05:00
Graham Christensen
3c392b8cd8 Jobsets.jobs: Fetch via Jobsets.id 2020-02-11 07:06:20 -05:00
Graham Christensen
8ef08f1385 Builds.jobset_id: make not-null 2020-02-11 07:06:20 -05:00
Graham Christensen
2cdcc7f188 Jobs.jobset_id: make not-null 2020-02-11 07:06:17 -05:00
Eelco Dolstra
100e09a5b3 Merge remote-tracking branch 'origin/master' into flake
Also update flake.lock
2020-02-10 17:58:10 +01:00
Graham Christensen
add4f610ce Merge pull request #711 from grahamc/jobset-id-pgsql-part-1
jobset_id, #710 Part 1
2020-02-10 11:43:38 -05:00
Graham Christensen
c4cc72f944 hydra-init: Warn about the schema version migration 2020-02-10 11:43:03 -05:00
Graham Christensen
f69260118b hydra-backfill-ids: create to add jobset_id values to Builds and Jobs
Vacuum every 10 iterations, update 10k at a time.
2020-02-10 11:43:03 -05:00
Graham Christensen
f3a561aecd Builds: populate Builds.jobset_id in hydra-eval-jobset 2020-02-10 11:43:02 -05:00
Graham Christensen
ddf00fa627 Builds: add a nullable jobset_id foreign key to Jobsets.
Also, adds an explicitly named "builds" accessor to the Jobsets
Schema object, which uses the project/jobset name.
2020-02-10 11:43:02 -05:00
Graham Christensen
624f1d8d2d Jobs: populate Jobs.jobset_id field when writing from hydra-eval-jobset 2020-02-10 11:43:02 -05:00
Graham Christensen
efa1f1d4fb Jobs: add a nullable jobset_id foreign key to Jobsets.
Also, adds an explicitly named "jobs" accessor to the Jobsets
Schema object, which uses the project/jobset name.
2020-02-10 11:43:02 -05:00
Graham Christensen
e00030563b Jobsets: add a SERIAL, unique, non-null id column
A postgresql column which is non-null and unique is treated with
the same optimisations as a primary key, so we have no need to
try and recreate the `id` as the primary key.

No read paths are impacted by this change, and the database will
automatically create an ID for each insert. Thus, no code needs to
change.
2020-02-10 11:42:59 -05:00
Eelco Dolstra
4a05bb36ac Merge pull request #713 from grahamc/backport-flake-migration
Copy the flake migration from the flake branch
2020-02-10 17:41:46 +01:00
Graham Christensen
6fe57ab5fa Copy the flake migration from the flake branch
hydra.nixos.org is already running this rev, and it should be safe to
apply to everyone else. If we make changes to this migration, we'll
need to write another migration anyway.
2020-02-09 15:21:28 -05:00
Eelco Dolstra
2b4f14963b Merge pull request #709 from grahamc/generate-from-postgresql
sql: Generate models from postgresql
2020-02-06 20:18:31 +01:00
Graham Christensen
c2f932a7e3 sql: Generate models from postgresql
Lowercasing is due to postgresql not having case-sensitive table names.
It always technically workde before, but those table names never
existed literally.

The switch to generating from postgresql is to handle an upcoming
addition of an auto-incrementign ID to the Jobset table. Sqlite doesn't
seem to be able to handle the table having an auto incrementing ID
field which isn't the primary key, but we can't change the primary
key trivially.

Since hydra doesn't support sqlite and hasn't for many year anyway,
it is easier to just generate from pgsql directly.
2020-02-06 12:23:47 -05:00
Eelco Dolstra
ba8814a245 Fix build 2020-02-03 18:43:45 +01:00
Eelco Dolstra
d1bc950de2 Doh 2020-02-03 18:38:05 +01:00
Eelco Dolstra
f0e8e56f89 Update flake.lock 2020-02-03 18:14:06 +01:00
Eelco Dolstra
bb94677526 Merge remote-tracking branch 'origin/master' into flake 2020-02-03 17:49:01 +01:00
Eelco Dolstra
9da60e3c66 Merge pull request #708 from basvandijk/remove-logdiff-button
Remove the "log diff" buttons
2020-01-27 14:36:56 +01:00
Bas van Dijk
5fab5e935b Remove the "log diff" buttons
because they're referencing the removed `logdiff` API.

This API was removed in 4d1816b152.

Fixes #409
2020-01-26 21:45:38 +01:00
Bas van Dijk
bd9b656c54 Fix printing aggregate status
`nrMembers` is undefined and it should have clearly be `nrConstituents`
which is calculated just before.

Fixes #693.
2020-01-26 20:15:18 +01:00
Kevin Quick
cdd9d6e071 Update haserrormsg logic implementation. 2020-01-20 10:40:33 -08:00
Bas van Dijk
08bfff9d13 hydra-queue-runner: sleep 5s after handling an exception
instead of immediately calling `readMachinesFiles` again which could
immediately throw another exception again.
2020-01-14 13:34:35 +01:00
Kevin Quick
ec8b2970e0 Remove added strictness to allow multiple query returns. 2020-01-12 10:18:52 -08:00
Kevin Quick
7bb6b5e206 Update libpqxx usage to move away from deprecated API interactions. 2020-01-11 22:38:40 -08:00
Kevin Quick
de24771a8e Handle case where jobset has no defined errormsg for api/jobsets 2020-01-11 17:01:44 -08:00
Eelco Dolstra
5c0c7d52a0 Merge pull request #700 from hamishmack/master
Fixes for macOS
2020-01-07 11:38:34 +01:00
Hamish Mackenzie
c40c887e50 Fixes for macOS
Building on macOS with the latest nixpkgs master and NixOS/nixpkgs#77147
fails.  It seems some `std::experimental` (optional) for instance are
not available as `experimental`, but are in `std`.  Also `toJSON` is
missing for `atomic< unsigned long long >`.
2020-01-07 12:38:06 +13:00
Eelco Dolstra
e7f2139e25 Build against nix-master 2019-12-30 22:49:26 +01:00
Graham Christensen
5cac40a438 Merge remote-tracking branch 'origin/master' into flake 2019-12-29 16:37:25 -05:00
Graham Christensen
d0f1bda0b8 job prometheus endpoint: drop nixname, too variable 2019-12-29 16:37:13 -05:00
Graham Christensen
d24de1b5de Merge remote-tracking branch 'origin/master' into flake 2019-12-28 20:58:03 -05:00
Graham Christensen
64cdc3413c job prometheus endpoint: d'oh 2019-12-28 20:57:27 -05:00
Graham Christensen
511c2db8aa Merge remote-tracking branch 'origin/master' into flake 2019-12-28 20:22:54 -05:00
Graham Christensen
f8875f2d68 Merge pull request #699 from grahamc/job-prom
job: create a prometheus endpoint
2019-12-28 20:22:24 -05:00
Graham Christensen
d5445bfc1d job: create a prometheus endpoint
Export the most recent stop time and exit status in
a prometheus-friendly format.
2019-12-28 16:41:49 -05:00
Eelco Dolstra
20dd0bbe6a Merge pull request #691 from knl/fix-missing-notification-stats
hydra-send-stats: Cleanup removed metrics
2019-11-13 11:49:32 +01:00
Nikola Knezevic
06abfd6b2f hydra-send-stats: Cleanup removed metrics
In 2946899504 these metrics got removed
due to refactoring of how notifications work.
2019-11-13 11:42:58 +01:00
Eelco Dolstra
4779757683 Update flake.lock 2019-11-08 15:45:21 +01:00
Eelco Dolstra
9e0e625bfa Update flake.lock 2019-11-08 14:41:13 +01:00
Eelco Dolstra
4c8f600eaa Update to latest Nix and fix compilation 2019-11-07 23:16:05 +01:00
Eelco Dolstra
1784c362ed Simplify flake.nix 2019-11-07 18:46:32 +01:00
Eelco Dolstra
55b0afa08f Merge remote-tracking branch 'origin/master' into flake 2019-11-07 18:42:15 +01:00
Graham Christensen
e89ea733d0 Merge pull request #687 from andir/more-roles
Add `cancel-build` & `bump-to-front` roles
2019-11-07 17:52:58 +01:00
Andreas Rammhold
841a47cabe Add cancel-build role 2019-11-05 22:56:01 +01:00
Andreas Rammhold
ce1e10c116 Add bump-to-front role 2019-11-05 19:32:06 +01:00
Eelco Dolstra
45f8a0ef66 Merge pull request #686 from basvandijk/remove-unused-firstOutput
hydra-eval-jobset: $firstOutput is not used so can be removed
2019-11-05 14:09:54 +01:00
Bas van Dijk
840e99f859 hydra-eval-jobset: $firstOutput is not used so can be removed 2019-11-05 13:58:40 +01:00
Eelco Dolstra
c7d1d34547 Merge pull request #683 from dasJ/flake
Fix declarative flake builds
2019-10-27 16:53:44 +01:00
Janne Heß
6f99d958bc Fix declarative flake builds 2019-10-27 14:57:53 +01:00
Eelco Dolstra
26ea7e493d Update flake.lock 2019-10-23 21:32:37 +02:00
Eelco Dolstra
a816730d8b uri -> url 2019-10-23 20:31:27 +02:00
Eelco Dolstra
43d4bc9108 Fix reproduction instructions 2019-10-23 16:29:12 +02:00
Eelco Dolstra
7ba06c13ac Bump flake dependencies 2019-10-22 20:19:40 +02:00
Eelco Dolstra
551e936fac Update flake.nix
Currently Hydra is only supported on x86_64-linux.
2019-10-15 20:21:42 +02:00
Eelco Dolstra
4b28068925 Update flake.lock 2019-10-04 21:43:59 +02:00
Eelco Dolstra
80738fadb1 Add hydraProxy module 2019-10-04 21:31:27 +02:00
Eelco Dolstra
d0b972bdd0 Use the overlay from the nix flake 2019-10-04 17:32:29 +02:00
Eelco Dolstra
8d2896b36b epoch -> edition 2019-09-26 18:35:00 +02:00
Eelco Dolstra
037f6488f6 Merge pull request #680 from grahamc/prometheus
export a /prometheus endpoint
2019-09-25 19:46:42 +02:00
Eelco Dolstra
7c6fd83dda Merge remote-tracking branch 'origin/master' into flake 2019-09-25 17:28:00 +02:00
Eelco Dolstra
d4b4255dd2 hydra-queue-runner: Support running in a NixOS container
In a NixOS container, cmdBuildDerivation doesn't work because we're
not privileged. But we also don't need it because the store already
has the derivation.

Also, don't copy from/to the store since this gives errors about
missing signatures.
2019-09-25 17:26:03 +02:00
Eelco Dolstra
554bb7d9ce hydra-queue-runner: Don't pass IN_SYSTEMD to child processes
This caused local builds to have journal priority prefixes
(e.g. '<3>').
2019-09-25 17:25:07 +02:00
Graham Christensen
3a04f28459 hydra: upgrade nixpkgs to 19.09 2019-09-24 16:51:18 -04:00
Graham Christensen
937e165328 export a /prometheus endpoint
Currently only shows per-machine build times
2019-09-24 16:50:52 -04:00
Eelco Dolstra
e110d5a38f Build the container in Hydra 2019-09-24 21:48:28 +02:00
Eelco Dolstra
40e7b6e884 Add a NixOS container to demo Hydra
It contains Hydra, PostgreSQL and an frontend proxy. So you can get a
running Hydra instance by doing

  $ nixos-container create hydra --flake hydra
  $ nixos-container start hydra

The web interface is available on port 80.
2019-09-24 19:58:10 +02:00
Eelco Dolstra
0ccf36ca3b Merge remote-tracking branch 'origin/master' into flake 2019-09-24 19:03:18 +02:00
Eelco Dolstra
4223202c99 Merge pull request #432 from LumiGuide/better-buildMachinesFiles-default
Only set buildMachinesFiles when nix.buildMachines is defined
2019-09-24 19:00:32 +02:00
Eelco Dolstra
1ab3b26b67 Update lock file 2019-09-19 00:10:12 +02:00
Eelco Dolstra
66d71689ec flake.nix improvements
The hydra flake now exports a Nixpkgs overlay and a NixOS module.
2019-09-17 17:25:59 +02:00
Eelco Dolstra
ada640d340 Update flake.nix 2019-08-30 17:23:10 +02:00
Eelco Dolstra
242b8b7a31 Merge pull request #676 from knl/fix-term-size-any-log-message
Add Term::Size::Any
2019-08-30 14:17:12 +02:00
Nikola Knezevic
a9d744d2a3 Add Term::Size::Any
This removes a supper annoying set of messages that polute the logs:

    Aug 30 09:00:30 xxx.compute.internal hydra-server[957]: Trouble trying to detect your terminal size, looking at $ENV{COLUMNS}
    Aug 30 09:00:30 xxx.compute.internal hydra-server[957]: Term::Size::Any is not installed, can't autodetect terminal column width
2019-08-30 11:58:24 +02:00
Graham Christensen
906d2493c5 Merge pull request #673 from nlewo/jobset-error
Add error boolean attribute to jobset API response
2019-08-26 10:23:52 -04:00
Antoine Eiche
c8983ca076 Add haserrormsg boolean attribute to jobset API response
This attribute allows to know if an error occurred or not: when an
error occurs, errormsg is not an empty string. Note we can not use the
errormsg attribute because it can be arbitrarily long and is excluded
from the jobset API response.
2019-08-26 16:07:49 +02:00
Rob Vermaas
f10b2c2da8 Update Hydra schema, otherwise hydra-notify will not work. 2019-08-19 17:05:11 +02:00
Eelco Dolstra
89ee74f1e3 Merge pull request #672 from gilligan/extend-jobset-api-response
Extend the jobset API response
2019-08-16 19:39:57 +02:00
tobias pflug
919195b04f Extend the jobset API response
This adds the following (pre-existing) attributes to the jobset response:

- nrtotal
- lastcheckedtime
- starttime
- checkinterval
- triggertime
- fetcherrormsg
- errortime
2019-08-16 16:04:04 +02:00
Eelco Dolstra
2de52d8538 Merge remote-tracking branch 'origin/master' into flake 2019-08-15 13:56:00 +02:00
Eelco Dolstra
c8a4030c5f Fix error in GitlabStatus plugin
May 15 09:20:10 chef hydra-queue-runner[27523]: Hydra::Plugin::GitlabStatus=HASH(0x519a7b8)->buildFinished: Can't call method "value" on an undefined value at /nix/store/858hinflxcl2jd12wv1r3a8j11ybsf6w-hydra-0.1.2629.89fa829/libexec/hydra/lib/Hydra/Plugin/GitlabStatus.pm line 57.

(cherry picked from commit 438ddf5289)
2019-08-15 13:55:47 +02:00
Eelco Dolstra
f17cd94bac Merge pull request #668 from NixOS/notifications
Turn hydra-notify into a daemon
2019-08-14 13:05:56 +02:00
Eelco Dolstra
92d8d6baa5 Avoid fetching Projects/Jobsets just to get the name column
In particular, doing a 'select * from Jobsets where ...' must be
avoided, because the 'errormsg' column can be very big.
2019-08-13 18:18:25 +02:00
Eelco Dolstra
16811d3e78 Plugins: Add isEnabled method
Plugins are now disabled at startup time unless there is some relevant
configuration in hydra.conf. This avoids hydra-notify having to do a
lot of redundant work (a lot of plugins did a lot of database queries
*before* deciding they were disabled).

Note: BitBucketStatus users will need to add 'enable_bitbucket_status
= 1' to hydra.conf.
2019-08-13 18:18:25 +02:00
Eelco Dolstra
f49a089fc0 hydra-notify: Don't do an unnecessary fetch of Jobsets 2019-08-13 18:18:24 +02:00
Eelco Dolstra
e2537f741b Restart hydra-notify 2019-08-13 18:18:24 +02:00
Eelco Dolstra
d08cfa48d7 Add a 'step_started' notification 2019-08-13 18:18:24 +02:00
Eelco Dolstra
72c36373bb hydra-notify: Fix processing notifications 2019-08-13 18:18:24 +02:00
Eelco Dolstra
7c7cc8c059 Fix duplicate step_finished notification 2019-08-13 18:18:24 +02:00
Eelco Dolstra
976d88d675 Send notifications when evaluations start/finish/fail
* 'eval_started' has the format '<tmpId>\t<project>\t<jobset>'.

* 'eval_failed' has the format '<tmpId>'. (The cause of the error can
  be found in the database.)

* 'eval_added' has the format '<tmpId>:<evalId>'.
2019-08-13 18:18:24 +02:00
Eelco Dolstra
7114d2aceb Separate payload elements using \t 2019-08-13 18:18:24 +02:00
Eelco Dolstra
c7861b85c4 Add hydra-notify service 2019-08-13 18:18:24 +02:00
Eelco Dolstra
2946899504 Turn hydra-notify into a daemon
It now receives notifications about started/finished builds/steps via
PostgreSQL. This gets rid of the (substantial) overhead of starting
hydra-notify for every event. It also allows other programs (even on
other machines) to listen to Hydra notifications.
2019-08-13 18:18:21 +02:00
Eelco Dolstra
1c9e22e73c Use nixFlakes in devShell 2019-08-09 13:10:50 +02:00
Eelco Dolstra
a74dec6fb1 Merge remote-tracking branch 'origin/master' into flake 2019-08-09 12:46:52 +02:00
Eelco Dolstra
f13a2cb6dc Merge pull request #666 from craigem/you_look
Corrected grammar typo
2019-08-09 12:12:32 +02:00
Craige McWhirter
bb4f349161 Corrected grammer typo
Replaced you with look
2019-08-09 13:49:21 +10:00
Eelco Dolstra
9ec258dd4d Merge pull request #665 from basvandijk/influxdb
Added the InfluxDBNotification plugin including a NixOS test
2019-07-26 17:57:08 +02:00
Nikola Knezevic
06bdc8f85c Added the InfluxDBNotification plugin including a NixOS test
This adds a `InfluxDBNotification` plugin which is configured as:

```
<influxdb>
  url = http://127.0.0.1:8086
  db = hydra
</influxdb>
```

which will write a notification for every finished job to the
configured database in InfluxDB looking like:

```
hydra_build_status,cached=false,job=job,jobset=default,project=sample,repo=default,result=success,status=success,system=x86_64-linux build_id="1",build_status=0i,closure_size=584i,duration=0i,main_build_id="1",queued=0i,size=168i 1564156212
```
2019-07-26 17:47:03 +02:00
Eelco Dolstra
5e9439e774 Merge pull request #657 from nlewo/create-pg-trgm-in-module
Create `pg_trgm` extension in the NixOS module
2019-07-25 17:48:45 +02:00
Antoine Eiche
8a0a5ec3a3 Create extension pg_trgm in the NixOS module
The creation of the `pg_trgm` extension needs superuser power. So,
this patch makes the extension creation in the Hydra NixOS module when
a local database is used.

If it is not possible to create this extension (remote database for
instance with nosuperuser), the creation of the `pg_trgm` index is
skipped (this index speedup queries on builds.drvpath) and warnings
are emitted:

    initialising the Hydra database schema...
    WARNING:  Can not create extension pg_trgm: permission denied to create extension "pg_trgm"
    WARNING:  HINT: Temporary provide superuser role to your Hydra Postgresql user and run the script src/sql/upgrade-57.sql
    WARNING:  The pg_trgm index on builds.drvpath has been skipped (slower complex queries on builds.drvpath)

This allows to keep smooth migrations: the migration process doesn't
require a manual step (but this manual step is recommended on big
remote databases).
2019-07-25 16:19:33 +02:00
Antoine Eiche
42784a9053 sql: refactor some sql statements to lowercase 2019-07-25 16:19:33 +02:00
Graham Christensen
8c9aec5f12 Merge pull request #658 from nlewo/fix-test-api
test.api: use Hydra perl dependencies to run `api-test.pl`
2019-07-24 10:56:19 -04:00
Antoine Eiche
c620bc2be0 test.api: use Hydra perl dependencies to run api-test.pl
The test was failing with:

    machine# Can't locate LWP/UserAgent.pm in @INC (you may need to install the LWP::UserAgent module)...
2019-06-21 16:57:12 +02:00
Eelco Dolstra
c85bf668e6 Merge pull request #656 from nlewo/search-limit-param
hydra-server: add limit parameter on search path
2019-06-19 16:45:51 +02:00
Antoine Eiche
d1e590af1f hydra-server: add limit parameter to the search path
This allows a client to set a limit to the search results it wants to
get:

    http://hydra.nixos.org/search?query=emacs&limit=1

This returns only 1 results (while the default is 500).
2019-06-19 14:30:32 +02:00
Antoine Eiche
cb1fce21ba hydra-server: set a limit on builds and buildoutputs search
This patch adds a limit statement for Postgresql queries on `builds`
and `buildsoutputs` tables.
2019-06-19 14:28:55 +02:00
Eelco Dolstra
d834ac9c14 Update flake.{nix,lock} 2019-06-18 18:00:40 +02:00
Eelco Dolstra
2b4658b6ea Merge pull request #654 from nlewo/lewo-search-by-hash
Allow to search builds by hash
2019-06-13 14:36:29 +02:00
Antoine Eiche
7935cffd6b Create a pg_trgm index on builds.drvpath
The search query uses the LIKE operator which requires a sequential
scan (it can't use the already existing B-tree index). This new
index (trigram) avoids a sequential scan of the builds table when the
LIKE operator is used.

Here is the analyze of a request on the builds table with this index:

     explain analyze select * from builds where drvpath like '%k3r71gz0gv16ld8rhcp2bb8gb5w1xc4b%';
                                                                 QUERY PLAN
     -----------------------------------------------------------------------------------------------------------------------------------
      Bitmap Heap Scan on builds  (cost=128.00..132.01 rows=1 width=492) (actual time=0.070..0.077 rows=1 loops=1)
        Recheck Cond: (drvpath ~~ '%k3r71gz0gv16ld8rhcp2bb8gb5w1xc4b%'::text)
        ->  Bitmap Index Scan on indextrgmbuildsondrvpath  (cost=0.00..128.00 rows=1 width=0) (actual time=0.047..0.047 rows=3 loops=1)
              Index Cond: (drvpath ~~ '%k3r71gz0gv16ld8rhcp2bb8gb5w1xc4b%'::text)
      Total runtime: 0.206 ms
     (5 rows)
2019-06-06 14:28:25 +02:00
Antoine Eiche
778fc03570 Allow to search builds by hash
Currently, a full store path has to be provided to search in
builds. This patch permits to search jobs with a output path or
derivation hash.

Usecase: we are building Docker images with Hydra. The tag of the
Docker image is the hash of the image output path. This patch would
allow us to find back the build job from the tag of a running
container image.
2019-06-05 11:56:42 +02:00
Eelco Dolstra
7936a29364 hydra-eval-jobs: Use 'checks' output if there is no 'hydraJobs' output 2019-06-03 13:55:32 +02:00
Eelco Dolstra
9a8880fd28 Doh 2019-06-03 13:53:22 +02:00
Eelco Dolstra
517acb4ca8 Add some flake checks 2019-06-03 12:29:42 +02:00
Eelco Dolstra
0042183717 Fix build 2019-06-03 12:23:49 +02:00
Eelco Dolstra
bc11ab22a3 Update flake.nix 2019-06-03 12:09:18 +02:00
Graham Christensen
1be7de15a8 Merge pull request #648 from danbst/pg-changes
tests: change postgresql socket dir to /tmp
2019-05-23 15:59:31 -04:00
Eelco Dolstra
b7be2bf9ad Fix build against the latest flakes branch 2019-05-22 14:51:55 +02:00
Eelco Dolstra
8717d69a36 Build using the nix flake 2019-05-22 14:44:10 +02:00
Eelco Dolstra
438ddf5289 Fix error in GitlabStatus plugin
May 15 09:20:10 chef hydra-queue-runner[27523]: Hydra::Plugin::GitlabStatus=HASH(0x519a7b8)->buildFinished: Can't call method "value" on an undefined value at /nix/store/858hinflxcl2jd12wv1r3a8j11ybsf6w-hydra-0.1.2629.89fa829/libexec/hydra/lib/Hydra/Plugin/GitlabStatus.pm line 57.
2019-05-15 10:28:16 +02:00
Eelco Dolstra
89fa82930a Create projects in enabled state 2019-05-11 00:55:26 +02:00
Eelco Dolstra
f68cb7b57e "Reproduce" action: Support flakes
No more need for a reproduction script! It just says something like

  If you have Nix installed, you can reproduce this build on your own
  machine by running the following command:

  # nix build github:edolstra/dwarffs/09c823e977946668b63ad6c88ed358b48220f124:hydraJobs.build.x86_64-linux
2019-05-11 00:53:00 +02:00
Eelco Dolstra
4ec51032ee Jobset eval page: Show immutable flake URI 2019-05-11 00:52:06 +02:00
Eelco Dolstra
ed00f0b25e Cache flake-based jobset evaluations 2019-05-11 00:41:13 +02:00
Eelco Dolstra
30e8fe951b Improve error message 2019-05-11 00:40:40 +02:00
Eelco Dolstra
0387787e7e TODO 2019-05-11 00:14:18 +02:00
Eelco Dolstra
842ef9af24 hydra-eval-jobset: Support flakes 2019-05-11 00:11:38 +02:00
Eelco Dolstra
f9f595cd21 Add flake configuration to the web interface 2019-05-11 00:11:38 +02:00
Eelco Dolstra
6ee6ec3bda hydra-eval-jobs: Support flakes
E.g. 'hydra-eval-jobs ~/Dev/patchelf' is enough to evaluate patchelf -
no need to set up a $NIX_PATH, pass arguments, etc.
2019-05-11 00:11:38 +02:00
Eelco Dolstra
ddcf05ac22 release.nix: Do not rely on currentSystem 2019-05-11 00:11:38 +02:00
Eelco Dolstra
2c60019910 hydra-eval-jobs: Modernize argument parser 2019-05-11 00:11:38 +02:00
Eelco Dolstra
8f3114960c Remove the hydra-eval-jobs restart hack
It's not very effective.
2019-05-10 21:57:19 +02:00
Eelco Dolstra
80fe42e77e Update flake.lock 2019-05-09 15:10:16 +02:00
Eelco Dolstra
950e8bef6c Disable deprecation warnings 2019-05-08 21:22:52 +02:00
Eelco Dolstra
2ecc06e557 Replace shell.nix with a flake devShell attribute 2019-05-08 18:12:24 +02:00
Eelco Dolstra
4172b5b290 Add flake.nix 2019-05-08 13:57:51 +02:00
Kevin Quick
ff64583d07 Add evaluation error status to evaluation time on project jobset tab. 2019-05-06 14:08:32 +02:00
Graham Christensen
c88745140b Merge pull request #649 from mayflower/upstream-gitlab-status
Create a gitlab status plugin
2019-04-28 08:18:03 -04:00
Graham Christensen
bcb1c2916d release: bump to 19.03 2019-04-26 15:14:27 +02:00
Robin Gloster
f4e7c104ff Create a gitlab status plugin
This plugin expects as inputs to a jobset the following:
 - gitlab_status_repo => Name of the repository input pointing to that
   status updates should be POST'ed, i.e. the jobset has a git input
   "nixexprs": "https://gitlab.example.com/project/nixexprs", in which
   case "gitlab_status_repo" would be "nixexprs".
 - gitlab_project_id => ID of the project in Gitlab, i.e. in the above
   case the ID in gitlab of "nixexprs"
2019-04-11 16:40:44 +02:00
danbst
4171ab4c4f tests: change postgresql socket dir to /tmp
In https://github.com/NixOS/nixpkgs/pull/57677 default postgresql socket directory was changed
to `/run/postgresql`, which doesn't exist (and can't be created) in
Nix build environment. We'll use /tmp as socket dir explicitly then.

Fixes build failure https://hydra.nixos.org/build/91221682

Cc @aszlig @edolstra
2019-03-29 23:46:38 +02:00
Graham Christensen
0e337e6f9c Merge pull request #644 from input-output-hk/declarative-jobset-error-message
improve the error messages when invalid declarative jobsets are defined
2019-03-21 14:25:23 -04:00
Michael Bishop
c741576563 improve the error messages when invalid declarative jobsets are defined
(cherry picked from commit 7568b89a1a)
2019-03-20 15:27:37 -04:00
Graham Christensen
2c142868a0 Merge pull request #643 from input-output-hk/github-plugin-short-context-debug
allow using a shorter context and increase hydra-notify debug
2019-03-20 14:23:31 -05:00
Michael Bishop
3ad091faf3 allow using a shorter context and increase hydra-notify debug
(cherry picked from commit 1c76ad3936)
2019-03-20 15:22:24 -04:00
Graham Christensen
8a41ea5f60 Merge pull request #571 from kquick/moreinfo
Additional helpful information in error messages.
2019-03-18 15:18:14 -05:00
Graham Christensen
215ca5da9c Merge pull request #607 from nlewo/json-search
Add JSON search API endpoint
2019-03-18 15:08:32 -05:00
Kevin Quick
2e225ba7c8 Do not attempt to report dir for grab command failure if not specified. 2019-03-17 23:15:24 -07:00
Graham Christensen
0721f6623f Merge pull request #627 from samueldr/hydra-eval-jobs/warn-max-heap-size
hydra-eval-jobs: Warn and resets maxHeapSize on bad values
2019-03-17 19:36:53 -04:00
Graham Christensen
44e7f0dece Merge pull request #530 from pinktrink/master
Fix bad ordering in projects documentation.
2019-03-17 17:28:51 -04:00
Graham Christensen
baf828a560 Merge pull request #624 from kquick/job_headers
Add job status headers (web useability for red/green colorblindness).
2019-03-17 17:24:38 -04:00
Graham Christensen
88a92256e1 Merge pull request #636 from Ma27/serve-json-for-evals-and-machines
Serialize data as JSON with `Accept: application/json`
2019-03-17 17:17:17 -04:00
Graham Christensen
21a4433fec Merge branch 'master' into job_headers 2019-03-17 17:16:37 -04:00
Graham Christensen
c8fa7ffc12 Merge pull request #629 from Ma27/fix-maintainer-notifications
hydra-eval-jobs: fix maintainer resolution
2019-03-17 17:12:55 -04:00
Graham Christensen
014e5aa10d Merge pull request #628 from dasJ/patch-1
Support $X-Request-Base for the Logo
2019-03-17 16:22:53 -04:00
Eelco Dolstra
be2791330e Merge pull request #641 from basvandijk/fix-linux-build-on-darwin
Fix Linux build on Darwin
2019-03-15 21:33:00 +08:00
Bas van Dijk
e9d032bfe9 Fix Linux build on Darwin
Without this patch running the following on MacOS:

  nix-build release.nix -A build.x86_64-linux

results in the following error during the configuration phase (note that Nix
should be configured with a x86_64-linux build machine):

  building '/nix/store/jb6ca1gmplyb69ayd43z7fb0y9npxd53-hydra-0.1.2581.8b5948f4cf12424c04df67a6eb136c9846fb2cfd.drv' on 'ssh://my-linux-build-machine'...
  ...
  checking whether /nix/store/s6bhdppx66bkgf741vk4d29hgsj1h1zp-hydra-perl-deps/bin/nix-store is recent enough... ./configure: line 16254: /nix/store/s6bhdppx66bkgf741vk4d29hgsj1h1zp-hydra-perl-deps/bin/nix-store: cannot execute binary file: Exec format error
  no
  configure: error: `/nix/store/s6bhdppx66bkgf741vk4d29hgsj1h1zp-hydra-perl-deps/bin/nix-store' doesn't support `--timeout'; please use a newer version.
  build time elapsed:  0m1.624s 0m1.774s 0m9.366s 0m6.110s
  builder for '/nix/store/jb6ca1gmplyb69ayd43z7fb0y9npxd53-hydra-0.1.2581.8b5948f4cf12424c04df67a6eb136c9846fb2cfd.drv' failed with exit code 1

This problem is that the `nix` dependency of hydra is selected from a nixpkgs
set configured with a default `system` parameter,
i.e. `builtin.currentSystem`. This means that the hydra derivation which is
build for and on Linux depends on the nix derivation build for Darwin.

The fix is to select nix from the nixpkgs set configured with a system specified
by the user.
2019-03-15 11:27:16 +01:00
Maximilian Bosch
1cbbc6c52c Serialize data as JSON with Accept: application/json
Similar to #607. According to the Catalyst[1] docs it's possible to
specify a data structure that is supposed to be serialized when
requesting i.e. a JSON response.

[1] https://metacpan.org/pod/Catalyst::Controller::REST#status_ok
2019-02-14 01:22:48 +01:00
Eelco Dolstra
8b5948f4cf Merge pull request #634 from NixOS/fix-build
tests: disable sandbox
2019-02-01 09:17:39 +01:00
Graham Christensen
4160132278 tests: disable sandbox
Prior, tests would all fail to build, causing, roughly, the following
error (roughly, because I added some debug log messages :)):

    ok 68 - Evaluating jobs/build-products.nix should result in 2 builds
    Queue runner stderr: using 4185024512 bytes for the NAR buffer
    locking path '/build/source/tests/data/queue-runner/lock'
    lock acquired on '/build/source/tests/data/queue-runner/lock.lock'
    warning: unknown setting 'max-connection-age'
    warning: unknown setting 'max-connections'
    dispatcher woken up
    dispatcher woken up
    dispatcher sleeping for 7674380800s
    adding new machine ‘localhost’
    dispatcher woken up
    checking the queue for builds > 0...
    dispatcher sleeping for 7674380800s
    sending notification about build 1
    loading build 18 (tests:build-products:simple)
    considering derivation ‘/build/source/tests/nix/store/24h0i450d4k00a4jhhk6r7qpqdvzskw6-build-product-simple.drv’
    sending notification about build 2
    creating build step ‘/build/source/tests/nix/store/24h0i450d4k00a4jhhk6r7qpqdvzskw6-build-product-simple.drv’
    added build 18 (top-level step /build/source/tests/nix/store/24h0i450d4k00a4jhhk6r7qpqdvzskw6-build-product-simple.drv, 1 new steps)
    got 1 new runnable steps from 1 new builds
    step ‘/build/source/tests/nix/store/24h0i450d4k00a4jhhk6r7qpqdvzskw6-build-product-simple.drv’ is now runnable
    dispatcher woken up
    dispatcher sleeping for 7674380800s
    performing step ‘/build/source/tests/nix/store/24h0i450d4k00a4jhhk6r7qpqdvzskw6-build-product-simple.drv’ 1 times on ‘localhost’ (needed by build 18
    and 0 others)
    sending closure of ‘/build/source/tests/nix/store/24h0i450d4k00a4jhhk6r7qpqdvzskw6-build-product-simple.drv’ to ‘localhost’
    building ‘/build/source/tests/nix/store/24h0i450d4k00a4jhhk6r7qpqdvzskw6-build-product-simple.drv’ on ‘localhost’
    killing process 10462
    marking build 18 as failed
    finishing build step ‘/build/source/tests/nix/store/24h0i450d4k00a4jhhk6r7qpqdvzskw6-build-product-simple.drv’

    ok 69 - Build 'simple' from jobs/build-products.nix should exit with code 0
    ok 70 - newbuild->finished was '1' instead of 1
    not ok 71 - newbuild->buildstatus was '1' instead of 0
    not ok 72 - Build 'simple' from jobs/build-products.nix should have buildstatus 0
    Can't call method "name" on an undefined value at ./evaluation-tests.pl line 173.
    FAIL: evaluation-tests.pl
2019-02-01 04:31:11 +01:00
Eelco Dolstra
5dd4736aed Merge pull request #632 from nlewo/localhost-error-message
hydra-queue-runner: better error message if nix-store can not be started
2019-01-23 10:46:30 +01:00
Antoine Eiche
9a73ec6455 hydra-queue-runner: better error message if nix-store can not be started
The hydra-queue-runner opens a connection to the builder. If the
builder is 'localhost' it starts `nix-store`, otherwise it starts
'ssh'.

Currently, if the hydra-queue-runner can not start `nix-store` (not in
the PATH for instance), the error message is:

  cannot connect to ‘localhost’: error: cannot start ssh: No such file
  or directory

This is not useful since ssh is actually not started:/

With this patch the error message is now:

  cannot connect to ‘localhost’: error: cannot start nix-store: No such file
  or directory
2019-01-23 10:42:47 +01:00
Eelco Dolstra
f5686e0958 Merge pull request #633 from samueldr/feature/dev-server
Add hydra-dev-server which uses the classic Catalyst server
2019-01-23 10:39:47 +01:00
Eelco Dolstra
804c29703f Merge pull request #631 from samueldr/feature/dates
Enhances user-facing dates
2019-01-23 10:36:40 +01:00
Samuel Dionne-Riel
04ff9e217b Add hydra-dev-server which uses the classic Catalyst server
This, in turns allows

 - Using --restart for reloading the perl code
 - Printing traces on error
2019-01-22 20:34:21 -05:00
Samuel Dionne-Riel
a16d0c7d6b Makes user-facing dates local when possible
Also ensures it makes available the hydra timezone in the title of the
dates.
2019-01-22 17:53:46 -05:00
Samuel Dionne-Riel
2430b12ec9 Adds moment.js for client-side date manipulations 2019-01-21 19:57:22 -05:00
Eelco Dolstra
e0d8dcfe2d Merge pull request #619 from samueldr/feature/lazy_errors
Adds error messages to lazy tabs
2019-01-20 23:22:17 +01:00
Shea Levy
b298ba4bbe Merge branch 'pr-gitlabpulls' of git://github.com/nlewo/hydra 2019-01-11 10:08:23 -05:00
Maximilian Bosch
aa87e7a52e hydra-eval-jobs: fix maintainer resolution
Some time ago the data structure for maintainer descriptions in
`nixpkgs` changed from a simple attr set with maintainer emails as
values to an attribute set where the maintainer' nick is associated to
an attribute set with email, GitHub handle and full name.

Hydra can either parse a Nix list or fetches `shortName` from the
associated attribute set (which is used for `meta.licenses` as each
value in it contains a `shortName`). This behavior needs to be
replicated for maintainers to retrieve the emails for `hydra-notify`.

This change is backwards-compatible since `queryMetaStrings` is still
able to understand lists, so old versions of `nixpkgs` or packages using
the old maintainer data structure remain usable.
2018-12-29 14:47:03 +01:00
Janne Heß
3a70688985 Support $X-Request-Base for the Logo 2018-12-27 17:08:20 +01:00
Samuel Dionne-Riel
dd188d3035 hydra-eval-jobs: Warn and resets maxHeapSize on bad values
This is because setting only the initial heap size to more than
the default value (or the configured value) will cause all initial evals
until maxHeapSize expands to the given value to abort.

The 1.1 multiplier comes from the the configured defaults on NixOS' hydra,
and from the previous multiplier used before
7876cf677c.
2018-12-21 22:57:07 -05:00
Eelco Dolstra
423c0440ea Typo 2018-12-20 12:07:02 +01:00
Kevin Quick
8315e20ab5 Lighten delta mark to blend better with other column headers. 2018-12-16 22:34:22 -08:00
Kevin Quick
dfce2ad69a Use rowspans to align Jobs reference in evaluations rendering 2018-12-16 22:26:44 -08:00
Kevin Quick
0e7593a4a1 Remove blank lines, consistent attribute quoting, use svg for delta header, column sizes. 2018-12-15 22:25:02 -08:00
Kevin Quick
5716e69767 Add job status headers (web useability for red/green colorblindness). 2018-12-15 11:58:26 -08:00
Samuel Dionne-Riel
51ce620681 Stops the pager from blocking at configurePhase (#618)
This is caused by the autoconf check for `nix-store` which is equivalent
to running this:

```
$ nix-store --timeout 123 -q
```

This would open the pager on a 2.1.1 version of nix.

```
$ nix-store --version
nix-store (Nix) 2.1.1
```

Setting `PAGER` to `cat` ensures the pager doesn't block the
configurePhase.

```
$ PAGER=cat nix-store --timeout 123 -q
```
2018-12-01 22:01:40 +00:00
Samuel Dionne-Riel
ed85daf2ac User: jobs tab returns its error as a lazy error. 2018-12-01 13:40:41 -05:00
Samuel Dionne-Riel
9986053e73 Controllers: allows lazy tabs to return custom errors. 2018-12-01 13:40:41 -05:00
Antoine Eiche
d9253543e4 plugin/GitLabPulls: support for using a personal access token (PAT)
In order to access protected or private repositories. Using the target
repository URL along with the merge-request ref instead of the source
repository url and branch is necessary to avoid running into issues if
the source repository is not actually accessible to the user Hydra is
authenticating as.

Thanks Alexei Robyn for this patch.
2018-11-20 16:27:40 +01:00
Rob Vermaas
14d5577bf8 Add duration to Slack notification. 2018-11-20 14:57:50 +01:00
Eelco Dolstra
cd234f6a14 Merge pull request #529 from bennofs/feat-all-builds
feat: add /eval/<id>/builds endpoint
2018-11-19 17:36:19 +01:00
Eelco Dolstra
f9870b5fce Merge pull request #612 from input-output-hk/devops-1126
[DEVOPS-1126] throttle github status calls to remain under api ratelimits
2018-11-12 10:09:38 +01:00
Michael Bishop
7916c6b185 [DEVOPS-1126] throttle github status calls to remain under api ratelimits 2018-11-09 12:06:37 -04:00
Eelco Dolstra
1c44de1779 Merge pull request #567 from phile314/bitbucket_pulls
Add BitBucket pull request support
2018-11-06 10:48:37 +01:00
Antoine Eiche
0d2a2d8923 Add json output for the search API endpoint
This commit also add a test of this feature.

Note the search JSON output doesn't contain any jobs because they can
not be exported to JSON yet.

The JSON output on a search query matching a build looks like:

```
{
  "builds": [
    {
      "buildoutputs": {
        "out": {
          "path": "/nix/store/wdag3pznrvqk01byk989irg7rq3q2a2c-job"
        }
      },
      "finished": 0,
      "releasename": null,
      "starttime": null,
      "project": "sample",
      "buildproducts": {},
      "timestamp": 1541007629,
      "buildstatus": null,
      "nixname": "job",
      "drvpath": "/nix/store/n9zqndn7j7nyr6gg3bmxvw26cfmdwv2n-job.drv",
      "job": "job",
      "id": 1,
      "stoptime": null,
      "priority": 100,
      "system": "x86_64-linux",
      "jobsetevals": [
        1
      ],
      "jobset": "default",
      "buildmetrics": {}
    }
  ],
  "projects": [],
  "jobsets": [],
  "buildsdrv": []
}
```
2018-11-01 09:31:15 +01:00
Antoine Eiche
dd1e4a92c0 api-test: make created project and jobset visible 2018-10-31 18:51:02 +01:00
Rob Vermaas
adf59a3959 Merge pull request #604 from andir/single-build-restart
allow users with 'restart-jobs' role to restart individual builds
2018-10-31 12:26:35 +01:00
Michael Bishop
3ef253c65f also add CatalystXRoleApplicator
f7fe61207b
2018-10-30 15:11:01 +01:00
Michael Bishop
6d693b6b2a fix hydra build on nixpkgs master
copied from c501958535
2018-10-30 14:50:22 +01:00
Eelco Dolstra
8d26144121 Fix building against nix master 2018-10-30 14:41:21 +01:00
Antoine Eiche
68aad22d19 Add GitlabPulls input plugin 2018-10-15 14:45:26 +02:00
Andreas Rammhold
63a294d4ca allow users with 'restart-jobs' role to restart individual builds 2018-10-04 21:59:42 +02:00
Eelco Dolstra
e0f204f3da Merge pull request #599 from tomberek/19.03_fixes
submodule fix
2018-10-03 09:20:02 +02:00
Tom Bereknyei
8bffbb7928 evalSettings deprecated, submodule fix 2018-10-03 00:45:42 -04:00
Eelco Dolstra
0bc548ee2d Merge pull request #595 from kquick/darcs_cache_dir
Fix darcs input to use darcs-specific SCM cache dir.
2018-09-10 10:51:08 +02:00
Kevin Quick
d9515b208c Update prompt for Local path input to indicate a URL is also valid.
The PathInput input for local paths was previously enhanced to allow
URLs for which it would use a nix-prefetch-url operation.  This change
updates the prompt for the declarative input type to indicate this
capability.
2018-09-09 22:08:06 -07:00
Kevin Quick
35bcab74ed Fix darcs input to use darcs-specific SCM cache dir.
Currently re-using the git cache dir which could cause overlap problems.
2018-09-09 22:04:32 -07:00
Eelco Dolstra
b7c42a38a3 Merge pull request #575 from Ma27/fix-tab-jobset-view
jobset view: jump back to the proper tab when displaying all failed jobsets
2018-09-06 21:11:59 +02:00
Eelco Dolstra
b15288bea4 Merge pull request #590 from Taneb/one-runcommand
Allow for precisely one instance of RunCommand plugin
2018-08-21 17:00:23 +02:00
Nathan van Doorn
a77954be4d Allow for precisely one instance of RunCommand plugin 2018-08-21 15:52:41 +01:00
Eelco Dolstra
b542b73ced hydra-eval-jobs: Reinitialize Boehm GC in the child
This is necessary to prevent hangs in the garbage collector.
2018-08-10 20:25:43 +02:00
Eelco Dolstra
7876cf677c Increase maxHeapSize more gradually 2018-08-10 19:23:31 +02:00
Eelco Dolstra
4dca8fe14d Gradually increase maxHeapSize 2018-08-07 11:47:53 +02:00
Eelco Dolstra
e122d3bef3 RunCommand: Return metrics as a float
Apparently, DBIx::Class doesn't handle columns with type 'double
precision' properly.
2018-08-02 12:31:28 +02:00
Eelco Dolstra
6db2cbf094 Add a plugin to execute arbitrary commands when a build finishes
The plugin can be configured using one or more <runcommand> sections
in hydra.conf, e.g.

<runcommand>
  command = echo Build finished
</runcommand>

Optionally, the command can be executed for specific
projects/jobsets/jobs:

  job = patchelf:master:tarball

or

  job = patchelf:*:*

The default is *:*:*.

The command is executed with the environment variable $HYDRA_JSON
pointing to a JSON file containing info about the build, e.g.

  {
    "build": 3772978,
    "buildStatus": 0,
    "drvPath": "/nix/store/9y4h1fyx9pl3ic08i2f09239b90x1lww-patchelf-tarball-0.8pre894_ed92f9f.drv",
    "event": "buildFinished",
    "finished": 1,
    "job": "tarball",
    "jobset": "master",
    "metrics": [
      {
        "name": "random1",
        "unit": null,
        "value": "20282"
      },
      {
        "name": "random2",
        "unit": "KiB",
        "value": "6664"
      }
    ],
    "outputs": [
      {
        "name": "out",
        "path": "/nix/store/39h5xciz5pnh1aypmr3rpdx0536y5s2w-patchelf-tarball-0.8pre894_ed92f9f"
      }
    ],
    "products": [
      {
        "defaultPath": "",
        "fileSize": 148216,
        "name": "patchelf-0.8pre894_ed92f9f.tar.gz",
        "path": "/nix/store/39h5xciz5pnh1aypmr3rpdx0536y5s2w-patchelf-tarball-0.8pre894_ed92f9f/tarballs/patchelf-0.8pre894_ed92f9f.tar.gz",
        "productNr": 4,
        "sha1hash": "9f27d18382436a7f743f6c2f6ad66e1b536ab4c8",
        "sha256hash": "b04faef2916c411f10711b58ea26965df7cb860ca33a87f1e868051b874c44b3",
        "subtype": "source-dist",
        "type": "file"
      },
      {
        "defaultPath": "",
        "fileSize": 121279,
        "name": "patchelf-0.8pre894_ed92f9f.tar.bz2",
        "path": "/nix/store/39h5xciz5pnh1aypmr3rpdx0536y5s2w-patchelf-tarball-0.8pre894_ed92f9f/tarballs/patchelf-0.8pre894_ed92f9f.tar.bz2",
        "productNr": 3,
        "sha1hash": "7a664841fb779dec19023be6a6121e0398067b7c",
        "sha256hash": "c81e36099893f541a11480f869fcdebd2fad3309900519065c8745f614dd024a",
        "subtype": "source-dist",
        "type": "file"
      },
      {
        "defaultPath": "README",
        "fileSize": null,
        "name": "",
        "path": "/nix/store/39h5xciz5pnh1aypmr3rpdx0536y5s2w-patchelf-tarball-0.8pre894_ed92f9f",
        "productNr": 2,
        "sha1hash": null,
        "sha256hash": null,
        "subtype": "readme",
        "type": "doc"
      },
      {
        "defaultPath": "",
        "fileSize": 6230,
        "name": "README",
        "path": "/nix/store/39h5xciz5pnh1aypmr3rpdx0536y5s2w-patchelf-tarball-0.8pre894_ed92f9f/README",
        "productNr": 1,
        "sha1hash": "dc6bb09093183ab52d7e6a35b72d179869bd6fbf",
        "sha256hash": "5371aee9de0216b3ea2d5ea869da9d5ee441b99156a99055e7e11e7a705f7920",
        "subtype": "readme",
        "type": "doc"
      }
    ],
    "project": "patchelf",
    "startTime": 1533137091,
    "stopTime": 1533137094,
    "timestamp": 1533136076
  }

So for example, the following command:

  command = echo Build $(jq -r .build $HYDRA_JSON) \($(jq -r .project $HYDRA_JSON):$(jq -r .jobset $HYDRA_JSON):$(jq -r .job $HYDRA_JSON)\) finished, metrics: $(jq -r '.metrics[].value' $HYDRA_JSON).

will print

  Build 3772978 (patchelf:master:tarball) finished, metrics: 20282 6664.
2018-08-01 19:43:50 +02:00
Eelco Dolstra
8e17a413f5 hydra-notify step-finished: Don't barf if the step has no log file 2018-08-01 17:17:46 +02:00
Eelco Dolstra
dca6c5a983 hydra-eval-jobs: Filter ANSI escape sequences 2018-08-01 17:06:32 +02:00
Eelco Dolstra
1898e31ed8 hydra-eval-jobset: Respect email_notification 2018-08-01 16:56:53 +02:00
Eelco Dolstra
a71e6301d2 Fix Hydra VM tests 2018-07-31 21:49:05 +02:00
Eelco Dolstra
1a899890ac Use nixUnstable 2018-07-31 21:19:10 +02:00
Eelco Dolstra
162d671c48 Revert "Fix broken build.x86_64-linux job (#573)"
This reverts commit c2e2b42877, which
breaks building with nixUnstable.
2018-07-31 10:23:41 +02:00
Maximilian Bosch
37d35ac51e jobset view: jump back to the proper tab when displaying all failed jobsets
When I press "n builds omitted" I get back to the first tab of a jobset.
This is extremely counter-intuitive, instead this notice should link to
the currently opened tab.
2018-07-15 17:52:14 +02:00
Jacob Mitchell
c2e2b42877 Fix broken build.x86_64-linux job (#573)
The job has been failing since https://hydra.nixos.org/eval/1461286
with the following error:

    hydra-eval-jobs.cc:278:17: error: 'evalSettings' was not declared in this scope
                     evalSettings.restrictEval = true;
                     ^~~~~~~~~~~~

This is likely due to a typo in 0882519 where that line and the
corresponding comment were moved, and `settings` was changed in that
one place to `evalSettings`.

I reproduced the error by running `nix-build release.nix -A
build.x86_64-linux` on my machine, and this small change fixes it.
2018-07-07 19:15:01 +01:00
Kevin Quick
e523e8a643 Additional helpful information in error messages. 2018-06-29 17:41:23 -07:00
Philipp Hausmann
f738f6feb3 Add BitBucket pull request support 2018-06-22 11:22:54 +02:00
Rob Vermaas
879333fd3c Make /api/push-github public for private Hydra instances. This makes it possible to use webhooks to trigger evaluations for private Hydra instances. 2018-06-14 17:23:01 +02:00
Eelco Dolstra
cff52ab151 Merge pull request #556 from AmineChikhaoui/machine-types-stats
add some more statistics about runnable/running builds per arch/system features
2018-06-12 14:02:57 +02:00
AmineChikhaoui
298e99449b add metrics for hydra notifications. 2018-06-12 13:00:39 +01:00
AmineChikhaoui
99e6c19672 add some more statistics about runnable/running builds per arch/system
features.
2018-06-12 13:00:00 +01:00
Eelco Dolstra
b11789f399 Add boost dependency 2018-06-05 13:24:23 +02:00
Eelco Dolstra
0882519b10 hydra-eval-jobs: Ugly hackery to reduce memory usage
You can now set 'evaluator_max_heap_size' to make hydra-eval-jobs
restart itself if the Boehm heap exceeds the specified size.

For example, with 'evaluator_max_heap_size = 256000000',

  $ hydra-eval-jobs '<nixpkgs/pkgs/top-level/release.nix>' -I nixpkgs=channel:nixos-17.09

has a max RSS of .56 GiB rather than 4.7 GiB.

Unfortunately it doesn't help much for the NixOS jobsets because of
the "tested" job which requires a huge amount of memory all by itself.
2018-06-05 13:24:23 +02:00
Eelco Dolstra
821f8bf5a0 release.nix: Use fetchGit to get Nixpkgs 2018-06-05 13:24:23 +02:00
Eelco Dolstra
39eca8bef1 Fix build against Nix master 2018-06-05 13:24:23 +02:00
Eelco Dolstra
7f6d52f4c3 Merge pull request #562 from grahamc/141-redux
Allow channels to be usefully imported by other nix expressions.
2018-05-25 18:30:15 +02:00
Shea Levy
70eb67fe5b Allow channels to be usefully imported by other nix expressions. 2018-05-25 11:22:20 -04:00
Eelco Dolstra
4013e83e3f Merge pull request #560 from Synthetica9/nixpkgs-40521-hydra
Remove "bashism"
2018-05-17 12:03:19 +02:00
Patrick Hilhorst
d27732bdf0 Remove "bashism"
Replace `bash <(...)` with `... | bash`

See also: NixOS/nixpkgs#40521
2018-05-16 23:56:40 +02:00
Eelco Dolstra
09a4c9fad2 hydra-evaluator: Allow setting the maximum number of concurrent evaluations 2018-05-16 14:22:00 +02:00
Eelco Dolstra
4e27796eba Allow setting GC_INITIAL_HEAP_SIZE for hydra-eval-jobs
This cannot be done in the hydra-evaluator systemd unit, since then
every other Nix process (e.g. hydra-evaluator and nix-prefetch-*) will
also allocate the specified heap size, probably leading to OOM.
2018-05-16 14:14:53 +02:00
Eelco Dolstra
691f7e168c Fix building on Nixpkgs 17.09 2018-05-10 15:11:24 +02:00
Eelco Dolstra
215b724e44 Fix passing arguments to the reproduction script 2018-05-10 15:11:08 +02:00
Eelco Dolstra
df27358e11 Merge pull request #547 from cleverca22/fix-githubpulls-newline
fix a stray newline in a path
2018-03-16 18:41:09 +01:00
Michael Bishop
4015bca225 fix a stray newline in a path 2018-03-16 13:04:48 -03:00
Eelco Dolstra
85524b2d0f Disable jobset deletion
This is a good way to make Hydra hang. (E.g. we had a deletion of
nixos:gcc-7 running for > 12 hours and blocking UPDATE statements from
hydra-queue-runner.) Generally it's better to just disable/hide an old
jobset anyway.
2018-03-13 14:05:55 +01:00
Eelco Dolstra
02888105a8 Add a hydra.conf option to enable email notification
Note that it's disabled by default.
2018-03-12 14:04:23 +01:00
Eelco Dolstra
c0fac52872 Add some debug code 2018-03-07 10:23:43 +01:00
Eelco Dolstra
5a1f2a50e5 Handle derivations with system type 'builtin'
Fixes #540.
2018-03-07 10:22:35 +01:00
Eelco Dolstra
68afa2bf6f Dump more system info in /queue-runner-status 2018-03-07 10:06:56 +01:00
Eelco Dolstra
cb43da06f3 Use Nix 2.0 and default GCC 2018-03-07 09:52:18 +01:00
Eelco Dolstra
3ec73c93e2 Remove unused dependency on aws-sdk-cpp 2018-02-23 16:47:24 +01:00
Eelco Dolstra
028ecf7c1f Merge pull request #536 from phile314-fh/master
[ Fix #531 ] Trim github pr plugin store paths.
2018-02-12 18:05:03 +01:00
Philipp Hausmann
3cf2ffe367 [ Fix #531 ] Trim github pr plugin store paths.
nix-store --add returns a trailing LF which caused wrong include
paths for the github PR plugin JSON input.
2018-02-12 17:59:56 +01:00
Eelco Dolstra
ae080615d1 Merge pull request #535 from grahamc/patch-3
Typo: on the build view page: Yu -> You
2018-02-08 18:50:00 +01:00
Graham Christensen
aeca462de0 Typo: on the build view page: Yu -> You 2018-02-08 12:37:21 -05:00
Chloe Kever
9eb149b509 Fix bad ordering in projects documentation. 2018-01-17 13:34:01 -08:00
Eelco Dolstra
fd463ff403 Remove nix-install-package support
'nix-install-package' no longer exists in Nix 1.12.

Closes #268.
2018-01-15 14:27:58 +01:00
Benno Fünfstück
3ab5d299c1 feat: add /eval/<id>/builds endpoint
This endpoint allows efficient retrieval of all the builds in an
evaluation, without making a request for each single build.
2018-01-14 01:29:37 +01:00
Eelco Dolstra
a4fc292c83 Merge pull request #526 from grahamc/add-restart-jobs-role
Add a restart-jobs role
2018-01-02 11:27:33 +01:00
Graham Christensen
83a48d2d4f Add a restart-jobs role
Frequently users want Hydra access just to restart jobs. However,
prior to this commit the only way to grant that access was by giving
them full Admin access which isn't necessarily what we want to do.

By having a restart-jobs role, we can grant this privilege to users
who are known to the community and want to help, but aren't long-time
members.

I haven't tested this commit, but it looks good to me...
2017-12-30 08:28:23 -05:00
Eelco Dolstra
8913c682cf Doh 2017-12-25 15:02:17 +01:00
Eelco Dolstra
0d79f16fd5 git-export -> source 2017-12-25 14:31:30 +01:00
Eelco Dolstra
7ccec0900b Fix links to steps in the machines page 2017-12-07 16:20:23 +01:00
Eelco Dolstra
e9670641ec Distinguish build step states
The web interface now shows whether a build step is connecting,
copying inputs/outputs, building, etc.
2017-12-07 15:35:31 +01:00
Eelco Dolstra
457483ba0e Don't lock the BuildSteps table when inserting
Instead, optimistically insert a row and retry if there is a conflict.
2017-12-07 14:41:29 +01:00
Eelco Dolstra
2660c3cc54 Remove redundant check 2017-12-05 16:00:18 +01:00
Eelco Dolstra
d0b19d3172 Merge pull request #520 from AmineChikhaoui/master
hide disabled jobsets by default.
2017-12-05 15:28:41 +01:00
AmineChikhaoui
52e0ebcfed hide disabled jobsets by default. 2017-12-05 14:07:58 +01:00
Eelco Dolstra
364e21919a hydra-eval-{jobs,jobset}: Pass file name as <...> 2017-11-28 16:51:00 +01:00
Eelco Dolstra
b7bc4384b7 Fix serving plain text files 2017-11-21 17:55:52 +01:00
Eelco Dolstra
5986aae704 Add option eval_substituter
When using the "build" or "sysbuild" jobset input types in conjunction
with a binary cache store, the evaluator needs to be able to fetch
store paths from the binary cache. Typical usage:

  store_uri = s3://nix-test-cache?secret-key=...
  eval_substituter = s3://nix-test-cache

Also, the public key of the binary cache must be added to
binary-cache-public-keys in nix.conf, otherwise the local nix-daemon
won't allow the store paths to be copied over.
2017-11-20 16:12:20 +01:00
aszlig
a0b1875a4f release.nix: Fix quoting of ${LOGNAME:-foo} (#517)
In order to use ${...} literally within an indented string we need to
prefix it with two single quotes.

Signed-off-by: aszlig <aszlig@nix.build>
2017-11-15 11:46:30 +00:00
Eelco Dolstra
7857f83251 Serve directories and symlinks correctly 2017-11-14 17:17:07 +01:00
Eelco Dolstra
100249c066 Use git rev-list --count 2017-11-14 16:18:54 +01:00
Eelco Dolstra
5216b7eb2c Don't rely on ${LOGNAME:-foo} evaluating to a string 2017-11-14 15:11:14 +01:00
Eelco Dolstra
2cdc84f34f Fix build against Nix master
Also, remove support in hydra-eval-jobs for multiple jobset input
alternatives. The web interface hasn't supported this in a long
time. Thus we can use the regular "--arg" handler.
2017-10-26 13:10:14 +02:00
Eelco Dolstra
eef0d8861b Remove test line 2017-10-19 13:17:29 +02:00
Eelco Dolstra
b04dc6c76e Fix root creation when the root already exists but is owned by another user 2017-10-19 12:28:38 +02:00
Eelco Dolstra
b904f25247 Hide contents links 2017-10-18 15:57:43 +02:00
Eelco Dolstra
d8d71ea4a3 hydra-server: Use server_store_uri instead of store_uri, if set
The store_uri may contain parameters that cause Nix to fail when
running under the hydra-server user (e.g. the signing key).
2017-10-18 15:33:55 +02:00
Eelco Dolstra
f39c13b2ff hydra-server: Set XDG_CACHE_HOME, other Nix barfs 2017-10-18 15:33:46 +02:00
Eelco Dolstra
3e7938c61a hydra-module: Include "=" in hydra.conf
hydra-queue-runner is more anal about the format than Catalyst, so it
was misinterpreting gc_roots_dir.
2017-10-18 14:23:10 +02:00
Eelco Dolstra
62c6cca937 Make one-click installs work for binary cache stores
This requires setting binary_cache_public_uri in hydra.conf.
2017-10-18 14:09:28 +02:00
Eelco Dolstra
44ef743d84 Hide some things that require a local store 2017-10-18 13:44:41 +02:00
Eelco Dolstra
40a9b70df2 Shut up warning 2017-10-18 13:39:39 +02:00
Eelco Dolstra
30943dd217 Detect MIME type 2017-10-18 13:38:34 +02:00
Eelco Dolstra
42fbde0383 Use "nix cat-store" to serve files from the Nix store
This makes downloading/viewing build results work with binary cache
stores. For good performance, this should be used in conjunction with
ca580bec35,
i.e. you should set store_uri to something like

  s3://my-cache?local-nar-cache=/tmp/nar-cache

to cache NARs between requests.
2017-10-18 12:48:31 +02:00
Eelco Dolstra
bc60fccf78 Remove remaining references to store_mode etc. 2017-10-18 12:23:07 +02:00
Eelco Dolstra
cc64e51f75 USER -> LOGNAME for consistency
Don't remember why we use LOGNAME. Also ensure that it's set.
2017-10-18 11:23:00 +02:00
Eelco Dolstra
e70f9e872a Merge pull request #514 from dtzWill/fix/issue-513
hydra-queue-runner: ensure roots directory exists
2017-10-18 11:16:42 +02:00
Will Dietz
c81594f470 hydra-queue-runner: ensure roots directory exists
Fixes #513
2017-10-17 13:04:56 -05:00
Eelco Dolstra
45b138373b hydra-queue-runner: Write GC roots for outputs paths
We lost this behaviour somewhere. So build outputs could be GC'ed when
running the collector with --option gc-keep-outputs false.
2017-10-12 18:55:38 +02:00
Remy Goldschmidt
eb7631fb9d hydra-create-user now has --password-hash option (#504)
When creating a Hydra user with the `hydra-create-user` command, you can now
provide a SHA1 password hash with the `--password-hash` flag. This is useful for
the upcoming work on Fully Declarative Hydra, since the end user should not have
to specify plaintext passwords in their `configuration.nix` file.
2017-10-08 11:55:51 +01:00
Keshav Kini
4b1af1fc1b Fix link syntax in README.md (#511) 2017-09-30 22:39:36 +01:00
Rob Vermaas
b645b03536 Fix string comparison 2017-09-25 11:54:55 +00:00
Eelco Dolstra
27103398c9 Make maxLogSize configurable 2017-09-22 15:23:58 +02:00
Eelco Dolstra
d9cbf8cf01 Use PostgreSQL 9.5
9.2 is no longer in Nixpkgs.
2017-09-22 15:18:22 +02:00
Rob Vermaas
2318baaade Add 'readonly_ips' option, to allow readonly access for certain IPs when 'private' option is enabled. 2017-09-22 11:36:49 +00:00
Eelco Dolstra
b828224fee Periodically close RemoteStore connections
This prevents an accumulation of temproots. See
89dc62c174.
2017-09-14 18:16:33 +02:00
Eelco Dolstra
6517446c34 Update to latest nixUnstable 2017-09-14 17:22:48 +02:00
Eelco Dolstra
d676c91bd5 Return Builds.drvpath in the JSON API
E.g.

  curl -H 'Accept: application/json' http://127.0.0.4/build/3772858 | jq -r .drvpath
  /nix/store/97vla79lavlcsk8milskr06rfm34bskx-patchelf-0.8pre843_f4522f4.drv
2017-09-12 18:42:18 +02:00
Eelco Dolstra
4af97c57f5 Acquire the send lock only while actually sending
Thus, we no longer hold the send lock while substituting missing paths
on the build machine. This is a good thing in particular for macOS
builders which have a tendency to hang forever in curl downloads.
2017-09-01 16:28:49 +02:00
Eelco Dolstra
50ab80caf2 Don't wait forever to acquire the send lock 2017-09-01 15:29:06 +02:00
Eelco Dolstra
b405837d4d Merge pull request #474 from zraexy/patch-1
Make all content of rotated table header clickable
2017-08-22 22:37:23 +02:00
Eelco Dolstra
337a72ef4d Fix displaying errors from JSON requests 2017-08-17 15:32:46 +02:00
montag451
48609664a5 Fixes NixOS/hydra#402 (#424) 2017-08-10 14:16:24 +02:00
spacefrogg
7e9b6acbce Fix perl search path; avoid reference to build path (#471)
Fixes #460
2017-08-10 14:13:00 +02:00
Rob Vermaas
3fc320db32 Merge pull request #498 from AmineChikhaoui/hydra-timeboard
Hydra status datadog timeboard
2017-07-27 09:33:32 +00:00
Amine Chikhaoui
c0fb091fe3 add space 2017-07-26 16:56:16 +01:00
Amine Chikhaoui
20c4655adb fix style 2017-07-26 16:55:07 +01:00
Amine Chikhaoui
b9ed08d703 move file and add a basic README 2017-07-26 16:54:04 +01:00
Amine Chikhaoui
d6f029bf82 remove hydra.nixos.org reference 2017-07-26 15:26:41 +01:00
Amine Chikhaoui
964811d385 rename resource 2017-07-26 15:22:18 +01:00
Amine Chikhaoui
3089f15745 Add hydra status dd timeboard expression 2017-07-26 15:20:40 +01:00
Eelco Dolstra
7c976d2aec hydra-queue-runner: Make build notification more reliable
Previously, when hydra-queue-runner was restarted, any pending "build
finished" notifications were lost. Now hydra-queue-runner marks
finished but unnotified builds in the database and uses that to run
pending notifications at startup.
2017-07-26 15:17:51 +02:00
Eelco Dolstra
5ee74dd3a0 Merge pull request #497 from dtzWill/fix/no-skip-buildid-forward
queue-monitor: never move lastBuildId forward without processing jobs.
2017-07-26 11:40:48 +02:00
Will Dietz
719df63190 queue-monitor: never move lastBuildId forward without processing jobs. 2017-07-25 20:05:37 -05:00
Eelco Dolstra
e117d85c2a hydra-queue-runner: Set a thread title for the builder threads
This should make debugging slightly easier.
2017-07-25 15:59:41 +02:00
Shea Levy
a6d9201947 GithubStatus: Allow config to specify the integration description and context 2017-07-24 15:44:10 -04:00
Eelco Dolstra
e78b9fd4ee hydra-queue-runner: Allow concurrent notifications
The queue runner can now run up to ‘max-concurrent-notifications’ in
parallel (default is 2). This is useful when some hydra-notify
invocations can take a long time to complete (e.g. because they need
to compress a giant build log) and we don't want this to block all
other notifications.
2017-07-24 16:35:34 +02:00
Eelco Dolstra
bba383bf1b hydra-queue-runner: Keep some notification statistics 2017-07-24 16:26:44 +02:00
Eelco Dolstra
f46a21e16e Slight cleanup 2017-07-21 17:22:11 +02:00
Eelco Dolstra
dc5e0b120a Fix a race that can cause hydra-queue-runner to ignore newly added builds
As @dtzWill discovered, with the concurrent hydra-evaluator, there can
be multiple active transactions adding builds to the database. As a
result, builds can become visible in a non-monotonically increasing
order, breaking the queue monitor's assumption that build IDs only go
up.

The fix is to have hydra-eval-jobset provide the lowest build ID it
just added in the builds_added notification, and have the queue
monitor check from there.

Fixes #496.
2017-07-21 14:34:48 +02:00
Eelco Dolstra
b0432c7762 Sync with nixUnstable 2017-07-21 13:09:08 +02:00
Eelco Dolstra
6fc851d376 Improve erorr message 2017-07-17 14:10:34 +02:00
Eelco Dolstra
66ae66024e Sync with latest Nix 2017-07-17 11:38:58 +02:00
Eelco Dolstra
064fd20b6f Merge pull request #494 from Chakerbh/master
Use build id for bitbucket Key
2017-07-11 17:41:22 +02:00
Chaker Benhamed
c5666095a1 Use build id for bitbucket Key 2017-07-11 16:13:56 +01:00
Eelco Dolstra
f95516a82b Merge pull request #466 from cyraxjoe/configurable-git-input
Allow to configure the timeout value for the GitInput plugin in different places.
2017-07-07 11:03:06 +02:00
Eelco Dolstra
e07987b44b Merge pull request #492 from Chakerbh/master
Add BitBucket plugin
2017-07-05 17:29:04 +02:00
Chaker Benhamed
8da3ca6e94 Skip the input if the emailResponsible field is disabled 2017-07-05 15:51:20 +01:00
Chaker Benhamed
fd8cb39a11 Add BitBucket plugin
This plugin will post to the build status system in BitBucket. In order
to use it you need to add to ExtraConfig
<bitbucket>
username = bitbucket_username
password = bitbucket_password
</bitbucket>
You can use an application password https://blog.bitbucket.org/2016/06/06/app-passwords-bitbucket-cloud/
2017-07-04 10:07:25 +01:00
Eelco Dolstra
9cc25b0c96 Merge pull request #491 from NixOS/restart-daemons-on-config-change
hydra-module.nix: restart daemons on config change
2017-06-27 16:37:00 +02:00
Domen Kožar
f220f45d29 hydra-module.nix: restart daemons on config change 2017-06-27 16:01:06 +02:00
Eelco Dolstra
803833aba7 Disable the build-queued hook
This can take an excessive amount of time. For example, on
hydra.nixos.org, a call to hydra-notify takes 0.7s even if there are
no plugins. So for an eval with ~45K new builds, the calls to
hydra-notify add up to about 9 hours.

The proper fix would be to pass a list of build IDs, or an eval ID.
2017-06-22 15:09:04 +02:00
Shea Levy
207d2dd10c GithubStatus: Don't send a pending status for already-finished builds
Fixes #488
2017-06-21 14:51:09 -04:00
michael bishop
6e4a7a30f7 fix github pulls json to be deterministic 2017-06-21 09:35:26 -03:00
Eelco Dolstra
f0d24af940 Fix "Evaluation pending since..." message even though the jobset has been evaluated 2017-06-12 14:15:00 +02:00
Shea Levy
dfb3a52f67 Fix build-queued plugin hook 2017-05-24 11:12:48 -04:00
Shea Levy
c40077ece1 Fix tests 2017-05-24 10:00:38 -04:00
Shea Levy
582c399420 Add buildQueued plugin hook 2017-05-24 09:45:31 -04:00
Shea Levy
3d044d2ec2 Github status API: Pull authorization from github_authorization by default 2017-05-24 08:53:29 -04:00
Shea Levy
08708e899a GithubPulls: Add 'revision' to the input 2017-05-24 07:33:06 -04:00
Shea Levy
c6f0753435 Add GithubPulls input plugin.
This can be used with declarative projects to build PRs.

The github_authorization section should contain verbatim Authorization header contents keyed by repo owner for private repos
2017-05-24 05:31:27 -04:00
Eelco Dolstra
941665044e /api/scmdiff: Set correct MIME type
It was set to application/json but should be text/plain.
2017-05-05 15:58:38 +02:00
Eelco Dolstra
8abc595d1c preHook -> shellHook
Adding the build directory to $PERL5LIB causes it to end up in the
wrapper scripts, which is bad.
2017-05-04 15:25:22 +02:00
Joel Rivera
a39ffba042 Include the project and jobset names in the configuration blocks
to set the timeout for a specific input in the GitInput plugin.

Remove the comments about using inputs with spaces.
2017-04-28 21:43:35 -05:00
Eelco Dolstra
1f94f03699 Fix build 2017-04-26 15:11:12 +02:00
Shea Levy
86aa851d8d Merge branch 'circleci-plugin' 2017-04-24 11:28:09 -04:00
zraexy
b3c4c4ef0d Make all content of rotated table header clickable 2017-04-20 15:58:17 -08:00
Shea Levy
4c26cf0c81 getHydraConfig: Allow multiple includes 2017-04-20 08:00:09 -04:00
Shea Levy
f4b4ee5751 Add CircleCI plugin. 2017-04-19 15:20:09 -04:00
Eelco Dolstra
cc85208fe4 Fix build 2017-04-18 20:50:18 +02:00
Joel Rivera
af2f8122e3 Allow to configure the timeout value for the GitInput plugin in different places.
1. From the hydra configuration file.

    The configuration is loaded from the "git-input" block.
    Currently only the "timeout" variable is been looked up in the file.

    <git-input>
      # general timeout
      timeout = 400
      <input-name>
        # specific timeout for a particular input name
        timeout = 400
      </input-name>

      # use quotes when the input name has spaces
      <"foot with spaces">
        # specific timeout for a particular input name
        timeout = 400
      </"foo with spaces">
    </git-input>

2. As an argument in the input value after the repo url and branch (and after the deepClone if is defined)
   "timeout=<value>"

The preference on which value is used:

 1. input value
 2. Block with the name of the input in the <git-input> block
 3. "timeout" inside the <git-input> block
 4. Default value of 600 seconds. (original hard-coded value)

The code is generalized for more values to be configured, it might be too much
for a single value on a single plugin.
2017-04-13 19:10:53 -05:00
Shea Levy
fed37ea640 nix-prefetch-git: Only remove .git, not e.g. .gitkeep (#454) 2017-04-12 21:08:04 +02:00
Eelco Dolstra
468b048fa2 Revert "Move build logic for the core hydra package into its own default.nix."
This reverts commit 949e5865c6. This
makes release.nix harder to read/maintain IMHO. There already is a Nix
expression for Hydra in Nixpkgs that can be used for this purpose.
2017-04-12 13:10:01 +02:00
Shea Levy
949e5865c6 Move build logic for the core hydra package into its own default.nix.
This allows users to build hydra using a normal mkDerivation, package overrides, etc.
2017-04-11 13:07:46 -04:00
Eelco Dolstra
a0376a92e5 Add dependency on nix-perl
Fixes #459.
2017-04-11 15:48:22 +02:00
Eelco Dolstra
c2c2633e50 Fix link to cached build log
Fixes #462.
2017-04-11 14:25:48 +02:00
Eelco Dolstra
433b94ee68 Fix Mercurial diff
It only showed the log messages of $rev1 and $rev2. Now it shows the
range $rev1::$rev2, excluding $rev1.
2017-04-11 13:39:54 +02:00
Eelco Dolstra
585d3274e3 Better error message if jobset doesn't evaluate to an attrset 2017-04-11 13:01:15 +02:00
Shea Levy
7e3f12fe10 Merge branch 'decl-project-remote-store' 2017-04-10 11:36:41 -04:00
Domen Kožar
81fee456c2 fix #425: parsable config by hydra-queue-runner 2017-04-10 14:59:58 +02:00
Eelco Dolstra
426aea1236 hydra-queue-runner: Allow multiple concurrent daemon connections 2017-04-06 18:50:53 +02:00
Eelco Dolstra
5810042a3b Periodically clear Store's path info cache
Otherwise the queue runner can consider paths as valid that have been
garbage-collected since the first time it queried them.
2017-04-06 17:20:23 +02:00
Eelco Dolstra
8364f4ec70 Upload log files to the right location
We were mixing up builds and steps. So for example

  https://cache.nixos.org/log/2w66a98iqbjdppc5s2b8qvhi3gprvy45-freecell-solver-4.8.0.drv

at the moment contains the log for
/nix/store/442r9d5ihbcpgq8q9dhijhvhlmplzp96-perl-namespace-autoclean-0.28.drv
because the latter is a step in http://hydra.nixos.org/build/51300420.
Oops.
2017-04-06 13:05:30 +02:00
Eelco Dolstra
fec895a642 hydra-server: Support logs in S3 2017-04-05 17:55:56 +02:00
Eelco Dolstra
4f11cf45dc Fix build cancellation
We nowadays ignore SIGINT, so the sshd child process inherited this
and ignored SIGINT as well.
2017-04-05 11:01:57 +02:00
Shea Levy
a738f826e8 declarative projects: Pull jobset spec build from the remote store
Fixes #443
2017-04-01 10:38:49 -04:00
Richard Zetterberg
3e0ee24b87 Adds documentation for the external API (#441)
Documents all the endpoints that can be used to retrieve data from
the API without authenticating.

Authentication and manipulating data with the API is not documented.
2017-04-01 11:20:49 +02:00
Will Dietz
90870f1416 NixExprs.pm: encode default.nix as utf-8 to fix missing chars/data. (#455)
cc #254
2017-04-01 11:18:51 +02:00
Eelco Dolstra
147ba3ca31 Set proper charset on log files 2017-03-31 18:00:08 +02:00
Shea Levy
ec1c8efd43 Merge branch 'eval-no-build-hook' 2017-03-30 13:19:37 -04:00
Eelco Dolstra
8771f7f913 Merge pull request #382 from shlevy/cached-build-notifications
Send BuildFinished notifications on cached build results.
2017-03-29 18:52:20 +02:00
Eelco Dolstra
57bc0eaead hydra-queue-runner: Limit concurrent database connections
Adding a 96-core aarch64 build machine to the build farm caused the
potential number of database connections to increase a lot, so we
started hitting the Postgres connection limit.
2017-03-21 11:53:46 +01:00
Shea Levy
3b5fd2d857 hydra-eval-jobs: Disable the build hook.
For some reason this causes an unexpected EOF when doing import-from-derivation.
2017-03-20 12:57:05 -04:00
Eelco Dolstra
150228d7de Upload build logs to the binary cache 2017-03-15 16:59:57 +01:00
Eelco Dolstra
7e6486e694 Move log compression to a plugin 2017-03-15 16:59:57 +01:00
Eelco Dolstra
285754aff6 hydra-evaluator improvements
* The "Jobset" page now shows when evaluations are in progress (rather
  than just pending).

* Restored the ability to do a single evaluation from the command line
  by doing "hydra-evaluator <project> <jobset>".

* Fix some consistency issues between jobset status in PostgreSQL and
  in hydra-evaluator. In particular, "lastCheckedTime" was never
  updated internally.
2017-03-15 16:59:57 +01:00
Eelco Dolstra
242ea8009f hydra-evaluator: Don't use the "timeout" command
"timeout" does not propagate PR_SET_PDEATHSIG, so it prevents
hydra-eval-jobset from being killed when hydra-evaluator quits.
2017-03-15 16:59:56 +01:00
Eelco Dolstra
d1afb42f12 Supress debug message 2017-03-15 16:59:56 +01:00
Eelco Dolstra
73900e9f5f Fix std::stoi exception 2017-03-08 15:07:52 +01:00
Eelco Dolstra
edebdf33f0 hydra-queue-runner: Handle SIGINT 2017-03-03 12:41:00 +01:00
Eelco Dolstra
500c27e4d5 Add hydra.conf option "nar_buffer_size" to configure memoryTokens limit
It defaults to half the physical RAM.
2017-03-03 12:37:27 +01:00
Eelco Dolstra
7c3e5c99c0 Include nix/config.h 2017-03-03 12:33:22 +01:00
Rob Vermaas
fd754d678e Do not trigger eval on jobset change when check interval is 0 (disabled). 2017-02-23 09:15:26 +00:00
Eelco Dolstra
9f6afb3375 Lock paths in the scm cache
This is necessary now that hydra-evaluator runs multiple evaluations
in parallel, to prevent corruption of Git/Mercurial clones.
2017-02-21 18:12:52 +01:00
Eelco Dolstra
52753e49c2 hydra-evaluator: Handle SIGINT
This makes "systemctl stop hydra-evaluator" work promptly again.
2017-02-21 17:54:31 +01:00
Eelco Dolstra
81ac547d2b Move most of AddBuilds to hydra-eval-jobset
Having this stuff in a separate module is a remnant of the time when
hydra-server could add builds to the queue directly. This is no longer
the case.
2017-02-21 17:20:48 +01:00
Eelco Dolstra
7081f97f3a Pedantry: CLOCK_REALTIME -> CLOCK_MONOTONIC 2017-02-21 16:17:17 +01:00
Eelco Dolstra
53b1f7da64 Decrease memoryTokens 2017-02-03 14:44:52 +01:00
Eelco Dolstra
a366f362e1 Use latest nixUnstable 2017-02-03 14:39:18 +01:00
Renzo Carbonara
63d8c8d631 Revert "Sort inputs table" (#448)
This reverts commit c103163825.

Fixes #412 #445
2017-01-30 18:20:08 +01:00
Bas van Dijk
4efd078977 Only set buildMachinesFiles when nix.buildMachines is defined 2016-12-11 15:35:38 +01:00
Renzo Carbonara
de55303197 Fix SQL syntax for migration 50. It failed with PostgreSQL 9.4. (#416) 2016-12-09 18:18:17 +01:00
Eelco Dolstra
8a120006f0 Fix version test 2016-12-08 16:03:50 +01:00
Eelco Dolstra
9989e6c0f4 Get exact build start/stop times from the remote 2016-12-07 16:10:21 +01:00
Eelco Dolstra
f6081668dc Allow determinism checking for entire jobsets
Setting

  xxx-jobset-repeats = patchelf:master:2

will cause Hydra to perform every build step in the specified jobset 2
additional times (i.e. 3 times in total). Non-determinism is not fatal
unless the derivation has the attribute "isDeterministic = true"; we
just note the lack of determinism in the Hydra database. This will
allow us to get stats about the (lack of) reproducibility of all of
Nixpkgs.
2016-12-07 15:57:13 +01:00
Eelco Dolstra
8bb36e79bd Support testing build determinism
Builds can now specify the attribute "isDeterministic = true" to tell
Hydra to build with build-repeat > 0. If there is a mismatch between
rounds, the step / build fails with a suitable status.

Maybe this should be a meta attribute, but that makes it invisible to
hydra-queue-runner, and it seems reasonable to make a claim of
mandatory determinism part of the derivation (since e.g. enabling this
flag should trigger a rebuild).
2016-12-06 17:46:06 +01:00
Eelco Dolstra
d0ad3fd806 Revert "Remove the global channel"
This reverts commit 2f6c2f5622.

This unintentionally also removed /all, which is actually somewhat
useful.
2016-12-06 14:25:09 +01:00
phile314-isska
cf12356572 Document ssmtp for email notifications. (#426) 2016-11-29 15:27:53 +01:00
Leonid Onokhov
8758d719c6 Remove logfile.css from templates (#428)
It is no longer used, and causes unnecessary 404s
2016-11-29 15:26:04 +01:00
Leonid Onokhov
96dc9ccecb Document how to serve hydra behind reverse proxy (#423) 2016-11-24 16:10:50 +01:00
Eelco Dolstra
2f6c2f5622 Remove the global channel
It's useless and it makes it very easy to kill the server by fetching
/channel/latest/closure.
2016-11-17 18:17:02 +01:00
Eelco Dolstra
98e7e37832 hydra-server: Fix and simplify robots.txt 2016-11-17 18:13:57 +01:00
Eelco Dolstra
aef048b3cb Bump Nix dependency 2016-11-16 17:52:26 +01:00
Eelco Dolstra
afb8765ae4 hydra-queue-runner: Bump memory limit to reflect more accurate accounting 2016-11-16 17:51:18 +01:00
Eelco Dolstra
b4d32a3085 hydra-queue-runner: More accurate memory accounting
We now take into account the memory necessary for compressing the NAR
being exported to the binary cache, plus xz compression overhead.

Also, we now release the memory tokens for the NAR accessor *after*
releasing the NAR accessor. Previously the memory for the NAR accessor
might still be in use while another thread does an allocation, causing
the maximum to be exceeded temporarily.

Also, use notify_all instead of notify_one to wake up memory token
waiters. This is not very nice, but not every waiter is requesting the
same number of tokens, so some might be able to proceed.
2016-11-16 17:48:50 +01:00
Eelco Dolstra
cb5e438a08 Bump Nix
Fixes #398.
2016-11-09 19:15:13 +01:00
Eelco Dolstra
e2a012de8c hydra-evaluator: Set jobset error if hydra-eval-jobset dies 2016-11-08 17:08:54 +01:00
Eelco Dolstra
4576b3d35b hydra-evaluator: Show friendlier exit status 2016-11-08 17:00:17 +01:00
Eelco Dolstra
1ecc8a4f40 hydra-queue-runner: Fix a race keeping cancelled steps alive
If a step is cancelled just as its builder step is starting,
doBuildStep() will return sRetry. This causes builder() to make the
step runnable again, since the queue monitor may have added new builds
referencing it. The idea is that if the latter condition is not true,
the step's reference count will drop to zero and it will be
deleted. However, if the dispatcher thread sees and locks the step
before the reference count can drop to zero in the builder thread, the
dispatcher thread will start a new builder thread for the step. Thus
the step can be kept alive for an indefinite amount of time.

The fix is for State::builder() to use a weak pointer to the step, to
ensure that the step's reference count can drop to zero *before* it's
added to the runnable queue.
2016-11-08 11:47:49 +01:00
Eelco Dolstra
de9d7bcf25 hydra-queue-runner: Handle exceptions in the dispatcher thread
E.g. "resource unavailable" when creating new threads.
2016-11-08 11:25:43 +01:00
Eelco Dolstra
7863d2e1da Step cancellation: Don't use pthread_cancel()
This was a bad idea because pthread_cancel() is unsalvageable broken
in C++. Destructors are not allowed to throw exceptions (especially in
C++11), but pthread_cancel() can cause a __cxxabiv1::__forced_unwind
exception inside any destructor that invokes a cancellation
point. (This exception can be caught but *must* be rethrown.) So let's
just kill the builder process instead.
2016-11-07 19:38:24 +01:00
Eelco Dolstra
95aa1f0590 Merge pull request #407 from grahamc/images
Update build images to be more friendly to users with color blindness.
2016-11-07 14:20:17 +01:00
Graham Christensen
6f6562bc5f Update build images to be more friendly to users with color blindness.
Closes #406
2016-11-07 06:53:27 -05:00
Eelco Dolstra
d7453bd8be hydra-queue-runner: Fix message 2016-11-02 12:44:18 +01:00
Eelco Dolstra
4f08c85c69 hydra-queue-runner: Fix assertion failure
It was hitting

    assert(reservation.unique());

Since we do want the machine reservation to be released before calling
wakeDispatcher(), let's use a different object for keeping track of
active steps.
2016-11-02 12:41:00 +01:00
Eelco Dolstra
07decd6915 Also hide disabled projects on the overview page by default 2016-11-01 13:15:55 +01:00
Eelco Dolstra
9072adece8 Fix broken logic for showing/hiding jobsets 2016-11-01 13:03:14 +01:00
Eelco Dolstra
ef711ce845 Handle Referer not having a trailing slash
Fixes #415.
2016-11-01 11:00:59 +01:00
Shea Levy
d6ccbeedbd doc: add basic docs about declarative projects
Conversion of Shea's *.md, added as a subsection.  Shea is left as author.
I made this new bit a separate file, though it might be questionable.
2016-10-31 18:33:17 +01:00
Eelco Dolstra
b3169ce438 Kill active build steps when builds are cancelled
We now kill active build steps when there are no more referring
builds. This is useful e.g. for preventing cancelled multi-hour TPC-H
benchmark runs from hogging build machines.
2016-10-31 14:58:29 +01:00
Eelco Dolstra
a816ef873d Warn against empty machines file 2016-10-31 11:40:36 +01:00
Eelco Dolstra
a2be29377e Hide hidden jobsets for project admins by default
This unclutters project pages.

Fixes #390.
2016-10-31 11:40:36 +01:00
Graham Christensen
3c8f00c76f Clean up unused images (#404)
* Drop information_{32,64,128,256}.png because it appears to be unused.

* Delete unused images
2016-10-30 17:06:44 +01:00
Eelco Dolstra
2b790ceefa Remove the pretty-printed log
It didn't work anymore due to the removal of nix-log2xml. And in any
case XSL is the work of the devil.
2016-10-27 14:43:17 +02:00
Eelco Dolstra
41a020e323 Fix typo 2016-10-27 13:43:05 +02:00
Eelco Dolstra
cc866bff1e Fix API tests
POST requests require a referrer now.

http://hydra.nixos.org/build/42775011
2016-10-27 13:15:09 +02:00
Eelco Dolstra
3b84d4711b Bump Nix 2016-10-26 15:10:56 +02:00
Eelco Dolstra
a0c8e2b055 Merge pull request #410 from LumiGuide/fix-hydra-eval-jobset-not-found
Allow hydra-eval-jobset to be found by the hydra-evaluator
2016-10-26 15:10:44 +02:00
Eelco Dolstra
0b00d51baf Prevent orphaned build steps
If two active steps of the same build failed, then the first would be
marked as "failed", but the second would end up as "orphaned", causing
it to be marked as "aborted" later on. Now it's correctly marked as
"failed".
2016-10-26 14:42:28 +02:00
Eelco Dolstra
8e1d791d0c Truncate the log just before starting the remote build
This gets rid of all those remote substitution messages that were
polluting the build logs.
2016-10-26 13:41:51 +02:00
Bas van Dijk
cba7e7e0e2 Allow hydra-eval-jobset to be found by the hydra-evaluator
Without this I got the following error in my journal:

  Oct 25 22:42:29 mymachine hydra-evaluator[4085]: starting evaluation of jobset ‘myproject:.jobsets’
  Oct 25 22:42:29 mymachine hydra-evaluator[4085]: timeout: failed to run command ‘hydra-eval-jobset’: No such file or directory
  Oct 25 22:42:29 mymachine hydra-evaluator[4085]: evaluation of jobset ‘myproject:.jobsets’ finished with status 32512
2016-10-25 22:55:32 +02:00
Eelco Dolstra
a12e9478e7 When manually scheduling an eval, force re-instantiation of store derivations
Without this, if (failed or aborted) derivations have been
garbage-collected, there is no way to restart them, which is very
annoying. Now we set a forceEval flag in the jobset to cause it to be
re-evaluated even if none of the inputs have changed.
2016-10-24 20:20:20 +02:00
Eelco Dolstra
140cbe9302 Set utf-8 charset for raw logs
Also fix incorrect use of Content-Encoding header in View::Plain.
2016-10-24 17:14:33 +02:00
Eelco Dolstra
3fcfa20d1a Fix regression caused by ee2e9f53
‘basicDrv.inputSrcs’ also contains the outputs of inputDrvs. These
don't necessarily exist in the local store, so copying them may cause
an exception. We should only copy the real inputSrcs.
2016-10-24 16:49:11 +02:00
Eelco Dolstra
f7ff7f741b Fix a couple of encoding issues 2016-10-24 16:49:11 +02:00
Graham Christensen
3586bf28e4 Build status: copy the alt attribute to the title attribute for on-hover tool tips. (#405) 2016-10-23 13:21:21 +02:00
Eelco Dolstra
881d3bc017 Bump Nix 2016-10-21 19:19:28 +02:00
Eelco Dolstra
a3efdcdfd9 Use std::regex 2016-10-21 18:06:26 +02:00
Eelco Dolstra
5d8fbc6ca1 Fix referer check 2016-10-21 17:56:34 +02:00
Eelco Dolstra
c928c41ee1 Add XSRF protection for POST requests
Some Hydra API requests were vulnerable to XSRF attacks, e.g. you
could have a form on another website using http://hydra/logout as the
form action. So we now require POST requests to come from the same
origin.

Reported by Hans-Christian Esperer.
2016-10-20 16:11:33 +02:00
Eelco Dolstra
bbe45ed844 Remove Persona support
Persona is no longer supported by Mozilla, so let's remove it.
2016-10-20 14:14:04 +02:00
Eelco Dolstra
e0b2921ff2 Concurrent hydra-evaluator
This rewrites the top-level loop of hydra-evaluator in C++. The Perl
stuff is moved into hydra-eval-jobset. (Rewriting the entire evaluator
would be nice but is a bit too much work.) The new version has some
advantages:

* It can run multiple jobset evaluations in parallel.

* It uses PostgreSQL notifications so it doesn't have to poll the
  database. So if a jobset is triggered via the web interface or from
  a GitHub / Bitbucket webhook, evaluation of the jobset will start
  almost instantaneously (assuming the evaluator is not at its
  concurrency limit).

* It imposes a timeout on evaluations. So if e.g. hydra-eval-jobset
  hangs connecting to a Mercurial server, it will eventually be
  killed.
2016-10-14 14:22:12 +02:00
Eelco Dolstra
16feddd5d4 Drop obsolete -laws-cpp-sdk-s3 2016-10-14 14:22:12 +02:00
Eelco Dolstra
dd5af7637d Remove finally.hh 2016-10-14 14:22:12 +02:00
Domen Kožar
386a972244 README: fix manual links, fixes #401 2016-10-13 13:36:09 +02:00
Domen Kožar
607eeda9bb svn.nixos.org -> github.com 2016-10-12 18:00:34 +02:00
Eelco Dolstra
7221bd7e5a manual: Add index.html 2016-10-10 15:52:11 +02:00
Eelco Dolstra
303718dbd6 Doh 2016-10-10 15:26:50 +02:00
Eelco Dolstra
0b5a7472be Add a job for the manual 2016-10-10 15:26:18 +02:00
Eelco Dolstra
633724cc8a services.hydra -> services.hydra-dev
Since Nixpkgs 16.09 contains a Hydra module, we were getting a
conflict. I guess we should have a way to override modules in
Nixpkgs...
2016-10-10 11:29:15 +02:00
Eelco Dolstra
2f0d2f8d91 Bump Nix 2016-10-10 11:18:17 +02:00
Eelco Dolstra
ee2e9f5335 Update to reflect BinaryCacheStore changes
BinaryCacheStore no longer implements buildPaths() and ensurePath(),
so we need to use copyPath() / copyClosure().
2016-10-07 20:23:05 +02:00
Eelco Dolstra
fb0d2d2dda Build against the bleeding edge of Nix 2016-10-06 17:26:12 +02:00
Eelco Dolstra
e94ef4627c Tests: Clear $NIX_REMOTE_SYSTEMS 2016-10-06 17:19:16 +02:00
Eelco Dolstra
f2724d088d Test: Show error output from hydra-queue-runner on timeout 2016-10-06 17:18:59 +02:00
Eelco Dolstra
6a313c691b hydra-queue-runner: Fix build 2016-10-06 16:58:54 +02:00
Alexander Ried
7089142fdc Add error/warnings for deprecated store specification 2016-10-06 15:10:14 +02:00
Alexander Ried
a73f211bf2 Use store-api for binary cache instantiation 2016-10-06 15:09:44 +02:00
Alexander Ried
1c2f6281b9 Remove signing parameter (nix#f435f82) 2016-10-06 15:09:12 +02:00
Alexander Ried
232e6e8556 Replace buildVerbosity with verboseBuild (nix#5761827) 2016-10-06 15:08:02 +02:00
Alexander Ried
492d16074c Remove s3binarystore (moved to nix in d155d80) 2016-10-06 15:07:21 +02:00
Eelco Dolstra
706e06e8d7 hydra-eval-jobs: Fix build 2016-10-06 15:05:05 +02:00
Eelco Dolstra
934829a1a9 Remove NetStatsd since it's also in Nixpkgs 2016-10-06 14:50:59 +02:00
Eelco Dolstra
c9ab3b9ffd README.md: Point to the manual
Let's not duplicate the hacking instructions here (especially since
they were actually wrong).
2016-10-06 14:37:47 +02:00
Eelco Dolstra
b1512a152a Fix build failure on GCC 5.4 2016-09-30 17:05:07 +02:00
Michele Guerini Rocco
fb5e7f9570 Use the new logo (#396) 2016-09-29 13:08:15 +02:00
Eric Sagnes
dedcb76bed module: add default to buildMachinesFiles (#372) 2016-08-20 19:50:12 +02:00
Eelco Dolstra
682b4bcc73 Merge pull request #311 from domenkozar/product-list-table
product list: convert to a proper table
2016-08-19 13:40:42 +02:00
Eelco Dolstra
b03e3c593c Merge pull request #338 from expipiplus1/apache-include
Enable apache style includes in the config file
2016-08-19 13:32:44 +02:00
Shea Levy
5962367ffc Send BuildFinished notifications on cached build results.
Fixes #342
2016-08-17 06:40:12 -04:00
Domen Kožar
2840a5e089 push_github: return empty response instead of a template, fixes #309 2016-08-17 00:21:18 +02:00
Joe Hermaszewski
12194447ee GitHub push suffix (#332)
* Fix api/push-github

Fixes #309

* Don't require .git suffix on jobset inputs
2016-08-17 00:00:09 +02:00
Domen Kožar
03e8538746 Merge pull request #331 from expipiplus1/github-push
Fix api/push-github
2016-08-16 23:59:12 +02:00
Eelco Dolstra
71440e7bd7 Merge pull request #379 from domenkozar/sort-inputs-tables
Sort inputs table
2016-08-12 14:10:14 +02:00
Domen Kožar
c103163825 Sort inputs table 2016-08-12 13:05:28 +02:00
Eelco Dolstra
7b3dfe8363 Merge pull request #377 from domenkozar/pixz
Use pixz instead of bzip2 for compressing nars
2016-08-12 12:41:51 +02:00
Domen Kožar
23bf99b8e2 Use pixz instead of bzip2 for compressing nars
According to following two benchmarks:

- https://www.rootusers.com/gzip-vs-bzip2-vs-xz-performance-comparison/
- http://catchchallenger.first-world.info/wiki/Quick_Benchmark:_Gzip_vs_Bzip2_vs_LZMA_vs_XZ_vs_LZ4_vs_LZO

xz has better compression ratio than bzip2 at lowest compression rate.

https://github.com/vasi/pixz has been chosen as it can scale compressing
over multiple cores linearly.

We're using this in snabblab for a month now and it has improved CPU
wise the main Hydra server.
2016-08-12 11:39:07 +02:00
Eelco Dolstra
dd32033657 hydra-update-gc-roots: Only keep outputs when in direct mode
This prevents the server from gradually filling up due to store paths
fetched by hydra-server that then get turned into a GC root by
hydra-update-gc-roots.
2016-07-12 19:23:10 +02:00
Domen Kožar
fe82a666d5 Merge pull request #360 from expipiplus1/failing-name
Print jobset name when evaluator fails
2016-07-12 10:27:33 +02:00
Joe Hermaszewski
35a67d19ba Print jobset name when evaluator fails 2016-07-11 17:37:09 +01:00
Domen Kožar
d317e2d49a Merge pull request #340 from expipiplus1/github-push-ssh
Trigger ssh like urls from github pushes
2016-06-27 09:45:28 +02:00
Joe Hermaszewski
02d56dda58 Trigger ssh like urls from github pushes
URLs like "git@github.com:owner/repo.git

This commit removed the need for a forward slash between 'github.com' and
'owner'.
2016-06-21 16:34:54 +01:00
Joe Hermaszewski
02baff987a Enable apache style includes in the config file 2016-06-19 16:59:24 +01:00
Joe Hermaszewski
eb9aba0ff4 Fix api/push-github
Fixes #309
2016-06-14 10:36:43 +01:00
Domen Kožar
6bcbabb4df Merge pull request #307 from groxxda/fix/trivial
Trivial fixes (readme, comment, missing dependency in release.nix)
2016-05-31 09:59:07 +01:00
Eelco Dolstra
a55942603a Provide a plugin hook for when build steps finish
Fixes #318.
2016-05-27 14:35:32 +02:00
Eelco Dolstra
f70946efca Allow public dashboards
Dashboards can now be marked as publically visible in the user
preferences. The dashboard URL has changed from /user/<name>/dashboard
to /dashboard/<name> because /user/<name> requires being logged in as
<name> or as an admin.
2016-05-27 14:35:32 +02:00
Domen Kožar
f3a3f8de46 Merge pull request #320 from abbradar/master
hydra-module: fix useSubstitutes configuration option
2016-05-26 19:25:25 +01:00
Nikolay Amiantov
6f10cd297b hydra-module: fix useSubstitutes configuration option 2016-05-26 14:16:47 +03:00
Domen Kožar
3bfce978e6 Merge pull request #298 from peti/master
hydra-module.nix: add 'useSubstitutes' option to control use of binary caches
2016-05-23 20:21:18 +01:00
Domen Kožar
1a99761a8e product-list: remove redundant Icon table header 2016-05-19 13:32:53 +01:00
Domen Kožar
026f891ed6 product list: convert to a proper table 2016-05-12 20:06:22 +01:00
Alexander Ried
2b7fd6e509 readme: update hacking section 2016-05-12 09:45:51 +02:00
Alexander Ried
51d21b9b91 hydra-module.nix: fix warning about deprecated types.list 2016-05-09 19:09:33 +02:00
Alexander Ried
2c78a92ac5 release.nix: add missing dependency on nix 2016-05-09 18:35:24 +02:00
Eelco Dolstra
615c10bcc4 Merge pull request #277 from shlevy/declarative-project
Enable declarative projects.
2016-05-09 16:16:20 +02:00
Shea Levy
aa7cc6d599 Declarative projects: Include the fetch info for the declarative input in the project eval 2016-05-09 08:54:27 -04:00
Shea Levy
4392d3e21d Enable declarative projects.
This allows fully declarative project specifications. This is best
illustrated by example:

* I create a new project, setting the declarative spec file to
  "spec.json" and the declarative input to a git repo pointing
  at git://github.com/shlevy/declarative-hydra-example.git
* hydra creates a special ".jobsets" jobset alongside the project
* Just before evaluating the ".jobsets" jobset, hydra fetches
  declarative-hydra-example.git, reads spec.json as a jobset spec,
  and updates the jobset's configuration accordingly:
{
    "enabled": 1,
    "hidden": false,
    "description": "Jobsets",
    "nixexprinput": "src",
    "nixexprpath": "default.nix",
    "checkinterval": 300,
    "schedulingshares": 100,
    "enableemail": false,
    "emailoverride": "",
    "keepnr": 3,
    "inputs": {
        "src": { "type": "git", "value": "git://github.com/shlevy/declarative-hydra-example.git", "emailresponsible": false },
        "nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs.git release-16.03", "emailresponsible": false }
    }
}
* When the "jobsets" job of the ".jobsets" jobset completes, hydra
  reads its output as a JSON representation of a dictionary of
  jobset specs and creates a jobset named "master" configured
  accordingly (In this example, this is the same configuration as
  .jobsets itself, except using release.nix instead of default.nix):
{
    "enabled": 1,
    "hidden": false,
    "description": "js",
    "nixexprinput": "src",
    "nixexprpath": "release.nix",
    "checkinterval": 300,
    "schedulingshares": 100,
    "enableemail": false,
    "emailoverride": "",
    "keepnr": 3,
    "inputs": {
        "src": { "type": "git", "value": "git://github.com/shlevy/declarative-hydra-example.git", "emailresponsible": false },
        "nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs.git release-16.03", "emailresponsible": false }
    }
}
2016-05-09 08:54:27 -04:00
Peter Simons
3ca0e50e01 hydra-module.nix: add 'useSubstitutes' option to control use of binary caches
Gives users who want to use binary caches a way to do so without messing
with module internals. Fixes https://github.com/NixOS/hydra/issues/297.
2016-05-06 10:30:54 +02:00
Eelco Dolstra
995f3b21db Merge pull request #303 from groxxda/fix/searchpath
release.nix use makeBinPath to construct PATH
2016-04-29 12:58:07 +02:00
Eelco Dolstra
fa335bf090 Merge pull request #302 from groxxda/fix/debugging
hydra-module: fix debug attribute
2016-04-29 12:57:45 +02:00
Eelco Dolstra
a2a9ff64b5 Merge pull request #300 from groxxda/patch-1
Update link to hydra nixexpression
2016-04-29 12:57:16 +02:00
Alexander Ried
3f5ccfc7f3 release.nix use makeBinPath to construct PATH
makeBinPath takes care to use the correct output.

nix-repl> lib.makeSearchPath "bin" [pkgs.nix]
"/nix/store/zpp83pr21ihxwsr15l6mkzwkr49zj71d-nix-1.11.2-dev/bin"

nix-repl> lib.makeBinPath [pkgs.nix]
"/nix/store/9n8c3g541qn43yjjs94f1a0m69wp8scg-nix-1.11.2/bin"
2016-04-29 04:23:54 +02:00
Alexander Ried
5777f246a5 hydra-module: fix debug attribute 2016-04-29 04:21:05 +02:00
Eelco Dolstra
b829be29b6 Lazy load Google and Persona login stuff 2016-04-28 17:13:02 +02:00
Eelco Dolstra
0c4e8b13a1 Update jquery and jquery-ui and use SRI checking 2016-04-28 15:13:54 +02:00
Alexander Ried
5232557b1a Update link to hydra nixexpression 2016-04-21 02:36:59 +02:00
Eelco Dolstra
b50a105ca7 S3BinaryCacheStore: Use disk cache 2016-04-20 15:29:40 +02:00
Eelco Dolstra
b2b978eda0 Fix JSON output for builds 2016-04-18 11:44:59 +02:00
Eelco Dolstra
afb86638cd Updates for negative .narinfo caching 2016-04-15 15:39:20 +02:00
Eelco Dolstra
177bf25d64 Queue monitor: Bail out earlier if a step has failed previously
Currently, the hydra.nixos.org queue contains 1000s of Darwin builds
that all depend on a stdenv-darwin that previously failed. However,
before, first createStep() would construct a dependency graph for each
build, then getQueuedBuilds() would discover that one of the steps had
failed previously and discard all those steps. Since the graph
construction involves a lot of uncached calls to isValidPath(), this
took several seconds per build.

Now createStep() detects the previous failure right away and bails
out.
2016-04-15 14:32:16 +02:00
Eelco Dolstra
2f0f7406d4 Merge pull request #292 from shlevy/git-rev-test
Add eval test for specific git revision
2016-04-14 20:05:00 +02:00
Eelco Dolstra
ef72569cc3 Merge pull request #280 from shlevy/github-status-api
Add a plugin to interact with the github status API.
2016-04-14 20:03:45 +02:00
Eelco Dolstra
7dad867498 Add smtpHost option 2016-04-13 16:46:24 +02:00
Eelco Dolstra
d6f188a01a Typo 2016-04-13 16:45:40 +02:00
Eelco Dolstra
fd20c726e1 Remove ssmtp from $PATH again
See 10cad61231.
2016-04-13 16:33:38 +02:00
Eelco Dolstra
b1e36b550c max-output-size -> max_output_size
To be consistent with other Catalyst/Hydra config option names.
2016-04-13 16:30:52 +02:00
Eelco Dolstra
077ed3f571 Periodically clear orphaned build steps
These are build steps that remain "busy" in the database even though
they have finished, because they couldn't be updated (e.g. due to a
PostgreSQL connection problem). To prevent them from showing up as
busy in the "Machine status" page, we now periodically purge them.
2016-04-13 16:30:52 +02:00
Eelco Dolstra
f3f661bac1 Reuse build products / metrics stored in the database
Previously, if the queue monitor thread encounters a build that Hydra
has previously built, it downloaded the output paths from the binary
cache, just to determine the build products and metrics. This is very
inefficient. In particular, when doing something like merging
nixpkgs:staging into nixpkgs:master, the queue monitor thread will be
locked up for a long time fetching files from S3, causing the build
farm to be mostly idle.

Of course this is entirely unnecessary, since the build
products/metrics are already in the Hydra database. So now we just
look up a previous build with the same output path, and copy the
products/metrics.
2016-04-13 16:30:52 +02:00
Eelco Dolstra
a7755678fe Drop unused BuildProducts.description column 2016-04-13 16:30:52 +02:00
Eelco Dolstra
8c7edb1005 Fix narrowing conversion 2016-04-13 16:30:52 +02:00
Eelco Dolstra
00c78440b1 Disambiguate "marking build as succeeded" message 2016-04-13 16:30:52 +02:00
Eelco Dolstra
ad834343b5 Fix build against current Nix master 2016-04-13 16:30:52 +02:00
Shea Levy
93f9846425 git-rev: Remove superfluous git tag 2016-04-12 16:30:42 -04:00
Shea Levy
10e036238c Add eval test for specific git revision 2016-04-12 16:27:11 -04:00
Shea Levy
ae24e7fb31 GithubStatus: Include the full job name and build ID in the context.
Build ID can be omitted by setting excludeBuildFromContext in config
2016-04-12 15:19:05 -04:00
Shea Levy
0d0b925af1 Add a plugin to interact with the github status API.
Mutliple <githubstatus> sections are possible:
* jobs: regexp for jobs to match
* inputs: the input which corresponds to the github repo/rev whose
  status we want to report. Can be repeated
* authorization: Verbatim contents of the Authorization header. See
  https://developer.github.com/v3/#authentication.
2016-04-12 14:42:01 -04:00
Shea Levy
9b37cb89ae Add buildStarted plugin hook 2016-04-12 14:42:01 -04:00
Eelco Dolstra
49f94bac3a Merge pull request #291 from elitak/typo
typo
2016-04-06 21:07:21 +02:00
Eric Litak
17035661f2 typo 2016-04-06 11:28:32 -07:00
Eelco Dolstra
68b636c1f2 Merge pull request #290 from svanderburg/master
Fix problem with delegating builds to localhost due to nix-store not being in the PATH
2016-04-06 16:21:07 +02:00
Sander van der Burg
cbd2e3a50d Fix problem with delegating builds to localhost due to nix-store not being in the PATH 2016-04-06 14:16:04 +00:00
Eelco Dolstra
74dfcc84e9 Make NIX_REMOTE_SYSTEMS configurable 2016-03-25 15:41:38 +01:00
Eelco Dolstra
ed88bbaac0 Set Vary to Accept
Otherwise, the browser may mix up HTML and JSON responses if it has
requested both. For example, hitting the back button to return to a
job metric page will show a JSON response, because that was the last
thing the browser fetched for that URL.

This requires Catalyst::Action::Rest >= 1.20.
2016-03-25 14:48:12 +01:00
Eelco Dolstra
32adc53070 Add tooltips to metrics showing the exact value of the data point 2016-03-25 14:32:36 +01:00
Eelco Dolstra
3e2911803d Add link to metrics 2016-03-25 13:57:17 +01:00
Eelco Dolstra
dab16fb26b Lazy load the metrics tab 2016-03-25 13:49:06 +01:00
Eelco Dolstra
7a72f64e5e Move chart code to common.js 2016-03-25 13:33:10 +01:00
Eelco Dolstra
dc2010eafc Fix rendering of metrics with dots in their name 2016-03-25 13:24:43 +01:00
Eelco Dolstra
ef63dd77e3 Fix metric alignment 2016-03-25 12:08:18 +01:00
Eelco Dolstra
759bd38ef2 Sort metrics by name 2016-03-25 11:56:25 +01:00
Eelco Dolstra
32fa392146 Fix hydra-queue-runner PATH 2016-03-23 12:35:55 +01:00
Eelco Dolstra
aa4c1fb1ab Fix version 2016-03-22 17:26:50 +01:00
Eelco Dolstra
6fc4dc4e27 /queue-summary: Show number of queued builds by system type 2016-03-22 17:03:26 +01:00
Eelco Dolstra
aba2356932 Restore path in nix-shell 2016-03-22 16:59:05 +01:00
Eelco Dolstra
ddc9f3cc6a Temporarily disable machines on any exception, not just connection failures 2016-03-22 16:54:40 +01:00
Eelco Dolstra
0aecd65e59 /queue-runner-status: Include info about temporarily disabled machines 2016-03-22 16:54:06 +01:00
Eelco Dolstra
1332463b02 Don't wrap C++ programs 2016-03-22 13:35:09 +01:00
Eelco Dolstra
4dfbe5c642 Don't pollute the source directory 2016-03-22 13:19:00 +01:00
Eelco Dolstra
e624652dd8 Use patched aws-sdk-cpp 2016-03-22 13:11:30 +01:00
Eelco Dolstra
a727643286 inNixShell considered harmful 2016-03-22 13:10:37 +01:00
Eelco Dolstra
74426e6820 Simplify running nix-shell
This also removes building a separate source tarball or building a PDF
manual since it's unlikely anybody cares.
2016-03-22 12:53:28 +01:00
Eelco Dolstra
ac23bd1539 Revert "Apply IndexBuildsOnJobFinishedId to unfinished builds only"
This reverts commit 1de5ce7a0e.
2016-03-16 17:04:20 +01:00
Eelco Dolstra
7d8bf1b0f2 Shorten host names 2016-03-16 15:23:56 +01:00
Eelco Dolstra
d5cffd4bc7 Make "Running builds" and "Machine status" pages faster 2016-03-16 15:19:18 +01:00
Eelco Dolstra
1de5ce7a0e Apply IndexBuildsOnJobFinishedId to unfinished builds only 2016-03-16 15:17:10 +01:00
Eelco Dolstra
520c8a5826 Use faster query to determine number of running builds
The previous query

  select count(*) from builds b left join buildsteps s on s.build = b.id where busy = 1 and finished = 0

is suddenly taking several minutes. Probably PostgreSQL decided to use
a suboptimal query plan.
2016-03-16 13:41:43 +01:00
Eelco Dolstra
405a43c171 Queue summary: Make rows clickable 2016-03-10 16:48:06 +01:00
Eelco Dolstra
5535bc28ca Tweak 2016-03-10 16:46:15 +01:00
Eelco Dolstra
60e7930d2b Bump memory limit a bit 2016-03-10 16:46:01 +01:00
Eelco Dolstra
75e7b35477 Fix retry of transient failures 2016-03-10 16:44:26 +01:00
Eelco Dolstra
de71d5b622 Fix showing machine name for aborted build steps 2016-03-10 16:42:36 +01:00
Eelco Dolstra
33da40f272 Doh 2016-03-09 17:31:57 +01:00
Eelco Dolstra
4b9c76e502 hydra-queue-runner: Ensure regular status dumps 2016-03-09 17:11:34 +01:00
Eelco Dolstra
4151be7e69 Make the output size limit configurable
The maximum output size per build step (as the sum of the NARs of each
output) can be set via hydra.conf, e.g.

  max-output-size = 1000000000

The default is 2 GiB.

Also refactored the build error / status handling a bit.
2016-03-09 17:00:09 +01:00
Eelco Dolstra
dc790c5f7e Fix bad format string 2016-03-09 16:59:35 +01:00
Eelco Dolstra
80ff78b1b6 Unify build and step status codes
Also remove the obsolete status code 5 from the database.
2016-03-09 15:30:43 +01:00
Eelco Dolstra
9127f5bbc3 hydra-queue-runner: Limit memory usage
When using a binary cache store, the queue runner receives NARs from
the build machines, compresses them, and uploads them to the
cache. However, keeping multiple large NARs in memory can cause the
queue runner to run out of memory. This can happen for instance when
it's processing multiple ISO images concurrently.

The fix is to use a TokenServer to prevent the builder threads to
store more than a certain total size of NARs concurrently (at the
moment, this is hard-coded at 4 GiB). Builder threads that cause the
limit to be exceeded will block until other threads have finished.

The 4 GiB limit does not include certain other allocations, such as
for xz compression or for FSAccessor::readFile(). But since these are
unlikely to be more than the size of the NARs and hydra.nixos.org has
32 GiB RAM, it should be fine.
2016-03-09 14:30:13 +01:00
Eelco Dolstra
49a4639377 Add a more concise queue page
The old page didn't scale very well if you have 150K builds in the
queue, in fact it tended to make browsers hang. The new one just
shows, for each jobset, the number of queued builds. The actual builds
can be seen by going to the corresponding jobset page and looking at
the evals.
2016-03-08 19:44:51 +01:00
Eelco Dolstra
b77a43b83d Get rid of "will retry" messages after "maybe cancelling..." 2016-03-08 13:09:39 +01:00
Eelco Dolstra
718fef29ef Keep track of time required to load builds 2016-03-08 13:09:29 +01:00
Eelco Dolstra
2feb17c681 Some more logging 2016-03-08 13:08:07 +01:00
Eelco Dolstra
45b237453a hydra-queue-runner: Recycle finishedDrvs
This should prevent the queue monitor thread from looking up the same
derivations over and over again.
2016-03-08 11:52:13 +01:00
Eelco Dolstra
2ab8e9a1e0 hydra-queue-runner: Fix handling of missing derivations
This barfed with 'queue monitor: ERROR: column "errormsg" of relation
"builds" does not exist' due to the removal of the errorMsg column.
2016-03-07 19:05:24 +01:00
Eelco Dolstra
e7ce225558 Fix build 2016-03-04 17:51:32 +01:00
Eelco Dolstra
76104accda Return unique store paths 2016-03-03 11:32:30 +01:00
Eelco Dolstra
86a2d6471c Fix a boost format string abort 2016-03-02 20:06:48 +01:00
Eelco Dolstra
e7655fdcbc Fix latest-finished 2016-03-02 18:06:20 +01:00
Eelco Dolstra
232ca8fea2 Fix build 2016-03-02 17:05:07 +01:00
Eelco Dolstra
e45bbfbef0 Fix .nixpkg channel uri
Fixes #274.
2016-03-02 15:38:40 +01:00
Eelco Dolstra
8b4f90b0d4 .nixpkgs: Drop obsolete manifest URI 2016-03-02 15:24:23 +01:00
Eelco Dolstra
ec82bc2517 Add /eval/NNN/store-paths action to return store paths in an eval
Needed by the NixOS channel scripts since we can no longer get a
MANIFEST from Hydra.
2016-03-02 15:17:22 +01:00
Eelco Dolstra
a74251af2b Disable channels on binary cached based Hydra instances 2016-03-02 15:08:53 +01:00
Eelco Dolstra
f09b92e289 Remove another obsolete SSL variable 2016-03-02 15:03:54 +01:00
Eelco Dolstra
2d6b585cb3 Merge branch 'slack-plugin' of https://github.com/shlevy/hydra 2016-03-02 15:03:03 +01:00
Shea Levy
6eb1c5bf19 Remove PERL_LWP_SSL_CA_FILE.
Real fix is NixOS/nixpkgs@bd7f379a3f
2016-03-02 09:02:48 -05:00
Eelco Dolstra
b98a061c24 Add some instrumentation to keep track of dispatcher cost 2016-03-02 14:18:39 +01:00
Eelco Dolstra
6beee0ab49 Fix segfault sorting runnable steps
Same problem as d744362e4a.

    at /nix/store/ksvsbr7pg4z69bv6fbbc8h7x7rm2104m-gcc-4.9.3/include/c++/4.9.3/bits/predefined_ops.h:166
    __last@entry=..., __comp=...) at /nix/store/ksvsbr7pg4z69bv6fbbc8h7x7rm2104m-gcc-4.9.3/include/c++/4.9.3/bits/stl_algo.h:1827
    __comp=...) at /nix/store/ksvsbr7pg4z69bv6fbbc8h7x7rm2104m-gcc-4.9.3/include/c++/4.9.3/bits/stl_algo.h:4717
2016-03-02 13:59:24 +01:00
Shea Levy
0f5937503e SlackNotification: Use bigger images 2016-03-01 11:25:18 -05:00
Shea Levy
006ac1fc03 Add slack plugin.
Respects <slack> blocks in the hydra config, with attributes:

* jobs: a regexp matching the job name (in the format project:jobset:job)
* url: The URL to a slack incoming webhook
* force: If true, always send messages. Otherwise, only when the build status changes

Multiple <slack> blocks are allowed
2016-02-29 14:48:36 -05:00
Eelco Dolstra
bc958c508b Merge branch 'binary-cache' 2016-02-29 18:29:07 +01:00
Eelco Dolstra
7cd08c7c46 Warn if PostgreSQL appears stalled 2016-02-29 15:10:30 +01:00
Eelco Dolstra
922dc541c2 Add log message 2016-02-29 11:58:06 +01:00
Eelco Dolstra
ad035b5227 hydra-queue-runner: Enable core dumps 2016-02-28 14:09:04 +01:00
Eelco Dolstra
610a8d67ae Better AWS error messages 2016-02-26 22:40:27 +01:00
Eelco Dolstra
1693354506 Remove unnecessary call to hydra-queue-runner --unlock 2016-02-26 21:45:59 +01:00
Eelco Dolstra
1a055e7e9e Reduce severity level of some message 2016-02-26 21:31:08 +01:00
Eelco Dolstra
6bb860fd6e Add FIXME 2016-02-26 21:15:05 +01:00
Eelco Dolstra
e8cdfe5171 hydra-server: Don't barf if the binary cache public key can't be read 2016-02-26 21:14:40 +01:00
Eelco Dolstra
53ca41ef9f Use US standard S3 region 2016-02-26 20:57:47 +01:00
Eelco Dolstra
c635f5d0ea Fix Makefile.am 2016-02-26 19:54:55 +01:00
Eelco Dolstra
b1ce76c2b4 Fix test
nix-support/failed is supposed to be a file, not a directory.
2016-02-26 19:54:32 +01:00
Eelco Dolstra
07e5fc5618 Hackery to make downloads work when using a binary cache 2016-02-26 17:28:26 +01:00
Eelco Dolstra
b00bdefa98 Fix hydra-server signing 2016-02-26 17:28:16 +01:00
Eelco Dolstra
9de336de7c Proxy local binary caches via hydra-server 2016-02-26 17:27:30 +01:00
Eelco Dolstra
b9afaadfb3 Keep better bytesReceived/bytesSent stats 2016-02-26 16:17:05 +01:00
Eelco Dolstra
6d741d2ffa Prevent download of NARs we just uploaded 2016-02-26 15:21:44 +01:00
Eelco Dolstra
02190b0fef Support hydra-build-products on binary cache stores 2016-02-26 14:45:03 +01:00
Eelco Dolstra
8e24ad6f0d Sync with Nix 2016-02-25 10:58:31 +01:00
Eelco Dolstra
8321a3eb27 Sync with Nix 2016-02-24 14:04:31 +01:00
Eelco Dolstra
7b509237cd Bleh Automake 2016-02-22 18:05:15 +01:00
Eelco Dolstra
6c3ae36648 hydra-queue-runner: Get store mode configuration from hydra.conf
To use the local Nix store (default):

  store_mode = direct

To use a local binary cache:

  store_mode = local-binary-cache
  binary_cache_dir = /var/lib/hydra/binary-cache

To use an S3 bucket:

  store_mode = s3-binary-cache
  binary_cache_s3_bucket = my-nix-bucket

Also, respect binary_cache_{secret,public}_key_file for signing the
binary cache.
2016-02-22 17:23:06 +01:00
Eelco Dolstra
94817d77d9 BinaryCacheStore: Respect build-use-substitutes 2016-02-22 17:21:39 +01:00
Eelco Dolstra
5668aa5f71 After uploading a .narinfo, add it to the LRU cache 2016-02-20 10:35:16 +01:00
Eelco Dolstra
88a05763cc Pool local store connections 2016-02-20 00:04:08 +01:00
Eelco Dolstra
1cefd6cac8 Fix log message 2016-02-20 00:02:37 +01:00
Eelco Dolstra
a593ebc58e Add missing file 2016-02-19 20:58:40 +01:00
Eelco Dolstra
2b76094a23 S3BinaryCacheStore::isValidPath(): Do a GET instead of HEAD 2016-02-19 17:41:11 +01:00
Eelco Dolstra
bd76f9120a Cache .narinfo lookups 2016-02-19 16:19:40 +01:00
Eelco Dolstra
a0f74047da Keep some statistics for the binary cache stores 2016-02-19 14:24:23 +01:00
Eelco Dolstra
dc4a00347d Use a single BinaryCacheStore for all threads
This will make it easier to do caching / keep stats. Also, we won't
have S3Client's connection pooling if we create multiple S3Client
instances.
2016-02-18 17:31:19 +01:00
Eelco Dolstra
00a7be13a2 Make queue runner internal status available under /queue-runner-status 2016-02-18 17:11:46 +01:00
Eelco Dolstra
8c9fc677c1 Typo 2016-02-18 16:43:24 +01:00
Eelco Dolstra
db3fcc0f5e Enable substitution on the build machines
If properly configured, this allows them to get store paths directly
from S3, rather than having to receive them from the queue runner.
2016-02-18 16:42:05 +01:00
Eelco Dolstra
2d40888e2e Add an S3-backed binary cache store 2016-02-18 16:18:50 +01:00
Eelco Dolstra
0e254ca66d Refactor local binary cache code into a subclass 2016-02-18 14:06:17 +01:00
Eelco Dolstra
a992f688d1 Rename class 2016-02-18 13:02:20 +01:00
Eelco Dolstra
de77cc2910 Rename file 2016-02-18 13:02:20 +01:00
Rob Vermaas
633381a501 Merge pull request #271 from gulrotkake/master
Construct uri using uri_for, which respects X-Request-Base.
2016-02-18 10:27:20 +01:00
Michael Mortensen
d9a4f7a211 Construct uri using uri_for, which respects X-Request-Base. 2016-02-17 21:27:44 +01:00
Eelco Dolstra
ce5790285a Merge remote-tracking branch 'origin/master' into binary-cache 2016-02-17 11:54:59 +01:00
Eelco Dolstra
d7a123fcd4 Keep track of the time we spend copying to/from build machines 2016-02-17 10:30:23 +01:00
Eelco Dolstra
25022bf5fd hydra-queue-runner: Support generating a signed binary cache 2016-02-16 16:41:42 +01:00
Eelco Dolstra
744cee134e hydra-queue-runner: Compress binary cache NARs using xz 2016-02-15 21:56:53 +01:00
Eelco Dolstra
2d0dd7fb49 hydra-queue-runner: Write directly to a binary cache 2016-02-15 21:10:29 +01:00
Eelco Dolstra
e46acbf05b Remove the errorMsg column from the Builds table
The queue runner no longer uses this field, and it doesn't provide
very interesting historical data (mostly SSH failures), but it takes
up a lot of space. Also, it contained some bad UTF-8 which was
preventing an upgrade to Postgres 9.5, so a good occasion to get rid
of it.
2016-02-12 17:21:55 +01:00
Eelco Dolstra
5c5bb3762c Fix display of builds that don't have an eval
Like http://hydra.nixos.org/build/22872.
2016-02-12 16:27:25 +01:00
Eelco Dolstra
92d8b59361 Process Nix API changes 2016-02-11 15:59:47 +01:00
Eelco Dolstra
993647d1e3 Use Google's verifier 2016-01-14 12:54:47 +01:00
Eelco Dolstra
5a580b1bb2 Add support for logging in via a Google account
The required configuration in hydra.conf:

  enable_google_login = 1
  google_client_id = 238429sdjkds....apps.googleusercontent.com

and optionally persona_allowed_domains to restrict to one or more
domains.
2016-01-13 17:32:52 +01:00
Eelco Dolstra
f11ce7e219 Bump evaluation timeout to 6 hours
This is necessary given the current size of the Nixpkgs/NixOS
jobsets. Once we have a Nix store + Postgres on SSD, we can reduce
this again.

Should really make this configurable...
2016-01-07 16:19:54 +01:00
Eelco Dolstra
0ca6bb79af Shut up warning 2016-01-07 16:19:54 +01:00
Eelco Dolstra
97f8c61928 Fix hydra-queue-runner --build-one 2015-12-29 17:53:33 +01:00
Eelco Dolstra
29db16bc69 Fix 'Can't locate object method "buildstepoutputs"'
Template::Toolkit braindamage strikes again. See
8f85fe67d4.
2015-12-15 11:55:57 +01:00
Eelco Dolstra
b081133dcc Move GC roots to /nix/var/nix/gcroots/hydra
The uid split a while back caused the web interface to create GC roots
in /nix/var/nix/gcroots/per-user/hydra-www, where they wouldn't be
purged by hydra-update-gc-roots. Thus restarted builds would
accumulate forever. The fix is to keep the roots in a shared directory
with gid=hydra.
2015-12-14 13:31:24 +01:00
Eelco Dolstra
e04fb5c8e7 Sort build steps 2015-12-14 13:01:35 +01:00
Eelco Dolstra
8f7614030e Better fix for dots in jobset names 2015-11-17 11:31:11 +01:00
Eelco Dolstra
ea80a75204 Move getBaseUrl 2015-11-17 11:21:20 +01:00
Rob Vermaas
dddb9a281d Allow dots in job specifier of input type 'Previous build' 2015-11-17 08:36:46 +00:00
Eelco Dolstra
b6d2c6f03a Further fix for the channel regression 2015-11-02 14:58:23 +01:00
aszlig
20b412224e ListBuilds: Fix legacy channel URLs.
Regression introduced by 1fdc258de0.

The commit introduced a channel/custom PathPart which uses the new
custom channel expressions, but I forgot to remove CaptureArgs, so the
URL really is channel/latest/ignored-value.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Reported-by: Peter Simons <simons@cryp.to>
2015-11-02 14:51:42 +01:00
Eelco Dolstra
c087472c71 Remove superfluous "has" function 2015-11-02 14:29:12 +01:00
Eelco Dolstra
a5879cbeb8 Consistent terminology: "Clear" -> "Cancel" 2015-11-02 14:22:25 +01:00
Eelco Dolstra
e1f9a209c5 Fix cancelling non-current builds 2015-11-02 14:20:27 +01:00
Eelco Dolstra
1b1fdb3f8d Revert "Don't wrap hydra-queue-runner / hydra-eval-jobs"
This reverts commit f8ee98f455.
2015-10-31 15:32:19 +01:00
Eelco Dolstra
2d128d2a6f Don't show redundant "removing machine..." messages 2015-10-30 18:22:43 +01:00
Eelco Dolstra
f8ee98f455 Don't wrap hydra-queue-runner / hydra-eval-jobs 2015-10-30 18:13:23 +01:00
Eelco Dolstra
53d270c007 Enable debug info 2015-10-30 18:12:30 +01:00
Eelco Dolstra
d8d188301d Fix division-by-zero crash
Not clear why step_->jobsets was empty...
2015-10-30 18:01:48 +01:00
Eelco Dolstra
1ff48da3d3 int2String -> std::to_string 2015-10-30 18:01:38 +01:00
Eelco Dolstra
19b52e907f Add action to restart all failed builds in an eval 2015-10-28 15:04:12 +01:00
Eelco Dolstra
b9ebd38edf Fix restarting builds
Failed paths were not cleared because the $builds query becomes empty
as soon as the "finished" flag has been cleared. So this needs to be
done last.
2015-10-28 14:54:54 +01:00
Eelco Dolstra
bbe1fb2f9f Ignore non-existence of IndexBuildsOnFinishedBusy
Apparently for some reason not all Hydra installations had this
index. Another -1 for non-declarative schema definition languages.
2015-10-28 14:09:45 +01:00
Eelco Dolstra
d22e7ac03d hydra-compress-logs: Use bzip2 -f flag 2015-10-27 16:10:02 +01:00
Eelco Dolstra
4d1816b152 Remove obsolete Builds columns and provide accurate "Running builds"
This removes the "busy", "locker" and "logfile" columns, which are no
longer used by the queue runner. The "Running builds" page now only
shows builds that have an active build step.
2015-10-27 15:37:17 +01:00
Eelco Dolstra
9fb91460e3 Restart jobset evals efficiently
Fixes

  DBIx::Class::Storage::DBI::_dbh_execute(): DBI Exception: DBD::Pg::st execute failed: ERROR: stack depth limit exceeded
  HINT: Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate. [for Statement "UPDATE Builds SET busy = ?, finished = ?, iscachedbuild = ?, locker = ? WHERE ( ( id = ? OR id = ? OR ...
2015-10-27 13:43:19 +01:00
Eelco Dolstra
53c80d9526 getQueuedBuilds(): Periodically stop to handle priority bumps
Previously, priority bumps could take a long time to get noticed if
getQueuedBuilds() was busy processing zillions of queue
additions. (This was made worse by the reintroduction of substitute
checking.)
2015-10-22 17:00:46 +02:00
Eelco Dolstra
71bf7e02d5 Use nix::willBuildLocally() 2015-10-21 15:44:29 +02:00
Eelco Dolstra
30823078c4 Merge branch 'custom-channels' of https://github.com/aszlig/hydra 2015-10-16 17:00:29 +02:00
Eelco Dolstra
4759323514 Tweak 2015-10-16 16:59:07 +02:00
dantheho
8ecd84c160 Fix schema update for schedulingShares 2015-10-16 16:58:37 +02:00
aszlig
92e85f05e2 hydra.sql: Make isChannel a not null column.
We have this set in upgrade-42.sql, so it's better to stay consistent
with the basic SQL file to avoid problems with new Hydra installations.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Reported-by: Eelco Dolstra <eelco.dolstra@logicblox.com>
2015-10-14 21:37:30 +02:00
Eelco Dolstra
7b9f488949 Check Nix version 2015-10-14 13:17:24 +02:00
Eelco Dolstra
1a92f971d4 Restart: Clear failed dependencies 2015-10-09 15:39:41 +02:00
Eelco Dolstra
3fa3e6414c Fix "Use of uninitialized value $mode" 2015-10-09 15:06:57 +02:00
Eelco Dolstra
ca58e97691 Prevent inputs from being garbage collected during evaluation
There is still a tiny window between the calls to nix-prefetch-* and
addTempRoot. This could be eliminated by adding a "-o" option to
nix-prefetch-*, or by not using those scripts at all (and use
addToStore directly).
2015-10-09 12:50:23 +02:00
Eelco Dolstra
d959afebe1 Store unset descriptions etc. as nulls 2015-10-08 12:37:56 +02:00
Eelco Dolstra
4b31b23c04 Handle attrsets in meta.license (i.e. lib.licenses) 2015-10-08 11:56:30 +02:00
Eelco Dolstra
b8ff29f0db Periodically compress logs 2015-10-07 13:12:24 +02:00
Eelco Dolstra
8e8e31ce86 Re-implement log size limits
The old queue runner already had this. However, we now store "log
limit exceeded" as a separate status code in the database.
2015-10-06 17:35:08 +02:00
Eelco Dolstra
82504fe010 hydra-queue-runner: Use substitutes
This allows Hydra to use binaries from available binary caches. It
makes the queue monitor thread quite a bit slower, so if you don't
want to use binary caches, it's better to add "--option
build-use-substitutes false" to the hydra-queue-runner invocation.

Fixed #243.
2015-10-05 14:57:44 +02:00
Eelco Dolstra
ae2cc61be6 Fix hydra.queue.machines.total stat
This was broken by the fact that "machines" now also contains
removed/disabled machines.
2015-09-22 12:59:19 +02:00
Eelco Dolstra
f8141fdc98 Set propagatedFrom for cached failed build steps 2015-09-11 15:55:26 +02:00
Eelco Dolstra
2dc9b9e32a Don't show "localhost" as machine for cached failed build steps 2015-09-11 14:12:07 +02:00
Eelco Dolstra
aea1ed7445 hydra-evaluator: Fix error handling in fetching inputs
This caused bogus "cannot find the input containing the job
expression" errors.
2015-09-11 13:49:46 +02:00
aszlig
99cbe06b0d channel-contents: Fix display of last paragraph.
The last paragraph states about package installation of the "following"
jobs, but it only applies to generic channels, so let's only display it
there.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:39:55 +02:00
aszlig
8b4f51f657 Channel.pm: Actually deliver channel expressions.
So this is the final part which is needed in order to be able to deliver
custom channels, everything else is now just polishing.

We do this by simply redirecting to the build product download URL and
we use binary_cache_url the same way as in NixChannel.pm.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:39:55 +02:00
aszlig
db0ef9e49b Tie custom channels into channel-contents.tt.
We should now get an overview and help text on how to add a particular
channel and also a bit of information about the builds that are required
for a channel to get upgraded.

Right now we only select the latest successful build in the latest
successful evaluation, so if someone wants to have more information about
which channel has failed, (s)he still has to look at the "Channels" tab
of the jobset.

We can make this more fancy at some later point if this is really
needed, because right now we're only interested in the latest build,
because it's the only thing necessary to deliver the channel contents.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:39:55 +02:00
aszlig
f1dd08afc8 build.tt: Fix reference to build.ischannel.
It's actually lower-case _despite_ the spelling in the SQL file(s),
because the schema auto-generator from DBIx::Class doesn't take it into
account because it's working on SQLite and the latter seems to ignore
case.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:39:55 +02:00
aszlig
d1de12cac1 product-list: Handle channel along with "file".
We want to have contents and detauls of channel expressions as well and
we already have that in product.type == file, so why not reuse the same
for the channel expression?

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:38:45 +02:00
aszlig
c9aadd8b7d Jobset.pm: Factor out build->eval mapping.
We now have a searchBuildsAndEvalsForJobset, which creates such a
mapping for us, so we don't need to duplicate code in jobs_tab and
channels_tab.

Also, we're going to use this for the overview of a particular channel
as well, so it makes sense to put it in CatalystUtils instead of
directly in Jobset.pm.

Instead of eval->jobs, it's now eval->builds, because it's really an
aggregate over the builds schema, rather than the job schema.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:38:45 +02:00
aszlig
1fdc258de0 ListBuilds: Simplify nix channel dispatcher.
We only allow channel/latest anyway, so it really doesn't make sense to
explicitly specify this in the PathPart and provide other dispatcher
once we have more than just "latest", which greatly simplifies the
dispatch tree.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:38:44 +02:00
aszlig
ed361a0145 Build.pm: Don't get isChannel using buildproducts.
We now have a column for that, so no need for counting rows which was a
bit inefficient anyway, because we only would have needed the first row
in the result.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:38:44 +02:00
aszlig
ba7402ed6c Jobset.pm: Don't show channels in "Jobs" tab.
Now that we have our dedicated "Channels" tab, there is no need anymore
to show redundant information.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:36:38 +02:00
aszlig
8f7486cd9c Jobset.pm: Detect channels by isChannel attribute.
We now no longer need that additional join of the build outputs and can
solely use the isChannel column of the Builds table to determine whether
it's a channel build.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:36:38 +02:00
aszlig
06b76ab275 Add isChannel column and meta attribute.
This is to properly separate channels from regular jobs and also make
sure that we can always iterate on them, no matter whether the build has
failed. The reason why we were not able to do this until now was because
we were iterating on the build products, and whenever some constituent
of a channel job has failed, we didn't get a build output.

So whenever there is a meta.isHydraChannel, we can now properly
distinguish it from the other jobs.

I still don't have any clue, why "make -C src/sql update-dbix" without
*any* modifications tries to create additional schema definitions. But
I've checked the md5sums of the existing schema definitions and they
don't seem to match, so it seems that they already have been tampered
with.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:36:38 +02:00
aszlig
a235de3ad7 Make channels a product type instead of subtype.
Now we can provide different channel expressions for one particular
channel build. Not sure yet how this would be useful, but I found it
more appropriate to use a type instead of a subtype of "file".

This should get us consistent with the provious commit.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:12:13 +02:00
aszlig
f6bb8afc30 Show build products on aggregates with channels.
This is to get a bit more consistency among channel builds but doesn't
do a radical change on the display. Ideally we may want to have a
channel overview with all the constituents and a small help showing how
the user can add the channel.

Unfortunately, this also introduces an inconsistency: We previously used
the *subtype* "channel", but now we're expecting "channel" as the type
of the product, so we need to change this for the channels overview as
well.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:12:12 +02:00
aszlig
7b60aed5ed jobset: Add a new "channels" tab.
It's very similar to "jobs" and the code is pretty much the same, except
that we don't do filtering on it. At least it doesn't waste space for a
filter option when there are usually WAY less channel jobs than ordinary
jobs.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:08:24 +02:00
aszlig
19e7114f0e Add channel as a product type.
Currently I'm using a (not very well) downscaled version of the NixOS
logo, so we want to replace it by a proper image ASAP.

Other than that, the idea is to have something like this in
hydra-build-products:

file channel $out/channel.tar.bz2

Right now of course, it's only displayed at the corresponding builds, so
we might want to have aggregates on all channels for a project, jobset
or maybe even single jobs?

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-09-10 17:08:24 +02:00
Eelco Dolstra
c1dd3fe4be Machine status page: Show disabled machines and some machine stats 2015-09-09 16:51:43 +02:00
Eelco Dolstra
6075ac6fed Remove localhost hack 2015-09-09 16:50:59 +02:00
Eelco Dolstra
ee9bf7ace7 Account steps with preferLocalBuild as a separate system type
They will show up in machineTypes as (e.g.) x86_64-linux:local instead
of x86_64-linux. This is to prevent the Hydra provisioner from
creating machines for steps that are supposed to be executed locally.
2015-09-02 13:42:25 +02:00
Eelco Dolstra
7e954aff03 Keep machine stats even when a machine is removed from the machines file
This is important for the Hydra provisioner, since it needs to be able
to see whether a disabled machine still has jobs running on it.
2015-09-02 13:31:47 +02:00
Eelco Dolstra
2d116d758a Return JSON for /eval 2015-09-02 13:13:55 +02:00
Eelco Dolstra
4f018b0612 Include the eval IDs in the JSON /build result 2015-09-02 12:57:58 +02:00
Eelco Dolstra
2b9bf7526d hydra-send-stats: Keep track of the number of machines 2015-08-27 12:05:06 +02:00
Eelco Dolstra
68796b2762 Fix email notification 2015-08-26 17:25:00 +02:00
Eelco Dolstra
2a7fbd57cc Allow the machines file to specify host public keys
It's easier for the Hydra provisioner to put host public keys in the
machines file than to separately manage the known_hosts file
(especially when the provisioner runs on a different machine).
2015-08-26 13:43:02 +02:00
Eelco Dolstra
88d7eb5247 Remove double entry for localhost on machines status page 2015-08-26 13:01:45 +02:00
Eelco Dolstra
7aa52517e9 Support multiple machines files
This is primarily useful for the Hydra provisioner, which can write
its machines to another file than /etc/nix/machines.
2015-08-25 15:34:53 +02:00
Rob Vermaas
442bed3b59 Force bash usage in dev-shell. Should fix #236 2015-08-17 15:47:58 +00:00
Eelco Dolstra
7a654259ff Wake the dispatcher when the machines file has changed 2015-08-17 15:48:10 +02:00
Eelco Dolstra
092d60735b Keep track of wait time per system type
I.e., how much time the currently runnable steps per system type have
been waiting. This is useful for deciding whether to provision more
machines.
2015-08-17 15:45:44 +02:00
Eelco Dolstra
99bfc37764 Don't abort steps that have an unsupported system type
This is necessary because the required system type can become
available later (e.g. by being provisioned by the
auto-scaler). However, in the future, we may want to fail steps if
they have been unsupported for more than a certain amount of time.
2015-08-17 15:10:41 +02:00
Eelco Dolstra
ea1eb2e3fb Keep track of requiredSystemFeatures in the machine stats
For example, steps that require the "kvm" feature may require a
different kind of machine to be provisioned. This can also be used to
require performance-sensitive tests to run on a particular kind of
machine, e.g., by setting requiredSystemFeatures to something like
"ec2-i2.8xlarge".
2015-08-17 14:37:57 +02:00
Eelco Dolstra
a6e3cb53b9 Use /usr/bin/env to find perl
This is nicer in nix-shell.
2015-08-17 14:18:20 +02:00
Eelco Dolstra
d571e44b86 Keep stats for the Hydra auto scaler
"hydra-queue-runner --status" now prints how many runnable and running
build steps exist for each machine type. This allows additional
machines to be provisioned based on the Hydra load.
2015-08-17 13:50:41 +02:00
Eelco Dolstra
69e9f73cf6 Use nixUnstable for the tarball
Not needed for building, only for dev-shell.
2015-08-17 11:17:54 +02:00
Eelco Dolstra
b0c8eecd37 Merge branch 'build-ng' 2015-08-12 20:32:48 +02:00
Eelco Dolstra
48d6f0de2a Fix the API test 2015-08-12 16:07:19 +02:00
Eelco Dolstra
62cd9d18b6 Check for a valid number of shares 2015-08-12 15:36:55 +02:00
Eelco Dolstra
006d105f93 Fix syntax error 2015-08-12 14:53:34 +02:00
Eelco Dolstra
d4759c1da2 hydra-queue-runner: Detect changes to the scheduling shares 2015-08-12 13:17:56 +02:00
Eelco Dolstra
2e3899ed27 Don't set Expires header for logs of unfinished builds/steps 2015-08-12 12:22:14 +02:00
Eelco Dolstra
576dc0c120 For completeness, re-implement meta.schedulingPriority 2015-08-12 12:05:43 +02:00
Eelco Dolstra
b7965df928 Load the queue in order of global priority 2015-08-11 02:14:34 +02:00
Eelco Dolstra
97f11baa8d Revive jobset scheduling
(I.e. taking the jobset scheduling share into account.)
2015-08-11 01:31:56 +02:00
Eelco Dolstra
cf9516baa4 Merge pull request #231 from shlevy/prev-build-drv-info
Pass along drvPath and outputName for inputs that are previous builds.
2015-08-10 20:23:29 +02:00
Shea Levy
1705ca41e7 Remove unneeded camelcase 2015-08-10 13:59:22 -04:00
Shea Levy
163e696813 Copy-paste error 2015-08-10 13:52:40 -04:00
Shea Levy
882b6b3377 Pass a build's drv path as a store path 2015-08-10 13:48:09 -04:00
Shea Levy
ce5ffa9fba Only pass the drv path if it is still valid 2015-08-10 13:47:39 -04:00
Eelco Dolstra
08739a2a5a Allow bumping an entire evaluation to the front of the queue
This is mostly useful if we need to prioritize (say) a nixos-stable
eval that has some critical security bug fix.
2015-08-10 18:57:59 +02:00
Eelco Dolstra
eb13007fe6 Allow build to be bumped to the front of the queue via the web interface
Builds now have a "Bump up" action. This will cause the queue runner
to prioritise the steps of the build above all other steps.
2015-08-10 16:19:47 +02:00
Eelco Dolstra
27182c7c1d Start steps in order of ascending build ID 2015-08-10 16:19:47 +02:00
Shea Levy
2a240e458e Pass along drvPath and outputName for inputs that are previous builds.
This allows importing the .drv and getting the same store paths as if the
input had been passed in as nix expressions defining a proper derivation.
2015-08-10 08:02:10 -04:00
Eelco Dolstra
52ec971154 Don't render machine name if not applicable to step 2015-08-10 12:54:56 +02:00
Eelco Dolstra
593850b956 Fix potential race in dispatcher wakeup 2015-08-10 12:54:55 +02:00
Eelco Dolstra
6a1c950e94 Unindent 2015-08-10 11:33:22 +02:00
Eelco Dolstra
f21b88e388 Remove superfluous check 2015-08-07 04:20:34 +02:00
Eelco Dolstra
f1fbf8c605 Fix race in finishing builds that have been cancelled 2015-08-07 04:18:48 +02:00
Eelco Dolstra
90c462a222 Merge remote-tracking branch 'origin/master' into build-ng
Conflicts:
	hydra-module.nix
2015-08-04 14:30:22 +02:00
Eelco Dolstra
9e33f07cb8 Merge pull request #229 from shlevy/pass-all-inputs
hydra-eval-jobs: Pass all inputs as 'inputs' arg.
2015-08-04 14:19:23 +02:00
Shea Levy
7b7f189b3e Whoops, misread signature 2015-08-04 08:12:24 -04:00
Shea Levy
a5b986cf33 Only pass the first value of each input in the inputs argument
Multiple alts are on their way out
2015-08-04 08:10:47 -04:00
Shea Levy
4d967dd17a hydra-eval-jobs: Pass all inputs as 'inputs' arg.
If there is no input named 'inputs', hydra-eval-jobs now passes in a set
of lists, where each attribute corresponds to an input defined in the
jobset specification and each list element is a different input alt, as
an argument named 'inputs'.

Among other things, this allows for generic hydra expressions to be
shared amongst projects with similar structures but different sets of
specific inputs.
2015-08-04 07:54:24 -04:00
Eelco Dolstra
deee99b518 Merge pull request #226 from shlevy/pass-input-uri-and-type
buildInputToString: Pass along the input's type and urr
2015-08-04 13:01:26 +02:00
Shea Levy
d450d08929 buildInputToString: Use inputType attribute instead of type attribute 2015-08-04 06:50:04 -04:00
Eelco Dolstra
6f04299411 Allow downloading file by filename
For instance, instead of

  http://.../build/3770911/download/4/source.tar.gz

you can get

  http://.../build/3770911/download/source.tar.gz

This is useful when file names are constant across builds but product
numbers are not.
2015-07-31 17:50:22 +02:00
Shea Levy
07634e8862 buildInputToString: Pass along the input's type and urr 2015-07-31 09:47:44 -04:00
Eelco Dolstra
ff3f5eb4d8 Fix remote building on Nix 1.10 2015-07-31 03:41:55 +02:00
Eelco Dolstra
5b9a288123 Workaround for RemoteStore not supporting cmdBuildDerivation yet 2015-07-31 03:39:20 +02:00
Eelco Dolstra
706746d4bf Fix build 2015-07-31 01:45:16 +02:00
Eelco Dolstra
4d26546d3c Add support for tracking custom metrics
Builds can now emit metrics that Hydra will store in its database and
render as time series via flot charts. Typical applications are to
keep track of performance indicators, coverage percentages, artifact
sizes, and so on.

For example, a coverage build can emit the coverage percentage as
follows:

  echo "lineCoverage $pct %" > $out/nix-support/hydra-metrics

Graphs of all metrics for a job can be seen at

  http://.../job/<project>/<jobset>/<job>#tabs-charts

Specific metrics are also visible at

  http://.../job/<project>/<jobset>/<job>/metric/<metric>

The latter URL also allows getting the data in JSON format (e.g. via
"curl -H 'Accept: application/json'").
2015-07-31 00:57:30 +02:00
Eelco Dolstra
8092149a9f Use nixUnstable 2015-07-30 16:55:11 +02:00
Eelco Dolstra
9afaf322b3 Use latest DBIx::Class::Schema::Loader 2015-07-30 16:55:11 +02:00
Eelco Dolstra
fed1cc88c0 Merge pull request #225 from aszlig/fix-scmdiff-url
common.tt: Properly generate URL for /api/scmdiff.
2015-07-22 13:00:21 +02:00
aszlig
36cbdd1bd8 common.tt: Properly generate URL for /api/scmdiff.
If Hydra isn't hosted on https://example.com/ but something like
https://example.com/hydra/, the URL for /api/scmdiff would have ended up
on /api/scmdiff rather than /hydra/api/scmdiff.

This is because we didn't use the URI resolver from the controller,
hence we're using it now to build up the whole URL including the query
string.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-07-22 12:00:15 +02:00
Eelco Dolstra
c18fb0ad74 Temporarily disable machines after a connection failure 2015-07-21 15:58:47 +02:00
Eelco Dolstra
7e026d35f7 Split hydra-queue-runner.cc more 2015-07-21 15:14:17 +02:00
Eelco Dolstra
6ddcd37df1 hydra-queue-runner.service: Set IN_SYSTEMD 2015-07-21 01:54:24 +02:00
Eelco Dolstra
5370be9f52 hydra-queue-runner: Use cmdBuildDerivation
See 1511aa9f48 and eda2f36c2a.
2015-07-21 01:54:24 +02:00
Eelco Dolstra
62b1b095ad Handle IP addresses as machine names 2015-07-21 01:54:24 +02:00
Rob Vermaas
fbd48f5684 Make cloning of jobsets work again.
(cherry picked from commit 706551453800fb3a4bb3d8b681dad157a8cea98b)
2015-07-14 09:07:10 +00:00
Eelco Dolstra
3ded87329d Keep track of how many threads are waiting 2015-07-10 19:10:14 +02:00
Eelco Dolstra
06d75699a7 Fix restarting a build 2015-07-10 16:56:53 +02:00
Eelco Dolstra
7f865a30d5 hydra-evaluator: Fix input change check
Because inputs were processed in random order by inputsToArgs, the
inputs hash could be different every time, leading to unnecessary
re-evaluations.
2015-07-10 16:44:06 +02:00
Eelco Dolstra
3e7bbec40b hydra-evaluator: Send statistics to statsd 2015-07-10 16:40:50 +02:00
Eelco Dolstra
5919e911db Don't show how long a machine has been idle
Without an index on (machine, stoptime desc), this requires a
sequential scan. And adding a whole index for this seems
overkill. (Possibly the queue runner could maintain this info more
efficiently.)
2015-07-10 15:41:57 +02:00
Eelco Dolstra
3bb9e17e5c IndexJobsetEvalsOnJobsetId: Only index jobsets with new builds 2015-07-10 15:41:57 +02:00
Eelco Dolstra
b09f7e0989 Add page showing latest build steps 2015-07-10 15:41:57 +02:00
Shea Levy
fc16c53886 Merge branch 'no-local-psql' 2015-07-10 09:09:34 -04:00
Eelco Dolstra
0da08df4eb Stream logs if possible and remove size limit 2015-07-08 19:05:17 +02:00
Eelco Dolstra
f5548dc225 Fix Persona logins 2015-07-08 16:57:33 +02:00
Eelco Dolstra
f933762358 Disable building the PDF manual 2015-07-08 16:51:05 +02:00
Eelco Dolstra
296213e90a Drop obsolete graphviz dependency 2015-07-08 16:30:58 +02:00
Eelco Dolstra
d8acaf2181 Index BuildSteps on propagatedFrom
This significantly speeds up deleting Builds, since it removes the
need for a sequential scan on BuildSteps.
2015-07-08 12:12:44 +02:00
Eelco Dolstra
bbee81efae Use triggers for all notifications on Builds table changes 2015-07-08 12:05:32 +02:00
Eelco Dolstra
89fb723ace Notify the queue runner when a build is deleted 2015-07-08 11:43:35 +02:00
Eelco Dolstra
95c4294560 Allow cancelling builds marked as busy
Note that if there are active build *steps*, this won't cancel them.
2015-07-07 14:08:46 +02:00
Eelco Dolstra
35b7c4f82b Allow only 1 thread to send a closure to a given machine at the same time
This prevents a race where multiple threads see that machine X is
missing path P, and start sending it concurrently. Nix handles this
correctly, but it's still wasteful (especially for the case where P ==
GHC).

A more refined scheme would be to have per machine, per path locks.
2015-07-07 14:06:48 +02:00
Eelco Dolstra
16696a4aee Namespace cleanup 2015-07-07 10:29:43 +02:00
Eelco Dolstra
63745b8e25 Move buildRemote() into State 2015-07-07 10:25:33 +02:00
Eelco Dolstra
df29527531 Refactor 2015-07-07 10:17:21 +02:00
Eelco Dolstra
dd4f6e695e Merge branch 'master' into build-ng 2015-07-06 17:17:51 +02:00
Eelco Dolstra
ccf6e6062c Store full Mercurial revision hashes 2015-07-06 17:17:17 +02:00
Eelco Dolstra
309ef5baa9 Merge branch 'master' into build-ng 2015-07-06 15:57:09 +02:00
Eelco Dolstra
b85e9ef1cd Support using Git revisions as branch names 2015-07-06 15:56:24 +02:00
Eelco Dolstra
b03de925cb Allow a jobset to be created from an evaluation
Fixes #150.
2015-07-06 15:56:20 +02:00
Eelco Dolstra
535e936732 Hackery 2015-07-02 02:55:15 +02:00
Eelco Dolstra
377d9d37f3 Fix paths 2015-07-02 02:54:59 +02:00
Eelco Dolstra
8ea05cc7f2 Don't require postgresql.service 2015-07-02 02:54:30 +02:00
Eelco Dolstra
dffb629b8a Unify Hydra's NixOS module with the one used for hydra.nixos.org
In particular, the queue runner and web server now run under different
UIDs.
2015-07-02 01:01:44 +02:00
Eelco Dolstra
3e0f5f664a GitInput plugin: Don't clone during getCommits
This doesn't work if hydra-queue-runner has no write access to the scm
directory, and in any case races with the evaluator.
2015-07-02 00:44:40 +02:00
Eelco Dolstra
ae52fc7f61 Remove display of queue runner log file (it no longer exists) 2015-07-02 00:18:33 +02:00
Eelco Dolstra
e35b704d80 Drop the 5 minute minimum interval between triggered evals 2015-07-01 14:45:39 +02:00
Eelco Dolstra
85a1ce99c9 Only include Persona JS when Persona is enabled 2015-07-01 14:24:18 +02:00
Eelco Dolstra
1e87b15f91 Remove Nix options not needed by the new queue runner 2015-07-01 11:40:00 +02:00
Eelco Dolstra
3c665dac82 Remove superfluous HYDRA_LOGO environment variable 2015-07-01 11:34:19 +02:00
Eelco Dolstra
60e8b9881b The new queue runner requires "hydra" to be a trusted Nix user
(Because it does unsigned imports into the store.)
2015-07-01 10:47:43 +02:00
Eelco Dolstra
7e6135a8c6 Don't repeat links to build step logs
Hydra only stores the last log for a particular derivation, so only
show log links for the last one.
2015-06-30 00:27:31 +02:00
Eelco Dolstra
2ece42b2b9 Support preferLocalBuild
Derivations with "preferLocalBuild = true" can now be executed on
specific machines (typically localhost) by setting the mandary system
features field to include "local". For example:

  localhost x86_64-linux,i686-linux - 10 100 - local

says that "localhost" can *only* do builds with "preferLocalBuild =
true". The speed factor of 100 will make the machine almost always win
over other machines.
2015-06-30 00:20:19 +02:00
Eelco Dolstra
171303864e Fix type 2015-06-29 09:29:04 +00:00
Eelco Dolstra
008d610467 getQueuedBuilds(): Don't catch errors while loading a build from the queue
Otherwise we never recover from reset daemon connections, e.g.

  hydra-queue-runner[16106]: while loading build 599369: cannot start daemon worker: reading from file: Connection reset by peer
  hydra-queue-runner[16106]: while loading build 599236: writing to file: Broken pipe
  ...

The error is now handled queueMonitor(), causing the next call to
queueMonitorLoop() to create a new connection.
2015-06-26 21:06:35 +02:00
Eelco Dolstra
f5e5a1b96e Don't wake up the queue runner for cached evals 2015-06-26 20:59:14 +02:00
Eelco Dolstra
401f5bdce2 Add a unit for hydra-send-stats 2015-06-26 15:24:12 +02:00
Eelco Dolstra
17924ce012 Note in the log when the queue runner / evaluator gets killed 2015-06-26 11:56:11 +02:00
Eelco Dolstra
aabe514d07 Update the hydra-queue-runner unit 2015-06-26 11:29:30 +02:00
Eelco Dolstra
73a78c2073 Give services.hydra.package a reasonable default 2015-06-26 11:29:19 +02:00
Eelco Dolstra
9a041f9a36 Restart builds failed due to unsupported system type 2015-06-26 11:28:38 +02:00
Eelco Dolstra
2f4676bd97 JSONObject doesn't handle 64-bit integers 2015-06-25 16:59:48 +02:00
Eelco Dolstra
c54a04688e Fix email sender address when notification_sender is not set 2015-06-25 16:49:01 +02:00
Eelco Dolstra
c6fcce3b3b Moar stats 2015-06-25 16:47:39 +02:00
Eelco Dolstra
b5815e2aa6 Run PostgreSQL during "make check" 2015-06-25 16:47:39 +02:00
Eelco Dolstra
18a3c3ff1c Update "make check" for the new queue runner
Also, if the machines file contains an entry for localhost, then run
"nix-store --serve" directly, without going through SSH.
2015-06-25 16:47:39 +02:00
Eelco Dolstra
32210905d8 Automatically reload $NIX_REMOTE_SYSTEMS when it changes
Otherwise, you'd have to restart the queue runner to add or remove
machines.
2015-06-25 16:47:25 +02:00
Eelco Dolstra
1a0e1eb5a0 More stats 2015-06-24 13:19:27 +02:00
Eelco Dolstra
3f8891b6ff Fix incorrect debug message 2015-06-23 17:53:15 +02:00
Eelco Dolstra
62219adaf3 Send queue runner stats to statsd
This is currently done by a separate program that periodically
calls "hydra-queue-runner --status". Eventually, I'll do this
in the queue runner directly.

Fixes #220.
2015-06-23 14:56:43 +02:00
Eelco Dolstra
af5cbe97aa createStep(): Cache finished derivations
This gets rid of a lot of redundant calls to readDerivation().
2015-06-23 03:25:31 +02:00
Eelco Dolstra
681f63a382 Typo 2015-06-23 02:15:11 +02:00
Eelco Dolstra
524ee295e0 Fix sending notifications in the successful case 2015-06-23 02:13:06 +02:00
Eelco Dolstra
4db7c51b5c Rate-limit the number of threads copying closures at the same time
Having a hundred threads doing I/O at the same time is bad on magnetic
disks because of the excessive disk seeks. So allow only 4 threads to
copy closures in parallel.
2015-06-23 01:49:14 +02:00
Eelco Dolstra
a317d24b29 hydra-queue-runner: Send build notifications
Since our notification plugins are written in Perl, sending
notification from C++ requires a small Perl helper named
‘hydra-notify’.
2015-06-23 00:14:49 +02:00
Eelco Dolstra
5312e1209b Keep per-machine stats 2015-06-22 17:11:17 +02:00
Eelco Dolstra
d06366e7cf Remove obsolete comment 2015-06-22 16:59:50 +02:00
Eelco Dolstra
e069ee960e Doh 2015-06-22 16:58:40 +02:00
Eelco Dolstra
a757b783f4 Update $PATH 2015-06-22 16:15:16 +02:00
Eelco Dolstra
e32ee3d5b9 Remove hydra-build and the old hydra-queue-runner 2015-06-22 15:43:15 +02:00
Eelco Dolstra
41ba7418e2 hydra-queue-runner: More stats 2015-06-22 15:34:33 +02:00
Eelco Dolstra
62b53a0a47 Guard against concurrent invocations of hydra-queue-runner 2015-06-22 14:24:03 +02:00
Eelco Dolstra
fbd7c02217 Periodically dump/log status 2015-06-22 14:15:43 +02:00
Eelco Dolstra
4f4141e1db Add command ‘hydra-queue-runner --status’ to show current status 2015-06-22 14:06:44 +02:00
Eelco Dolstra
44a2b74f5a Keep track of the number of build steps that are being built
(As opposed to being in the closure copying stage.)
2015-06-22 11:23:00 +02:00
Eelco Dolstra
fed71d3fe9 Move "created" field into Step::State 2015-06-22 11:07:52 +02:00
Eelco Dolstra
90a08db241 hydra-queue-runner: Fix assertion failure 2015-06-22 10:59:07 +02:00
Eelco Dolstra
d744362e4a hydra-queue-runner: Fix segfault sorting machines by load
While sorting machines by load, the load of a machine
(machine->currentJobs) can be changed by other threads. If that
happens, the comparator is no longer a proper ordering, in which case
std::sort() can segfault. So we now make a copy of currentJobs before
sorting.
2015-06-21 16:21:42 +02:00
Eelco Dolstra
a0eff6fc15 Fix machine selection 2015-06-19 17:45:26 +02:00
Eelco Dolstra
a0c4120232 Don't copy src for nix-shell 2015-06-19 17:45:11 +02:00
Eelco Dolstra
81abb6e166 Improve parsing of hydra-build-products 2015-06-19 17:20:20 +02:00
Eelco Dolstra
e13477bdf2 Robustness 2015-06-19 16:35:49 +02:00
Eelco Dolstra
f196967c43 Don't create a propagated build step to the same build 2015-06-19 15:33:37 +02:00
Eelco Dolstra
7afc61691b Doh 2015-06-19 15:27:49 +02:00
Eelco Dolstra
133d298e26 Asynchronously compress build logs 2015-06-19 15:06:12 +02:00
Eelco Dolstra
8e408048e2 Create build step for non-top-level cached failures
This fixes the missing build step on failures like

  http://hydra.nixos.org/build/23222231
2015-06-19 11:33:15 +02:00
Eelco Dolstra
77c8bfd392 Improve logging for aborts 2015-06-19 10:37:22 +02:00
Eelco Dolstra
8db1ae2855 Less verbosity 2015-06-18 17:43:13 +02:00
Eelco Dolstra
89b629eeb1 Fix finishing steps that are not top-level of any build 2015-06-18 17:37:35 +02:00
Eelco Dolstra
9cdbff2fdf Handle concurrent finishing of the same build
There is a slight possibility that the queue monitor and a builder
thread simultaneously decide to mark a build as finished. That's fine,
as long as we ensure the DB update is idempotent (as ensured by doing
"update Builds set finished = 1 ... where finished = 0").
2015-06-18 17:12:51 +02:00
Eelco Dolstra
948473c909 Fix race between the queue monitor and the builder threads 2015-06-18 16:30:28 +02:00
Eelco Dolstra
9c03b11ca8 Simplify retry handling 2015-06-18 14:51:50 +02:00
Eelco Dolstra
e039f5f840 Create failed build steps for cached failures 2015-06-18 04:35:37 +02:00
Eelco Dolstra
92ea800cfb Set finishedInDB in a few more places 2015-06-18 04:19:21 +02:00
Eelco Dolstra
47367451c7 hydra-queue-runner: Set isCachedBuild 2015-06-18 03:28:58 +02:00
Eelco Dolstra
8257812d0a Acquire exclusive table lock earlier 2015-06-18 02:44:29 +02:00
Eelco Dolstra
69be3cfe93 hydra-queue-runner: Handle status queries on the main thread
Doing it on the queue monitor thread was problematic because
processing the queue can take a while.
2015-06-18 01:57:01 +02:00
Eelco Dolstra
a40ca6b76e hydra-queue-runner: Improve dispatcher
We now take the machine speed factor into account, just like
build-remote.pl.
2015-06-18 01:52:20 +02:00
Eelco Dolstra
3855131185 hydra-queue-runner: Improve SSH flags 2015-06-18 00:50:48 +02:00
Eelco Dolstra
f57d0b0c54 hydra-queue-runner: Maintain count of active build steps 2015-06-18 00:24:56 +02:00
Eelco Dolstra
59dae60558 hydra-queue-runner: More stats 2015-06-17 22:38:12 +02:00
Eelco Dolstra
ec8e8edc86 hydra-queue-runner: Handle $HYDRA_DBI 2015-06-17 22:11:01 +02:00
Eelco Dolstra
4d9c74335d Add forgotten file 2015-06-17 21:39:28 +02:00
Eelco Dolstra
ce9e859a9c hydra-queue-runner: Implement --unlock 2015-06-17 21:35:20 +02:00
Eelco Dolstra
ca48818b30 Fix remote building 2015-06-17 17:28:59 +02:00
Eelco Dolstra
11be780948 Handle failure with output 2015-06-17 17:11:42 +02:00
Eelco Dolstra
b1a75c7f63 getQueuedBuilds(): Handle dependent builds first
If a build A depends on a derivation that is the top-level derivation
of some build B, then we should process B before A (meaning we
shouldn't make the derivation runnable before B has been
added). Otherwise, the derivation will be "accounted" to A rather than
B (so the build step will show up in the wrong build).
2015-06-17 14:46:02 +02:00
Eelco Dolstra
c6d504edbb Handle SSH hosts without a @ 2015-06-17 13:49:18 +02:00
Eelco Dolstra
745efce828 hydra-queue-runner: Implement timeouts
Also, keep track of timeouts in the database as a distinct build
status.
2015-06-17 13:32:33 +02:00
Eelco Dolstra
2da4987bc2 Don't lock the CPU 2015-06-17 11:48:38 +02:00
Eelco Dolstra
b91a616520 Automatically retry aborted builds
Aborted builds are now put back on the runnable queue and retried
after a certain time interval (currently 60 seconds for the first
retry, then tripled on each subsequent retry).
2015-06-17 11:45:20 +02:00
Eelco Dolstra
e02654b3a0 Prefer cached failure over unsupported system type 2015-06-16 18:00:39 +02:00
Eelco Dolstra
a984c0badc Merge branch 'master' into build-ng 2015-06-15 18:21:07 +02:00
Eelco Dolstra
42e7301c08 Add status dump facility
Doing

  $ psql hydra -c 'notify dump_status'

will cause hydra-queue-runner to dump some internal status info on
stderr.
2015-06-15 18:20:14 +02:00
Eelco Dolstra
dd104f14ea Make the queue monitor more robust, and better debug output 2015-06-15 16:54:52 +02:00
Eelco Dolstra
147eb4fd15 Support requiredSystemFeatures 2015-06-15 16:33:50 +02:00
Eelco Dolstra
508ab7f8a2 Tweak build steps 2015-06-15 15:48:05 +02:00
Eelco Dolstra
21aaa0596b Fail builds with previously failed steps early 2015-06-15 15:31:42 +02:00
Eelco Dolstra
c00bf7cd1a Check non-runnable steps for unsupported system type 2015-06-15 15:13:03 +02:00
Eelco Dolstra
5019fceb20 Add a error type for "unsupported system type" 2015-06-15 15:07:04 +02:00
Eelco Dolstra
541fbd62cc Immediately abort builds that require an unsupported system type 2015-06-15 14:51:49 +02:00
Eelco Dolstra
bf87d3a6ed Use stable Nix 2015-06-15 14:51:38 +02:00
Eelco Dolstra
d6354cbe1f Fix Perl error in tests.api
Doing "su hydra" causes Perl to be invoked with a wrong PERL5LIB
(pointing to root's profile), leading to "Can't locate strict.pm".
2015-06-15 11:56:51 +02:00
Eelco Dolstra
abca7a87da Cleanup 2015-06-12 18:15:58 +02:00
Eelco Dolstra
f06ec78859 Handle building from a dirty Git tree 2015-06-12 18:15:58 +02:00
Eelco Dolstra
18e0a62e24 Disable 32-bit builds again
They're failing consistently:

http://hydra.nixos.org/job/hydra/master/build.i686-linux/all
2015-06-12 15:35:14 +02:00
Eelco Dolstra
f9cd5adae8 Queue monitor: Get only the fields we need 2015-06-11 18:09:50 +02:00
Eelco Dolstra
c974fb893b Support cancelling builds 2015-06-11 18:07:45 +02:00
Eelco Dolstra
c08883966c Use PostgreSQL notifications for queue events
Hydra-queue-runner now no longer polls the queue periodically, but
instead sleeps until it receives a notification from PostgreSQL about
a change to the queue (build added, build cancelled or build
restarted).

Also, for the "build added" case, we now only check for builds with an
ID greater than the previous greatest ID. This is much more efficient
if the queue is large.
2015-06-11 17:41:59 +02:00
Eelco Dolstra
672bbb1c67 hydra-update-gc-roots: Get Builds and BuildOutputs in the same query
This greatly reduces the number of roundtrips to the database.
2015-06-11 14:10:21 +02:00
Eelco Dolstra
9989a90e99 Keep the most recent successful build of current jobs
Fixes #140.
2015-06-11 14:10:21 +02:00
Eelco Dolstra
d72a88b562 Don't try to handle SIGINT
It just makes things unnecessarily complicated. We can just exit
without cleaning anything up, since the only thing to do is unmark
builds and build steps as busy. But we can do that by having systemd
call "hydra-queue-runner --unlock" from ExecStopPost.
2015-06-10 15:55:46 +02:00
Eelco Dolstra
a4fb93c119 Lock builds for a shorter amount of time 2015-06-10 15:36:21 +02:00
Eelco Dolstra
6d738a31bf Keep track of failed paths in the Hydra database
I.e. don't use Nix's failed paths feature anymore. Easier to keep
everything in one place.
2015-06-10 14:57:16 +02:00
Eelco Dolstra
c68036f8b0 Pass ssh key 2015-06-10 14:57:07 +02:00
Eelco Dolstra
7dd1f0097e Finish copyClosure 2015-06-09 16:03:41 +02:00
Eelco Dolstra
c93aa92563 Create BuildSteps race-free
If multiple threads create a step for the same build, they could get
the same "max(stepnr)" and allocate conflicting new step numbers. So
lock the BuildSteps table while doing this. We could use a different
isolation level, but this is easier.
2015-06-09 15:03:20 +02:00
Eelco Dolstra
61d4060522 Record the machine used for a build step 2015-06-09 14:57:49 +02:00
Eelco Dolstra
08633508da Fix colspan 2015-06-09 14:42:02 +02:00
Eelco Dolstra
ca1fbdd058 Mark builds as busy 2015-06-09 14:31:43 +02:00
Eelco Dolstra
8b12ac1f6d Basic remote building
This removes the need for Nix's build-remote.pl.

Build logs are now written to $HYDRA_DATA/build-logs because
hydra-queue-runner doesn't have write permission to /nix/var/log.
2015-06-09 14:21:21 +02:00
Eelco Dolstra
3a6cb2f270 Implement a database connection pool 2015-05-29 20:55:13 +02:00
Eelco Dolstra
214b95706c On SIGINT, shut down the builder threads
Note that they don't get interrupted at the moment (so on SIGINT, any
running builds will need to finish first).
2015-05-29 20:02:15 +02:00
Shea Levy
bc36c7ddd0 hydra-module: Don't assume hydra is running on localhost.
In the long run we should add retry logic to hydra-init...
2015-05-29 12:16:04 -04:00
Eelco Dolstra
e778821940 Make concurrency more robust 2015-05-29 17:14:20 +02:00
Eelco Dolstra
8640e30787 Very basic multi-threaded queue runner 2015-05-29 01:31:12 +02:00
Eelco Dolstra
604fdb908f Pass null values to libpqxx properly 2015-05-28 19:06:17 +02:00
Eelco Dolstra
dc446c3980 Start of single-process hydra-queue-runner 2015-05-28 17:39:29 +02:00
Eelco Dolstra
a91cbefda0 Shut up warnings 2015-05-28 17:38:17 +02:00
Eelco Dolstra
ff8cb93fe7 reproduce.tt: Wrap script to prevent problems piping into bash 2015-05-26 17:11:29 +02:00
Eelco Dolstra
c32a244bd7 reproduce.tt: Add --print-flags option
Useful when scripting stuff (e.g. if you want to do a nix-instantiate
instead of a nix-build).
2015-05-26 16:36:08 +02:00
Eelco Dolstra
f5ecb7a81a reproduce.tt: Use -I instead of $NIX_PATH 2015-05-26 16:07:00 +02:00
Eelco Dolstra
b8a0956443 reproduce.tt: Add option to fetch but not build 2015-05-26 16:01:37 +02:00
Eelco Dolstra
91ecee0e5d Fix reproduce script 2015-05-26 15:54:38 +02:00
Eelco Dolstra
c93ff1e817 Doh 2015-05-26 15:25:21 +02:00
Eelco Dolstra
1ab0f96079 Rename c -> hydra-eval-jobs 2015-05-26 13:58:01 +02:00
Shea Levy
880ba75a4f Merge pull request #216 from Warbo/master
Allow running on i686-linux
2015-05-17 14:01:37 -04:00
Chris Warburton
d64ba15357 Allow running on i686-linux 2015-05-17 18:41:27 +01:00
Eelco Dolstra
e003665146 Split timeSpent query into 2 separate queries, as postgresql isn't able to figure out a decent query plan. With 120k jobs in queue, this makes some queries go from 100s to 1-2s. 2015-05-01 12:28:29 +02:00
Eelco Dolstra
d9ab964203 UTF-8 fix 2015-04-14 15:20:56 +02:00
Eelco Dolstra
01cd6397cb Better error message 2015-04-14 15:16:24 +02:00
Eelco Dolstra
5a61aefe4f Use Nix's restricted evaluation mode 2015-04-14 15:16:00 +02:00
Eelco Dolstra
5d8a563e90 Merge pull request #204 from aszlig/tail-improvements
Improvements of tail-reload output
2015-04-14 12:44:36 +02:00
Ricardo M. Correia
5af301ee82 configure.ac: Declare we're using the serial test harness
Fixes #200.
2015-04-13 12:52:08 +02:00
Eelco Dolstra
63306aaf5a hydra-evaluator: Add some debug code 2015-04-09 17:35:04 +02:00
Eelco Dolstra
a2dc92d871 Die tabs die 2015-04-09 17:22:10 +02:00
Eelco Dolstra
9e664cf8b0 Fix not-null constraint violation inserting build step
DBIx::Class::Storage::DBI::_dbh_execute(): DBI Exception: DBD::Pg::st execute failed: ERROR:  null value in column "machine" violates not-null constraint
2015-04-07 13:34:00 +02:00
aszlig
7a48ad375a plain-reload: Scroll down at document load.
When visiting the tail-reload page, for a short amount of time the
"unscrolled" version is shown. To circumvent that, let's scroll down
immediately at the first possibility to fill the gap between the loading
of the document and the first AJAX request coming in.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-04-03 00:00:27 +02:00
aszlig
c251598241 plain-reload: Constrain tail output to 50 lines.
There are quite a lot of build outputs which have lines with a length
exceeding the width of the taillog <pre/> and thus visually produce more
lines than 50. This causes the tail "box" to change height frequently
and to get to the bottom you need to scroll down.

We now set a fixed line-height to 120% of the font size and cap the
maximum height based on that value (50 * 1.2 = 60). It's probably not
nice to override the line-height, but max-lines is currently only
available using browser-specific property names. But after all it's just
for the tail output, if people complain about the line-height, we can
still change it :-)

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-04-02 17:29:48 +02:00
aszlig
be051bcadc plain-reload.tt: Properly escape tail content.
We're just implicitly escaping the tail content by not using .load() but
explicitly setting the text content using .text(), so that escaping
isn't needed on our side.

This should get rid of a few formatting errors and possibly XSS if
someone manages to place JS code in the tail of a build and manages to
lurk a user to that tail output.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2015-04-02 16:55:59 +02:00
Eelco Dolstra
aec0a35114 Fix duplicate row-link 2015-03-24 14:31:27 +01:00
Rob Vermaas
125dd80dd8 Respect hideJobset in renderBuildListBody. 2015-03-24 08:38:40 +00:00
Rob Vermaas
cad82493b0 Restore build and eval IDs. 2015-03-23 15:11:38 +00:00
Rob Vermaas
91e7e6f6ab Use DAG range to determine commits between mercurial revisions. Previously it would show also commits in other branches. 2015-03-23 13:52:06 +00:00
Eelco Dolstra
3b5e84cc73 Tweak debug output 2015-03-23 12:59:41 +01:00
Eelco Dolstra
479632efa3 Call initGC() 2015-03-19 20:16:38 +01:00
Eelco Dolstra
4c0e3e4703 Debug tweak 2015-03-18 22:03:55 +01:00
Eelco Dolstra
ad2b7646ac Don't show missing paths in logs 2015-03-04 15:44:04 +01:00
Eelco Dolstra
522bcea8fc Hide build IDs from build lists
Like eval IDs, build IDs don't convey useful information.

Also, make the job name link to the build rather than the job. When
people click on a build, they expect to go to the build page, not the
job page.
2015-02-26 13:28:14 +01:00
Eelco Dolstra
62805dd73c Queue: Remove the scheduling priority
Scheduling is mostly based on jobset shares these days. So showing and
sorting by priority just wastes space and gives the incorrect
impression that Hydra executes builds in the order shown on the queue
page.
2015-02-26 13:16:25 +01:00
Eelco Dolstra
7f6faee08a Show some eval stats 2015-02-26 13:11:33 +01:00
Eelco Dolstra
f835ae492f Likewise remove eval IDs from eval lists 2015-02-26 13:06:53 +01:00
Eelco Dolstra
c04c8c2bf1 Jobset job tab: Show eval date rather than eval ID
Eval IDs carry no useful information, so it's better to show the date
of the eval. If the date is recent, a relative date is given (e.g. "3h
ago").
2015-02-26 13:01:01 +01:00
Eelco Dolstra
fa1e043526 Make input value wider
Fixes #187.
2015-02-25 17:42:47 +01:00
Eelco Dolstra
adc72d2409 Record which build a failed build step was propagated from 2015-02-25 16:42:32 +01:00
Eelco Dolstra
48af914e28 When propagating failure, propagate the duration and machine
Previously the duration would just show as "0" and you would have to
search for the original build to get the duration.
2015-02-25 16:21:54 +01:00
Eelco Dolstra
2f946bdfd7 Render machine correctly if it doesn't contain @ 2015-02-25 16:21:29 +01:00
Eelco Dolstra
9282bcb95f Show eval input changes in deterministic order 2015-02-25 13:13:12 +01:00
Eelco Dolstra
7c048cbbcf Allow a different state directory for hydra-server
This is necessary if hydra-server runs under a different uid than the
other Hydra processes.
2015-02-24 11:40:24 +01:00
Eelco Dolstra
00e03b9db5 For consistency, Use base32 hashes in manifests 2015-02-19 12:44:52 +01:00
Eelco Dolstra
69adcd4be1 Update binary cache signing to Nix 1.9 2015-02-17 20:15:37 +01:00
Rob Vermaas
14752d7801 Build from source remark in README.md 2015-02-10 13:06:04 +00:00
Rob Vermaas
e211e7771e Add README.md 2015-02-10 13:04:06 +00:00
Eelco Dolstra
ea815d55b8 More robot exclusions 2015-01-13 13:50:13 +01:00
Eelco Dolstra
80116b648e Exclude robots from all of /build 2015-01-13 13:45:39 +01:00
Eelco Dolstra
a12135fc51 Don't use Perl's -w flag 2014-12-12 17:39:52 +01:00
Eelco Dolstra
6a0b9a3476 hydra-build: Handle new trace messages
Now build step duration no longer includes network overhead (i.e.
time to copy closures to the build machine).
2014-12-12 17:20:50 +01:00
Eelco Dolstra
c0ca5489e1 Don't use given/when
These give warnings in Perl >= 5.18:

  given is experimental at /home/hydra/src/hydra/src/lib/Hydra/Helper/CatalystUtils.pm line 241.
  when is experimental at /home/hydra/src/hydra/src/lib/Hydra/Helper/CatalystUtils.pm line 242.
  ...
2014-12-12 11:27:17 +01:00
Shea Levy
e56e743f97 S3Backup: Create a proper nar 2014-12-10 23:06:52 -05:00
Shea Levy
208bbbb4b0 s3backup: Create temporary file in temp dir 2014-12-10 22:06:32 -05:00
Rob Vermaas
4190f5b00d Merge pull request #192 from iElectric/status_images
Make sure status images always display for a list of builds
2014-12-03 13:56:51 +01:00
Domen Kožar
8de15ce38d make sure status images always display for a list of builds 2014-12-03 13:54:22 +01:00
Eelco Dolstra
9e00d98d34 Shut up some Perl 5.20 warnings 2014-11-25 00:27:52 +01:00
Eelco Dolstra
5e265e6739 Tweak blame message 2014-11-19 15:24:31 +01:00
Eelco Dolstra
7b5b434014 Fix getResponsibleAuthors 2014-11-19 15:22:30 +01:00
Eelco Dolstra
0d28e9372b Remove dead code 2014-11-19 14:59:36 +01:00
Eelco Dolstra
2d46741840 Fix message 2014-11-19 14:52:42 +01:00
Eelco Dolstra
8523130ebb Use Email::MIME instead of Email::Simple
Email::Simple cannot handle non-ASCII characters.

Fixes #191.
2014-11-19 14:45:46 +01:00
Eelco Dolstra
41bc918382 Fix robots.txt 2014-11-18 14:55:52 +01:00
Rob Vermaas
d5db1d3bc1 Revert "Make evaluation fail with proper error when a input of type build is not available."
This reverts commit a1b5020562.
2014-11-18 11:13:34 +01:00
Rob Vermaas
fd36d79581 Fix Changes section on build page. Now shows the changes of the first evaluation a build was part of compared to the previous one. Also separated previous builds from the changes section, as that was confusing sometimes. 2014-11-18 11:00:28 +01:00
Rob Vermaas
a1b5020562 Make evaluation fail with proper error when a input of type build is not available. 2014-11-18 11:00:28 +01:00
Eelco Dolstra
cb1395ee47 hydra-server.service: Shut up warning about the terminal size being unknown 2014-11-12 13:50:25 +01:00
Eelco Dolstra
d28ee3fd3f Remove Term::Size::Any dependency
This is now propagated by Catalyst::Runtime.
2014-11-12 13:49:04 +01:00
Eelco Dolstra
3b93c4721c hydra-module.nix: Remove log compression which is a local policy 2014-11-12 13:47:55 +01:00
Eelco Dolstra
eb2965071e Depend on Term::Size::Any
This shuts up a warning from Catalyst.
2014-11-06 15:36:46 +01:00
Eelco Dolstra
c503876a7e Don't cache nix-cache-info very long 2014-11-06 15:30:24 +01:00
Eelco Dolstra
c250407f3c Set Expires headers for Hydra's binary cache
This allows caching by reverse proxies.
2014-11-06 14:31:48 +01:00
Rob Vermaas
55eb55478d Allow HipChat notification on all builds, in stead of status changes only. 2014-10-21 07:50:12 +00:00
Eelco Dolstra
aad3a11eca Build page: Show output / closure sizes 2014-10-07 18:12:00 +02:00
Eelco Dolstra
83d4930101 Reorder 2014-10-07 17:16:41 +02:00
Eelco Dolstra
52ec8abf97 Update flot to 0.8.3 2014-10-07 13:35:31 +02:00
Eelco Dolstra
dfe5325490 Scale the Y axis to the visible points 2014-10-07 13:10:10 +02:00
Eelco Dolstra
1b12daa032 Move the build time chart to the job page 2014-10-07 12:59:09 +02:00
Eelco Dolstra
0bb027e633 Move the store path size chart to the job page
The history is a property of the job, not individual builds.
2014-10-07 11:53:17 +02:00
Eelco Dolstra
5f474b252c Add a chart to the job pages showing the closure size over time 2014-10-07 11:23:15 +02:00
Eelco Dolstra
3687c9c30b Validate build IDs 2014-10-01 17:05:39 +02:00
Eelco Dolstra
5a7efc0469 Fix aggregate handling 2014-10-01 15:34:05 +02:00
Eelco Dolstra
3f51ac6603 Partially revert 1c20cfdf24
Not clear why update-dbix messed up the Jobsets and Projects
classes. This will probably happen again in the future...
2014-10-01 15:28:18 +02:00
Eelco Dolstra
9b38b5f134 Remove the longDescription field
It's not useful and takes up a lot of space.
2014-09-30 15:44:09 +02:00
Eelco Dolstra
f4acc9a522 Create Builds with iscurrent set
This should eliminate a subsequent update.
2014-09-30 15:44:09 +02:00
Eelco Dolstra
5b4de2dee6 hydra-evaluator: Reduce verbosity 2014-09-30 15:44:08 +02:00
Eelco Dolstra
09a96c642a hydra-eval-jobs: Use JSON instead of XML
XML::Simple is pretty slow - reading the output for the Nixpkgs jobset
takes half a minute or so. JSON is pretty much instantaneous.
2014-09-30 15:44:08 +02:00
Eelco Dolstra
d9a5143fcb Use partial indexes
There is no point in indexing rows with common column values like
"finished = 1", since those are the majority of the table. Only the
exceptions ("finished = 0") are interesting. Having smaller tables
should make updates/insertions faster.
2014-09-30 15:44:08 +02:00
Eelco Dolstra
773c7e89cf Get rid of some obsolete indexes 2014-09-30 15:44:08 +02:00
Eelco Dolstra
1c20cfdf24 Drop the errorMsg column in the Jobs table
We're not using it anywhere.
2014-09-29 19:46:11 +02:00
Eelco Dolstra
f53e3c738d Fix test
http://hydra.nixos.org/build/14852570
2014-09-26 13:47:42 +02:00
Eelco Dolstra
beb94d5fb3 Machine status page: Add link to build step 2014-09-25 20:24:55 +02:00
Eelco Dolstra
2054759fdf Status page: Show running builds rather than build steps
The active build steps list was redundant, because the "Machine
status" page also shows them. So instead show active builds.
2014-09-25 20:17:33 +02:00
Eelco Dolstra
23a9fea26c Remove the ability to add multiple jobset input alternatives
Now each jobset input has exactly one value. (Actually, adding
multiple values was already broken, so all this does is clean up the
UI...)
2014-09-25 16:43:17 +02:00
Eelco Dolstra
c28e7ac692 Fix XML wellformedness 2014-09-25 16:06:07 +02:00
Eelco Dolstra
b04c8adbd5 build.tt: Show jobset eval inputs instead of build inputs
We're not recording build inputs anymore, so we now just show all
inputs of the build's first evaluation.
2014-09-25 14:49:09 +02:00
Eelco Dolstra
01f4037d6f hydra-eval-jobs: Don't keep track of used inputs
We no longer store this in the database, so it's not necessary for
hydra-eval-jobs to do this.
2014-09-25 13:38:43 +02:00
Eelco Dolstra
6284fd540d Disallow multiple jobs with the same name
This has been deprecated since a8db329839.

Issue #60.
2014-09-24 18:12:59 +02:00
Eelco Dolstra
0d5a38a40b Really fix hydra-eval-jobs
Fixes #183.
2014-09-24 15:55:19 +02:00
Eelco Dolstra
594fb7a009 Disable the S3 backup test
This test has never succeeded
(http://hydra.nixos.org/job/hydra/master/tests.s3backup.x86_64-linux)
so until somebody fixes it, there is not much point in building it.
2014-09-24 15:21:01 +02:00
Eelco Dolstra
b11cb37044 Handle derivations without a system attribute 2014-09-22 16:53:40 +02:00
Eelco Dolstra
eb2f3eb8d4 Fix build 2014-09-22 16:47:02 +02:00
Eelco Dolstra
4727165832 Use pkgconfig to find Nix 2014-09-18 12:24:05 +02:00
Eelco Dolstra
c1bf3bb0f2 hydra-eval-jobs: Add --dry-run option 2014-09-12 14:30:01 +02:00
Eelco Dolstra
748c3409b4 Don't maintain BuildInputs anymore
We don't need to record inputs per build anymore because we have
JobsetEvalInputs now.
2014-09-06 19:06:07 +02:00
aszlig
9c7f303255 Use mktemp for tempdir creation in prefetchers.
This incorporates the following two commits from <nixpkgs>:

NixOS/nixpkgs@f83af95f8a
NixOS/nixpkgs@5e7a1cf955

Hydra was the original reason why I was fixing tempdir creation in the
first place. Seeing that Hydra ships its own versions of these scripts,
we need to patch them here as well.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2014-08-29 12:40:11 +02:00
Eelco Dolstra
2f7e928f4e Bump default silent timeout to 2 hours 2014-08-25 11:35:56 +02:00
Eelco Dolstra
d6b61f4925 More charset hackery 2014-08-23 16:39:20 +02:00
Rob Vermaas
f5c04bfa49 Merge pull request #178 from svanderburg/master
Compose release name for an evaluation if none has been defined
2014-08-23 16:24:33 +02:00
Sander van der Burg
ede4a10353 Compose release name for an evaluation if none has been defined 2014-08-23 16:20:58 +02:00
Eelco Dolstra
319e053368 Hopefully fix UTF-8 chars in Hipchat notification messages 2014-08-18 14:01:39 +02:00
Eelco Dolstra
2ffceef875 Tweak 2014-08-17 23:54:12 +02:00
Eelco Dolstra
28b528c1ab Ensure proper escaping of /build/.../contents pages 2014-08-17 23:43:22 +02:00
Eelco Dolstra
f50066ab6f Fix encoding of Hydra logs 2014-08-17 23:43:01 +02:00
Eelco Dolstra
a80bfceaca Remove timeout detection hack 2014-08-17 19:26:03 +02:00
Eelco Dolstra
42b23133e8 Fix UTF-8 handling of log files 2014-08-13 18:53:29 +02:00
Eelco Dolstra
a2b27c7cf2 Preserve whitespace in string inputs 2014-08-13 17:25:08 +02:00
Eelco Dolstra
9334b84d6f Fix registerRoot
Fixes #175.
2014-08-13 16:29:00 +02:00
Eelco Dolstra
3520315fea Fix build and handling of string inputs starting with a dash
Fixes #176.
2014-08-13 16:24:26 +02:00
Eelco Dolstra
69e3aa0438 Write Hydra roots as regular files instead of symlinks
Note that this requires at least NixOS/Nix@1c208f2b7e.
2014-08-01 17:24:55 +02:00
Ronny Esterluss
7351752066 fixed string comparison 2014-07-31 22:18:28 +02:00
Tino Breddin
5ebc2e5419 only checkout the target branch when topgit is used 2014-07-31 22:18:28 +02:00
Ronny Esterluss
55aaf807eb added clean command 2014-07-31 21:53:25 +02:00
Ronny Esterluss
ee840be313 forcing branch switch 2014-07-31 21:53:25 +02:00
Eelco Dolstra
6b88be040e Make restartBuilds faster 2014-07-18 00:03:26 +02:00
Eelco Dolstra
365de86ead Fix hydra-update-gc-roots 2014-07-16 23:20:58 +02:00
Eelco Dolstra
fb5f01097b Fix race between hydra-eval-jobs and hydra-update-gc-roots
If hydra-eval-jobs creates a new root, and hydra-update-gc-roots runs
before hydra-evaluator has had a chance to add the corresponding build
to the database, then hydra-update-gc-roots will remove the root. If
subsequently the Nix garbage collector kicks in, it may remove the
build's .drv file before the build is performed. Since evaluation of
the Nixpkgs and NixOS jobsets nowadays takes a lot of time (e.g. an
hour), the probability of this happening is fairly high.

The quick fix is not to delete roots that are less than a day old. So
long as evaluation doesn't take longer than a day, this should be fine
;-)

Fixes #166.
2014-07-14 13:18:07 +02:00
Shea Levy
114f8a26ee Fix build for new nixUnstable 2014-06-16 12:24:17 -04:00
Shea Levy
91f895b3d6 hydra-module.nix: Take lib from the module system, not from pkgs 2014-05-14 15:06:57 -04:00
Rob Vermaas
268f273a3e Add value and dependency fields to eval json output. 2014-05-08 17:08:31 +02:00
Eelco Dolstra
da73eb5f8a Include dependency column in JSON output 2014-05-08 16:36:15 +02:00
Rob Vermaas
1c92d760fa Merge pull request #161 from thoughtpolice/coverity
hydra: add Coverity Scan plugin
2014-05-03 17:46:35 +02:00
Rob Vermaas
14ccf84e46 Merge pull request #160 from thoughtpolice/extraEnv
hydra-module: add config.extraEnv
2014-05-03 17:46:22 +02:00
Austin Seipp
4166974657 hydra: add Coverity Scan plugin
This adds a Hydra plugin for users to submit their open source projects
to the Coverity Scan system for analysis.

First, add a <coverityscan> section to your Hydra config, including the
access token, project name, and email, and a regex specifying jobs to
upload:

    <coverityscan>
      project = testrix
      jobs    = foobar:.*:coverity.*
      email   = aseipp@pobox.com
      token   = ${builtins.readFile ./coverity-token}
    </coverityscan>

This will upload the scan results for any job whose name matches
'coverity.*' in any jobset in the Hydra 'foobar' project, for the
Coverity Scan project named 'testrix'.

Note that one upload will occur per job matched by the regular
expression - so be careful with how many builds you upload.

The jobs which are matched by the jobs specification must have a file in
their output path of the form:

  $out/tarballs/...-cov-int.(xz|lzma|zip|bz2|tgz)

The file must have the 'cov-int' directory produced by `cov-build` in
the root.

(You can also output something into
$out/nix-support/hydra-build-products for the Hydra UI.)

This file will be found in the store, and uploaded to the service
directly using your access credentials. Note the exact extension: don't
use .tar.xz, only use .xz specifically.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
2014-05-02 14:15:25 -05:00
Eelco Dolstra
1306291c6c Handle utf-8 properly
Fixes errors like:

  Caught exception in engine "Wide character in syswrite at /nix/store/498lwsrn5kkdh1q8kn3vcpd3457w6m7a-hydra-perl-deps/lib/perl5/site_perl/5.16.3/Starman/Server.pm line 547."

Note that these errors didn't happen if the database encoding was set
to SQL_ASCII (which was the case for hydra.nixos.org, explaining why
it didn't get these errors). However, now the encoding must be
UTF8. To change it, do:

  update pg_database set encoding = pg_char_to_encoding('UTF8') where datname = 'hydra';
2014-05-01 16:33:25 +02:00
Eelco Dolstra
67c79a16a8 Remove unnecessary join against releases table
This gets rid of the warning:

  DBIx::Class::Storage::DBI::select_single(): Query returned more than one row.  SQL that returns multiple rows is DEPRECATED for ->find and ->single at /home/eelco/Dev/hydra/src/script/../lib/Hydra/Controller/Project.pm line 15
2014-05-01 13:03:34 +02:00
Austin Seipp
76a7cdc897 hydra-module: add config.extraEnv
This makes it easy to set environment variables for the Hydra server
(for example, your configuration.nix can use readFile to read an API
token to upload build results somewhere).

Signed-off-by: Austin Seipp <aseipp@pobox.com>
2014-04-30 11:54:47 -05:00
Eelco Dolstra
6c6ce7a781 Fix cloning jobsets 2014-04-30 09:26:53 +02:00
Eelco Dolstra
d9475273c5 trunk -> master 2014-04-25 14:56:29 +02:00
Eelco Dolstra
a052bba1bb Fix test 2014-04-24 16:08:04 +02:00
Eelco Dolstra
4d9edd0ca8 Also redirect /job requests that refer to a renamed jobset 2014-04-24 11:05:16 +02:00
Eelco Dolstra
23416f9960 Do a permanent redirect 2014-04-24 10:52:46 +02:00
Eelco Dolstra
affec8881d Remove support for views
They're replaced by aggregates, which are declarative, faster, and
have a better interface.
2014-04-23 23:22:44 +02:00
Eelco Dolstra
5e0d10a392 When renaming a jobset, add a redirect from the old name 2014-04-23 23:15:22 +02:00
Rob Vermaas
5a5f1e42e6 Merge pull request #153 from aszlig/permissions-start-only
hydra-module: Use PermissionsStartOnly in init.
2014-04-15 21:50:26 +02:00
aszlig
72d3504fbd hydra-module: Use PermissionsStartOnly in init.
Oops, forgot to add this in f75509099a.

This is necessary because we actually want to run the preStart script as
root (because it chmod/chowns stuff and also needs to create the
database using PostgreSQL's superuser) and the actual creation of the
database as user hydra.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2014-04-11 00:11:34 +02:00
Eelco Dolstra
b7816eacd5 Merge pull request #152 from aszlig/module-without-su
hydra-module: Don't rely on su being available in shadow.
2014-04-10 20:30:42 +02:00
aszlig
f75509099a hydra-module: Don't rely on su being available.
The su binary is now in a separate output of the shadow package and
isn't included in the main output path anymore.

But instead of changing the call to use pkgs.su, we're now entirely
dropping the dependency because systemd is already able to execute
processes under a specific user by itself.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2014-04-10 20:09:29 +02:00
Eelco Dolstra
be63c50560 Show whether a job still exists
In the dashboard and on the job page, indicate whether the job appears
in the latest jobset eval. That way, the user gets some indication if
a job has accidentally disappeared (e.g. due to an evaluation error).
2014-04-08 18:50:37 +02:00
Ludovic Courtès
4471cae07e hydra-eval-guile-jobs: Add "This file is part of Hydra". 2014-04-08 18:22:21 +02:00
Ludovic Courtès
cc46456598 hydra-eval-guile-jobs: Register derivations as GC roots.
* src/script/hydra-eval-guile-jobs.in (register-gc-root): New
  procedure.
  (job-evaluations->sxml): Add #:gc-roots-dir parameter.  Call
  'register-gc-root'.
  (job-evaluations->xml): Add #:gc-roots-dir parameter; pass it to
  'job-evaluations->sxml'.
  (eval-guile-jobs): Warn when --gc-roots-dir isn't passed.  Pass
  GC-ROOTS-DIR to 'job-evaluations->xml'.
2014-04-08 18:22:21 +02:00
Ludovic Courtès
e3e8c1bc74 hydra-eval-guile-jobs: Honor $NIX_STORE_DIR.
* src/script/hydra-eval-guile-jobs.in (strip-store-path): Honor
  $NIX_STORE_DIR.
2014-04-08 18:22:21 +02:00
Eelco Dolstra
4cf0d7c4b3 hydra-update-gc-roots: Keep derivations of failed builds
By keeping the derivations of failed builds in the most recent
evaluations, we ensure that failed builds can be restarted.
2014-04-08 17:54:11 +02:00
Eelco Dolstra
4aa01e021e Fix building against the latest Nix 2014-04-08 17:08:09 +02:00
Shea Levy
d087aeb0d9 Fix adding jobset inputs 2014-03-06 08:22:59 -05:00
Shea Levy
5fe09e9bf0 nix's libs live in $out/lib now, not $out/nix/lib 2014-03-06 07:56:50 -05:00
Shea Levy
024a5e7d75 edit-jobset.tt: Retain old inputs with dashes in their name
Fixes #149
2014-03-06 07:50:49 -05:00
Eelco Dolstra
2d8f2503c5 Build against latest Nix 2014-03-05 11:11:59 +01:00
Ludovic Courtès
ccdb6f2b23 Honor $NIX_STORE_DIR. 2014-02-28 14:09:12 +01:00
Your Name
f409d2b4f6 Allow notify option to be set for hipchat notification. (https://www.hipchat.com/docs/api/method/rooms/message) 2014-02-28 09:27:33 +00:00
Your Name
421950aede Use minutes in build history charts. 2014-02-28 09:16:45 +00:00
Ludovic Courtès
61448ca2bd guile: Raise default absolute timeout to from 2h to 20h. 2014-02-27 22:19:52 +01:00
Shea Levy
b29d7b1091 Only email responsible authors when the build has changed 2014-02-26 11:05:46 -05:00
Eelco Dolstra
8dcef7702f Add jobset/job menus on buid log pages 2014-02-26 11:49:28 +01:00
Eelco Dolstra
66b8c1a9e0 Return 410 Gone (rather than 500) if an output is no longer available 2014-02-26 11:38:02 +01:00
Rob Vermaas
6327edd63f Add a convenient way to get logs of a path/drv. Requested by phreedom. 2014-02-19 10:21:59 +00:00
Eelco Dolstra
73a0cb57c5 Jobset evals page: Don't show nrFailed if it's zero 2014-02-18 11:08:12 +01:00
Rob Vermaas
78974abb69 Remove sqlite from the docs. Not (properly) supported. 2014-02-17 12:24:34 +01:00
Hydra
d4d9896f9f Re-add the history tab (store size and build time), now as lazy-loaded tab on build page. 2014-01-28 11:55:19 +01:00
Rob Vermaas
b3c1c57a5b Add postgresql 9.2 remark 2014-01-24 13:00:18 +01:00
Rob Vermaas
ac177d0984 Add nixexprpath/nixexprinput to GET of jobset (API). 2014-01-23 12:44:02 +01:00
Eelco Dolstra
2398f2ce49 Spelling fix 2014-01-15 16:09:02 +01:00
Eelco Dolstra
492fe121ea Jobset eval page: Fix handling of aborted/cancelled builds
The fix in 85d51074 was not quite right.
2014-01-15 16:06:47 +01:00
Eelco Dolstra
cad2c07a35 Fix broken redirects 2014-01-14 18:17:33 +01:00
Eelco Dolstra
6572869596 clear-queue-non-current: Work around PostgreSQL query optimizer stupidity 2014-01-14 18:14:10 +01:00
Eelco Dolstra
62809f484f hydra-eval-jobs: Fix building against the latest unstable Nix 2014-01-12 17:37:56 +01:00
Rob Vermaas
1d392f64c6 Fix typo. 2014-01-10 15:20:19 +01:00
Rob Vermaas
bd7b6fc401 Allow Hydra to run as a private instance by requiring a login.
Use the following in your hydra.conf to make your instance a
private Hydra instance (public is the default):

  private 1

Currently, this will not allow you to use the API, channels
and the binary cache when running in private mode. We will add
solutions for these functionalities later.
2014-01-10 11:04:28 +01:00
Rob Vermaas
3e1a98668f Allow configuring a set of domains to allow logins from Persona.
E.g. add the following to only allow Persona logins from email.com and gmail.com email addresses.

  persona_allowed_domains email.com,gmail.com
2014-01-09 13:31:02 +01:00
Eelco Dolstra
a598fe7e81 Allow Hydra's binary cache to be signed
This requires adding the following to hydra.conf:

  binary_cache_key_name = <key-name>
  binary_cache_private_key_file = <path-to-private-key>

e.g.

  binary_cache_key_name = hydra.nixos.org-1
  binary_cache_private_key_file = /home/hydra/cache-key.sec
2014-01-08 15:19:17 +01:00
Shea Levy
de26b55afe User.pm: Handle params from JSON properly
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-12-12 09:38:57 -05:00
Rob Vermaas
f25f8dbfa3 Higher timeout for prefetching bazaar inputs. 2013-12-11 17:34:45 +01:00
Shea Levy
a92a57f3b0 hydra-evaluator: When evaluating a single jobset, exit with a failure code if evaluation fails
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-11-27 14:29:05 -05:00
Eelco Dolstra
dd4e57fb0c Allow passing a specific build as an input
Fixes #62.
2013-11-11 21:36:26 +00:00
Eelco Dolstra
8f104396ec Support passing a jobset evaluation as an input
All successful, non-garbage-collected builds in the evaluation are
passed in a attribute set.  So if you declare a Hydra input named
‘foo’ of type ‘eval’, you get a set with members ‘foo.<jobname>’.  For
instance, if you passed a Nixpkgs eval as an input named ‘nixpkgs’,
then you could get the Firefox build for x86_64-linux as
‘nixpkgs.firefox.x86_64-linux’.

Inputs of type ‘eval’ can be specified in three ways:

* As the number of the evaluation.

* As a jobset identifier (‘<project>:<jobset>’), which will yield the
  latest finished evaluation of that jobset.  Note that there is no
  guarantee that any job in that evaluation has succeeded, so it might
  not be very useful.

* As a job identifier (‘<project>:<jobset>:<job>’), which will yield
  the latest finished evaluation of that jobset in which <job>
  succeeded.  In conjunction with aggregate jobs, this allows you to
  make sure that the evaluation contains the desired builds.
2013-11-11 21:17:22 +00:00
Eelco Dolstra
7b35e4d0de Add a link to the latest finished eval of a jobset 2013-11-11 14:49:39 +01:00
Eelco Dolstra
a0fdf8d2ba Use local copy of the Persona sign in button 2013-11-06 22:20:57 +01:00
Eelco Dolstra
80267bcbb1 Merge branch 'persona' 2013-11-06 18:14:52 +01:00
Eelco Dolstra
c92410c147 Use hydra-module.nix in the tests 2013-11-06 18:10:52 +01:00
Shea Levy
066b982222 Revert "Add a unit template to run hydra-evaluator with arbitrary arguments"
Can't get the escaping to work right to pass more than one argument

This reverts commit 6cac7e9795.
2013-11-06 11:45:29 -05:00
Eelco Dolstra
8b67ad8787 hydra-module.nix: Export the HYDRA_* environment variables
This is useful if you want to run hydra-* commands manually.
2013-11-06 17:32:50 +01:00
Eelco Dolstra
ed9d57d0a4 hydra-module.nix: More paranoid permissions on the data directory 2013-11-06 17:29:34 +01:00
Eelco Dolstra
2614fe21fb hydra-module.nix: Use startAt 2013-11-06 17:29:22 +01:00
Eelco Dolstra
d710c1e443 hydra-module.nix: Fix setting the logo 2013-11-06 17:27:36 +01:00
Eelco Dolstra
243b05f1e7 hydra-module.nix: Use -p instead of HYDRA_PORT 2013-11-06 17:19:57 +01:00
Eelco Dolstra
f4845cde00 hydra-module.nix: Make services require hydra-init 2013-11-06 17:09:24 +01:00
Eelco Dolstra
1f6304c876 hydra-module.nix: Don't use a password
If PostgreSQL is running on the same system, then the "hydra" user can
can connect without a password (via Unix domain socket
authentication), so no need to set up a password.  If PostgreSQL is on
another machine, then creating a user/database won't work anyway.
2013-11-06 17:07:25 +01:00
Shea Levy
6cac7e9795 Add a unit template to run hydra-evaluator with arbitrary arguments
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-11-06 10:35:53 -05:00
Eelco Dolstra
ed69106c34 hydra-module.nix: Give types to options
Also, rename the "service.hydra.hydra" option to
"service.hydra.package" to be consistent with NixOS option naming
conventions.
2013-11-06 16:34:16 +01:00
Eelco Dolstra
6fc59aa0da hydra-module.nix: Remove the useWAL option
This is not a Hydra option but a Nix option so it shouldn't be here.
2013-11-06 16:17:11 +01:00
Eelco Dolstra
9dc3311ff7 hydra-module.nix: Don't create an admin user
It's the user's job to create users with the appropriate roles.
2013-11-06 16:15:53 +01:00
Eelco Dolstra
64cbdddea8 Test whether incorrect passwords are rejected 2013-11-06 16:12:08 +01:00
Eelco Dolstra
4fb3d67f49 Make /login give a proper JSON response again 2013-11-06 16:12:07 +01:00
Eelco Dolstra
bb2976693c Use hydra-init / hydra-create-user in the tests 2013-11-06 16:12:07 +01:00
Eelco Dolstra
8c2acdd294 make clean: Delete darcs-repo 2013-11-06 14:29:55 +00:00
Eelco Dolstra
60e7e4fbe9 Remove obsolete/broken timeline feature 2013-11-06 15:20:30 +01:00
Eelco Dolstra
e8d92445d7 Keep sessions for a week 2013-11-06 15:15:35 +01:00
Eelco Dolstra
5723fda7fc Keep session state across hydra-server restarts 2013-11-06 15:14:31 +01:00
Eelco Dolstra
33f01da507 Fix hydra_logo setting 2013-11-06 15:10:26 +01:00
Eelco Dolstra
df1a33c63f Fix layout at all page sizes 2013-11-06 14:50:21 +01:00
Eelco Dolstra
3c45992182 Make the logo configurable via hydra.conf 2013-11-06 14:40:30 +01:00
Eelco Dolstra
b44baf3746 Add a flag to enable Persona support
It's disabled by default.  To enable, add the following to hydra.conf:

  enable_persona = 1
2013-11-06 14:38:36 +01:00
Eelco Dolstra
d118a575e1 Use page-header on the front page 2013-11-06 14:11:56 +01:00
Eelco Dolstra
8928c35ecd Slight layout tweak 2013-11-06 14:07:43 +01:00
Eelco Dolstra
55f9d23933 Add a command `hydra-create-user' for managing user accounts 2013-11-06 13:36:29 +01:00
Eelco Dolstra
3315d1ea51 Remove obsolete hydra-control script 2013-11-06 11:42:49 +00:00
Eelco Dolstra
7a18e5f0c1 Remove unused file 2013-11-06 11:42:04 +00:00
Eelco Dolstra
63100b0ee8 Merge branch 'master' into persona 2013-11-06 12:35:36 +01:00
Eelco Dolstra
27a740d4b1 Don't show an empty projects list 2013-11-06 12:15:11 +01:00
Eelco Dolstra
a0b58b6b62 Fix typo that caused empty news item to show up 2013-11-06 12:15:11 +01:00
Eelco Dolstra
ecadcef642 Prevent a division by zero in hydra-queue-runner
Fixes #131.
2013-11-06 12:15:11 +01:00
Shea Levy
f1c187198c Stupid capitalization scheme
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-11-05 12:39:55 -05:00
Shea Levy
2e1c07c5f7 Argh
ALWAYS RUN THE TESTS

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-11-05 12:31:36 -05:00
aszlig
cfd4843290 topbar: Include "Create project" in menu.
For users who only have the "create-projects" role, actually display the
item in the menu as the only option.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2013-11-05 17:03:31 +01:00
aszlig
f6a83bcc5b user: Fix spelling of create-projects role.
This actually is right in the manual but displayed incorrectly on the
web interface.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2013-11-05 17:03:31 +01:00
Eelco Dolstra
8a0200edd2 Doh 2013-11-05 16:13:09 +01:00
Eelco Dolstra
ae85d2df23 Add a "My jobsets" tab to the dashboard 2013-11-05 16:05:29 +01:00
Shea Levy
d5574230e4 typo
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-11-05 09:57:15 -05:00
Shea Levy
217ba725a3 Restore accidentally-removed fields to the Builds API
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-11-05 09:43:32 -05:00
Shea Levy
385ceaff4d Show buildinput and buildproduct information in the Builds API
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-11-05 09:42:05 -05:00
Eelco Dolstra
589271bd72 In the "My jobs" tab, ignore disabled projects/jobsets 2013-11-05 14:53:52 +01:00
Eelco Dolstra
27b795f46e Doh 2013-11-05 14:46:20 +01:00
Eelco Dolstra
fc827a003a Be paranoid about the Persona email address 2013-11-05 14:40:40 +01:00
Eelco Dolstra
b53bd868fb Add a "My jobs" tab to the dashboard
It shows all current jobs of which the user is a maintainer.
2013-11-05 14:35:49 +01:00
Eelco Dolstra
3c981bed02 Slight cleanup in the Persona sign in code 2013-11-05 14:10:20 +01:00
Eelco Dolstra
bdd6e99fbd Clean up user editing 2013-11-05 14:02:04 +01:00
Eelco Dolstra
bd927eba66 Make sign in a modal dialog box rather than a separate page 2013-11-05 13:13:02 +01:00
Eelco Dolstra
299ac07cbc Re-enable adding new users via the web interface
Also unify user creation and user editing.
2013-11-05 12:41:10 +01:00
Eelco Dolstra
36c961a376 Store the account type ("hydra" or "persona") explicitly in the database 2013-11-05 11:46:05 +01:00
Eelco Dolstra
14b9b201e1 Don't show a password reset button for Persona accounts 2013-11-05 11:18:44 +01:00
Eelco Dolstra
b54cfbf032 Merge branch 'master' into persona
Conflicts:
	src/lib/Hydra/Helper/CatalystUtils.pm
	src/root/layout.tt
	src/root/topbar.tt
	src/root/user.tt
2013-11-05 11:11:48 +01:00
Eelco Dolstra
1f711403be Add a dev note 2013-11-05 10:50:02 +01:00
Eelco Dolstra
0fd6bb4e3f Drop building on i686-linux
Nobody cares.
2013-11-05 00:09:33 +01:00
Eelco Dolstra
32b6ddf772 hydra-eval-jobs: Support meta.license being a list
TODO: PostgreSQL has an array column type, we should use it for the
license and maintainers columns.
2013-11-04 22:50:32 +01:00
aszlig
484bcd10e2 hydra-module/compressLogs: Avoid creating /root/r.
We really don't need to touch a file in the current working directory
to find files that are older than one month. Since findutils 4.3.3 there
is a -newerXY option which allows to specify timestamps directly (as
with `date --date`).

But even when using a reference file, it really causes confusion if
people look into /root and try to debug where that misterious "r" file
is coming from.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2013-11-04 10:31:08 +01:00
Eelco Dolstra
647d6bc3f1 Force creation of a new uncached eval if jobs have been removed
Previously we only checked if jobs had been added.  We should probably
rename the "hasNewBuilds" field in the database.
2013-11-01 19:24:52 +01:00
Eelco Dolstra
a04c117eb6 Revert "Remove wacky "sysbuild" filtering"
This reverts commit 2d7e106d29.

Unfortunately some jobsets still depend on this behaviour.  They could
probably do something like "assert system == input.system; ..." but
changing them all is undesirable.
2013-11-01 18:30:36 +01:00
Eelco Dolstra
cbd56824a2 Use /etc/nix/machines 2013-10-30 11:21:23 +01:00
Eelco Dolstra
a919b503fb Restore api/get-info 2013-10-29 19:53:23 +01:00
Shea Levy
5da3dcfd57 Make the outputs' outpaths available via the Build JSON API
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-29 14:41:48 -04:00
Shea Levy
4eef090a45 Flesh out the API a bit
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-29 13:54:11 -04:00
Shea Levy
b51b8cddf4 Add in missing needed join
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-25 14:06:52 -04:00
Shea Levy
8e82ba0093 Get rid of old ToJSON code path
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-25 11:09:11 -04:00
Shea Levy
a89096ec5e Clean up root controller
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-25 11:09:11 -04:00
Shea Levy
5d3df69a0b Cleanup build serialization
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-25 11:09:11 -04:00
Shea Levy
e04477003e Cleanup eval serialization
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-25 11:09:11 -04:00
Shea Levy
917660442e Add eager fetching of relations and enable that for jobset->jobsetinputs
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-25 11:09:11 -04:00
Shea Levy
ec6568f9b7 Fix jobset input handling in the API
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-25 11:09:06 -04:00
Shea Levy
04d8adaad3 Cleanup Jobset serialization
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-24 11:39:40 -04:00
Shea Levy
78dcd3e619 Cleanup Project model
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-24 11:39:40 -04:00
Shea Levy
ee8275cfdb Start api cleanup with the User model
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-24 11:39:40 -04:00
Eelco Dolstra
f551de21f7 Fix creating jobsets in a RESTful way 2013-10-24 17:35:58 +02:00
Eelco Dolstra
c719bebcb4 Remove redundant newlines 2013-10-17 11:20:27 +02:00
Shea Levy
806af3fe68 Fix typos
I could've sworn I tested this...

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-16 08:57:48 -04:00
Shea Levy
0db950931a Merge remote-tracking branch 'upstream/who-broke-builds' into upstream-master
Include information about who changed the build status in notification
emails, and enable optional per-input notification of said committers.

Conflicts due to two branches modifying the database schema.

Signed-off-by: Shea Levy <shea@shealevy.com>

Conflicts:
	src/lib/Hydra/Schema/Jobsets.pm
	src/sql/upgrade-23.sql
2013-10-15 09:49:20 -04:00
Shea Levy
88217f5ad5 Stupid brittle tests
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-14 15:18:04 -04:00
Eelco Dolstra
2127d133cd Add a dashboard
Currently the dashboard allows users to get a quick overview of the
status of jobs they're interested in, but more will be added,
e.g. viewing all your jobsets or all jobs of which you're a
maintainer.
2013-10-14 20:07:26 +02:00
Eelco Dolstra
09b5679ee7 Clean up the authorization code a bit 2013-10-14 18:01:04 +02:00
Eelco Dolstra
86e9abeb15 Use c.req.captures 2013-10-14 17:43:31 +02:00
Eelco Dolstra
854d419b2c Use redirectJSON 2013-10-14 17:35:14 +02:00
Eelco Dolstra
c4e39d4769 Add one-shot jobsets
There are jobsets that are evaluated only once, that is, after they've
been evaluated, they're disabled automatically.  This is primarily
useful for doing releases: for instance, doing an evaluation with
"officialRelease" set to "true" should be done only once.
2013-10-11 12:01:52 +02:00
Eelco Dolstra
0babdf3532 Adjust to the NixOS/Nixpkgs merge 2013-10-11 10:58:34 +02:00
Eelco Dolstra
f592ce0026 Fix extreme slowness in hydra-queue-runner
If there are builds in the queue that depend on another scheduled
build, then hydra-queue-runner will start the dependency first and
block the dependent builds.  This is implemented in
findBuildDependencyInQueue.  However, if there are tens of thousands
of such dependent builds, since each call to
findBuildDependencyInQueue may take a second or so, hydra-queue-runner
will spend hours just deciding which builds *not* to do.  Thus very
little progress is made.

So now, when a build is started, we immediately check which builds are
"blocked" by it (i.e. depend on it), and remove such builds from
consideration.
2013-10-11 10:54:02 +02:00
Eelco Dolstra
a49457b2fd Don't break inside durations 2013-10-10 12:43:27 +02:00
Shea Levy
26470f1656 Check all inputs for blame but only email selected inputs
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-08 14:47:24 -04:00
Shea Levy
804617f075 Email responsible authors if requested
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-08 13:24:49 -04:00
Shea Levy
f8b80c99c2 Include who-broke-the-build information in notification emails
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-08 13:24:49 -04:00
Shea Levy
272d9e235d Remove unused assignment
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-08 13:24:49 -04:00
Shea Levy
2c90857689 getResponsibleAuthors: Respect checkResponsible
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-08 13:24:49 -04:00
Shea Levy
58ad3b4b6c Enable setting checkresponsible in the edit jobset form
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-08 13:24:49 -04:00
Shea Levy
3e1f930928 Enable setting emailresponsible in the edit jobset form
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-08 13:24:49 -04:00
Shea Levy
3e4a4e3761 Propagate checkresponsible from JobsetInput to BuildInput
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-08 13:24:49 -04:00
Shea Levy
07157f8125 Update Schema classes
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-08 13:24:49 -04:00
Shea Levy
6342464110 Add DB columns for when to notify responsible committers and which inputs should be checked
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-08 13:24:49 -04:00
Shea Levy
7913701d54 Factor a getResponsibleAuthors helper out of the HipChatNotification
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-10-08 13:24:49 -04:00
Rob Vermaas
20f1bf215a Make actions dropdown easier to find by making the dropdown title bold 2013-10-08 13:32:46 +02:00
Eelco Dolstra
0ec03aa0f4 Handle builds with multiple outputs correctly in Hydra channels 2013-10-07 17:06:17 +02:00
Eelco Dolstra
5ccff14f6b In Hydra channels, show only packages matching the user's system type
Fixes NixOS/nix#169.
2013-10-07 14:53:27 +02:00
Eelco Dolstra
5294a0a8a0 Register restarted derivations as GC roots 2013-10-04 17:11:42 +02:00
Eelco Dolstra
052bab169d Add a jobset eval action to restart all aborted/cancelled builds 2013-10-04 17:01:47 +02:00
Eelco Dolstra
85d51074b9 Jobset eval page: Show all aborted builds under the "aborted jobs" tab
Previously some might be included under the "new jobs" tab
2013-10-04 16:36:22 +02:00
Eelco Dolstra
e334ff541d Jobset eval page: Show the number of builds in each tab 2013-10-04 16:35:56 +02:00
Eelco Dolstra
aa49b128a8 Remove the "clone build" feature 2013-10-04 15:43:51 +02:00
Eelco Dolstra
7818bb75ed Add an action to cancel all builds in a jobset eval 2013-10-04 15:40:43 +02:00
Eelco Dolstra
3e54f0a6ab Fix an uninitialized value warning 2013-10-04 14:47:30 +02:00
Eelco Dolstra
ee5b655535 Maintain the order of the input alternatives 2013-10-03 20:03:57 +02:00
Eelco Dolstra
550bf210fe Use more flash messages 2013-10-03 19:54:22 +02:00
Eelco Dolstra
383bc62803 Restore link to clearvcscache 2013-10-03 19:43:21 +02:00
Eelco Dolstra
720c3892a3 Use delete instead of delete_all
DBIC's delete_all method fetches all rows separately, which is slow.
2013-10-03 19:42:44 +02:00
Eelco Dolstra
f32077b5e8 Simplify jobset cloning
We can just show the normal "edit jobset" page for the original jobset
and then do a PUT request to create a new jobset.

Also simplified updating the jobset inputs.  We can just delete all of
them and recreate them from the user parameters.  That's safe because
it's done in a transaction.
2013-10-03 19:28:25 +02:00
Eelco Dolstra
232f46c750 Use the REST API in the web interface for editing jobsets 2013-10-03 18:49:37 +02:00
Eelco Dolstra
63062f7bba Instead hard breaks in multi-line error messages 2013-10-03 18:05:37 +02:00
Eelco Dolstra
851c3329d0 Implement DELETE for jobsets and use it in the web interface 2013-10-03 17:54:40 +02:00
Eelco Dolstra
ae13dd3e67 Use the REST API in the web interface for editing projects 2013-10-03 17:23:41 +02:00
Eelco Dolstra
8355dc57ee Ensure proper encoding of error messages 2013-10-03 17:20:00 +02:00
Eelco Dolstra
acdeaa1d80 Fix tabs 2013-10-03 15:14:55 +02:00
Eelco Dolstra
97c76f34df Remove more dead code 2013-10-03 15:14:40 +02:00
Eelco Dolstra
ed132cf1fc Remove obsolete JobStatus source 2013-10-03 15:05:53 +02:00
Eelco Dolstra
c7a039bd05 Remove the Errors page
The same info is readily available under the most recent jobset eval
page.
2013-10-03 15:00:28 +02:00
Eelco Dolstra
64d617a6b2 Remove already disabled jobstatus code 2013-10-03 14:56:07 +02:00
Eelco Dolstra
adcdfcde6b Remove some obsolete JSON APIs 2013-10-03 14:50:56 +02:00
Eelco Dolstra
c8e5faf81e Clean up error handling 2013-10-03 14:45:23 +02:00
Eelco Dolstra
4ddb173ca1 Use notFound instead of status_not_found 2013-10-03 14:16:21 +02:00
Eelco Dolstra
2166c478ef Fix and clean up editing project settings 2013-10-03 14:05:10 +02:00
Eelco Dolstra
b1f7096935 Restore old findBuildDependencyInQueue behaviour 2013-10-03 13:08:32 +02:00
Eelco Dolstra
b1a26e6caa Revert "Add a dependency_lookup configuration option to enable (slow) dependency lookup in queue. This behaviour was disabled temporarily in accefbb79 due to slowness in very large queues, but some people might be dependent on it, so it is configurable until the previous behaviour is implemented more efficiently."
This reverts commit 24f5a6b15f.
2013-10-03 13:07:32 +02:00
Eelco Dolstra
9f3b47c963 Allow only project owners to delete projects / jobsets
Giant gaping security hole.
2013-10-03 13:06:16 +02:00
Eelco Dolstra
7a5ec00ea1 Fix a "Argument isn't numeric" warning if there are not jobsets 2013-10-03 13:04:20 +02:00
Eelco Dolstra
77fd72070f Fix showing the project's display name 2013-10-03 10:17:53 +00:00
Rob Vermaas
24f5a6b15f Add a dependency_lookup configuration option to enable (slow) dependency lookup in queue. This behaviour was disabled temporarily in accefbb79 due to slowness in very large queues, but some people might be dependent on it, so it is configurable until the previous behaviour is implemented more efficiently. 2013-10-03 09:09:18 +00:00
Eelco Dolstra
cc1fcf657c Show aborted/cancelled builds separately in jobset eval pages 2013-10-03 01:54:42 +02:00
Eelco Dolstra
9801cb76db Add an action menu to evaluations 2013-10-03 01:34:17 +02:00
Eelco Dolstra
4fa2821eea Move more actions from the top bar 2013-10-03 01:17:52 +02:00
Eelco Dolstra
a5cfae078e Remove the Build menu from the top bar
It's now a dropdown menu in the tabs thingy, which subsumes the
"Reproduce locally" button.  This makes the actions in the menu a bit
more visible, IMHO.
2013-10-02 19:10:00 +02:00
Eelco Dolstra
f50477141d Add an input type "nix" for passing arbitrary Nix expressions 2013-09-30 12:03:25 +02:00
Eelco Dolstra
4dd1197d89 Fix uninitialized value warning 2013-09-30 10:01:09 +00:00
Eelco Dolstra
af2b0c8bad Remove dead code 2013-09-30 11:57:38 +02:00
Eelco Dolstra
baafe77489 Fix HTML error
From Mats Erik Andersson.
2013-09-30 11:18:48 +02:00
Eelco Dolstra
d46ebeea99 Distinguish between permanent evaluation errors and transient input errors
Fixes #112.
2013-09-25 16:21:16 +02:00
Eelco Dolstra
e1c9e28589 Handle UTF-8 characters in eval error messages 2013-09-25 15:51:03 +02:00
Eelco Dolstra
a8db329839 Warn against multiple jobs with the same name 2013-09-25 15:30:59 +02:00
aszlig
da5824e11c hydra-module: Allow to specify the listen host.
It's currently possible to specify the port but not the address or
interface you want to listen on.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2013-09-25 14:48:13 +02:00
aszlig
0b202580ce templates: Use uri_for to reference static paths.
This commit is provided by (zsh syntax):

sed -i 's|/static[^"]*|[% c.uri_for("&") %]|;s/\[% size %\]/${size}/' **/*.tt

And the reason for this change is to make it easier to change the base
path with headers like X-Request-Base to be served within a URI prefix,
especially when behind a reverse proxy.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2013-09-25 14:37:18 +02:00
Eelco Dolstra
a2491f76a4 Use the same start/stop time for the build steps as for the build 2013-09-25 01:00:20 +02:00
Eelco Dolstra
f037a318e3 *headdesk*
DBIC::Class helpfully doesn't warn you when you're matching against
unselected columns.  So this query actually returned all builds...
2013-09-25 01:00:20 +02:00
Eelco Dolstra
2d7e106d29 Remove wacky "sysbuild" filtering
It's none of our business if a jobset wants to return a build that
uses a build for another system as an input...
2013-09-25 01:00:20 +02:00
Rob Vermaas
b1e29e50a7 Only send email notification of evaluation error when the evaluation error has changed. Fixes #121. 2013-09-24 12:01:57 -04:00
Eelco Dolstra
550d6b79b1 Allow dots in jobset names (like "release-13.09") 2013-09-24 15:15:44 +02:00
Shea Levy
1a313ad566 Allow dashes in jobset input names
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-09-23 17:53:35 -04:00
Shea Levy
6d5a3d0580 Derivations with multiple outputs break the 'link name is store path' assumption
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-09-22 21:26:59 -04:00
Shea Levy
c476d13586 hydra-module.nix: Make it possible to add extra config lines
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-09-22 19:20:09 -04:00
Shea Levy
98c9559bf2 Delay initializing the s3 client until it's needed to silence warnings
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-09-22 18:48:37 -04:00
Eelco Dolstra
77dbf55abb hydra-queue-runner: Tweaked the selection method
Pick the jobset that has used the smallest fraction of its share,
rather than the jobset furthest below its share in absolute terms.
This gives jobsets with a small share a quicker start (but they
will also run out of their share quicker).
2013-09-21 19:54:58 +00:00
Eelco Dolstra
cf43c605cd hydra-queue-runner: Cache the lookup of time spent per jobset 2013-09-21 19:54:46 +00:00
Eelco Dolstra
4cdf1a270d hydra-queue-runner: Set the start time properly 2013-09-21 19:38:02 +00:00
Eelco Dolstra
52ce662710 hydra-queue-runner: Don't kill builds we just started 2013-09-21 20:51:43 +02:00
Eelco Dolstra
accefbb798 hydra-queue-runner: Disable findBuildDependencyInQueue for now
It's way too slow.
2013-09-21 20:35:02 +02:00
Eelco Dolstra
24c757845d Fix lazy tab loading 2013-09-21 19:25:01 +02:00
Eelco Dolstra
9602499c1c hydra-evaluator: Do the actual work in a subprocess
This should get rid of the slow memory leaks exhibited by
hydra-evaluator.
2013-09-21 15:49:27 +00:00
Eelco Dolstra
4ed877360b hydra-queue-runner: Improved scheduling
Each jobset now has a "scheduling share" that determines how much of
the build farm's time it is entitled to.  For instance, if a jobset
has 100 shares and the total number of shares of all jobsets is 1000,
it's entitled to 10% of the build farm's time.  When there is a free
build slot for a given system type, the queue runner will select the
jobset that is furthest below its scheduling share over a certain time
window (currently, the last day).  Withing that jobset, it will pick
the build with the highest priority.

So meta.schedulingPriority now only determines the order of builds
within a jobset, not between jobsets.  This makes it much easier to
prioritise one jobset over another (e.g. nixpkgs:trunk over
nixpkgs:stdenv).
2013-09-21 14:57:01 +00:00
Eelco Dolstra
7efe793ee6 Fix the Darcs schema upgrade 2013-09-19 12:00:29 +00:00
Shea Levy
74388353b5 Add a plugin for backing up builds in s3
In your hydra config, you can add an arbitrary number of <s3config>
sections, with the following options:

* name (required): Bucket name
* jobs (required): A regex to match job names (in project:jobset:job
  format) that should be backed up to this bucket
* compression_type: bzip2 (default), xz, or none
* prefix: String to prepend to all hydra-created s3 keys (if this is
  meant to represent a directory, you should include the trailing slash,
  e.g. "cache/"). Default "".

After each build with an output (i.e. successful or failed-with-output
builds), the output path and its closure are uploaded to the bucket as
.nar files, with corresponding .narinfos to enable use as a binary
cache.

This plugin requires that s3 credentials be available. It uses
Net::Amazon::S3, which as of this commit the nixpkgs version can
retrieve s3 credentials from the AWS_ACCESS_KEY_ID and
AWS_SECRET_ACCESS_KEY environment variables, or from ec2 instance
metadata when using an IAM role.

This commit also adds a hydra-s3-backup-collect-garbage program, which
uses hydra's gc roots directory to determine which paths are live, and
then deletes all files except nix-cache-info and any .nar or .narinfo
files corresponding to live paths. hydra-s3-backup-collect-garbage
respects the prefix configuration option, so it won't delete anything
outside of the hierarchy you give it, and it has the same credential
requirements as the plugin. Probably a timer unit running the garbage
collection periodically should be added to hydra-module.nix

Note that two of the added tests fail, due to a bug in the interaction
between Net::Amazon::S3 and fake-s3. Those behaviors work against real
s3 though, so I'm committing this even with the broken tests.

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-09-18 18:32:58 +02:00
Eelco Dolstra
4705af48b8 hydra-build: Hack to handle timeouts 2013-09-18 13:06:35 +00:00
Eelco Dolstra
e4cbd057e2 Fix an uninitialized value warning 2013-09-18 12:51:51 +00:00
Eelco Dolstra
e54b536bb7 hydra-update-gc-roots: Don't keep the most recent successful view result
Views are deprecated.
2013-09-18 11:12:33 +00:00
Eelco Dolstra
2845d46d21 hydra-update-gc-roots: Keep more evals
We now keep *all* unfinished evaluations of a jobset, in addition to
the <keepnr> most recent finished evaluations.

The main motivation is to ensure that mirror-{nixos,nixpkgs} work
properly: if building an evaluation takes too long, some of its builds
may already have been garbage-collected by the time the others finish.
2013-09-18 11:10:10 +00:00
Eelco Dolstra
3b70a807b5 Allow setting keepnr to 0 2013-09-18 11:27:37 +02:00
Eelco Dolstra
c667b9112d Don't trigger evaluation of disabled jobsets 2013-09-18 11:25:52 +02:00
Eelco Dolstra
c14a333062 Revive release button on eval page 2013-09-17 16:39:50 +02:00
Rob Vermaas
597fd827b1 Merge pull request #81 from mornfall/master
DARCS support
2013-09-14 06:18:48 -07:00
Eelco Dolstra
3f68076577 hydra-build: Don't send a giant query to the database
We had Postgres barfing with this error:

  DBIx::Class::Storage::DBI::_dbh_execute(): DBI Exception: DBD::Pg::st execute failed: ERROR: stack depth limit exceeded

because the ‘drvpath => [ @dependentDrvs ]’ in failDependents can
cause a query of unbounded size.  (In this specific case there was a
failure of Bison, which has > 10000 dependent derivations.)  So now we
just get all scheduled builds from the DB.
2013-09-10 11:01:29 +00:00
Eelco Dolstra
35aad40692 Kill builds that produce more than 64 MiB of log output 2013-09-10 10:33:55 +00:00
Petr Rockai
0041c336d1 DarcsInput: Avoid a chdir. 2013-09-07 14:47:49 +02:00
Petr Rockai
66f3e60e2a Add a test for darcs inputs. 2013-09-07 13:28:53 +02:00
Petr Rockai
d31e4469bb Put a 5-second CPU time limit on the log processing pipeline. 2013-09-07 13:28:53 +02:00
Petr Rockai
1e1a1f0838 Also allow : (colon) in pathCompRE. 2013-09-07 13:28:53 +02:00
Petr Rockai
bb38bdfe35 Allow : and + in build product filenames. 2013-09-07 13:28:53 +02:00
Petr Rockai
dcf386cfed Make getDrvLogPath work with both bucketed and non-bucketed nix logs. 2013-09-07 13:28:53 +02:00
Petr Rockai
bb8059e50c Add support for fetching URLs as inputs. 2013-09-07 13:28:53 +02:00
Petr Rockai
5a35912956 Add support for darcs repositories. 2013-09-07 13:28:51 +02:00
Eelco Dolstra
5078730cb5 Use evalFile() instead of parseExprFromFile() 2013-09-06 15:17:27 +00:00
Shea Levy
351a026c4e libexpr's symbol table has changed
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-09-06 10:58:03 -04:00
Shea Levy
788c2bebaa Not every buildstep has a defined drvpath
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-09-03 14:43:08 -04:00
Eelco Dolstra
04e6eda4c7 Remove unused function 2013-09-03 20:29:52 +02:00
Eelco Dolstra
d914845ad7 Use a distinct icon for cancelled builds 2013-09-03 17:37:47 +02:00
Eelco Dolstra
e8fb659d63 Fix some wellformedness issues
Also fixed some duplicate IDs reported by Mats Erik Andersson.
2013-09-03 17:35:21 +02:00
Eelco Dolstra
614f07755a Don't show logs bigger than 64 MB 2013-08-30 20:44:04 +00:00
Eelco Dolstra
6655ada236 Serve raw uncompressed logs directly 2013-08-30 18:11:03 +00:00
Eelco Dolstra
fd7e37ef89 Try harder to find build logs
Due to the fixed-output derivation hashing scheme, there can be
multiple derivations of the same output path.  But build logs are
indexed by derivation path.  Thus, we may not be able to find the
log of a build or build step using its derivation.  So as a fallback,
Hydra now looks for other derivations with the same output paths.
2013-08-30 13:53:25 +00:00
Eelco Dolstra
559a98cfee Use a different icon for aborted builds 2013-08-28 17:40:51 +02:00
Eelco Dolstra
2f7071ee9d Tabify the eval page
The different types of types (new, removed, newly failing, and so
on) now each have their own tab.
2013-08-28 17:40:51 +02:00
Eelco Dolstra
07747b7e88 Allow filtering jobs in eval pages 2013-08-28 17:40:51 +02:00
Eelco Dolstra
d0bcaa6284 Allow comparing an eval against the jobset one day/week/month before 2013-08-28 17:40:51 +02:00
Eelco Dolstra
ccc09c565e Sort jobsets by name 2013-08-28 17:40:51 +02:00
Eelco Dolstra
58a6fdc5ed Remove the job status pages
They're mostly redundant since there is a faster "jobs" tab on
the jobset pages now.  The only thing the latter lacks is the
ability to see status change times, but those are quite expensive
to compute, and are visible on build pages if you really need them.
2013-08-28 17:40:51 +02:00
Eelco Dolstra
42c4ef856f Fix incorrect removed jobs in eval pages
PostgreSQL and Perl have different sort orders, in particular when
comparing job names such as "aspell.x86_64-linux" and
"aspellDicts.cs.i686-freebsd".  This confused the evaluation
comparison code, causing some jobs to appear as "removed".
So now we do all the sorting in Perl.

Fixes #105.
2013-08-28 17:40:50 +02:00
Eelco Dolstra
d886ff9973 Integrate the "Job status" and "All jobs" tabs
The job status tabs now has a toggle to show inactive jobs, rendering
the "All jobs" tab redundant.
2013-08-28 17:40:50 +02:00
Eelco Dolstra
9002b69c2d By default, show the first 250 jobs only
This is particularly useful for the Nixpkgs jobsets, which now have
~24K jobs.
2013-08-28 17:40:50 +02:00
Eelco Dolstra
10d959a9ff Show visual feedback that the filter is being applied 2013-08-28 17:40:50 +02:00
Eelco Dolstra
11acf0be28 Load a tab only once 2013-08-28 17:40:50 +02:00
Eelco Dolstra
410060ec8a Jobset page: Add a new tab to show job status in a matrix 2013-08-28 17:40:50 +02:00
Eelco Dolstra
82e073d043 Show build status 2 and 5 in the same way
(Status 5 is obsolete.)
2013-08-28 17:40:50 +02:00
Eelco Dolstra
e69c7ac360 "limit" -> "rows" 2013-08-28 17:40:50 +02:00
Eelco Dolstra
7685596aa8 Transpose the aggregate constituents table
This way, it grows vertically rather than horizontally.  Horizontal
may be more "logical", but this is more practical.
2013-08-28 17:40:50 +02:00
Eelco Dolstra
7725038821 On aggregate job pages, show a matrix showing all the constituent builds 2013-08-28 17:40:50 +02:00
Rob Vermaas
bf42392fe4 Fix typo. 2013-08-27 15:12:41 +02:00
Eelco Dolstra
a57957df84 Handle job aliases in AggregateConstituents
Aggregate constituents are derivations.  However there can be multiple
builds in an evaluation that have the same derivation, i.e. they can
alias each other (e.g. "emacs", "emacs24" and "emacs24Packages.emacs"
in Nixpkgs).  Previously we picked a build arbitrarily for the
AggregateConstituents table.  Now we pick the one with the shortest
name (e.g. "emacs").
2013-08-27 11:48:02 +02:00
Rob Vermaas
a98075f386 HipChat notification: do not include latest commits of all inputs in 'who-broke-the-build' list. Use only committers from inputs that have actually changed since previous build. 2013-08-26 11:06:10 +00:00
Eelco Dolstra
9a9b798939 Work around 9P corruption on 32-bit
On 32-bit, Linux 3.4, and if the memory size is bigger than a certain
value, starting the stage 2 init script fails with "Exec format error"
because the 9P filesystem is returning garbage.  No such problem with
Linux 3.10.

http://hydra.nixos.org/build/5737226
2013-08-21 15:10:40 +02:00
Eelco Dolstra
02cba75610 Add an action to download a specific output of a build as a .nar.bz2
E.g. http://hydra/build/3515983/output/out downloads the output named
"out" as a bzip2-compressed NAR.
2013-08-21 14:30:38 +02:00
Eelco Dolstra
fda9b66dc7 Doh 2013-08-20 17:37:15 +02:00
Eelco Dolstra
edb88ef452 Remove unused ActiveJobs source 2013-08-20 15:22:46 +02:00
Eelco Dolstra
14e418cafa Don't show bogus last-checked times 2013-08-16 18:26:01 +02:00
Eelco Dolstra
6264995198 Remove the jobs status page
The per-system presentation doesn't make much sense any more given
issue #60.  It should be replaced by (say) a grid showing each job per
evaluation.
2013-08-16 17:16:15 +02:00
Eelco Dolstra
e54c361a95 Remove per-platform links from the job page
Having different builds within a job is obsolete (issue #60), one
should have different job per platform (e.g. build.x86_64-linux).
2013-08-16 16:39:42 +02:00
Eelco Dolstra
056e2ce503 Don't mess with $LOGNAME in nix-shell 2013-08-16 16:38:09 +02:00
Eelco Dolstra
a9c6f522e6 clear_queue_non_current: Don't use isCurrent 2013-08-16 16:38:09 +02:00
Eelco Dolstra
46f8b25c1f Keep builds that failed with output
The user may want to look at the output, so they shouldn't be
GC'ed right away.
2013-08-16 16:36:06 +02:00
Eelco Dolstra
d16738e130 hydra-update-gc-roots: Keep the most recent evaluations
We now keep all builds in the N most recent evaluations of a jobset,
rather than the N most recent builds of every job.  Note that this
means that typically fewer builds will be kept (since jobs may be
unchanged across evaluations).
2013-08-16 16:21:30 +02:00
Eelco Dolstra
8e1ade4422 Fix display of non-aggregate builds 2013-08-15 13:57:47 +02:00
Eelco Dolstra
242072bbd6 Hide the views tab for project that don't have them
Views are obsolete (replaced by the declarative "aggregate" build
mechanism) so we don't want people creating new ones.
2013-08-15 13:54:23 +02:00
Eelco Dolstra
c9a0e12804 Hide project/jobset in constituent list 2013-08-15 03:35:18 +02:00
Eelco Dolstra
72a0fa6ec5 Sort constituents by job name 2013-08-15 03:28:21 +02:00
Eelco Dolstra
06c74085b5 Make "Add to release" a modal dialog 2013-08-15 03:07:20 +02:00
Eelco Dolstra
d92d83a82a Fix broken redirect when editing a release 2013-08-15 02:57:36 +02:00
Eelco Dolstra
1776d9118f Rename aggregate members to constituents 2013-08-15 02:33:10 +02:00
Eelco Dolstra
e4141afcc9 On the build page, show how many aggregate constituents failed
(Also, renamed aggregate "member" to "constituent", since "member" is
rather vague.)
2013-08-15 02:17:06 +02:00
Eelco Dolstra
81322de94e Show aggregate members 2013-08-15 00:30:19 +02:00
Eelco Dolstra
d30b49ebac Forgot to commit 2013-08-14 03:50:07 +02:00
Eelco Dolstra
d58142b3f0 Store aggregate members in the database
For presentation purposes, we need to know what builds are part of an
aggregate build.  So at evaluation time, look at the "members"
attribute, find the corresponding builds in the eval, and create a
mapping in the AggregateMembers table.
2013-08-14 01:59:29 +02:00
Eelco Dolstra
c27f4bbaf5 Add a redirect from an eval to a named member
E.g. /eval/798867/job/tarball redirects to the build with job name
"tarball".
2013-08-13 01:56:45 +02:00
Eelco Dolstra
a25ea193f7 Add a /eval action to /build to go from a build to the latest finished eval 2013-08-13 01:43:50 +02:00
Eelco Dolstra
fcdca0d4de Fix some XML wellformedness issues 2013-08-13 00:41:37 +02:00
Eelco Dolstra
4792256e43 Add some more fields to the JSON output of /build 2013-08-12 22:57:53 +02:00
Eelco Dolstra
bef263c930 Add a ‘latest-finished’ action
It redirects to the latest successful build from a finished
evaluation.  This is mostly useful for the Nixpkgs/NixOS mirroring
script, which need the latest finished evaluation in which some
aggregate job (such as ‘tested’ in NixOS) succeeded.
2013-08-12 22:17:04 +02:00
Eelco Dolstra
84acccb3ea Index builds on stop time
This is necessary to make the /all page fast, since it sorts builds on
descending stop time.
2013-08-12 20:19:10 +02:00
Eelco Dolstra
452c8e36d1 Materialize the number of finished builds
The NrBuilds table tracks the value of ‘select count(*) from Builds
where finished = 0’, keeping it up to date via a trigger.  This is
necessary to make the /all page fast, since otherwise it needs to do a
sequential scan on the Builds table.
2013-08-12 20:19:10 +02:00
Eelco Dolstra
182f725612 Don't pass an undefined input 2013-08-12 18:15:11 +02:00
Eelco Dolstra
d96df42c03 GitInput.pm: Don't do a chdir to the Git clone
Doing a chdir in the parent is evil.  For instance, we had Hydra core
dumps ending up in the cloned directory.  Therefore, the function
‘run’ allows doing a chdir in the child.  The function ‘grab’ returns
the child's stdout and throws an exception if the child fails.
2013-08-12 17:46:26 +02:00
Eelco Dolstra
1481badf21 For nix-shell, set some more variables in preHook 2013-08-12 17:23:33 +02:00
Rob Vermaas
90eedcf256 HipChat notification: add support for Mercurial inputs for determining who might have broken the build. 2013-08-07 08:53:32 +00:00
Shea Levy
96e987bbfa Use inputTypes from plugins to determine valid input types
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-29 17:42:49 -04:00
Shea Levy
687ca429c3 Pass project and jobset to fetchInput
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-29 15:33:22 -04:00
Shea Levy
5efe8365ef Whoops
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-28 12:16:46 -04:00
Shea Levy
30e3d57482 Install hydra-module.nix into $out/share/nix
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-28 11:24:31 -04:00
Shea Levy
0c0cf4113e Add an option to run the hydra server in debug mode
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-28 11:11:09 -04:00
Shea Levy
10cad61231 Don't put ssmtp in hydra's paths
Some installations may want to use system-wide sendmail (i.e.
/run/setuid-wrappers/sendmail) and those that want ssmtp can add it to
hydra's path themselves.

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-28 11:06:02 -04:00
Shea Levy
0bb568912b hydra-module.nix: Automatically create postgres db user for hydra and an admin hydra account
The initial password for the admin account can be found in /var/lib/hydra/.pgpass.

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-28 11:05:03 -04:00
Shea Levy
f231c23b75 Only serialize JSON and HTML, not the C::C::REST defaults
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-26 14:25:25 -04:00
Shea Levy
eab13d8736 ToJSON is automatically called recursively
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-26 13:54:07 -04:00
Shea Levy
d6b23272e3 Don't try to serialize if there's nothing to serialize
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-26 12:04:27 -04:00
Shea Levy
f7bcf9fc19 The field is actually enabled, not disabled
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-25 17:59:13 -04:00
Shea Levy
1404d33005 Show when a Project's jobsets are disabled
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-25 17:48:28 -04:00
Rob Vermaas
513c030268 Do not use local clone for Bazaar inputs. 2013-07-22 20:42:17 +02:00
Eelco Dolstra
967791f6f3 Add the actual file 2013-07-19 15:02:01 +02:00
Eelco Dolstra
1b5e0821d1 Add hacking.xml to the distribution 2013-07-19 15:01:18 +02:00
Eelco Dolstra
6574d125c7 Get rid of a warning in the HipChat plugin 2013-07-19 14:43:04 +02:00
Eelco Dolstra
b47d9814e3 Clear $HYDRA_CONFIG in the tests
Otherwise one might accidentally send out HipChat notifications when
running the tests...
2013-07-19 14:42:34 +02:00
Eelco Dolstra
659c829e88 Tweaks for nix-shell 2013-07-19 14:36:52 +02:00
Eelco Dolstra
7cd386894d Don't try to open the Nix DB from configure
Not sure how this ever worked before...
2013-07-19 10:57:40 +02:00
Ludovic Courtès
2d5e06918b Hydra::View::Plain: Explicitly set the response body.
This fixes a bug with Catalyst 1.39 whereby a raw hash table would
erroneously be returned for /nix-cache-info.
2013-07-12 16:53:48 +02:00
Ludovic Courtès
438d7f7c5c Reply 404 for requests for non-existent .narinfo. 2013-07-12 16:52:40 +02:00
Eelco Dolstra
db3647aa15 Set the character set
Cherry-picked from the persona branch.
2013-07-12 15:04:13 +02:00
Eelco Dolstra
d071bbfb28 Fix Hipchat notification 2013-07-12 15:04:13 +02:00
Shea Levy
7a0f80f016 Include the email override list in the Jobset serialization
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-11 11:01:36 -04:00
Eelco Dolstra
ccd2292458 Link to both the Persona and legacy sign in 2013-07-09 14:39:28 +02:00
Eelco Dolstra
486a844866 Fix audience URL 2013-07-09 14:05:04 +02:00
Eelco Dolstra
1db9381473 Fix legacy login 2013-07-09 13:55:44 +02:00
Eelco Dolstra
9aa44fa944 Some escaping 2013-07-09 13:55:29 +02:00
Eelco Dolstra
895f21cfad Show a user's roles in the preferences page 2013-07-09 13:07:04 +02:00
Eelco Dolstra
476203d0bb Prevent Persona users from setting a password 2013-07-09 13:01:56 +02:00
Eelco Dolstra
5fecf8e385 Show sign in as success 2013-07-09 12:07:18 +02:00
Eelco Dolstra
08f3bb78c4 Use the alert class for flash messages 2013-07-09 12:05:25 +02:00
Eelco Dolstra
12ca755bea Don't redirect to /login if authentication is required
We can just serve the login page in place.
2013-07-09 12:02:15 +02:00
Eelco Dolstra
13f0b54c49 Set the character set 2013-07-09 00:23:48 +02:00
Eelco Dolstra
c08fc6ce1e Add basic Persona support
This allows users to sign in to Hydra using Mozilla Persona accounts.
When a user first sign in, a row in the Users table for the given
Persona identity (an email address) is created automatically.

To do: figure out how to deal with legacy accounts.
2013-07-08 23:54:40 +02:00
Shea Levy
efd011fbc3 Revert "Don't call buildFinished after we already know it failed"
I don't understand perl strings.

This reverts commit b2f6be9686.

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-08 14:30:46 -04:00
Shea Levy
b2f6be9686 Don't call buildFinished after we already know it failed
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-08 13:52:51 -04:00
Shea Levy
166d56088f Call buildFinished when a cached build is added
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-08 13:35:34 -04:00
Shea Levy
b46f2134e0 Revert "Emable overriding the email template."
This doesn't work as planned, will re-work.

This reverts commit 304f8a5714.
2013-07-05 18:10:50 -04:00
Shea Levy
a168f43515 Revert "Handle HYDRA_EMAIL_TEMPLATES that are paths"
This doesn't work as planned, will re-work.

This reverts commit d2ce7747a0.
2013-07-05 18:10:21 -04:00
Shea Levy
d2ce7747a0 Handle HYDRA_EMAIL_TEMPLATES that are paths
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-05 17:22:51 -04:00
Shea Levy
304f8a5714 Emable overriding the email template.
The HYDRA_EMAIL_TEMPLATE env var can be set to any value understood by
https://metacpan.org/module/Template#process-template-vars-output-options
as the $template argument.

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-05 16:29:09 -04:00
Shea Levy
be3ca0dd84 Fix jobset update
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-05 14:44:29 -04:00
Shea Levy
93a14ccf32 Check if we want to send email for a build before iterating through its users
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-05 14:06:10 -04:00
Shea Levy
117ae78a45 32-bit qemu can only do 2047 MB
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-03 16:42:10 -04:00
Shea Levy
002ac9ef63 Merge in the first bits of the API work
The catalyst-action-rest branch from shlevy/hydra was an exploration of
using Catalyst::Action::REST to create a JSON API for hydra. This commit
merges in the best bits from that experiment, with the goal that further
API endpoints can be added incrementally.

In addition to migrating more endpoints, there is potential for
improvement in what's already been done:
* The web interface can be updated to use the same non-GET endpoints as
  the JSON interface (using x-tunneled-method) instead of having a
  separate endpoint
* The web rendering should use the $c->stash->{resource} data structure
  where applicable rather than putting the same data in two places in
  the stash
* Which columns to render for each endpoint is a completely debatable
  question
* Hydra::Component::ToJSON should turn has_many relations that have
  strings as their primary keys into objects instead of arrays

Fixes NixOS/hydra#98

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-07-02 14:00:46 -04:00
Eelco Dolstra
d18fc4fc38 Include names of committers in HipChat notifications
HipChat notification messages now say which committers were
responsible, e.g.

  Job patchelf:trunk:tarball: Failed, probably due to 2 commits by Eelco Dolstra
2013-07-02 13:54:18 +02:00
Eelco Dolstra
7e11d01abf Remove tabs 2013-07-02 11:37:16 +02:00
Eelco Dolstra
663b6a747b release.nix: Get rid of the "system" argument 2013-07-01 19:37:14 +02:00
Eelco Dolstra
fe030331b5 Revert "Don't compress already-compressed files."
This reverts commit 190bffd846.
2013-07-01 18:46:18 +02:00
Eelco Dolstra
11414b0447 Revert "Doh"
This reverts commit f1f938512d.
2013-07-01 18:46:14 +02:00
Rob Vermaas
f1f938512d Doh 2013-07-01 18:12:33 +02:00
Rob Vermaas
9d7c14b342 Merge pull request #103 from civodul/nar-uncompressed
Don't compress already-compressed files.
2013-07-01 08:16:51 -07:00
Eelco Dolstra
9939ddf22c Add a plugin for HipChat notification
This plugin sends notification of build failure or success to a
HipChat room, if the status differs from the last build.

The plugin can be configured by adding one or more of these stanzas to
hydra.conf:

  <hipchat>
    jobs = (patchelf|nixops):.*:.*
    room = 1234
    token = 39ab2198fe...
  </hipchat>

Here "jobs" is a regular expression against which the fully qualified
job name of the build is matched (so for instance
"nixops:master:tarball" will match the stanza above).
2013-06-27 18:56:31 +02:00
Eelco Dolstra
698d6eac89 Eliminate duplicate getPreviousBuild functions
And move some stuff into CatalystUtils for use by other plugins.
2013-06-27 18:08:00 +02:00
Eelco Dolstra
c65f40e146 Add common.js to the tarball 2013-06-25 12:48:25 +02:00
Eelco Dolstra
611f402a70 Move common Javascript code into a separate file 2013-06-25 01:16:28 +02:00
Eelco Dolstra
a5436be2ce After editing a project/jobset, redirect back to the config tab 2013-06-25 01:00:59 +02:00
Eelco Dolstra
68a03bc674 When a tab is selected, change the fragment id
And when a page is visited, active the tab identified by the fragment
id.  This allows linking to a specific tab.

Fixes #93.
2013-06-25 00:55:14 +02:00
Eelco Dolstra
afc90b36db Don't print to stdout 2013-06-24 22:22:43 +00:00
Ludovic Courtès
190bffd846 Don't compress already-compressed files.
Fixes <https://github.com/NixOS/hydra/issues/102>.
2013-06-23 15:23:16 +02:00
Eelco Dolstra
51f0185797 Allow _ in release names 2013-06-18 16:00:24 +02:00
Eelco Dolstra
98a105fe69 hydra-build: Give a nicer error message if the derivation is gone 2013-06-14 11:01:53 +00:00
Eelco Dolstra
cceab7308b hydra-queue-runner: Handle restarted builds whose derivation is gone
Restarted builds whose derivation has been garbage-collected in the
meantime caused hydra-queue-runner to get stuck in a loop saying:

Jun 14 11:54:25 lucifer hydra-queue-runner[31844]: system type `x86_64-darwin': 0 active, 2 allowed, started 2 builds
Jun 14 11:54:25 lucifer hydra-queue-runner[31844]: {UNKNOWN}: path `/nix/store/wcizsch2garjlvs4pswrar47i1hwjaia-inconsolata.drv' is not valid at
/nix/store/ypkdm4v13yrk941rvp8h0y425a5ww6nm-hydra-0.1pre1353-40debf1/bin/.hydra-queue-runner-wrapped line 51. at
/nix/store/kjpsc2zdaxnd44azxyw60f2px839m1cd-hydra-perl-deps/lib/perl5/site_perl/5.16.2/Catalyst/Model/DBIC/Schema.pm line 501
2013-06-14 11:00:05 +00:00
Eelco Dolstra
289b29791f Add note on restarting builds that times out 2013-06-13 20:54:28 +02:00
Eelco Dolstra
0046c81857 Remove Switch dependency, we're not using it 2013-06-13 15:14:33 +02:00
Eelco Dolstra
7a926935a5 Add Catalyst::DispatchType::Regex for forward compatibility 2013-06-13 15:13:52 +02:00
Eelco Dolstra
1c30a777ad Fix project/jobset deletion 2013-06-11 16:57:22 +02:00
Eelco Dolstra
40debf1515 hydra-queue-runner: Don't unlock builds we just started
This happens if the previous iteration took more than 60 seconds.
Then the queue runner may think that builds failed to start properly
and unlock them, e.g.

build 5264936 pid 19248 died, unlocking
build 5264951 pid 19248 died, unlocking
build 5257073 pid 19248 died, unlocking
...
2013-06-07 20:15:37 +00:00
Eelco Dolstra
5d9b7c6ab2 Speed up findBuildDependencyInQueue
This was taking a long time due to the giant SQL query.

Issue #99.
2013-06-07 20:15:32 +00:00
Eelco Dolstra
8e36343b62 hydra-queue-runner: Start as many builds as possible on each iteration
Because we don't start a build if a dependency is already building,
it's possible that some or all of the $extraAllowed highest-priority
builds in the queue are not eligible.  E.g. with $extraAllowed = 32,
we might start only 3 builds even though there are thousands in the
queue.  The fix is to try all queued builds until $extraAllowed have
been started.

Issue #99.
2013-06-07 20:15:20 +00:00
Eelco Dolstra
2974fea1a7 Use https://ajax.googleapis.com if we're on https 2013-06-07 15:45:37 +02:00
Eelco Dolstra
f4ecf27def Fix Perl warning about $path masking earlier definition 2013-06-02 23:32:09 +02:00
Eelco Dolstra
8e246a835a Don't do camel case in filenames 2013-06-02 23:30:46 +02:00
Eelco Dolstra
66c695e1c3 Fix ‘Unable to handle files with the extension 'conf'’
Config::Any uses Module::Pluggable to seach for plugins, so it needs
the patched Module::Pluggable in Nixpkgs (rather than the one in Perl
itself) to properly find plugins in symlink trees created by buildEnv.
2013-06-02 23:29:24 +02:00
Shea Levy
591acda6f9 reproduce.tt: Save the revCount when reproducing more than once
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-05-30 14:06:32 -04:00
Shea Levy
8e716ff062 reproduce.tt: Create the checkout dir before an hg clone
For some reason, hg clone from a local (path-based) repo will fail if
the parent directory of the destination directory doesn't exist (though
it succeeds when cloning from an http repo).

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-05-30 13:31:53 -04:00
Eelco Dolstra
1277a8fc1c Don't break certain table columns
For instance, if the "timestamp" column becomes too small, then every
timestamp is spread out across two lines, doubling the size of the
table.
2013-05-29 14:58:44 +02:00
Eelco Dolstra
47c49cf3d4 Show links on products of type "doc" 2013-05-29 11:39:23 +02:00
Eelco Dolstra
77e37c1ea3 Don't add a nix-build build product unless $out is a directory 2013-05-28 18:43:05 +02:00
Eelco Dolstra
1f1615e80b Support revision control systems via plugins 2013-05-25 15:36:58 -04:00
Eelco Dolstra
5e0542d3af Use buildEnv to combine Hydra's Perl dependencies
This makes the Perl search path ($PERL5LIB) much shorter, cutting down
the number of stat() calls when starting hydra-server from ~432000 to
~9000.
2013-05-24 15:26:47 -04:00
Eelco Dolstra
e0c411220e built.tt: Handle the case where the original build is not known
And remove some parentheses.
2013-05-24 12:43:31 -04:00
Eelco Dolstra
9ac363d32a Fill in starttime/stoptime for cached builds 2013-05-24 12:43:02 -04:00
Petr Rockai
6c0577b226 Respect X-Request-Base header coming from a frontend proxy. 2013-05-23 13:07:40 -04:00
Eelco Dolstra
5e5b344527 Make latest/latest-for more efficient
Getting all matching rows from the database is expensive.
2013-05-23 12:18:38 -04:00
Eelco Dolstra
7b5e92868b Remove unused Jobs columns
Actually, we can *almost* get rid of the Jobs table entirely...
2013-05-23 12:12:19 -04:00
Eelco Dolstra
b1f89bf92d Ensure that stoptime and starttime are set for finished builds 2013-05-23 12:05:12 -04:00
Eelco Dolstra
57b2bb0674 Let Builds.timestamp refer to the time the build was added
Previously, for scheduled builds, "timestamp" contained the time the
build was added to the queue, while for finished builds, it was the
time the build finished.  Now it's always the former.
2013-05-23 10:45:49 -04:00
Eelco Dolstra
e09622eb29 Include # of failed builds in Subject 2013-05-21 18:30:05 -04:00
Shea Levy
4b1a8384db reproduce.tt: Set revCount for hg repos
The revision counting changes depending on which revision is cloned
initially, so clone the default branch first and then checkout the
required revision to match hydra's revCount.

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-05-16 11:24:17 -04:00
Rob Vermaas
666f398e98 Always show the links related to the build product. 2013-05-16 11:29:54 +00:00
Eelco Dolstra
444b03bad2 Omit the system type if it's part of the job name 2013-05-15 11:43:06 +02:00
Eelco Dolstra
ac6a152ec5 Improve email notifications status messages
Add "Failed with output", and shorten "Failed with non-zero exit code"
to "Failed".
2013-05-15 11:31:37 +02:00
Rob Vermaas
43785dfca9 Merge pull request #85 from peti/dont-clutter-system-log-with-debug-messages
hydra-queue-runner: don't clutter the system log with debug message
2013-05-10 14:52:13 -07:00
Eelco Dolstra
3939974df8 Set build status to 1 if the primary build failed 2013-05-10 00:51:45 +02:00
Eelco Dolstra
102359bf44 Add separate build step status codes for cached failures and timeouts 2013-05-09 22:13:01 +00:00
Eelco Dolstra
a6d8566faf If a build aborts, mark any remaining active build steps as aborted
See e.g. http://hydra.nixos.org/build/4915744.

P.S. existing active build steps of finished builds can be marked as
aborted by running:

update buildsteps set busy = 0, status = 4
  where (build, stepnr) in
    (select s.build, s.stepnr from buildsteps s join builds b on s.build = b.id where b.finished = 1 and s.busy = 1);
2013-05-09 18:03:34 +02:00
Eelco Dolstra
7b78596412 Install plugins 2013-05-09 17:02:16 +02:00
Eelco Dolstra
184d23dc41 Remove debug line 2013-05-09 15:10:30 +02:00
Eelco Dolstra
3ca7b84297 Don't float the search bar to the right in collapsed mode 2013-05-09 14:36:51 +02:00
Eelco Dolstra
26b3da5d13 Fix tests
http://hydra.nixos.org/build/4902041
2013-05-09 14:29:04 +02:00
Eelco Dolstra
de89c566f8 Use Template::Toolkit to generate email messages
Also, make the messages much shorter by not including build details.
2013-05-09 14:23:15 +02:00
Eelco Dolstra
b378d94087 If multiple dependent builds fail, send a single email 2013-05-09 11:39:58 +02:00
Eelco Dolstra
038db3abeb Pass failing dependent builds to buildFinished 2013-05-08 18:54:01 +02:00
Eelco Dolstra
44b8d6f449 Use OO-style plugins
This is mostly so we don't have to pass around common parameters like
"db" and "config", and we don't have to check for the existence of
methods.

A plugin now looks like this:

  package Hydra::Plugin::TwitterNotification;

  use parent 'Hydra::Plugin';

  sub buildFinished {
      my ($self, $build, $dependents) = @_;
      print STDERR "tweeting about build ", $build->id, "\n";
      # Send tweet...
      # Hydra database is $self->{db}.
  }
2013-05-08 18:35:24 +02:00
Eelco Dolstra
a420a33f66 Use "can" to check whether a plugin supports buildFinished 2013-05-08 17:57:48 +02:00
Eelco Dolstra
1d8bb0764b Add a plugin mechanism
You can now add plugins to Hydra by writing a module called
Hydra::Plugin::<whatever> and putting it in Perl's search path.  The
only plugin operation currently supported in buildFinished, called
when hydra-build has finished doing a build.

For instance, a Twitter notification plugin would look like this:

  package Hydra::Plugin::TwitterNotification;

  sub buildFinished {
      my ($self, $db, $config, $build, $dependents) = @_;
      print STDERR "tweeting about build ", $build->id, "\n";
      # send tweet...
  }

  1;
2013-05-08 17:30:30 +02:00
Eelco Dolstra
f447c7d9db Add separation between news items 2013-05-07 17:04:42 +02:00
Eelco Dolstra
a84db1c7cc Use extra-binary-caches 2013-05-07 15:57:20 +02:00
Eelco Dolstra
9947415ef0 Remove Twitter notification support
Turns out Twitter is not an ideal medium for sending build
notifications :-)
2013-05-03 18:33:11 +02:00
Eelco Dolstra
f762d111f1 If a build step fail, immediately fail all queued builds that depend on it
This prevents unnecessary work, but it's mostly a refactoring to
support combining notification emails.
2013-05-03 18:30:13 +02:00
Eelco Dolstra
507e5bb190 Drop unused "disabled" columns 2013-05-03 16:39:17 +02:00
Eelco Dolstra
906b129f6a Fix findBuildDependencyInQueue
Previously this function didn't actually have a lot of effect.  If a
build A had a dependency B, Hydra would start B first.  But on the
next scan through the queue, it would start A anyway, because of the
"busy => 0" restriction.

Now the queue runner won't start a build if a dependency is already
running.  (This is not necessarily optimal, since the build may have
other dependencies that don't correspond to a build in the queue but
could run.  One day we'll start all Hydra builds in parallel...)

Also, for performance, use computeFSClosure instead of "nix-store
-qR".  And don't bother with topological sorting because it didn't
have an effect anyway since the database returns dependencies in
arbitrary order.
2013-05-03 16:27:26 +02:00
Eelco Dolstra
9e72c64eff Restore the links to the contents pages
These were accidentally lost in
80e0e7c84a.
2013-05-03 14:13:14 +02:00
Eelco Dolstra
e96916533f Allow a per-jobset check interval
This allows checking a jobset (say) at most once a day.  It's also
possible to disable polling by setting the interval to 0.  This is
useful for jobsets that use push notification or are manually
evaluated.
2013-05-02 17:55:47 +02:00
Eelco Dolstra
edaeb892e7 reproduce.tt: Use color 2013-05-02 17:55:47 +02:00
Eelco Dolstra
a468a28840 reproduce.tt: Check for the presence of commands like nix-build 2013-05-02 17:55:47 +02:00
Eelco Dolstra
659898bd67 reproduce.tt: Add --help flag
And a --dir flag to override the directory where inputs etc. are
stored.
2013-05-02 17:55:47 +02:00
Shea Levy
adb9ad83dd hydra-evaluator: Respect triggers of disabled jobsets
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-05-02 11:32:25 -04:00
Shea Levy
b8ea428bb1 Allow manually scheduling disabled jobsets for evaluation
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-05-02 11:21:43 -04:00
Eelco Dolstra
3003bb1c99 Don't fall thru to Hydra::View::NARInfo
This caused exceptions like:

  Caught exception in Hydra::Controller::Build->view_build "writing to file: Broken pipe at /nix/store/ihdb3widsq1dk7sbl5vqjxfcxb5ypad4-hydra-0.1pre1297-8158093/libexec/hydra/lib/Hydra/Controller/Build.pm line 59."

because the connection to the Nix daemon would be terminated due to a
protocol violation (calling queryPathInfo with an empty string).
2013-04-30 16:23:19 +02:00
Eelco Dolstra
45a1bb9926 Remove unnecessary parentheses in SQL query
These make SQLite 3.7.16.2 crash.

http://hydra.nixos.org/build/4815315
2013-04-29 21:38:57 +02:00
Eelco Dolstra
8158093884 Add correct bootstrap-2.3.1.zip 2013-04-29 09:54:01 +02:00
Rob Vermaas
7fe63854fb Replace bootstrap tarball 2013-04-28 07:06:24 +02:00
Eelco Dolstra
80e0e7c84a Use popovers for the product list help/details 2013-04-26 17:51:06 +02:00
Eelco Dolstra
ea4c88bda1 Use a popover to show how to use the build reproduction script 2013-04-26 17:51:06 +02:00
Eelco Dolstra
7bd1fab268 Use the default navbar style for readability 2013-04-26 17:51:06 +02:00
Eelco Dolstra
74262dd9c4 Remove project/jobset/job/build id from the navbar
They take up too much space, and they're visible in the page title
anyway.  But include them as a nav-header in the submenus.
2013-04-26 17:51:05 +02:00
Eelco Dolstra
ac2bdaf1c5 Remove tablesorter
We haven't used it for a while now.
2013-04-26 17:51:05 +02:00
Eelco Dolstra
4a2cb5e206 Update bootstrap to 2.3.1 2013-04-26 17:51:05 +02:00
Eelco Dolstra
bbc3e25d5a Use bootstrap's pager (instead of pagination) class 2013-04-26 17:51:05 +02:00
Eelco Dolstra
67ed2da50d Add some gitignores 2013-04-26 17:51:05 +02:00
Eelco Dolstra
002793bf2d makeLink -> menuItem 2013-04-26 17:51:05 +02:00
Eelco Dolstra
77a0fd9488 Remove unused file 2013-04-26 17:51:05 +02:00
Eelco Dolstra
3058ce2ca3 Don't do <tt> on input type 2013-04-26 17:51:05 +02:00
Eelco Dolstra
71eaa115f8 Ellipsize long jobset/job names to prevent bootstrap navbar breakage 2013-04-26 17:51:05 +02:00
Rob Vermaas
fd7acd9bbf When searching a path / drv path, use separate queries for both options to prevent seq. scan. 2013-04-26 08:51:49 -04:00
Eelco Dolstra
591aee0793 getPrimaryBuildsForView: Return all view results
Returning only the first 20 results can cause NixOS/Nixpkgs channel
generation to fail, if the first 20 view results correspond to
evaluations that haven't finished yet.  Then URLs like
/view/nixos/tested/latest-finished will return 500 rather than the
latest finished view.
2013-04-26 13:21:41 +02:00
Rob Vermaas
bfc1b0e76a Allow searching for store and drv paths. Only does a complete match to reduce load on database. 2013-04-25 09:57:30 -04:00
Eelco Dolstra
2c7a479994 Minor tweak 2013-04-23 15:39:05 +02:00
Eelco Dolstra
72a44cfcaa Make negative narinfo responses much smaller 2013-04-23 15:33:58 +02:00
Eelco Dolstra
54b03527cb Remove some redundant SQL queries 2013-04-23 15:23:08 +02:00
Eelco Dolstra
7528a9c7e7 Machine status: Don't show removed machines anymore
This requires a sequential scan on the BuildSteps table, which by now
takes > 8s.
2013-04-23 15:20:24 +02:00
Eelco Dolstra
b3612b8a81 Fix showing build steps in the machine status page
This was broken because of the comparison

  step.machine.match('@(.*)').0 == m.key

where m.key contains the SSH user.

Also some style tweaks.
2013-04-23 14:24:48 +02:00
Ludovic Courtès
bd5454d5d9 hydra-eval-guile-jobs: Use `--fresh-auto-compile'.
* src/script/hydra-eval-guile-jobs.in (main): Run `guile' with
  `--fresh-auto-compile'.
2013-04-13 18:59:42 +02:00
Eelco Dolstra
7807ff27b7 Fix the test 2013-04-12 01:24:16 +02:00
Rob Vermaas
4b517488d0 Merge pull request #84 from peti/update-hydra-check-space-for-systemd
hydra-module.nix: update hydra-check-space for systemd
2013-04-11 03:45:31 -07:00
Peter Simons
ccbe75781b hydra-queue-runner: don't clutter the system log with debug message
Avoid the frequently printed

  hydra-queue-runner[10293]: system type `x86_64-linux': 2 active, 2 allowed, starting 0 builds

message. That information is only interesting when some build are
actually started.
2013-04-11 10:56:40 +02:00
Peter Simons
b0d6993a6c hydra-module.nix: update hydra-check-space for systemd
The "stop" alias is not available to this script when run from cron.
2013-04-11 10:48:07 +02:00
Eelco Dolstra
9f027b22b1 Allow users to reproduce builds on their own systems
You can now do:

  bash <(curl http://hydra-server/build/1238757/reproduce)

to download and execute a script that reproduces a Hydra build
locally.  This script fetches all inputs (e.g. Git repositories) and
then invokes nix-build.

The downloaded sources are stored in /tmp/build-<buildid> and reused
between invocations of the script.

Any additional command line options are passed to nix-build.  So

  bash <(curl http://hydra-server/build/1238757/reproduce) --run-env

will drop you in a shell where you can interactively hack on the
build, e.g.

  $ source $stdenv/setup
  $ set +e
  $ unpackPhase
  $ cd $sourceRoot
  $ configurePhase
  $ emacs foo.c &
  $ make

and so on.
2013-04-04 17:30:07 +02:00
Eelco Dolstra
48bb9c48ed Security: Prevent shell injection attack in rendering build contents 2013-04-03 00:13:03 +02:00
Eelco Dolstra
841e03ecba Hack to render empty lines in logs correctly 2013-04-02 23:40:19 +02:00
Eelco Dolstra
e7926e046b Security: Improve checking of build products
Build product paths cannot reference locations outside of the Nix
store.  We previously disallowed paths from being symlinks, but this
didn't take into account that parent path elements can be symlinks as
well.  So a build product /nix/store/bla.../foo/passwd, with
/nix/store/bla.../foo being a symlink to /etc, would still work.

So now we check all paths encountered during path resolution.
Symlinks are allowed again so long as they point to the Nix store.
2013-04-02 23:32:04 +02:00
Eelco Dolstra
94984270b0 Pretty log: Number lines and make them linkable 2013-04-02 11:25:46 +02:00
Eelco Dolstra
b8369a6a5f Put build status in front of the notification mail subject 2013-04-02 10:40:50 +02:00
Hydra
16dbec332d Postgresql 8.x needs as for column. 2013-04-01 20:18:00 -04:00
Eelco Dolstra
d11b08aa51 Fix the tests 2013-03-29 01:34:59 +01:00
Eelco Dolstra
61405ec58a hydra-eval-jobs: Use function argument default values 2013-03-29 01:14:24 +01:00
Eelco Dolstra
d734b435fa Remove the link for creating views since they're deprecated 2013-03-29 00:59:48 +01:00
Eelco Dolstra
ee5b762919 Disable account creation for now 2013-03-28 11:56:12 +01:00
Ludovic Courtès
f3aa48978e hydra-eval-guile-jobs: Allow use of the installed Guix.
* src/script/hydra-eval-guile-jobs.in: Leave GUILE_LOAD_PATH and
  GUILE_LOAD_COMPILED_PATH unchanged.
2013-03-27 00:07:57 +01:00
Ludovic Courtès
9a9f37f209 hydra-eval-guile-jobs: Adjust to multiple-output format.
This is a followup to commit
10882a1ffd ("Add multiple output
support").

* src/script/hydra-eval-guile-jobs.in (job-evaluations->sxml): Return
  several `output' tags in the body, and remove the `outPath' attribute
  of `job'.
2013-03-27 00:07:57 +01:00
Ludovic Courtès
9da89dd32b hydra-eval-guile-jobs: Adjust to <license> objects.
* src/script/hydra-eval-guile-jobs.in (job-evaluations->sxml): Output
  the license name, not the external representation of <license>
  objects.
2013-03-27 00:07:57 +01:00
Peter Simons
5ffc925ae7 hydra-queue-{runner,evaluator}: don't clutter the system log with debug messages 2013-03-26 11:03:15 +01:00
Rob en Lizi Vermaas
52a9f1a14e Use get_column for 'as' column (max_stoptime). 2013-03-24 18:50:17 +01:00
Shea Levy
fb36de0f48 hydra-module: Set GIT_SSL_CAINFO for git over https
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-03-22 13:22:33 -04:00
Shea Levy
7cb2c13c88 hydra-module: Run hydra-init during hydra-init.service
Signed-off-by: Shea Levy <shea@shealevy.com>
2013-03-22 13:22:00 -04:00
Shea Levy
e4a8818bae hydra-module.nix: Cleanup
Remove some unnecessary configurability, remove all hydra.nixos.org
assumptions, remove some policy (e.g. nix.gc.automatic) that are
orthogonal to hydra.

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-03-22 12:16:05 -04:00
Sander van der Burg
d8e2dfc0ed Ported/merged properties from the TUD configuration's hydra-module 2013-03-22 13:58:08 +01:00
Rob Vermaas
f4ae655ee6 Merge pull request #74 from svanderburg/master
Implemented support to allow spaces in hydra-build-products
2013-03-20 10:11:39 -07:00
Sander van der Burg
3884725bfd Added build product test files 2013-03-20 18:08:25 +01:00
Sander van der Burg
03189bf62b Implemented quoted strings support in hydra-build-products to allow file names with spaces + testcase 2013-03-20 18:05:21 +01:00
Eelco Dolstra
50434d76c2 Fix rendering of jobset inputs 2013-03-19 16:14:47 +01:00
Eelco Dolstra
c1aefc4c41 Update bootstrap to 2.0.3
This makes the navbar collapse properly on small screens.
2013-03-19 00:15:12 +01:00
Ludovic Courtès
93f4a26058 Don't always include "Hydra" in the logo part.
This partially reverts 67986b03fa.
2013-03-15 11:23:00 +01:00
Shea Levy
94382bd8f0 Admin controller: Use PathPart, not Path
Chaining paths only works properly when PathPart is used. Before this
fix, the affected URIs bypassed the top-level 'admin' sub.

Signed-off-by: Shea Levy <shea@shealevy.com>
2013-03-14 19:22:02 -04:00
Eelco Dolstra
c96e427ec0 Log segfaults from the evaluator 2013-03-14 17:39:24 +01:00
Shea Levy
152c392198 Whoops 2013-03-07 10:52:31 -05:00
Eelco Dolstra
6d131719be Respect SystemTypes if defined 2013-03-05 18:01:44 +01:00
Eelco Dolstra
fcd511c4de Revert "Remove now-unused SystemTypes table"
This reverts commit 71d020735b.
Unfortunately there are still some cases where we need to set Hydra's
concurrency separately.  (Ideally, Hydra would start *all* queued
builds in parallel and let Nix take care of everything...)
2013-03-05 17:42:16 +01:00
Eelco Dolstra
5b6b9d37f0 Add a button to compare a jobset eval against other jobsets
So now "?compare=<jobset name>" is no longer a hidden feature!

P.S. Encountered this wonderful TemplateToolkit brainfuck again: if
you want to get the number of rows in (say) project.jobsets, you can't
say "project.jobsets.size".  That will *usually* give the right
result, except that if there is only one row in project.jobsets, it
will evaluate to 3.  Instead you have to use "project.jobsets_rs.count".
2013-03-05 17:41:50 +01:00
Eelco Dolstra
fe7e0ff1f4 Show inputs and input changes on the jobset eval page 2013-03-05 17:41:50 +01:00
Shea Levy
71d020735b Remove now-unused SystemTypes table 2013-03-04 17:46:37 -05:00
Shea Levy
d764c135ce hydra-queue-runner: Use nix.machines instead of the SystemTypes table to determine how many build jobs are allowed per system type.
Note that on machines that support multiple system types, EACH system type gets the full number of build slots, which is almost certainly not what we want.
2013-03-04 17:44:19 -05:00
Shea Levy
233e485a55 Remove the BuildMachines and BuildMachinesSystemTypes tables 2013-03-04 16:32:16 -05:00
Shea Levy
232170e301 Remove all entry points to modify machines 2013-03-04 16:05:50 -05:00
Shea Levy
170c7c98d0 machines: Read /etc/nix.machines instead of using the BuildMachines table 2013-03-04 16:03:04 -05:00
Shea Levy
f9426f365b machine-status: Read /etc/nix.machines instead of using the BuildMachines table 2013-03-04 15:37:20 -05:00
Eelco Dolstra
a77161e40a Allow users to edit their own settings
Also, don't use the flash anymore for going back to the referer.
2013-03-04 15:25:23 +01:00
Eelco Dolstra
f831287d4b Add font for the captcha
Taken from http://www.thibault.org/fonts/staypuft/.
2013-03-04 12:16:13 +01:00
Eelco Dolstra
e8cbcb50ac Add user registration 2013-02-27 18:33:47 +01:00
Eelco Dolstra
180068605a Active build steps: Make the rows clickable 2013-02-26 19:12:10 +01:00
Eelco Dolstra
d1c2771ab8 Ensure that each eval is compared to the previous one from the same jobset
Also, reduce the number of database hits.
2013-02-26 19:08:39 +01:00
Eelco Dolstra
1007735364 Render links to changed input builds
Also, use get_column('dependency') instead of dependency.id to prevent
an expensive row fetch.
2013-02-26 18:55:59 +01:00
Eelco Dolstra
56a62c3d88 Make jobset deletion consistent with project deletion 2013-02-26 17:36:49 +01:00
Eelco Dolstra
d596b58991 "Evaluate" command: push the jobset to the front of the eval queue
Don't let hydra-server call hydra-evaluate.  That will probably just
timeout, get killed, etc.
2013-02-26 16:56:19 +01:00
Eelco Dolstra
eea3846754 After editing a jobset, push it to the front of the evaluation queue 2013-02-26 16:10:36 +01:00
Eelco Dolstra
96e24fcf24 Tweaks 2013-02-26 16:04:33 +01:00
Eelco Dolstra
5462be23d5 Don't show duration of unfinished builds 2013-02-26 16:01:00 +01:00
Eelco Dolstra
2a3e832fc4 Add some margin about h3 elements 2013-02-26 16:00:46 +01:00
Eelco Dolstra
4b70be6753 Fix same system inputs 2013-02-26 15:51:56 +01:00
Eelco Dolstra
5a0054f38c Fix adding jobset inputs 2013-02-26 15:45:34 +01:00
Eelco Dolstra
1e338e7958 api/push: Don't barf on non-existent jobsets 2013-02-26 01:46:19 +01:00
Eelco Dolstra
f501648cd2 Add simpler push support for GitHub
You can use the URL

  http://<hydra-server>/api/push-github

as GitHub's WebHook URL.  Hydra will automatically trigger an
evaluation of all affected jobsets.
2013-02-26 01:14:50 +01:00
Eelco Dolstra
11d87c6f82 Use query_params instead of params
Otherwise crazy things happen with POST requests from GitHub.
2013-02-26 00:38:18 +01:00
Eelco Dolstra
5e6896b2d9 Turn prepared statements back on
We once turned these off (in commit
abe71a767b) because they caused the
PostgreSQL query optimizer to use very suboptimal plans.  However,
PostgreSQL 9.2 has supposedly fixed this:

  http://www.postgresql.org/docs/9.2/static/release-9-2.html

So let's try again.
2013-02-25 21:20:52 +01:00
Eelco Dolstra
f51b93da03 Remove debug line 2013-02-25 21:18:29 +01:00
Eelco Dolstra
42d2015357 Support push notification of repository changes
External machines can now notify Hydra that it should check a
repository by sending a GET or PUSH request to /api/push, providing a
list of jobsets to be checked and/or a list of repository URLs.  In
the latter case, all jobsets that have any of the specified
repositories as an input will be checked.

For instance, you can configure GitHub or BitBucket to send a request
to the URL

  http://hydra.example.org/api/push?repos=git://github.com/NixOS/nixpkgs.git

to trigger evaluation of all jobsets that have
git://github.com/NixOS/nixpkgs.git as an input, or to the URL

  http://hydra.example.org/api/push?jobsets=patchelf:trunk,nixpkgs:trunk

to trigger evaluation of just the specified jobsets.
2013-02-25 21:10:32 +01:00
Eelco Dolstra
ddcb9f1d5d Handle the case where a jobset has never been evaluated 2013-02-25 19:38:11 +00:00
Eelco Dolstra
65db523e46 Fix duplicate function name 2013-02-25 19:01:43 +01:00
Eelco Dolstra
24de044c55 hydra-evaluator: Always pick the jobset that hasn't been evaluated longest 2013-02-25 18:47:54 +01:00
Eelco Dolstra
c30cee55dd Send ETag and Expires headers 2013-02-25 18:18:05 +01:00
Eelco Dolstra
fb643cd971 Install bootbox 2013-02-23 17:01:43 +01:00
Eelco Dolstra
6658419f69 Disallow build products that are symlinks
Otherwise you can do

  ln -s /etc/passwd $out/foo
  echo "file misc $out/foo" >> $out/nix-support/hydra-build-products

and get Hydra to serve its /etc/passwd file.
2013-02-23 16:28:44 +01:00
Eelco Dolstra
aa7ddeb8e9 Use hashFile instead of nix-hash
Calling a shell command is a security hole if $path contains special
characters (e.g. "${foo}").  Observed in
http://hydra.nixos.org/build/4041321.
2013-02-23 16:09:34 +01:00
Eelco Dolstra
67986b03fa Fix logo size
Also, always include the text "Hydra" in the navbar.
2013-02-23 14:31:30 +00:00
Eelco Dolstra
77fa6d2646 Set mouse pointer to indicate you can click on rows 2013-02-22 18:13:18 +01:00
Eelco Dolstra
c0f9c9b4aa Make some more tables clickable 2013-02-22 18:11:29 +01:00
Eelco Dolstra
9422c9d2a7 Optimise clickable rows
Set a click handler on the table instead of on every row.  This should
be faster on large tables.  Also, it's easier to use: you just set the
clickable-rows class on the table, and the row-link class on the <a>
element that contains the "main" link of the row.
2013-02-22 18:05:04 +01:00
Eelco Dolstra
bd7be1cb84 Remove obsolete CSS classes 2013-02-22 17:11:10 +01:00
Eelco Dolstra
f5a2859ce2 Show current query in the search box 2013-02-22 16:44:39 +01:00
Eelco Dolstra
08dc6650e1 Search: Limit the number of results 2013-02-22 16:41:42 +01:00
Eelco Dolstra
4d4ea8c754 Search: Mark disabled projects/jobsets/jobs 2013-02-22 16:21:50 +01:00
Eelco Dolstra
f3f6e8a4e3 Search: Don't return hidden projects/jobsets 2013-02-22 15:56:29 +01:00
Eelco Dolstra
07daff32b8 Add a search feature
This allows searching for projects, jobsets or jobs by name or
description.
2013-02-22 15:45:10 +01:00
Eelco Dolstra
4343781181 Clear failed builds etc.: Redirect back to the referrer
Would be better to do this AJAX style though.
2013-02-22 14:31:43 +01:00
Eelco Dolstra
629fe6f998 Jobset page: Load the jobs and status tabs on demand
This makes the jobset page much smaller and faster.  (E.g. for
nixpkgs:trunk, this page was ~2.5 MB.)
2013-02-22 14:29:12 +01:00
Eelco Dolstra
f2de374f28 Set a 500 HTTP status on errors 2013-02-22 14:27:38 +01:00
Eelco Dolstra
961feedf4e Show an error message if tab loading fails 2013-02-22 14:17:14 +01:00
Eelco Dolstra
47d2ee0dab Generalize lazy tabs 2013-02-22 13:36:15 +01:00
Eelco Dolstra
e2e973578f Some unnecessary job names 2013-02-22 13:17:07 +01:00
Eelco Dolstra
5d3494011f Job page: Put latest builds on top
Also, rename the "Latest builds" tabs to prevent confusion.
2013-02-22 13:00:40 +01:00
Eelco Dolstra
098368c3e3 Job page: Remove "Latest builds (latest evaluation)"
It was kind of confusing since there are two other "latest builds"
tabs/sections.
2013-02-22 12:53:10 +01:00
Eelco Dolstra
6dbb948f1f Job page: show queued as well as running builds 2013-02-22 12:52:11 +01:00
Eelco Dolstra
1643d90d92 Job page: Remove channel tab 2013-02-22 12:00:32 +01:00
Eelco Dolstra
0f10a37894 Fix indentation 2013-02-22 11:55:06 +01:00
Eelco Dolstra
d08a391b43 Jobset page: Show last evaluation time 2013-02-22 11:37:35 +01:00
Eelco Dolstra
c9ac7746b2 Allow showing all evaluations that contain a given build 2013-02-21 18:49:57 +01:00
Eelco Dolstra
6afe528570 Remove the related builds tab
You can now just click on the evaluation link on the first tab to see
all builds in the same jobset.  This also makes rendering build pages
quite a bit faster for jobsets like Nixpkgs.
2013-02-21 18:43:16 +01:00
Eelco Dolstra
c6fe9f00bf Also show number of evaluations of which a build is a part 2013-02-21 18:42:18 +01:00
Eelco Dolstra
edbe531ccc On build pages, provide a link to the build's first eval 2013-02-21 18:34:34 +01:00
Eelco Dolstra
d8370142c2 Remove garbage from Users.pm 2013-02-21 18:20:55 +01:00
Eelco Dolstra
c22d93438e Fix adding jobset inputs 2013-02-21 18:10:06 +01:00
Eelco Dolstra
ba68826860 Add a page to show the latest evaluations for the entire server 2013-02-21 17:27:17 +01:00
Eelco Dolstra
767cab6cd2 Correctly redirect to the referring page when logging in 2013-02-21 14:38:18 +01:00
Eelco Dolstra
26fa9ea0ea Add links to the project/jobset edit pages in the logical place 2013-02-21 14:19:34 +01:00
Eelco Dolstra
fec45d1f07 Remove dead code 2013-02-21 13:45:11 +01:00
Eelco Dolstra
36032e4bed Make the info tables less compressed 2013-02-21 13:42:44 +01:00
Eelco Dolstra
dd5eb51a84 Put job status on a separate tab
Also, show the "last checked time" on the initial tab.
2013-02-21 13:30:14 +01:00
Eelco Dolstra
5099375549 Indicate disabled/hidden projects/jobsets in the overviews 2013-02-21 11:57:48 +01:00
Eelco Dolstra
8db83d2017 Turn hiding/unhiding a jobset into a checkbox 2013-02-21 02:36:51 +01:00
Eelco Dolstra
547e41263d Split viewing and editing a jobset 2013-02-21 02:33:57 +01:00
Eelco Dolstra
9c7b416f8b Make the hide/unhide actions a checkbox in the project settings
Also use proper bootstrap layout for the project settings form.
2013-02-21 01:45:39 +01:00
Eelco Dolstra
3924780eac Tweaks 2013-02-21 01:26:29 +01:00
Eelco Dolstra
cea17fd57e Show releases in a tab on the project page 2013-02-21 01:23:42 +01:00
Eelco Dolstra
d9f6e662d8 Split viewing and editing a project 2013-02-21 01:12:57 +01:00
Eelco Dolstra
03aee6726f Add a menu item for deleting jobsets
Also add bootbox for sexier dialog boxes.
2013-02-21 00:47:21 +01:00
Eelco Dolstra
176b8cab7e Use a proper spinning wheel icon 2013-02-20 23:57:33 +01:00
Eelco Dolstra
b5273eed7a Don't generate clashing IDs 2013-02-20 18:26:26 +01:00
Eelco Dolstra
d1e983dfc6 All/recent builds -> Latest builds 2013-02-20 18:23:49 +01:00
Eelco Dolstra
85e3f69cdd Remove debug statement 2013-02-20 18:22:06 +01:00
Eelco Dolstra
78250581ed There is only one channel, so drop the "(latest)" suffix 2013-02-20 18:20:16 +01:00
Eelco Dolstra
af18808ca7 Dependency tree: Revert to "repeated" links 2013-02-20 18:15:42 +01:00
Eelco Dolstra
4552117e51 Load the dependency tabs on demand 2013-02-20 18:13:20 +01:00
Eelco Dolstra
36a1015444 Show the runtime/build dependencies in the build page 2013-02-20 17:58:27 +01:00
Eelco Dolstra
11c09e4c5c Always show the build duration (using the cached build if necessary) 2013-02-20 17:07:20 +01:00
Eelco Dolstra
aebefda6ab Remove unnecessary Javascript code
Tabs are activated automatically.
2013-02-20 17:03:11 +01:00
Eelco Dolstra
b5d59c5c63 Fix indentation of build.tt 2013-02-20 17:02:07 +01:00
Eelco Dolstra
f544c63607 Formatting tweaks 2013-02-20 16:47:57 +01:00
Eelco Dolstra
7da2398f27 Allow non-admin users to see the machine status page 2013-02-20 16:40:09 +01:00
Eelco Dolstra
656b1bd45a Group some menu items together under a "Status" menu 2013-02-20 16:24:54 +01:00
Eelco Dolstra
c63812afa5 Fix indentation
Also move flashing into layout.tt.
2013-02-20 16:14:30 +01:00
Eelco Dolstra
ea9862fdc1 Give every page a consistent title 2013-02-20 15:54:33 +01:00
Eelco Dolstra
5c317fa0e9 Remove unused file 2013-02-20 15:42:40 +01:00
Eelco Dolstra
84602f9ee6 Ensure that the first tab is selected 2013-02-20 14:29:35 +01:00
Eelco Dolstra
3df9665f60 Compatibility with latest bootstrap 2013-02-20 14:06:17 +01:00
Eelco Dolstra
c2e5bec1e1 Evil CSS hackery to prevent link targets from being under the navbar
http://stackoverflow.com/questions/9047703/fixed-position-navbar-obscures-anchors
2013-02-20 13:56:41 +01:00
Eelco Dolstra
f550f1a1de Revert to jQuery 1.8.3
1.9 removes the toggle() function which is actually useful (and used
by us).
2013-02-20 01:49:01 +01:00
Eelco Dolstra
1feca4b105 Turn repeated dependencies into hyperlinks 2013-02-20 01:28:29 +01:00
Eelco Dolstra
18da3ac397 Render the dependencies as a tree 2013-02-20 01:02:18 +01:00
Eelco Dolstra
41d7d63339 Simplify the tree implementation a bit more 2013-02-20 00:54:03 +01:00
Eelco Dolstra
1a992d170d Factor out the tree rendering 2013-02-19 17:22:28 +01:00
Eelco Dolstra
4266632eb0 Simplify the log tree implementation a bit
In particular use the :last-child selector, which is non-standard but
supported by all major browsers.
2013-02-19 17:14:02 +01:00
Eelco Dolstra
8c37f46955 Update jquery/jqueryui 2013-02-19 15:22:15 +01:00
Eelco Dolstra
7b4d4f1cd7 Move <style> to hydra.css 2013-02-19 14:39:50 +01:00
Shea Levy
dba8dc9668 Fix query-all-tables test count, there are more tables now 2013-02-19 14:21:57 +01:00
Eelco Dolstra
22ed3c4847 Fix some XML well-formedness problems 2013-02-14 18:03:12 +01:00
Eelco Dolstra
5620e3c386 Fix indentation and get rid of some unnecessary whitespace in the output 2013-02-14 17:51:09 +01:00
Eelco Dolstra
2fa1a7efa7 Get rid of unnecessary [%- and -%] tags 2013-02-14 16:51:42 +01:00
Eelco Dolstra
82daf4f8ca Show dependencies as a tree rather than a list 2013-02-14 15:53:34 +01:00
Eelco Dolstra
4e67665b7f Builds page: Remove redundant tab titles 2013-02-14 13:23:54 +01:00
Eelco Dolstra
1160e17bfc Add missing files
Doh!
2013-02-14 11:53:09 +01:00
Eelco Dolstra
2b3c72efeb Use getMainOutput 2013-02-13 18:36:01 +01:00
Eelco Dolstra
eb9d0c8992 Security: Also check paths in the web server 2013-02-13 18:34:33 +01:00
Eelco Dolstra
cd83b8e3aa Security: Ensure that a build product refers to the Nix store 2013-02-13 18:26:00 +01:00
Eelco Dolstra
10882a1ffd Add multiple output support
This requires turning the outPath columns in the Builds and BuildSteps
tables into separate tables, and so requires a schema upgrade.
2013-02-13 16:49:28 +00:00
Eelco Dolstra
799e5437bd Remove unnecessary "Page generated" line 2013-02-05 14:08:20 +01:00
Eelco Dolstra
e555c7bb36 Automatically chomp all [%...%] directives
This makes the use of [%-...-%] unnecessary.
2013-02-05 14:00:09 +01:00
Eelco Dolstra
f9948e6346 Remove empty files 2013-01-30 17:09:46 +01:00
Eelco Dolstra
b30f5f51c2 Drop explicit JSON dependency 2013-01-28 23:14:31 +01:00
Eelco Dolstra
f5000f0ad2 Update how to restart builds 2013-01-28 18:53:22 +01:00
Eelco Dolstra
58dd49e645 Fix handling of IPC::Run::run exit status
Turns out that the exit status is returned in $?, not as the return
value of run().  So our error checking was completely bogus.
2013-01-23 15:56:28 +01:00
Eelco Dolstra
60e36d3d1a Cleanup 2013-01-23 15:47:42 +01:00
Eelco Dolstra
3826fc5201 Use the JSON module
For some reason JSON::XS doesn't work since the last Perl packages
update.  Should investigate.
2013-01-23 15:47:09 +01:00
Eelco Dolstra
2d36b75d3e Fix indentation 2013-01-23 12:49:26 +00:00
Eelco Dolstra
e4c123ef7c Fix indentation 2013-01-23 12:48:02 +00:00
Eelco Dolstra
b1f7aa0583 Fail on failure 2013-01-23 12:46:01 +00:00
Eelco Dolstra
e0de5de91d Fix some warnings 2013-01-23 12:41:57 +00:00
Eelco Dolstra
418e57ec3f VM test: start the web server 2013-01-23 13:00:07 +01:00
Eelco Dolstra
15ee6147d0 Fix VM test 2013-01-23 12:55:29 +01:00
Eelco Dolstra
66c107364b Add missing file
Doh!
2013-01-23 12:49:44 +01:00
Eelco Dolstra
f3d6643724 Omit the small build status icon on the build page
It's kinda pointless next to the big-ass icon.
2013-01-22 23:05:02 +01:00
Eelco Dolstra
ecdbce1a61 Handle active build steps of aborted builds properly 2013-01-22 23:01:29 +01:00
Eelco Dolstra
30e5185acf Remove the logfile and logSize columns from the database
It's pointless to store these, since Nix knows where the logs are.
Also handle (in fact require) Nix's new log storage scheme.  Also some
cleanups in the build page.
2013-01-22 22:48:02 +01:00
Eelco Dolstra
36c2bf2f52 Update .gitignore 2013-01-22 15:00:46 +01:00
Eelco Dolstra
67aefde62c Remove trailing whitespace 2013-01-22 14:41:02 +01:00
Eelco Dolstra
aa28ffe3a8 Die tabs die 2013-01-22 14:09:37 +01:00
Eelco Dolstra
486b6037a9 Use $c->config 2013-01-22 14:06:12 +01:00
Eelco Dolstra
f188fe5683 hydra-evaluator: Don't require $HYDRA_CONFIG 2013-01-22 13:19:28 +01:00
Eelco Dolstra
fc39034772 Whitespace 2013-01-22 13:19:08 +01:00
Eelco Dolstra
ef37597c39 Build documentation last 2013-01-22 12:05:47 +01:00
Eelco Dolstra
f3a274657d Trailing whitespace 2013-01-22 12:05:33 +01:00
Rob Vermaas
d4e49773c5 Allow dashes in attrNames 2013-01-11 12:16:21 +01:00
Eelco Dolstra
64399991a7 Give Hydra binary caches a low priority
We only want to hit a Hydra binary cache if static caches don't
provide a binary.
2012-11-06 17:13:17 +01:00
Eelco Dolstra
2906116fda Log time required by a request 2012-11-05 17:37:23 +01:00
Eelco Dolstra
9ba1fd6952 Turn off overly verbose log messages by default
The "Request took ...s" messages are rather spammy, so turn them off
by default.  You can set CATALYST_DEBUG=1 if you need them.
2012-11-05 17:21:09 +01:00
Ludovic Courtès
8478088cee release.nix: Add dependency on Guile. 2012-10-18 23:20:53 +02:00
Ludovic Courtès
183078131a Capture the path to `guile', when available. 2012-10-17 16:25:49 +02:00
Ludovic Courtès
f27ae1d566 Add support for Guile & Guix. 2012-10-17 16:23:00 +02:00
Rob Vermaas
4ade8c5a1b Add dollar to pathCompRE, which allows files with dollars in them to be served by Hydra, e.g. sphinx generated docs often has these types of files. 2012-10-12 13:48:11 +02:00
Eelco Dolstra
5fa688acf5 Don't ignore assertion failures in getDerivation() 2012-10-04 15:24:25 -04:00
Eelco Dolstra
a4ff9b0d08 hydra-eval-jobs: Don't go into an infinite recursion
The function getDerivation() can return false if its argument is a
derivation.  This happens if evaluating the name or system attribute
triggers an assertion.  In that case, we shouldn't recurse into the
attributes of the derivation.
2012-10-04 14:31:47 -04:00
Rob Vermaas
f4a24b94ee Fallback for git fetch, which allows specific gits revisions to be used as build inputs. 2012-09-11 22:31:49 +02:00
Rob Vermaas
c57242c76d Show build status for up to 100 jobs in stead of 50. 2012-09-10 12:15:31 +02:00
Rob Vermaas
396a356198 Add create-user action that was mostly present already. 2012-08-06 00:02:14 +02:00
Rob Vermaas
90c9b5dd60 Do not send emails when build is cancelled/aborted. Also, ignore aborted/cancelled builds in comparing to previous build. 2012-08-06 00:00:07 +02:00
Eelco Dolstra
aa8bf564e2 Set the Content-Type properly 2012-08-01 18:00:55 +00:00
Eelco Dolstra
13688e364f Add a binary-cache-url file to channels to advertise the binary cache URL 2012-08-01 16:31:25 +00:00
Eelco Dolstra
fad2a084fa Provide the nix-cache-info file required by the binary cache substituter 2012-07-30 20:26:34 +00:00
Eelco Dolstra
d15dd6bac9 Include the URL of the binary cache in .nixpkg files 2012-07-30 20:26:11 +00:00
Eelco Dolstra
74fb2b37ce Add more spacing between products 2012-07-19 00:33:02 +02:00
Eelco Dolstra
00155aa7b1 Add an icon for binary distributions 2012-07-19 00:16:22 +02:00
Eelco Dolstra
67528698e6 Allow creating a release from an evaluation 2012-07-18 23:46:41 +02:00
Eelco Dolstra
2ab4c7d597 Update queryPathInfo calls 2012-07-18 23:14:45 +02:00
Eelco Dolstra
da960b507d Use queryPathFromHashPart to look up binary cache requests efficiently 2012-07-18 23:14:17 +02:00
Rob Vermaas
544f2f2503 Removing tarball as option for build input; does not exist. 2012-07-13 13:06:55 +02:00
Eelco Dolstra
1b3cf68b77 Generate *.narinfo files on the fly to support the binary cache substituter 2012-07-02 20:09:45 +02:00
Eelco Dolstra
fe2dab6fe8 Fix some warnings about undefined values 2012-07-02 15:18:30 +00:00
Rob Vermaas
d37c2c239c export logContents 2012-06-26 12:09:05 +02:00
Rob Vermaas
a2f56ce574 * Read logs using logContents function in stead of handling it everywhere separately. 2012-06-26 12:00:18 +02:00
Rob Vermaas
0701cd0da8 * Fix getBuildLog for bzip2'd files. 2012-06-26 08:04:35 +02:00
Rob Vermaas
2aa52131ac * Nix now stores logs by default as bzip2, make sure the build page uncompresses before showing. 2012-06-25 15:05:16 +02:00
Rob Vermaas
209c51ca6c * Remove accidentally commited foo/bar. 2012-06-25 13:37:06 +02:00
Rob Vermaas
9a7811aa92 * Add 'set -e' to all scm test setup scripts, to catch errors as early as possible
* Fix git setup
2012-06-25 13:33:36 +02:00
Rob Vermaas
478d3863bb Add bar with 1 2012-06-25 13:00:55 +02:00
Rob Vermaas
ebececb0ee Increase depth 2 2012-06-25 12:24:03 +02:00
Rob Vermaas
9e8d3cdcc5 Increase depth 1 2012-06-25 12:24:03 +02:00
Rob Vermaas
2cdcbd587a Increase depth 0 2012-06-25 12:24:03 +02:00
Rob Vermaas
12223d6202 Add bzip2 to buildInputs. 2012-06-25 12:04:25 +02:00
Ludovic Courtès
94ba1ed71f hydra-module: Always GC to have at least 100 GiB available. 2012-06-14 10:57:55 +02:00
Ludovic Courtès
6411d991c7 hydra-module: Fix typo in the job name in `checkSpace'. 2012-06-14 10:17:33 +02:00
Eelco Dolstra
ab4f0911ce Fix rendering of Subversion inputs in the Evaluations table
Broken since commit 75277311ac.

Fixes #30.
2012-06-04 14:55:24 +00:00
Eelco Dolstra
fdf441a8b7 Set utf-8 encoding on raw log pages 2012-05-25 14:27:56 +00:00
Rob Vermaas
75277311ac Different icons (darker red) for cancelled builds. Fixes #25. 2012-05-25 04:14:36 +02:00
Eelco Dolstra
d1da9a8823 Escape the log tail to ensure we produce correct HTML 2012-05-23 20:14:51 +00:00
Eelco Dolstra
fdc516289c Doh - clear $NIX_PATH properly 2012-05-23 14:44:23 -04:00
Ludovic Courtès
2865569392 doc: Update to use angle brackets and `tarball' in the same evaluation. 2012-05-23 00:07:49 +02:00
Rob Vermaas
97d41a2102 Allow project members to create jobsets, regression introduced by bootstrap make-over. Currently all logged in users see these options, however, only on performing the action the privileges are checked. Need to change that in the future. 2012-05-18 10:09:53 +02:00
Rob Vermaas
da206fdfac Add time to evaluation error tab. Fixes #21. 2012-05-18 10:06:55 +02:00
Eelco Dolstra
4ad8912aa3 Fix indentation 2012-05-11 18:25:56 -04:00
Eelco Dolstra
770bc15848 Number the sections 2012-05-11 18:22:46 -04:00
Eelco Dolstra
3e6b24930c Sync with the CSS of the Nix manual 2012-05-11 18:22:23 -04:00
Rob Vermaas
b591c443b0 Keep builds of disabled jobsets that are not hidden. Fixes #18. 2012-05-11 09:11:07 +02:00
Eelco Dolstra
8538953868 Don't write one character at a time, it's inefficient 2012-05-10 12:02:41 -04:00
Eelco Dolstra
48effa116c Delete obsolete CSS files 2012-05-07 15:12:56 -04:00
Eelco Dolstra
7d3c1852ed "r. " -> "r" in showing revisions 2012-05-04 17:12:45 -04:00
Rob Vermaas
0fdcd3176b Add numbered revision id of mercurial as revCount. 2012-05-01 09:15:52 +02:00
Eelco Dolstra
8f85fe67d4 Revert sorting build products
Sorting the build products list fails if there are fewer than 3 build
products.  This is because of extreme Template Toolkit brain damage:
it treats arrays of 0-2 elements differently in some magic way.  See
e.g.

  http://mail.template-toolkit.org/pipermail/templates/2011-April/011510.html
2012-04-30 22:19:38 +02:00
Rob Vermaas
df71a86183 Do not delete builds when clearing the queue. Fixes #8. 2012-04-30 22:13:53 +02:00
Eelco Dolstra
b52018e61a Use a span instead of a div in the pretty logs
Fixes #6.
2012-04-30 21:32:53 +02:00
Rob Vermaas
eb51065a16 Making pretty printed log look normal again. Issue #6 2012-04-30 20:22:03 +02:00
Rob Vermaas
437e59c4a8 When checking if build is already built, check for potential 'failed with result'. Fixes issue #7. 2012-04-30 19:47:21 +02:00
Eelco Dolstra
854513be8e I should test first 2012-04-30 17:57:13 +02:00
Eelco Dolstra
dcc570f454 Set the build status properly for failing local builds
If a build has ‘preferLocalBuilds = true’ (or we're not using remote
building), and the build has a non-permanent failure, then the build
status should be "Aborted" rather than "Failed".  This is denoted by
an exit status of 100 from nix-store.
2012-04-30 17:15:35 +02:00
Eelco Dolstra
4a6f798ef4 Fix Mercurial input fetching if a cached input has been GC'ed
Fixes Hydra/76.
2012-04-30 16:21:28 +02:00
Rob Vermaas
c1653a9561 Merge pull request #9 from nbp/deep-clone-check
Add tests for "git describe --long".
2012-04-30 01:15:00 -07:00
Nicolas Pierron
69f9175986 Add tests for "git describe --long".
* Move test logic to scm-update.sh scripts.
    * Check for "git describe --long".
2012-04-29 20:59:43 -07:00
Eelco Dolstra
1033178728 Ensure build products are in sorted order 2012-04-27 11:23:38 +02:00
Eelco Dolstra
29b40e6418 Fix the duration on Build pages 2012-04-27 10:54:49 +02:00
Rob Vermaas
4a1a2203ac I should sleep... grmbl 2012-04-26 09:37:48 +02:00
Rob Vermaas
3c465c3661 Revert nix-prefetch-git changes merged in earlier from Merge request #3, which broke git describe functionality used in GNU jobsets. 2012-04-26 09:31:00 +02:00
Rob Vermaas
6d5567bb16 Use git fetch -fu origin +$branch:$branch to fetch all changes for branch. 2012-04-26 08:36:40 +02:00
Rob Vermaas
be3748e1ec In case of deep clone, make sure there is local branch. 2012-04-25 13:49:28 +02:00
Rob Vermaas
7da48b5220 remove origin from git pull call, to get rid of fatal: fetch --all does not take a repository argument error 2012-04-25 10:17:22 +02:00
Rob Vermaas
b49e138e9c Merge pull request #3 from nbp/candidates/fetch-git
Optimize fetch-git.
2012-04-24 10:18:28 -07:00
Rob Vermaas
966cc22131 Fix query for certain postgresql versions. 2012-04-22 08:30:48 +02:00
Rob Vermaas
b0596c214a Merge branch 'master' of github.com:NixOS/hydra 2012-04-18 11:24:12 +02:00
Rob Vermaas
cc38d0352f Strip all whitespace from revision from subversion call. Patch provided by Petr Ročkai 2012-04-18 11:22:26 +02:00
Eelco Dolstra
f8c914297f Fix path to the session data 2012-04-17 22:25:32 +02:00
Eelco Dolstra
51b920c875 Bootstrapify the Hydra forms (except the project and jobset edit pages)
Plus lots of other tweaks.
2012-04-17 16:53:11 +02:00
Eelco Dolstra
8f31935ffa Handle the case where there are no builds and no previous eval 2012-04-17 12:32:44 +02:00
Eelco Dolstra
db09760e8c Move the "Cancel build" button to the menu 2012-04-17 11:39:08 +02:00
Eelco Dolstra
ea4aba83c3 Proper styling for flash message 2012-04-17 09:36:10 +00:00
Eelco Dolstra
634d8c092f Use <h3> for running/failed build steps 2012-04-17 09:35:37 +00:00
Eelco Dolstra
896a47d950 Clear nrSucceeded when restarting a build 2012-04-17 09:34:35 +00:00
Eelco Dolstra
d350b935f2 Add validation for project and jobset names 2012-04-17 08:53:00 +00:00
Rob Vermaas
90e0ba2a7a Revert changeset 4399683fa0, make jobset options available to project members as well 2012-04-17 09:49:27 +02:00
Ludovic Courtès
4399683fa0 Reinstate the edit/clone links on the jobset page.
They were removed in commit 17d30cd179.
2012-04-16 16:47:23 +02:00
Rob Vermaas
922bad7306 Also remove dep. graph from robots.txt. 2012-04-16 15:25:14 +02:00
Rob Vermaas
334135448e Remove buildtime and runtime dependency graph. It is useless on normal derivations. 2012-04-16 15:23:07 +02:00
Rob Vermaas
28b6ff3ed6 Add maximum nest level for input changes on build page. 2012-04-16 13:59:29 +02:00
Eelco Dolstra
1cf2a1592a Add missing upgrade-*.sql files 2012-04-15 23:23:01 +00:00
Eelco Dolstra
ec87ad2bf2 Missing part of aaacf9eda3 2012-04-15 22:57:10 +00:00
Eelco Dolstra
0446282a63 Fix the test 2012-04-15 22:56:15 +00:00
Eelco Dolstra
aaacf9eda3 Speed up the listing of jobset evals by caching some info in the DB
This denormalises the database, but it's the best we can do until
PostgreSQL has materialised views.
2012-04-16 00:46:19 +02:00
Eelco Dolstra
034d50069b Speed up the jobset eval list a bit 2012-04-15 22:11:20 +00:00
Eelco Dolstra
573a333bc9 Cleanup 2012-04-15 21:49:54 +00:00
Eelco Dolstra
5793baa3cd Doh 2012-04-15 21:35:46 +00:00
Eelco Dolstra
1e228267be Only show "Running build steps" if there are running build steps 2012-04-15 20:12:35 +00:00
Eelco Dolstra
2c6a38760b Consistent capitalisation 2012-04-15 20:10:22 +00:00
Eelco Dolstra
0daba6bb89 In the jobset evals lists, show what inputs changed between consecutive evals 2012-04-15 20:06:42 +00:00
Eelco Dolstra
b9824ca422 Cleanup 2012-04-15 18:47:22 +00:00
Eelco Dolstra
fd50ac1d4e Store the inputs of each evaluation in the database
Achtung: this requires a schema upgrade via "hydra-init".
2012-04-15 18:36:36 +00:00
Eelco Dolstra
12dd78d889 Change the "Available" link to "pretty"
"Available" is confusing in this context.  "Pretty" denotes that this
is the pretty-printed log.
2012-04-15 18:51:34 +02:00
Eelco Dolstra
e7fa54e48e Fix the spacing around some <h3> headers 2012-04-15 18:48:29 +02:00
Eelco Dolstra
80705c8a20 hydra-init: show SQL commands being executed 2012-04-15 18:34:32 +02:00
Eelco Dolstra
bf757f687d Remove close button on news items since it's not persistent, so kinda useless 2012-04-15 18:31:47 +02:00
Eelco Dolstra
a633e4b361 Make the jobset eval rows clickable 2012-04-15 18:21:56 +02:00
Eelco Dolstra
6b88640457 Remove the "There are evaluation errors!", instead emphasize the presence of the tab more 2012-04-15 18:17:19 +02:00
Eelco Dolstra
101e60b03d Nicer link to the rest of the jobset evals 2012-04-15 18:08:51 +02:00
Eelco Dolstra
794602d7ce Drop unused "tag" column
It was intended for CVS inputs but never used.
2012-04-15 12:42:46 +00:00
Nicolas Pierron
19d9955e89 Optimize fetch-git. 2012-04-14 18:17:35 -07:00
Rob Vermaas
ccc5d38976 Move Hide/Unhide links for project to toplevel menu. 2012-04-13 16:52:25 +02:00
Rob Vermaas
7f858928df Fix hide/unhide links. 2012-04-13 16:36:45 +02:00
Rob Vermaas
fbb857bf80 Do not load charts lazily for now. 2012-04-13 14:50:48 +02:00
Rob Vermaas
320632f7f4 Renamed running to started in queue. 2012-04-13 12:55:26 +02:00
Rob Vermaas
f339f5ae85 Fix evaluate link. 2012-04-13 12:42:58 +02:00
Rob Vermaas
516a644a7f Merge branch 'master' into bootstrap 2012-04-13 11:55:49 +02:00
Rob Vermaas
293c7d3507 update bootstrap.zip 2012-04-13 11:54:40 +02:00
Rob Vermaas
bb4f470348 Remove default logo, replaced by text for now. Hide template in jobset edit. 2012-04-13 11:47:05 +02:00
Rob Vermaas
f63e9a63b4 Replace last 5 builds on jobset page with last 5 evaluations. Moved hide/unhide and evaluate options to jobset topmenu. 2012-04-13 11:26:37 +02:00
Rob Vermaas
11bf848b09 Move channel link to top menu of Project and Jobset. 2012-04-13 10:56:02 +02:00
Rob Vermaas
bf197f0d77 Remove pagers on the bottom of paginated lists. 2012-04-13 10:43:56 +02:00
Rob Vermaas
b81aa89260 Replace old logo with Nix/NixOS logo. 2012-04-13 10:33:11 +02:00
Rob Vermaas
1e7f9c8a15 Fix pager prev/next button. 2012-04-13 10:23:27 +02:00
Rob Vermaas
6b65712045 Restructure build menu 2012-04-13 10:19:15 +02:00
Rob Vermaas
9a1f38e06e Remove comments, re-add logo. 2012-04-13 10:05:02 +02:00
Rob Vermaas
4f5327d7ed Added running icon in queue in stead of background color. 2012-04-12 22:10:16 +02:00
Rob Vermaas
8aaa0a1a8a Move 'keep build' and 'restart' to toplevel menu 2012-04-12 21:50:06 +02:00
Rob Vermaas
089a9c836f Machine status page now looks much better and more consistent with rest of Hydra 2012-04-12 21:42:21 +02:00
Rob Vermaas
6853d0398a Move 'clone build' and 'restart build' to top menu 2012-04-12 21:41:31 +02:00
Rob Vermaas
c630433b61 Move 'clone build' to top menu 2012-04-12 21:40:57 +02:00
Rob Vermaas
7886666b0b Replace ugly link with nice small buttons 2012-04-12 21:03:59 +02:00
Rob Vermaas
72785f35aa Some overriding of bootstrap default css 2012-04-12 21:03:25 +02:00
Rob Vermaas
06d6f5b5f7 remove header on build page 2012-04-12 20:19:52 +02:00
Rob Vermaas
5748262517 Add bootstrap.zip 2012-04-12 20:13:04 +02:00
Rob Vermaas
17d30cd179 Using twitter bootstrap for more consistent looks for Hydra 2012-04-12 20:12:07 +02:00
Ludovic Courtès
6e62d9b7b5 Allow use of a single Git clone for several branches.
This reinstates commit 53329ecc61, but
uses "git pull --all", instead of "git fetch --all", so that local
tracking branches get updated too.
2012-04-12 16:55:33 +02:00
Rob Vermaas
ed23a6e6d3 Add branch to local clone path of git repositories for now. 2012-04-10 10:06:12 +02:00
Rob Vermaas
79211d5efe Revert "Use git fetch --all to update local clone in stead of git pull. Also, do not use --branch in initial clone."
This reverts commit 53329ecc61.
2012-04-10 10:04:22 +02:00
Rob Vermaas
53329ecc61 Use git fetch --all to update local clone in stead of git pull. Also, do not use --branch in initial clone. 2012-04-05 15:49:48 +02:00
Eelco Dolstra
8b88ce19c2 Huuuge speedup in the Hydra evaluator
The check to see whether a build had been scheduled in a previous
evaluation took about 200 ms for the nixpkgs:trunk jobset.  Given
that it has more than 15000 builds, this added up to a lot.  Now
it takes 0.2 ms per build.
2012-04-04 17:29:03 +02:00
Eelco Dolstra
1cdc023427 Propagate URI parameters 2012-04-04 13:17:22 +02:00
Eelco Dolstra
e9dd3158a0 Propagate URI parameters
This allows URIs like

  http://hydra.nixos.org/jobset/nixpkgs/trunk/latest-eval?compare=stdenv

to do the right thing.
2012-04-04 12:56:49 +02:00
Eelco Dolstra
05d03ee153 Don't use colspan=0, it doesn't work in all browsers 2012-04-04 10:33:00 +00:00
Eelco Dolstra
7734de5817 Add OpenSSL as a dependency because Nix needs it
Actually the real problem is that a) Nix doesn't propagate the OpenSSL
dependency; b) Nix shouldn't link against OpenSSL by default anyway.
2012-04-04 11:43:14 +02:00
Eelco Dolstra
f52ca0c588 Add a redirect to the latest view result for which the underlying evaluation has finished completely
This will be useful for the Nixpkgs channel mirror script:

  http://hydra.nixos.org/view/nixpkgs/unstable/latest-finished/channel

is the channel containing the latest, consistent, tested set of builds.
2012-04-03 17:45:03 +02:00
Eelco Dolstra
bd93ca9316 Add a redirect to the evaluation page of a view result
E.g.

  http://hydra.nixos.org/view/nixpkgs/unstable/latest/eval

Thus this is the channel representing the latest Nixpkgs for which the
elements of the view "unstable" succeeded:

  http://hydra.nixos.org/view/nixpkgs/unstable/latest/eval/channel
2012-04-03 15:45:48 +02:00
Eelco Dolstra
2c677ec71a Always record inputs passed through -I in the BuildInputs table
We currently have no way to determine if the Nix evaluator used a
specific -I input, so we need to record all of them as inputs.
2012-04-03 10:10:45 +00:00
Eelco Dolstra
30e2b9046a Cleanup 2012-04-03 11:28:59 +02:00
Eelco Dolstra
db2b2b6134 Add a redirect to the latest finished jobset evaluation
The action .../jobset/<project>/<jobset>/latest-eval redirects to the
latest evaluation of the jobset that has no unfinished builds.  Thus,
for instance,

  http://hydra.nixos.org/jobset/nixpkgs/trunk/latest-eval/channel

is the channel containing the latest consistent set of Nixpkgs builds.
2012-04-03 01:30:54 +02:00
Eelco Dolstra
262f068e26 Support obtaining the contents of an evaluation as a channel
E.g. http://hydra.nixos.org/eval/552513/channel

The advantage of such a channel is that all builds come from the same
evaluation, and thus are consistent.
2012-04-02 23:27:17 +02:00
Eelco Dolstra
3e57cbfeb8 User color instead of a big animated GIF to indicate whether a build is running 2012-04-02 21:07:49 +02:00
Eelco Dolstra
69e600da89 Allow comparing an evaluation with an arbitrary other evaluation
The URI parameter "compare=..." can denote either an arbitrary
evaluation ID, or the name of a jobset in the same project.  In the
latter case, the comparison is made against the latest completed
evaluation of the specified jobset.
2012-04-02 20:40:59 +02:00
Eelco Dolstra
2f9153c640 Prevent multiple builds with the same (job, outPath) tuple from being added
This happened in a pathological case in Nixpkgs: the "grub" job is
evaluated for i686-linux and x86_64-linux, but in the latter case it
returns the same derivation as in the former case.  So only one build
should be added.
2012-04-02 15:56:29 +00:00
Eelco Dolstra
9d4cb29e08 Show queued builds in jobset evaluation pages 2012-04-02 15:23:42 +00:00
Eelco Dolstra
427e5e8db8 Show new and removed jobs 2012-04-02 16:45:05 +02:00
Eelco Dolstra
662cdf0421 Add support for viewing jobset evaluations 2012-04-02 16:11:22 +02:00
Eelco Dolstra
d33fbad438 Unpack jQuery etc. in the build tree for easier testing 2012-04-02 11:15:48 +00:00
Eelco Dolstra
0aae52bfcc In build tables, hide the project, jobset and/or job name if they're constant 2012-04-02 13:12:39 +02:00
Rob Vermaas
1904f82f06 add openssl to deps 2012-04-01 18:15:00 +02:00
Eelco Dolstra
d8f8143cc2 No wonder our disk was filling up 2012-03-26 17:13:50 +02:00
Rob Vermaas
4d4e1986e8 remove delete jobset button until we actually have implemented the action properly 2012-03-26 14:39:50 +02:00
Eelco Dolstra
e1768cae86 Don't barf if the SQLite DB is missing
This prevented hydra-init from starting.
2012-03-19 03:57:11 +00:00
Ludovic Courtès
3846c2407d Fix URL in the "password changed" email. 2012-03-13 18:30:57 +01:00
Ludovic Courtès
d0f18a1d6f Add dependency on Switch. 2012-03-13 18:12:37 +01:00
Ludovic Courtès
2b68e41ee4 Actually add SQL files to the distribution. 2012-03-13 17:49:18 +01:00
Ludovic Courtès
ace94192ac Update the list of SQL files to be installed.
This fixes `hydra-init', which would otherwise not find `upgrade-*.sql',
thus skipping the update altogether.
2012-03-13 17:45:14 +01:00
Eelco Dolstra
dae5032c1c I'm stupid 2012-03-13 13:33:19 +01:00
Eelco Dolstra
c844b9f09a Remove the global Job status and Errors links 2012-03-13 13:31:36 +01:00
Eelco Dolstra
161d7418f8 Doh 2012-03-13 13:30:41 +01:00
Eelco Dolstra
fa62c8b7f2 Fix tests 2012-03-13 13:18:40 +01:00
Eelco Dolstra
1f268d2d43 Update isCurrent properly 2012-03-13 13:09:10 +01:00
Eelco Dolstra
179b012a8e Open the DB using Hydra::Model::DB->new
This gets rid of the openHydraDB function and ensures that we
open the database in a consistent way.

Also drop the PostgreSQL sequence hacks.  They don't seem to be
necessary anymore.
2012-03-13 12:10:19 +01:00
Eelco Dolstra
914c5e248a Use <...> syntax 2012-03-13 11:03:32 +01:00
Eelco Dolstra
93efae0c23 Fix "make check" 2012-03-12 21:13:50 +01:00
Eelco Dolstra
13f4636436 hydra-evaluator: handle the case where there is no previous jobset eval 2012-03-12 21:13:28 +01:00
Eelco Dolstra
3f1bbf7ef4 Better fix 2012-03-12 21:06:42 +01:00
Eelco Dolstra
259afadbab Set $PERL5LIB properly in hydra-init in "make check" 2012-03-12 20:56:41 +01:00
Eelco Dolstra
a4cda5e337 Don't use the Switch module
It was removed in Perl 5.14.
2012-03-12 20:47:30 +01:00
Eelco Dolstra
87e4d43848 Fix the jobset unchanged check
When checking whether the jobset is unchanged, we need to compare with
the previous JobsetEval regardless of whether it had new builds.
Otherwise we'll keep adding new JobsetEval rows.
2012-03-12 20:47:30 +01:00
Eelco Dolstra
27619f18e2 Re-enable the "Related Builds" tab
However, there is a "limit 1" on the JobsetEval search to prevent a
sequential scan of the Builds table.
2012-03-12 20:47:30 +01:00
Eelco Dolstra
abe71a767b Disable prepared statements completely
Because of the way DBIx::Class does prepared statements, even
innocuous queries such

  $c->model('DB::Builds)->search({finished => 0})

can be extremely slow.  This is because DBIx::Class prepares a
PostgreSQL statement

  select ... from Builds where finished = ?

and since Builds is very large and there is a large fraction of rows
with "finished = 1", the PostgreSQL query planner decides to implement
this query with a sequential scan of the Builds table (despite the
existence of an index on "finished"), which is extremely slow.  It
would be nice if we could tell DBIx::Class that constants should be
part of the prepared statement, i.e.

  select ... from Builds where finished = 0

but AFAIK we can't.
2012-03-12 20:47:30 +01:00
Eelco Dolstra
2d1cf73974 Speed up channel processing
In particular the /pkg action is now O(lg n) instead of O(n) in the
number of packages in the channel, and listing the channel contents
no longer requires calling isValidPath() on all packages.

Derivations (and thus build time dependencies) are no longer included
in the channel, because they're not GC roots.  Thus they could
disappear unexpectedly.
2012-03-12 20:47:30 +01:00
Eelco Dolstra
9f10c0f9c0 Fix a reference to BuildResultInfo 2012-03-12 20:47:30 +01:00
Eelco Dolstra
07b3dffd20 Reduce I/O in build listings by only fetching required columns
Columns such as "longDescription" can be large, so fetching them
when they're not needed is wasteful.
2012-03-12 20:47:30 +01:00
Eelco Dolstra
6526d4a65f hydra-build: only send email if the status differs from the previous build
This isn't perfect because it doesn't handle the case where a
previous build hasn't finished yet.  But at least it won't send mail
for old builds that fail while a newer build has already succeeded.
2012-03-12 20:47:29 +01:00
Eelco Dolstra
47f877c5bb Evaluator cleanups
* Don't use isCurrent anymore; instead look up builds in the previous
  jobset evaluation.  (The isCurrent field is still maintained because
  it's still used in some other places.)

* To determine whether to perform an evaluation, compare the hash of
  the current inputs with the inputs of the previous jobset
  evaluation, rather than checking if there was ever an evaluation
  with those inputs.  This way, if the inputs of an evaluation change
  back to a previous state, we get a new jobset evaluation in the
  database (and thus the latest jobset evaluation correctly represents
  the latest state of the jobset).

* Improve performance by removing some unnecessary operations and
  adding an index.
2012-03-12 20:47:29 +01:00
Eelco Dolstra
bc82a82593 Fix a race condition in hydra-update-gc-roots
Since it read the actual roots after determining the set of desired
roots, there was a possibility that it would delete roots added by
hydra-evaluator or hydra-build while hydra-update-gc-roots was
running.  This could cause a derivation to be garbage-collected before
the build was performed, for instance.  Now the actual roots are read
first, so any root added after that time is not deleted.
2012-03-12 20:47:29 +01:00
Eelco Dolstra
29d5a02b94 Speed up hydra-update-gc-roots
The hydra-update-gc-roots script is taking around 95 minutes on our
Hydra instance (though a lot of that is I/O wait).  This patch
significantly reduces the number of database queries.  In particular,
the N most recent successful builds for each job in a jobset are now
determined in a single query.  Also, it removes the calls to
readlink().
2012-03-12 20:47:29 +01:00
Eelco Dolstra
5be004c999 Drop the merged tables after conversion 2012-03-12 20:47:29 +01:00
Eelco Dolstra
8d65ab6158 Don't use a prepared statement for the active build steps query
Prepared statements are sometimes much slower than unprepared
statements, because the planner doesn't have access to the query
parameters.  This is the case for the active build steps query (in
/status), where a prepared statement is three orders of magnitude
slower.  So disable the use of prepared statements in this case.

(Since the query parameters are constant here, it would be nicer if we
could tell DBIx::Class to prepare a statement with those parameters
fixed.  But I don't know an easy way to do so.)
2012-03-12 20:47:29 +01:00
Eelco Dolstra
68a867da67 Merge the BuildResultInfo table into the Builds table 2012-03-12 20:47:29 +01:00
Eelco Dolstra
25334715f8 Merge the BuildSchedulingInfo table into the Builds table
This simplifies the code and improves performance since it reduces
the number of joins.
2012-03-12 20:47:29 +01:00
Eelco Dolstra
19fe4b9b4a Add hydra-init to the tarball 2012-03-05 15:35:13 +01:00
624 changed files with 43175 additions and 13695 deletions

24
.editorconfig Normal file
View File

@@ -0,0 +1,24 @@
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{cc,hh,hpp,pl,pm,sh,t}]
indent_style = space
intend_size = 4
[Makefile]
indent_style = tab
[*.nix]
indent_style = space
indent_size = 2
# Match diffs, avoid to trim trailing whitespace
[*.{diff,patch}]
trim_trailing_whitespace = false

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

37
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,37 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Hydra Server:**
Please fill out this data as well as you can, but don't worry if you can't -- just do your best.
- OS and version: [e.g. NixOS 22.05.20211203.ee3794c]
- Version of Hydra
- Version of Nix Hydra is built against
- Version of the Nix daemon
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

6
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

27
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: "Test"
on:
pull_request:
merge_group:
push:
branches:
- master
jobs:
tests:
strategy:
matrix:
include:
- system: x86_64-linux
runner: ubuntu-latest
- system: aarch64-linux
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
extra-systems = ${{ matrix.system }}
- uses: DeterminateSystems/magic-nix-cache-action@main
- run: nix-build -A checks.${{ matrix.system }}.build -A checks.${{ matrix.system }}.validate-openapi

28
.github/workflows/update-flakes.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: "Update Flakes"
on:
schedule:
# Run weekly on Monday at 00:00 UTC
- cron: '0 0 * * 1'
workflow_dispatch:
jobs:
update-flakes:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- 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@v8
with:
commit-message: "flake.lock: Update"
title: "Update flake inputs"
body: |
Automated flake input updates.
This PR was automatically created by the update-flakes workflow.
branch: update-flakes
delete-branch: true

28
.gitignore vendored
View File

@@ -1,17 +1,13 @@
*.o
*~
Makefile
Makefile.in
.deps
/config.guess
/config.log
/config.status
/config.sub
/configure
/depcomp
/libtool
/ltmain.sh
/autom4te.cache
/aclocal.m4
/missing
/install-sh
/.direnv/
.test_info.*
/src/root/static/bootstrap
/src/root/static/fontawesome
/src/root/static/js/flot
/src/sql/hydra-postgresql.sql
/src/sql/hydra-sqlite.sql
/src/sql/tmp.sqlite
.hydra-data
result
result-*
outputs

10
.perlcriticrc Normal file
View File

@@ -0,0 +1,10 @@
theme = community
# 5 is the least complainy, 1 is the most complainy
severity = 1
# Disallow backticks - use IPC::Run3 instead for better security
include = InputOutput::ProhibitBacktickOperators
# Prohibit shell-invoking system() and exec() - use list form or IPC::Run3 instead
include = Hydra::ProhibitShellInvokingSystemCalls

View File

View File

@@ -1,4 +0,0 @@
SUBDIRS = doc src tests
BOOTCLEAN_SUBDIRS = $(SUBDIRS)
DIST_SUBDIRS = $(SUBDIRS)

0
NEWS
View File

6
Procfile Normal file
View File

@@ -0,0 +1,6 @@
hydra-evaluator: ./foreman/start-evaluator.sh
hydra-queue-runner: ./foreman/start-queue-runner.sh
hydra-notify: ./foreman/start-notify.sh
hydra-server: ./foreman/start-hydra.sh
manual: ./foreman/start-manual.sh
postgres: ./foreman/start-postgres.sh

0
README
View File

156
README.md Normal file
View File

@@ -0,0 +1,156 @@
# Hydra
[![CI](https://github.com/NixOS/hydra/workflows/Test/badge.svg)](https://github.com/NixOS/hydra/actions)
Hydra is a [Continuous Integration](https://en.wikipedia.org/wiki/Continuous_integration) service for [Nix](https://nixos.org/nix) based projects.
## Installation And Setup
**Note**: The instructions provided below are intended to enable new users to get a simple, local installation up and running. They are by no means sufficient for running a production server, let alone a public instance.
### Enabling The Service
Running Hydra is currently only supported on NixOS. The [hydra module](https://github.com/NixOS/nixpkgs/blob/release-20.03/nixos/modules/services/continuous-integration/hydra/default.nix) allows for an easy setup. The following configuration can be used for a simple setup that performs all builds on _localhost_ (Please refer to the [Options page](https://nixos.org/nixos/options.html#services.hydra) for all available options):
```nix
{
services.hydra = {
enable = true;
hydraURL = "http://localhost:3000";
notificationSender = "hydra@localhost";
buildMachinesFiles = [];
useSubstitutes = true;
};
}
```
### Creating An Admin User
Once the Hydra service has been configured as above and activated, you should already be able to access the UI interface at the specified URL. However some actions require an admin user which has to be created first:
```
$ su - hydra
$ hydra-create-user <USER> --full-name '<NAME>' \
--email-address '<EMAIL>' --password-prompt --role admin
```
Afterwards you should be able to log by clicking on "_Sign In_" on the top right of the web interface using the credentials specified by `hydra-create-user`. Once you are logged in you can click "_Admin -> Create Project_" to configure your first project.
### Creating A Simple Project And Jobset
In order to evaluate and build anything you need to create _projects_ that contain _jobsets_. Hydra supports imperative and declarative projects and many different configurations. The steps below will guide you through the required steps to creating a minimal imperative project configuration.
#### Creating A Project
Log in as administrator, click "_Admin_" and select "_Create project_". Fill the form as follows:
- **Identifier**: `hello-project`
- **Display name**: `hello`
- **Description**: `hello project`
Click "_Create project_".
#### Creating A Jobset
After creating a project you are forwarded to the project page. Click "_Actions_" and choose "_Create jobset_". Change **Type** to Legacy for the example below. Fill the form with the following values:
- **Identifier**: `hello-project`
- **Nix expression**: `examples/hello.nix` in `hydra`
- **Check interval**: 60
- **Scheduling shares**: 1
We have to add two inputs for this jobset. One for _nixpkgs_ and one for _hydra_ (which we are referencing in the Nix expression above):
- **Input name**: `nixpkgs`
- **Type**: `Git checkout`
- **Value**: `https://github.com/NixOS/nixpkgs nixos-24.05`
- **Input name**: `hydra`
- **Type**: `Git checkout`
- **Value**: `https://github.com/nixos/hydra`
Make sure **State** at the top of the page is set to "_Enabled_" and click on "_Create jobset_". This concludes the creation of a jobset that evaluates [./examples/hello.nix](./examples/hello.nix) once a minute. Clicking "_Evaluations_" should list the first evaluation of the newly created jobset after a brief delay.
## Building And Developing
### Building Hydra
You can build Hydra via `nix-build` using the provided [default.nix](./default.nix):
```
$ nix build
```
### Development Environment
You can use the provided shell.nix to get a working development environment:
```
$ nix develop
$ ln -svf ../../../build/src/bootstrap src/root/static/bootstrap
$ ln -svf ../../../build/src/fontawesome src/root/static/fontawesome
$ ln -svf ../../../../build/src/flot src/root/static/js/flot
$ meson setup build
$ ninja -C build
```
The development environment can also automatically be established using [nix-direnv](https://github.com/nix-community/nix-direnv).
### Executing Hydra During Development
When working on new features or bug fixes you need to be able to run Hydra from your working copy. This
can be done using [foreman](https://github.com/ddollar/foreman):
```
$ nix develop
$ # hack hack
$ ninja -C build
$ foreman start
```
Have a look at the [Procfile](./Procfile) if you want to see how the processes are being started. In order to avoid
conflicts with services that might be running on your host, hydra and postgress are started on custom ports:
- hydra-server: 63333 with the username "alice" and the password "foobar"
- postgresql: 64444, can be connected to using `psql -p 64444 -h localhost hydra`
Note that this is only ever meant as an ad-hoc way of executing Hydra during development. Please make use of the
NixOS module for actually running Hydra in production.
### Checking your patches
After making your changes, verify the test suite passes and perlcritic is still happy.
Start by following the steps in [Development Environment](#development-environment).
Then, you can run the tests and the perlcritic linter together with:
```console
$ nix develop
$ ninja -C build test
```
You can run a single test with:
```
$ nix develop
$ cd build
$ meson test --test-args=../t/Hydra/Event.t testsuite
```
And you can run just perlcritic with:
```
$ nix develop
$ cd build
$ meson test perlcritic
```
### JSON API
You can also interface with Hydra through a JSON API. The API is defined in [hydra-api.yaml](./hydra-api.yaml) and you can test and explore via the [swagger editor](https://editor.swagger.io/?url=https://raw.githubusercontent.com/NixOS/hydra/master/hydra-api.yaml)
## Additional Resources
- [Hydra User's Guide](https://nixos.org/hydra/manual/)
- [Hydra on the NixOS Wiki](https://wiki.nixos.org/wiki/Hydra)
- [hydra-cli](https://github.com/nlewo/hydra-cli)
- [Peter Simons - Hydra: Setting up your own build farm (NixOS)](https://www.youtube.com/watch?v=RXV0Y5Bn-QQ)
## License
Hydra is licensed under [GPL-3.0](./COPYING)
Icons provided free by [EmojiOne](http://emojione.com).

View File

@@ -1,2 +0,0 @@
#! /bin/sh -e
exec autoreconf -vfi

View File

@@ -1,97 +0,0 @@
AC_INIT([Hydra], [m4_esyscmd([echo -n $(cat ./version)$VERSION_SUFFIX])],
[nix-dev@cs.uu.nl], [hydra], [http://nixos.org/hydra/])
AM_INIT_AUTOMAKE([foreign])
AC_LANG([C++])
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_LIBTOOL
AC_PROG_CXX
dnl Optional dependencies to build the manual, normally not needed
dnl since the tarball comes with the PDF and HTML manuals.
AC_PATH_PROG([DBLATEX], [dblatex])
AC_PATH_PROG([XSLTPROC], [xsltproc])
AC_ARG_WITH([docbook-xsl],
[AS_HELP_STRING([--with-docbook-xsl=PATH],
[path of the DocBook XSL stylesheets])],
[docbookxsl="$withval"],
[docbookxsl="/docbook-xsl-missing"])
AC_SUBST([docbookxsl])
AC_DEFUN([NEED_PROG],
[
AC_PATH_PROG($1, $2)
if test -z "$$1"; then
AC_MSG_ERROR([$2 is required])
fi
])
NEED_PROG(perl, perl)
AC_ARG_WITH(nix, AC_HELP_STRING([--with-nix=PATH],
[prefix of nix]),
nix=$withval, nix=/nix-missing)
AC_SUBST(nix)
PATH="$nix/bin:$PATH"
export PATH
NEED_PROG([NIX_STORE_PROGRAM], [nix-store])
AC_MSG_CHECKING([whether $NIX_STORE_PROGRAM is recent enough])
if test -n "$NIX_STORE" -a -n "$TMPDIR"
then
# This may be executed from within a build chroot, so pacify
# `nix-store' instead of letting it choke while trying to mkdir
# /nix/var.
NIX_STATE_DIR="$TMPDIR"
export NIX_STATE_DIR
fi
if "$NIX_STORE_PROGRAM" --timeout 123 -q > /dev/null 2>&1
then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
AC_MSG_ERROR([`$NIX_STORE_PROGRAM' doesn't support `--timeout'; please use a newer version.])
fi
old_CPPFLAGS="$CPPFLAGS"
old_LIBS="$LIBS"
CPPFLAGS="$CPPFLAGS -I$nix/include/nix"
LDFLAGS="$LDFLAGS -L$nix/lib/nix"
AC_CHECK_HEADER([store-api.hh], [:],
[AC_MSG_ERROR([Nix headers not found; please install Nix or check the `--with-nix' option.])])
AC_CHECK_LIB([expr], [_ZN3nix9EvalState17parseExprFromFileESs], [:],
[AC_MSG_ERROR([Nix library not found; please install Nix or check the `--with-nix' option.])])
CPPFLAGS="$old_CPPFLAGS"
LIBS="$old_LIBS"
PKG_CHECK_MODULES([BDW_GC], [bdw-gc])
testPath="$(dirname $(type -p expr))"
AC_SUBST(testPath)
AC_CONFIG_FILES([
Makefile
doc/Makefile
doc/manual/Makefile
src/Makefile
src/c/Makefile
src/sql/Makefile
src/xsl/Makefile
src/lib/Makefile
src/root/Makefile
src/script/Makefile
tests/Makefile
tests/jobs/config.nix
])
AC_OUTPUT

21
datadog/README.md Normal file
View File

@@ -0,0 +1,21 @@
# Hydra status timeboard
In order to deploy hydra status dashboard you can:
* create a deployment
```
nixops create -d hydra-status /path/to/hydra/datadog/dd-dashboard.nix
```
* setup the default hostname and api/app keys
```
nixops set-args -d hydra-status --argst appKey <app_key> --argstr apiKey <api_key> --argstr host chef
```
* deploy
```
nixops deploy -d hydra-status
```

161
datadog/dd-dashboard.nix Normal file
View File

@@ -0,0 +1,161 @@
{
host
, appKey
, apiKey
, ...
}:
{
resources.datadogTimeboards.hydra-status = {
inherit appKey apiKey;
description = "Hydra build farm status";
graphs = [
{
definition = builtins.toJSON {
requests = [
{ q = "avg:hydra.queue.steps.active{$host}"; }
{ q = "avg:hydra.queue.steps.building{$host}"; }
{ q = "avg:hydra.queue.steps.copying_to{$host}"; }
{ q = "avg:hydra.queue.steps.copying_from{$host}"; }
{ q = "avg:hydra.queue.steps.waiting{$host}"; }
];
viz = "timeseries";
};
title = "Active/building steps";
}
{
definition = builtins.toJSON {
requests = [
{ q = "avg:hydra.queue.steps.avg_build_time{$host}"; }
{ q = "avg:hydra.queue.steps.avg_total_time{$host}"; }
];
viz = "timeseries";
};
title = "Build/total time per step";
}
{
definition = builtins.toJSON {
requests = [
{ q = "avg:hydra.queue.steps.finished{$host}"; }
{ q = "avg:hydra.queue.builds.finished{$host}"; }
];
viz = "timeseries";
};
title = "Finished builds/steps";
}
{
definition = builtins.toJSON {
requests = [
{ q = "max:system.io.await{$host} by {device}"; type = "area"; }
];
viz = "timeseries";
};
title = "Disk latency (ms, by device)";
}
{
definition = builtins.toJSON {
requests = [
{ q = "avg:hydra.queue.steps.unfinished{$host}"; }
{ q = "avg:hydra.queue.builds.unfinished{$host}"; }
{ q = "avg:hydra.queue.steps.runnable{$host}"; }
];
viz = "timeseries";
};
title = "Unfinished builds/steps";
}
{
definition = builtins.toJSON {
requests = [
{ q = "avg:system.load.1{$host}"; }
{ q = "avg:system.load.5{$host}"; }
{ q = "avg:system.load.15{$host}"; }
];
viz = "timeseries";
};
title = "Load Averages 1-5-15";
}
{
definition = builtins.toJSON {
requests = [
{ q = "per_hour(ewma_20(avg:hydra.queue.steps.finished{$host}))"; }
{
q = "per_hour(ewma_20(avg:hydra.queue.builds.finished{$host}))";
}
];
viz = "timeseries";
};
title = "Finished builds/steps / hour";
}
{
definition = builtins.toJSON {
requests = [ { q = "avg:hydra.mem.dirty{$host}"; } ];
viz = "timeseries";
};
title = "Dirty memory";
}
{
definition = builtins.toJSON {
requests = [
{
aggregator = "avg";
conditional_formats = [];
q = "avg:system.mem.used{$host}";
type = "line";
}
{
conditional_formats = [];
q = "avg:system.mem.free{$host}";
type = "line";
}
{
conditional_formats = [];
q = "avg:system.mem.usable{$host}";
type = "line";
}
];
viz = "timeseries";
};
title = "Memory usage";
}
{
definition = builtins.toJSON {
requests = [
{ q = "avg:hydra.queue.bytes_sent{$host}"; type = "line"; }
{ q = "avg:hydra.queue.bytes_received{$host}"; type = "line"; }
];
viz = "timeseries";
};
title = "Stores paths sent/received";
}
{
definition = builtins.toJSON {
requests = [
{ q = "per_minute(ewma_20(avg:hydra.queue.bytes_sent{$host}))"; }
{
q = "per_minute(ewma_20(avg:hydra.queue.bytes_received{$host}))";
}
];
viz = "timeseries";
};
title = "Store paths sent/received (GiB / minute)";
}
{
definition = builtins.toJSON {
requests = [
{ q = "avg:hydra.queue.machines.total{$host}"; type = "line"; }
{ q = "avg:hydra.queue.machines.in_use{$host}"; type = "line"; }
];
viz = "timeseries";
};
title = "Total and active machines";
}
];
templateVariables = [
{
default = "host:${host}";
name = "host";
prefix = "host";
}
];
title = "Hydra Status (deployed from nixops)";
};
}

6
default.nix Normal file
View File

@@ -0,0 +1,6 @@
# The `default.nix` in flake-compat reads `flake.nix` and `flake.lock` from `src` and
# returns an attribute set of the shape `{ defaultNix, shellNix }`
(import (fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz") {
src = ./.;
}).defaultNix

View File

@@ -1,38 +0,0 @@
{ pkgs }:
with pkgs;
[ perlPackages.CatalystAuthenticationStoreDBIxClass
perlPackages.CatalystPluginAccessLog
perlPackages.CatalystPluginAuthorizationRoles
perlPackages.CatalystPluginSessionStateCookie
perlPackages.CatalystPluginSessionStoreFastMmap
perlPackages.CatalystPluginStackTrace
perlPackages.CatalystViewDownload
perlPackages.CatalystViewJSON
perlPackages.CatalystViewTT
perlPackages.CatalystXScriptServerStarman
perlPackages.CryptRandPasswd
perlPackages.DBDPg
perlPackages.DBDSQLite
perlPackages.DataDump
perlPackages.DateTime
perlPackages.DigestSHA1
perlPackages.EmailSender
perlPackages.FileSlurp
perlPackages.IOCompress
perlPackages.IPCRun
perlPackages.JSONXS
perlPackages.NetTwitterLite
perlPackages.PadWalker
perlPackages.CatalystDevel
perlPackages.Readonly
perlPackages.SQLSplitStatement
perlPackages.Starman
perlPackages.SysHostnameLong
perlPackages.TestMore
perlPackages.TextDiff
perlPackages.TextTable
perlPackages.XMLSimple
nixUnstable
]

View File

@@ -1,4 +0,0 @@
SUBDIRS = manual
BOOTCLEAN_SUBDIRS = $(SUBDIRS)
DIST_SUBDIRS = $(SUBDIRS)

129
doc/architecture.md Normal file
View File

@@ -0,0 +1,129 @@
This is a rough overview from informal discussions and explanations of inner workings of Hydra.
You can use it as a guide to navigate the codebase or ask questions.
## Architecture
### Components
- Postgres database
- configuration
- build queue
- what is already built
- what is going to build
- `hydra-server`
- Perl, Catalyst
- web frontend
- `hydra-evaluator`
- Perl, C++
- fetches repositories
- evaluates job sets
- pointers to a repository
- adds builds to the queue
- `hydra-queue-runner`
- C++
- monitors the queue
- executes build steps
- uploads build results
- copy to a Nix store
- Nix store
- contains `.drv`s
- populated by `hydra-evaluator`
- read by `hydra-queue-runner`
- destination Nix store
- can be a binary cache
- e.g. `[cache.nixos.org](http://cache.nixos.org)` or the same store again (for small Hydra instances)
- plugin architecture
- extend evaluator for new kinds of repositories
- e.g. fetch from `git`
### Database Schema
[https://github.com/NixOS/hydra/blob/master/src/sql/hydra.sql](https://github.com/NixOS/hydra/blob/master/src/sql/hydra.sql)
- `Jobsets`
- populated by calling Nix evaluator
- every Nix derivation in `release.nix` is a Job
- `flake`
- URL to flake, if job is from a flake
- single-point of configuration for flake builds
- flake itself contains pointers to dependencies
- for other builds we need more configuration data
- `JobsetInputs`
- more configuration for a Job
- `JobsetInputAlts`
- historical, where you could have more than one alternative for each input
- it would have done the cross product of all possibilities
- not used any more, as now every input is unique
- originally that was to have alternative values for the system parameter
- `x86-linux`, `x86_64-darwin`
- turned out not to be a good idea, as job set names did not uniquely identify output
- `Builds`
- queue: scheduled and finished builds
- instance of a Job
- corresponds to a top-level derivation
- can have many dependencies that dont have a corresponding build
- dependencies represented as `BuildSteps`
- a Job is all the builds with a particular name, e.g.
- `git.x86_64-linux` is a job
- there maybe be multiple builds for that job
- build ID: just an auto-increment number
- building one thing can actually cause many (hundreds of) derivations to be built
- for queued builds, the `drv` has to be present in the store
- otherwise build will fail, e.g. after garbage collection
- `BuildSteps`
- corresponds to a derivation or substitution
- are reused through the Nix store
- may be duplicated for unique derivations due to how they relate to `Jobs`
- `BuildStepOutputs`
- corresponds directly to derivation outputs
- `out`, `dev`, ...
- `BuildProducts`
- not a Nix concept
- populated from a special file `$out/nix-support/hydra-build-producs`
- used to scrape parts of build results out to the web frontend
- e.g. manuals, ISO images, etc.
- `BuildMetrics`
- scrapes data from magic location, similar to `BuildProducts` to show fancy graphs
- e.g. test coverage, build times, CPU utilization for build
- `$out/nix-support/hydra-metrics`
- `BuildInputs`
- probably obsolute
- `JobsetEvalMembers`
- joins evaluations with jobs
- huge table, 10ks of entries for one `nixpkgs` evaluation
- can be imagined as a subset of the eval cache
- could in principle use the eval cache
### `release.nix`
- hydra-specific convention to describe the build
- should evaluate to an attribute set that contains derivations
- hydra considers every attribute in that set a job
- every job needs a unique name
- if you want to build for multiple platforms, you need to reflect that in the name
- hydra does a deep traversal of the attribute set
- just evaluating the names may take half an hour
## FAQ
Can we imagine Hydra to be a persistence layer for the build graph?
- partially, it lacks a lot of information
- does not keep edges of the build graph
How does Hydra relate to `nix build`?
- reimplements the top level Nix build loop, scheduling, etc.
- Hydra has to persist build results
- Hydra has more sophisticated remote build execution and scheduling than Nix
Is it conceptually possible to unify Hydras capabilities with regular Nix?
- Nix does not have any scheduling, it just traverses the build graph
- Hydra has scheduling in terms of job set priorities, tracks how much of a job set it has worked on
- makes sure jobs dont starve each other
- Nix cannot dynamically add build jobs at runtime
- [RFC 92](https://github.com/NixOS/rfcs/blob/master/rfcs/0092-plan-dynamism.md) should enable that
- internally it is already possible, but there is no interface to do that
- Hydra queue runner is a long running process
- Nix takes a static set of jobs, working it off at once

View File

@@ -8,39 +8,22 @@
* Setting the maximum number of concurrent builds per system type:
$ sqlite3 hydra.sqlite "insert into SystemTypes(system, maxConcurrent) values('i686-linux', 3);"
$ psql -d hydra <<< "insert into SystemTypes(system, maxConcurrent) values('i686-linux', 3);"
* Creating a user:
$ sqlite3 hydra.sqlite "insert into Users(userName, emailAddress, password) values('root', 'e.dolstra@tudelft.nl', '$(echo -n foobar | sha1sum | cut -c1-40)');"
$ hydra-create-user root --email-address 'e.dolstra@tudelft.nl' \
--password-prompt
(Replace "foobar" with the desired password.)
To make the user an admin:
$ sqlite3 hydra.sqlite "insert into UserRoles(userName, role) values('root', 'admin');"
$ hydra-create-user root --role admin
To enable a non-admin user to create projects:
$ sqlite3 hydra.sqlite "insert into UserRoles(userName, role) values('alice', 'create-projects');"
* Creating a release set:
insert into ReleaseSets(project, name) values('patchelf', 'unstable');
insert into ReleaseSetJobs(isPrimary, project, release, job, attrs, description) values(1, 'patchelf', 'unstable', 'tarball', 'officialRelease=false', 'Source distribution');
insert into ReleaseSetJobs(project, release, job, attrs, description) values('patchelf', 'unstable', 'build', 'system=i686-linux', 'Build on i686-linux');
insert into ReleaseSetJobs(project, release, job, attrs, description) values('patchelf', 'unstable', 'build', 'system=x86_64-linux', 'Build on x86_64-linux');
insert into ReleaseSetJobs(project, release, job, attrs, description, mayFail) values('patchelf', 'unstable', 'rpm_fedora9i386', '', 'Fedora 9 (i386)', 1);
insert into ReleaseSetJobs(project, release, job, attrs, description) values('patchelf', 'unstable', 'rpm_fedora10i386', '', 'Fedora 10 (i386)');
insert into ReleaseSetJobs(project, release, job, attrs, description) values('patchelf', 'unstable', 'deb_ubuntu804i386', '', 'Ubuntu 8.04 (i386)');
insert into ReleaseSets(project, name) values('patchelf', 'stable');
insert into ReleaseSetJobs(isPrimary, project, release, job, attrs, description) values(1, 'patchelf', 'stable', 'tarball', 'officialRelease=true', 'Source distribution');
insert into ReleaseSetJobs(project, release, job, attrs, description) values('patchelf', 'stable', 'build', 'system=i686-linux', 'Build on i686-linux');
insert into ReleaseSetJobs(project, release, job, attrs, description) values('patchelf', 'stable', 'build', 'system=x86_64-linux', 'Build on x86_64-linux');
insert into ReleaseSetJobs(project, release, job, attrs, description, mayFail) values('patchelf', 'stable', 'rpm_fedora9i386', '', 'Fedora 9 (i386)', 1);
insert into ReleaseSetJobs(project, release, job, attrs, description) values('patchelf', 'stable', 'rpm_fedora10i386', '', 'Fedora 10 (i386)');
insert into ReleaseSetJobs(project, release, job, attrs, description) values('patchelf', 'stable', 'deb_ubuntu804i386', '', 'Ubuntu 8.04 (i386)');
$ hydra-create-user root --role create-projects
* Changing the priority of a scheduled build:
@@ -70,48 +53,6 @@
- Start hydra_evaluator and hydra_queue_runner
* Upgrade notes:
alter table builds add column longDescription text;
alter table builds add column license text;
alter table projects add column homepage text;
alter table builds add column homepage text;
alter table BuildProducts add column defaultPath text;
alter table BuildResultInfo add column failedDepBuild integer;
alter table BuildResultInfo add column failedDepStepNr integer;
alter table ReleaseSetJobs add column jobset text not null default "trunk";
=== (DB dump/load needed after Sqlite upgrade) ===
insert into jobs(project, jobset, name, active) select distinct project, jobset, job, 0 from builds b where not exists (select 1 from jobs where project = b.project and jobset = b.jobset and name = b.job);
create index IndexBuildInputsByBuild on BuildInputs(build);
create index IndexBuildInputsByDependency on BuildInputs(dependency);
create index IndexBuildsByTimestamp on Builds(timestamp);
alter table jobs add column disabled integer not null default 0;
alter table builds add column maintainers text;
# Add the isCurrent column to Builds and use the obsolete Jobs.active to fill it in.
alter table builds add column isCurrent integer default 0;
update builds set isCurrent = 1 where id in (select max(id) from builds natural join (select distinct b.project, b.jobset, b.job, b.system from builds b join (select project, jobset, name from jobs where active = 1) j on b.project = j.project and b.jobset = j.jobset and b.job = j.name) b2 group by project, jobset, job, system);
alter table Jobsets add column enabled integer not null default 1;
# Releases -> Views.
alter table ReleaseSets rename to Views;
alter table ReleaseSetJobs rename to ViewJobs;
alter table ViewJobs rename column release_ to view_;
alter table ViewJobs drop column mayFail;
alter table ViewJobs add column autorelease integer not null default 0;
alter table Builds add column nixExprInput text;
alter table Builds add column nixExprPath text;
# Adding JobsetEvals.
drop table JobsetInputHashes;
(add JobsetEvals, JobsetEvalMembers)
* Job selection:
php-sat:build [system = "i686-linux"]
@@ -120,19 +61,15 @@
--if system i686-linux --arg build {...}
* Restarting a bunch of failed builds:
* Restart all aborted builds in a given evaluation (e.g. 820909):
$ sqlite3 hydra.sqlite "select x.id from builds x join buildresultinfo r on r.id = x.id where project = 'nixpkgs' and jobset = 'stdenv' and exists (select 1 from buildinputs where build = x.id and revision = 14806) and finished = 1 and buildstatus = 3" > ids
> update builds set finished = 0 where id in (select id from builds where finished = 1 and buildstatus = 3 and exists (select 1 from jobsetevalmembers where eval = 820909 and build = id));
$ for i in $(cat ids); do echo $i; sqlite3 hydra.sqlite "begin transaction; insert into buildschedulinginfo (id, priority, busy, locker) values($i, 100, 0, ''); delete from buildresultinfo where id = $i; update builds set finished = 0 where id = $i; commit transaction;"; done
Or with Postgres:
* Restart all builds in a given evaluation that had a build step time out:
(restarting all aborted builds with ID > 42000)
$ psql -h buildfarm.st.ewi.tudelft.nl -U hydra hydra -t -c 'select x.id from builds x join buildresultinfo r on r.id = x.id where finished = 1 and buildstatus = 3 and x.id > 42000' > ids
> update builds set finished = 0 where id in (select id from builds where finished = 1 and buildstatus != 0 and exists (select 1 from jobsetevalmembers where eval = 926992 and build = id) and exists (select 1 from buildsteps where build = id and status = 7));
$ for i in $(cat ids); do echo $i; PGPASSWORD=... psql -h buildfarm.st.ewi.tudelft.nl -U hydra hydra -t -c "begin transaction; insert into buildschedulinginfo (id, priority, busy, locker) values($i, 100, 0, ''); delete from buildresultinfo where id = $i; update builds set finished = 0 where id = $i; commit transaction;"; done
* select * from (select project, jobset, job, system, max(timestamp) timestamp from builds where finished = 1 group by project, jobset, job, system) x join builds y on x.timestamp = y.timestamp and x.project = y.project and x.jobset = y.jobset and x.job = y.job and x.system = y.system;
@@ -141,14 +78,9 @@
* Delete all scheduled builds that are not already building:
delete from builds where finished = 0 and not exists (select 1 from buildschedulinginfo s where s.id = builds.id and busy = 1);
delete from builds where finished = 0 and not exists (select 1 from buildschedulinginfo s where s.id = builds.id and busy != 0);
* Installing deps.nix in a profile for testing:
$ nix-env -p $NIX_USER_PROFILE_DIR/hydra-deps -f deps.nix -i \* --arg pkgs 'import /etc/nixos/nixpkgs {}'
* select x.project, x.jobset, x.job, x.system, x.id, x.timestamp, r.buildstatus, b.id, b.timestamp
from (select project, jobset, job, system, max(id) as id from Builds where finished = 1 group by project, jobset, job, system) as a_
natural join Builds x
@@ -159,7 +91,7 @@
where x.project = c.project and x.jobset = c.jobset and x.job = c.job and x.system = c.system
and x.id > c.id and r.buildstatus != r2.buildstatus);
* Using PostgreSQL:
* Using PostgreSQL (version 9.2 or newer is required):
$ HYDRA_DBI="dbi:Pg:dbname=hydra;" hydra-server
@@ -178,3 +110,13 @@
succeed in the nixpkgs:trunk jobset:
select job, system from builds b natural join buildresultinfo where project = 'nixpkgs' and jobset = 'stdenv' and iscurrent = 1 and finished = 1 and buildstatus != 0 and exists (select 1 from builds natural join buildresultinfo where project = 'nixpkgs' and jobset = 'trunk' and job = b.job and system = b.system and iscurrent = 1 and finished = 1 and buildstatus = 0) order by job, system;
* Get all Nixpkgs jobs that have never built succesfully:
select project, jobset, job from builds b1
where project = 'nixpkgs' and jobset = 'trunk' and iscurrent = 1
group by project, jobset, job
having not exists
(select 1 from builds b2 where b1.project = b2.project and b1.jobset = b2.jobset and b1.job = b2.job and finished = 1 and buildstatus = 0)
order by project, jobset, job;

View File

@@ -1,53 +0,0 @@
DOCBOOK_FILES = installation.xml introduction.xml manual.xml projects.xml
EXTRA_DIST = $(DOCBOOK_FILES)
xsltproc_opts = \
--param html.stylesheet \'style.css\' \
--param callout.graphics.extension \'.gif\'
dblatex_opts = \
-V \
-P doc.collab.show=0 \
-P latex.output.revhistory=0
# Include the manual in the tarball.
dist_html_DATA = manual.html style.css
dist_pdf_DATA = manual.pdf
# Embed Docbook's callout images in the distribution.
EXTRA_DIST += images
manual.html: $(DOCBOOK_FILES)
if test "$(XSLTPROC)" != ""; then \
$(XSLTPROC) $(xsltproc_opts) --nonet --xinclude \
--output manual.html \
$(docbookxsl)/html/docbook.xsl manual.xml; \
else \
echo "Please install xsltproc and rerun configure."; \
exit 1; \
fi
manual.pdf: $(DOCBOOK_FILES)
if test "$(DBLATEX)" != ""; then \
$(DBLATEX) $(dblatex_opts) manual.xml; \
else \
echo "Please install dblatex and rerun configure."; \
exit 1; \
fi
images:
$(MKDIR_P) images/callouts
if cp $(docbookxsl)/images/callouts/*.gif images/callouts; then \
chmod +wx images images/callouts; \
else \
echo "Please install Docbook XSL and try again."; \
exit 1; \
fi
install-data-hook: images
$(INSTALL) -d $(DESTDIR)$(htmldir)/images/callouts
$(INSTALL_DATA) images/callouts/* $(DESTDIR)$(htmldir)/images/callouts
distclean-hook:
-rm -rf images

View File

@@ -1,238 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="chap-installation">
<title>Installation</title>
<para>
This chapter explains how to install Hydra on your own build farm server.
</para>
<section>
<title>Prerequisites</title>
<para>
To install and use Hydra you need to have installed the following dependencies:
<itemizedlist>
<listitem>Nix</listitem>
<listitem>either PostgreSQL or SQLite</listitem>
<listitem>many Perl packages, notably Catalyst, EmailSender,
and NixPerl (see the <link
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/development/tools/misc/hydra/default.nix">Hydra
expression in Nixpkgs</link> for the complete
list).</listitem>
</itemizedlist>
At the moment, Hydra runs only on GNU/Linux
(<emphasis>i686-linux</emphasis> and
<emphasis>x86_64_linux</emphasis>).
</para>
<para>
For small projects, Hydra can be run on any reasonably modern
machine. For individual projects you can even run Hydra on a
laptop. However, the charm of a buildfarm server is usually that
it operates without disturbing the developer's working
environment and can serve releases over the internet. In
conjunction you should typically have your source code
administered in a version management system, such as
subversion. Therefore, you will probably want to install a
server that is connected to the internet. To scale up to large
and/or many projects, you will need at least a considerable
amount of diskspace to store builds. Since Hydra can schedule
multiple simultaneous build jobs, it can be useful to have a
multi-core machine, and/or attach multiple build machines in a
network to the central Hydra server.
</para>
<para>
Of course we think it is a good idea to use the <a
href="http://nixos.org/nixos">NixOS</a> GNU/Linux distribution
for your buildfarm server. But this is not a requirement. The
Nix software deployment system can be installed on any GNU/Linux
distribution in parallel to the regular package management
system. Thus, you can use Hydra on a Debian, Fedora, SuSE, or
Ubuntu system.
</para>
</section>
<section>
<title>Getting Nix</title>
<para>
If your server runs NixOS you are all set to continue with
installation of Hydra. Otherwise you first need to install Nix.
The latest stable version can be found one <link
xlink:href="http://nixos.org/nix/download.html">the Nix web
site</link>, along with a manual, which includes installation
instructions.
</para>
</section>
<section>
<title>Installation</title>
<!--
<para>
Hydra can be installed using Nixpkgs:
<screen>
nix-env -f /path/to/nixpkgs -iA hydra</screen>
This makes the tools available in your Nix user environment,
<literal>$HOME/.nix-profile</literal> by default.
</para>
-->
<para>
The latest development snapshot of Hydra can be installed
by visiting the URL <link
xlink:href="http://hydra.nixos.org/view/hydra/unstable"><literal>http://hydra.nixos.org/view/hydra/unstable</literal></link>
and using the one-click install available at one of the build
pages. You can also install Hydra through the channel by
performing the following commands:
<screen>
nix-channel --add http://hydra.nixos.org/jobset/hydra/trunk/channel/latest
nix-channel --update
nix-env -i hydra</screen>
</para>
<para>
Command completion should reveal a number of command-line tools from Hydra:
<screen>
hydra-build hydra-init hydra-update-gc-roots
hydra-eval-jobs hydra-queue-runner
hydra-evaluator hydra-server
</screen>
</para>
</section>
<section>
<title>Creating the database</title>
<para>
Hydra stores its results in a database, which can be a
PostgreSQL or SQLite database. The latter is easier to setup,
but the former scales better.
</para>
<para>
To setup a PostgreSQL database with <emphasis>hydra</emphasis>
as database name and user name, issue the following commands on
the PostgreSQL server:
<screen>
createuser -S -D -R -P hydra
createdb -O hydra hydra</screen>
Note that <emphasis>$prefix</emphasis> is the location of Hydra
in the nix store.
</para>
<para>
Hydra uses an environment variable to know which database should
be used, and a variable which point to a location that holds
some state. To set these variables for a PostgreSQL database,
add the following to the file <filename>~/.profile</filename> of
the user running the Hydra services.
<screen>
export HYDRA_DBI="dbi:Pg:dbname=hydra;host=dbserver.example.org;user=hydra;"
export HYDRA_DATA=/var/lib/hydra</screen>
You can provide the username and password in the file
<filename>~/.pgpass</filename>, e.g.
<screen>
dbserver.example.org:*:hydra:hydra:password</screen>
Make sure that the <emphasis>HYDRA_DATA</emphasis> directory
exists and is writable for the user which will run the Hydra
services. For a SQLite database, the
<varname>HYDRA_DBI</varname> should be set to something like
<literal>dbi:SQLite:/path/to/hydra.sqlite</literal>
</para>
<para>
Having set these environment variables, you can now initialise
the database by doing:
<screen>
hydra-init</screen>
</para>
<para>
To add a user <emphasis>root</emphasis> with
<emphasis>admin</emphasis> privileges, execute:
<screen>
echo "INSERT INTO Users(userName, emailAddress, password) VALUES ('root', 'some@email.adress.com', '$(echo -n foobar | sha1sum | cut -c1-40)');" | psql hydra
echo "INSERT INTO UserRoles(userName, role) values('root', 'admin');" | psql hydra</screen>
For SQLite the same commands can be used, with <command>psql
hydra</command> replaced by <command>sqlite3
/path/to/hydra.sqlite</command>.
</para>
</section>
<section>
<title>Upgrading</title>
<para>If you're upgrading Hydra from a previous version, you
should do the following to perform any necessary database schema migrations:
<screen>
hydra-init</screen>
</para>
</section>
<section>
<title>Getting Started</title>
<para>
To start the Hydra web server, execute:
<screen>
hydra-server</screen>
When the server is started, you can browse to
<ulink>http://localhost:3000/</ulink> to start configuring
your Hydra instance.
</para>
<para>
The <command>hydra-server</command> command launches the web
server. There are two other processes that come into play:
<itemizedlist>
<listitem>
The <emphasis>evaluator</emphasis> is responsible for
peridically evaluating job sets, checking out their
dependencies off their version control systems (VCS), and
queueing new builds if the result of the evaluation changed.
It is launched by the <command>hydra-evaluator</command>
command.
</listitem>
<listitem>
The <emphasis>queue runner</emphasis> launches builds (using
Nix) as they are queued by the evaluator, scheduling them
onto the configured Nix hosts. It is launched using the
<command>hydra-queue-runner</command> command.
</listitem>
</itemizedlist>
All three processes must be running for Hydra to be fully
functional, though it's possible to temporarily stop any one of
them for maintenance purposes, for instance.
</para>
</section>
</chapter>
<!--
Local Variables:
indent-tabs-mode: nil
ispell-local-dictionary: "american"
End:
-->

View File

@@ -1,267 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="chap-introduction">
<title>Introduction</title>
<section>
<title>About Hydra</title>
<para>
Hydra is a tool for continuous integration testing and software
release that uses a purely functional language to describe build jobs
and their dependencies. Continuous integration is a simple technique
to improve the quality of the software development process. An
automated system continuously or periodically checks out the source
code of a project, builds it, runs tests, and produces reports for the
developers. Thus, various errors that might accidentally be committed
into the code base are automatically caught. Such a system allows
more in-depth testing than what developers could feasibly do manually:
<itemizedlist>
<listitem> <emphasis>Portability testing</emphasis>: The
software may need to be built and tested on many different
platforms. It is infeasible for each developer to do this
before every commit.
</listitem>
<listitem> Likewise, many projects have very large test sets
(e.g., regression tests in a compiler, or stress tests in a
DBMS) that can take hours or days to run to completion.
</listitem>
<listitem> Many kinds of static and dynamic analyses can be
performed as part of the tests, such as code coverage runs and
static analyses.
</listitem>
<listitem> It may also be necessary to build many different
<emphasis>variants</emphasis> of the software. For instance,
it may be necessary to verify that the component builds with
various versions of a compiler.
</listitem>
<listitem> Developers typically use incremental building to
test their changes (since a full build may take too long), but
this is unreliable with many build management tools (such as
Make), i.e., the result of the incremental build might differ
from a full build.
</listitem>
<listitem> It ensures that the software can be built from the
sources under revision control. Users of version management
systems such as CVS and Subversion often forget to place
source files under revision control.
</listitem>
<listitem> The machines on which the continuous integration
system runs ideally provides a clean, well-defined build
environment. If this environment is administered through
proper SCM techniques, then builds produced by the system can
be reproduced. In contrast, developer work environments are
typically not under any kind of SCM control.
</listitem>
<listitem> In large projects, developers often work on a
particular component of the project, and do not build and test
the composition of those components (again since this is
likely to take too long). To prevent the phenomenon of ``big
bang integration'', where components are only tested together
near the end of the development process, it is important to
test components together as soon as possible (hence
<emphasis>continuous integration</emphasis>).
</listitem>
<listitem> It allows software to be
<emphasis>released</emphasis> by automatically creating
packages that users can download and install. To do this
manually represents an often prohibitive amount of work, as
one may want to produce releases for many different platforms:
e.g., installers for Windows and Mac OS X, RPM or Debian
packages for certain Linux distributions, and so on.
</listitem>
</itemizedlist>
</para>
<para>
In its simplest form, a continuous integration tool sits in a
loop building and releasing software components from a version
management system. For each component, it performs the
following tasks:
<itemizedlist>
<listitem>It obtains the latest version of the component's
source code from the version management system.
</listitem>
<listitem> It runs the component's build process (which
presumably includes the execution of the component's test
set).
</listitem>
<listitem> It presents the results of the build (such as error
logs and releases) to the developers, e.g., by producing a web
page.
</listitem>
</itemizedlist>
Examples of continuous integration tools include Jenkins,
CruiseControl Tinderbox, Sisyphus, Anthill and BuildBot. These
tools have various limitations.
<itemizedlist>
<listitem> They do not manage the <emphasis>build
environment</emphasis>. The build environment consists of the
dependencies necessary to perform a build action, e.g.,
compilers, libraries, etc. Setting up the environment is
typically done manually, and without proper SCM control (so it
may be hard to reproduce a build at a later time). Manual
management of the environment scales poorly in the number of
configurations that must be supported. For instance, suppose
that we want to build a component that requires a certain
compiler X. We then have to go to each machine and install X.
If we later need a newer version of X, the process must be
repeated all over again. An ever worse problem occurs if
there are conflicting, mutually exclusive versions of the
dependencies. Thus, simply installing the latest version is
not an option. Of course, we can install these components in
different directories and manually pass the appropriate paths
to the build processes of the various components. But this is
a rather tiresome and error-prone process.
</listitem>
<listitem> They do not easily support <emphasis>variability in software
systems</emphasis>. A system may have a great deal of build-time
variability: optional functionality, whether to build a debug or
production version, different versions of dependencies, and so on.
(For instance, the Linux kernel now has over 2,600 build-time
configuration switches.) It is therefore important that a continuous
integration tool can easily select and test different instances from
the configuration space of the system to reveal problems, such as
erroneous interactions between features. In a continuous integration
setting, it is also useful to test different combinations of versions
of subsystems, e.g., the head revision of a component against stable
releases of its dependencies, and vice versa, as this can reveal
various integration problems.
</listitem>
</itemizedlist>
</para>
<para>
<emphasis>Hydra</emphasis>, is a continuous integration tool
that solves these problems. It is built on top of the <link
xlink:href="http://nixos.org/nix/">Nix package manager</link>,
which has a purely functional language for describing package
build actions and their dependencies. This allows the build
environment for projects to be produced automatically and
deterministically, and variability in components to be expressed
naturally using functions; and as such is an ideal fit for a
continuous build system.
</para>
</section>
<section>
<title>About Us</title>
<para>
Hydra is the successor of the Nix Buildfarm, which was developed
in tandem with the Nix software deployment system. Nix was
originally developed at the Department of Information and
Computing Sciences, Utrecht University by the TraCE project
(2003-2008). The project was funded by the Software Engineering
Research Program Jacquard to improve the support for variability
in software systems. Funding for the development of Nix and
Hydra is now provided by the NIRICT LaQuSo Build Farm project.
</para>
</section>
<section>
<title>About this Manual</title>
<para>
This manual tells you how to install the Hydra buildfarm
software on your own server and how to operate that server using
its web interface.
</para>
</section>
<section>
<title>License</title>
<para>
Hydra is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
</para>
<para>
Hydra is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
<link xlink:href="http://www.gnu.org/licenses/">GNU General
Public License</link> for more details.
</para>
</section>
<section>
<title>Hydra at <literal>nixos.org</literal></title>
<para>
The <literal>nixos.org</literal> installation of Hydra runs at
<link
xlink:href="http://hydra.nixos.org/"><literal>http://hydra.nixos.org/</literal></link>.
That installation is used to build software components from the
<link xlink:href="http://nixos.org">Nix</link>,
<link xlink:href="http://nixos.org/nixos">NixOS</link>,
<link xlink:href="http://www.gnu.org/">GNU</link>,
<link xlink:href="http://strategoxt.org">Stratego/XT</link>,
and related projects.
</para>
<para>
If you are one of the developers on those projects, it is likely
that you will be using the NixOS Hydra server in some way. If
you need to administer automatic builds for your project, you
should pull the right strings to get an account on the
server. This manual will tell you how to set up new projects and
build jobs within those projects and write a release.nix file to
describe the build process of your project to Hydra. You can
skip the next chapter.
</para>
<para>
If your project does not yet have automatic builds within the
NixOS Hydra server, it may actually be eligible. We are in the
process of setting up a large buildfarm that should be able to
support open source and academic software projects. Get in
touch.
</para>
</section>
<section>
<title>Hydra on your own buildfarm</title>
<para>
If you need to run your own Hydra installation, <xref
linkend="chap-installation" /> explains how to download and
install the system on your own server.
</para>
</section>
</chapter>
<!--
Local Variables:
indent-tabs-mode: nil
ispell-local-dictionary: "american"
End:
-->

View File

@@ -1,69 +0,0 @@
<book xmlns="http://docbook.org/ns/docbook"
xmlns:xi="http://www.w3.org/2001/XInclude">
<info>
<title>Hydra User's Guide</title>
<subtitle>Draft</subtitle>
<authorgroup>
<author>
<personname>
<firstname>Eelco</firstname>
<surname>Dolstra</surname>
</personname>
<affiliation>
<orgname>Delft University of Technology</orgname>
<orgdiv>Department of Software Technology</orgdiv>
</affiliation>
<contrib>Author</contrib>
</author>
<author>
<personname>
<firstname>Rob</firstname>
<surname>Vermaas</surname>
</personname>
<affiliation>
<orgname>Delft University of Technology</orgname>
<orgdiv>Department of Software Technology</orgdiv>
</affiliation>
<contrib>Author</contrib>
</author>
<author>
<personname>
<firstname>Eelco</firstname>
<surname>Visser</surname>
</personname>
<affiliation>
<orgname>Delft University of Technology</orgname>
<orgdiv>Department of Software Technology</orgdiv>
</affiliation>
<contrib>Author</contrib>
</author>
<author>
<personname>
<firstname>Ludovic</firstname>
<surname>Courtès</surname>
</personname>
<contrib>Author</contrib>
</author>
</authorgroup>
<copyright>
<year>2009</year>
<year>2010</year>
<holder>Eelco Dolstra</holder>
</copyright>
<date>March 2010</date>
</info>
<xi:include href="introduction.xml" />
<xi:include href="installation.xml" />
<xi:include href="projects.xml" />
</book>

36
doc/manual/meson.build Normal file
View File

@@ -0,0 +1,36 @@
srcs = files(
'src/SUMMARY.md',
'src/about.md',
'src/api.md',
'src/configuration.md',
'src/hacking.md',
'src/installation.md',
'src/introduction.md',
'src/jobs.md',
'src/monitoring/README.md',
'src/notifications.md',
'src/plugins/README.md',
'src/plugins/RunCommand.md',
'src/plugins/declarative-projects.md',
'src/projects.md',
'src/webhooks.md',
)
manual = custom_target(
'manual',
command: [
mdbook,
'build',
'@SOURCE_ROOT@/doc/manual',
'-d', meson.current_build_dir() / 'html'
],
depend_files: srcs,
output: ['html'],
build_by_default: true,
)
install_subdir(
manual.full_path(),
install_dir: get_option('datadir') / 'doc/hydra',
strip_directory: true,
)

View File

@@ -1,523 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="chap-projects">
<title>Creating and Managing Projects</title>
<para>
Once Hydra is installed and running, the next step is to add
projects to the build farm. We follow the example of the <link
xlink:href="http://nixos.org/patchelf.html">Patchelf
project</link>, a software tool written in C and using the GNU
Build System (GNU Autoconf and GNU Automake).
</para>
<para>
Log in to the web interface of your Hydra installation using the
user name and password you inserted in the database (by default,
Hydra's web server listens on <link
xlink:href="http://localhost:3000/"><literal>localhost:3000</literal></link>).
Then follow the "Create Project" link to create a new project.
</para>
<section>
<title>Project Information</title>
<para>
A project definition consists of some general information and a
set of job sets. The general information identifies a project,
its owner, and current state of activity.
Here's what we fill in for the patchelf project:
<screen>
Identifier: patchelf
</screen>
The <emphasis>identifier</emphasis> is the identity of the
project. It is used in URLs and in the names of build results.
</para>
<para>
The identifier should be a unique name (it is the primary
database key for the project table in the database). If you try
to create a project with an already existing identifier you'd
get an error message such as:
<screen>
I'm very sorry, but an error occurred:
DBIx::Class::ResultSet::create(): DBI Exception: DBD::SQLite::st execute failed: column name is not unique(19) at dbdimp.c line 402
</screen>
So try to create the project after entering just the general
information to figure out if you have chosen a unique name.
Job sets can be added once the project has been created.
<screen>
Display name: Patchelf
</screen>
The <emphasis>display name</emphasis> is used in menus.
<screen>
Description: A tool for modifying ELF binaries
</screen>
The <emphasis>description</emphasis> is used as short
documentation of the nature of the project.
<screen>
Owner: eelco
</screen>
The <emphasis>owner</emphasis> of a project can create and edit
job sets.
<screen>
Enabled: Yes
</screen>
Only if the project is <emphasis>enabled</emphasis> are builds
performed.
</para>
<para>
Once created there should be an entry for the project in the
sidebar. Go to the project page for the <link
xlink:href="http://localhost:3000/project/patchelf">Patchelf</link>
project.
</para>
</section>
<section>
<title>Job Sets</title>
<para>
A project can consist of multiple <emphasis>job sets</emphasis>
(hereafter <emphasis>jobsets</emphasis>), separate tasks that
can be built separately, but may depend on each other (without
cyclic dependencies, of course). Go to the <link
xlink:href="http://localhost:3000/project/patchelf/edit">Edit</link>
page of the Patchelf project and "Add a new jobset" by providing
the following "Information":
<screen>
Identifier: trunk
Description: Trunk
Nix expression: release.nix in input patchelfSrc
</screen>
This states that in order to build the <literal>trunk</literal>
jobset, the Nix expression in the file
<filename>release.nix</filename>, which can be obtained from
input <literal>patchelfSrc</literal>, should be
evaluated. (We'll have a look at
<filename>release.nix</filename> later.)
</para>
<para>
To realize a job we probably need a number of inputs, which can
be declared in the table below. As many inputs as required can
be added. For patchelf we declare the following inputs.
<screen>
patchelfSrc
'Subversion checkout' https://svn.nixos.org/repos/nix/patchelf/trunk
nixpkgs 'Subversion checkout' https://svn.nixos.org/repos/nix/nixpkgs/trunk
officialRelease Boolean false
system String value "i686-linux"
</screen>
</para>
</section>
<section>
<title>Release Set</title>
<!-- TODO -->
there must be one primary job
check the radio button of exactly one job
https://svn.nixos.org/repos/nix/nixpkgs/trunk
</section>
<section>
<title>Building Jobs</title>
</section>
<section>
<title>Build Recipes</title>
<para>
Build jobs and <emphasis>build recipes</emphasis> for a jobset are
specified in a text file written in the <link
xlink:href="http://nixos.org/nix/">Nix language</link>. The
recipe is actually called a <emphasis>Nix expression</emphasis> in
Nix parlance. By convention this file is often called
<filename>release.nix</filename>.
</para>
<para>
The <filename>release.nix</filename> file is typically kept under
version control, and the repository that contains it one of the
build inputs of the correspondingoften called
<literal>hydraConfig</literal> by convention. The repository for
that file and the actual file name are specified on the web
interface of Hydra under the <literal>Setup</literal> tab of the
jobset's overview page, under the <literal>Nix
expression</literal> heading. See, for example, the <link
xlink:href="http://hydra.nixos.org/jobset/patchelf/trunk">jobset
overview page</link> of the PatchELF project, and <link
xlink:href="https://svn.nixos.org/repos/nix/patchelf/trunk/release.nix">
the corresponding Nix file</link>.
</para>
<para>
Knowledge of the Nix language is recommended, but the example
below should already give a good idea of how it works:
</para>
<example xml:id='ex-hello'>
<title><filename>release.nix</filename> file for GNU Hello</title>
<programlisting>
{ nixpkgs }: <co xml:id='ex-hello-co-nixpkgs' />
let
pkgs = import nixpkgs {}; <co xml:id='ex-hello-co-import-nixpkgs' />
jobs = rec { <co xml:id='ex-hello-co-jobs' />
tarball = <co xml:id='ex-hello-co-tarball' />
{ helloSrc }: <co xml:id='ex-hello-co-tarball-args' />
pkgs.releaseTools.sourceTarball { <co xml:id='ex-hello-co-source-tarball' />
name = "hello-tarball";
src = helloSrc;
buildInputs = (with pkgs; [ gettext texLive texinfo ]);
};
build = <co xml:id='ex-hello-co-build' />
{ tarball ? jobs.tarball {} <co xml:id='ex-hello-co-build-args' />
, system ? builtins.currentSystem
}:
let pkgs = import nixpkgs { inherit system; }; in
pkgs.releaseTools.nixBuild { <co xml:id='ex-hello-co-nix-build' />
name = "hello" ;
src = tarball;
configureFlags = [ "--disable-silent-rules" ];
};
};
in
jobs <co xml:id='ex-hello-co-body' />
</programlisting>
</example>
<para>
<xref linkend='ex-hello' /> shows what a
<filename>release.nix</filename> file for <link
xlink:href="http://www.gnu.org/software/hello/">GNU Hello</link>
would you like. GNU Hello is representative of many GNU
and non-GNU free software projects:
<itemizedlist>
<listitem>it uses the GNU Build System, namely GNU Autoconf,
and GNU Automake; for users, it means it can be installed
using the <link
xlink:href="http://www.gnu.org/prep/standards/html_node/Managing-Releases.html">usual
<literal>./configure &amp;&amp; make install</literal>
procedure</link>;
</listitem>
<listitem>it uses Gettext for internationalization;</listitem>
<listitem>it has a Texinfo manual, which can be rendered as PDF
with TeX.</listitem>
</itemizedlist>
The file defines a jobset consisting of two jobs:
<literal>tarball</literal>, and <literal>build</literal>. It
contains the following elements (referenced from the figure by
numbers):
<calloutlist>
<callout arearefs='ex-hello-co-nixpkgs'>
<para>
This specifies a function of one named arguments,
<varname>nixpkgs</varname>. This function and those
defined below is called by Hydra. Here the
<varname>nixpkgs</varname> argument is meant to be a
checkout of the <link
xlink:href="http://nixos.org/nixpkgs/">Nixpkgs</link>
software distribution.
</para>
<para>
Hydra inspects the formal argument list of the function
(here, the <varname>nixpkgs</varname> argument) and passes
it the corresponding parameter specified as a build input
on Hydra's web interface. In this case, the web interface
should show a <varname>nixpkgs</varname> build input,
which is a checkout of the Nixpkgs source code repository.
</para>
</callout>
<callout arearefs='ex-hello-co-import-nixpkgs'>
<para>
This defines a variable <varname>pkgs</varname> holding
the set of packages provided by Nixpkgs.
</para>
</callout>
<callout arearefs='ex-hello-co-jobs'>
<para>
This defines a variable holding the two Hydra
jobsan <emphasis>attribute set</emphasis> in Nix.
</para>
</callout>
<callout arearefs='ex-hello-co-tarball'>
<para>
This is the definition of the first job, named
<varname>tarball</varname>. The purpose of this job is to
produce a usable source code tarball.
</para>
</callout>
<callout arearefs='ex-hello-co-tarball-args'>
<para>
The <varname>tarball</varname> takes an additional
argument called <varname>helloSrc</varname>. Again, this
argument is passed by Hydra and is meant to be a checkout
of GNU Hello's source code repository.
</para>
</callout>
<callout arearefs='ex-hello-co-source-tarball'>
<para>
The <varname>tarball</varname> job calls the
<varname>sourceTarball</varname> function, which (roughly)
runs <command>autoreconf &amp;&amp; ./configure &amp;&amp;
make dist</command> on the checkout. The
<varname>buildInputs</varname> attribute specifies
additional software dependencies for the
job<footnote><para>The package names used in
<varname>buildInputs</varname>e.g.,
<varname>texLive</varname>are the names of the
<emphasis>attributes</emphasis> corresponding to these
packages in Nixpkgs, specifically in the <link
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/top-level/all-packages.nix"><filename>all-packages.nix</filename></link>
file. See the section entitled “Package Naming” in the
Nixpkgs manual for more information.</para></footnote>.
</para>
</callout>
<callout arearefs='ex-hello-co-build'>
<para>
This is the definition of the <varname>build</varname>
job, whose purpose is to build Hello from the tarball
produced above.
</para>
</callout>
<callout arearefs='ex-hello-co-build-args'>
<para>
The <varname>build</varname> function takes two additional
parameter: <varname>tarball</varname>, which is meant to
be the result of the <varname>tarball</varname> job, and
<varname>system</varname>, which should be a string
defining the Nix system typee.g.,
<literal>"x86_64-linux"</literal>.
</para>
<para>
Again, these parameters are passed by Hydra when it calls
<varname>build</varname>. Thus, they must be defined as
build inputs in Hydra: <varname>tarball</varname> should
have type <literal>Build Output</literal>, its value being
the latest output of the <varname>tarball</varname> job,
and <varname>system</varname> should be a string.
</para>
<para>
The question mark after <literal>tarball</literal> and
<literal>system</literal> defines default values for these
arguments, and is only useful for debugging.
</para>
</callout>
<callout arearefs='ex-hello-co-nix-build'>
<para>
The <varname>build</varname> job calls the
<varname>nixBuild</varname> function, which unpacks the
tarball, then runs <command>./configure &amp;&amp; make
&amp;&amp; make check &amp;&amp; make install</command>.
</para>
</callout>
<callout arearefs='ex-hello-co-body'>
<para>
Finally, the set of jobs is returned to Hydra, as a Nix
attribute set.
</para>
</callout>
</calloutlist>
</para>
</section>
<section>
<title>Building from the Command Line</title>
<para>
It is often useful to test a build recipe, for instance before
it is actually used by Hydra, when testing changes, or when
debugging a build issue. Since build recipes for Hydra jobsets
are just plain Nix expressions, they can be evaluated using the
standard Nix tools.
</para>
<para>
To evaluate the <varname>tarball</varname> jobset of <xref
linkend='ex-hello' />, just run:
<screen>
$ nix-build release.nix -A tarball
</screen>
However, doing this with <xref linkend='ex-hello' /> as is will
probably yield an error like this:
<screen>
error: cannot auto-call a function that has an argument without a default value (`nixpkgs')
</screen>
This is because no value was specified for the
<varname>nixpkgs</varname> argument of the Nix expression.
</para>
<para>
This is fixed by providing a default value for that argument in
the Nix expression, which will allow <command>nix-build</command>
to auto-call the function: instfead of writing <literal>{ nixpkgs
}:</literal>, we now write <literal>{ nixpkgs ? &lt;nixpkgs&gt;
}:</literal>. What it means is that, by default, the
<varname>nixpkgs</varname> variable will be bound to the absolute
path of any <filename>nixpkgs</filename> file found in the Nix
search path. Similarly, a default value for
<varname>helloSrc</varname> needs to be provided.
</para>
<para>
Thus, assuming a checkout of Nixpkgs is available under
<filename>$HOME/src/nixpkgs</filename>, the
<varname>tarball</varname> jobset can now be evaluated by running:
<screen>
$ nix-build -I ~/src release.nix -A tarball
</screen>
Similarly, the <varname>build</varname> jobset can be evaluated:
<screen>
$ nix-build -I ~/src release.nix -A build
</screen>
The <varname>build</varname> job reuses the result of the
<varname>tarball</varname> job, rebuilding it only if it needs to.
</para>
</section>
<section>
<title>Adding More Jobs</title>
<para>
<xref linkend='ex-hello' /> illustrates how to write the most
basic jobs, <varname>tarball</varname> and
<varname>build</varname>. In practice, much more can be done by
using features readily provided by Nixpkgs or by creating new jobs
as customizations of existing jobs.
</para>
<para>
For instance, test coverage report for projects compiled with GCC
can be automatically generated using the
<varname>coverageAnalysis</varname> function provided by Nixpkgs
instead of <varname>nixBuild</varname>. Back to our GNU Hello
example, we can define a <varname>coverage</varname> job that
produces an HTML code coverage report directly readable from the
corresponding Hydra build page:
<programlisting>
coverage =
{ tarball ? jobs.tarball {}
, system ? builtins.currentSystem
}:
let pkgs = import nixpkgs { inherit system; }; in
pkgs.releaseTools.coverageAnalysis {
name = "hello" ;
src = tarball;
configureFlags = [ "--disable-silent-rules" ];
}; </programlisting>
As can be seen, the only difference compared to
<varname>build</varname> is the use of
<varname>coverageAnalysis</varname>.
</para>
<para>
Nixpkgs provides many more build tools, including the ability to
run build in virtual machines, which can themselves run another
GNU/Linux distribution, which allows for the creation of packages
for these distributions. Please see <link
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/build-support/release/">the
<filename>pkgs/build-support/release</filename> directory</link>
of Nixpkgs for more. The NixOS manual also contains information
about whole-system testing in virtual machine.
</para>
<para>
Now, assume we want to build Hello with an old version of GCC, and
with different <command>configure</command> flags. A new
<varname>build_exotic</varname> job can be written that simply
<emphasis>overrides</emphasis> the relevant arguments passed to
<varname>nixBuild</varname>:
<programlisting>
build_exotic =
{ tarball ? jobs.tarball {}
, system ? builtins.currentSystem
}:
let
pkgs = import nixpkgs { inherit system; };
build = jobs.build { inherit tarball system; };
in
pkgs.lib.overrideDerivation build (attrs: {
buildInputs = [ pkgs.gcc33 ];
preConfigure = "gcc --version";
configureFlags =
attrs.configureFlags ++ [ "--disable-nls" ];
}); </programlisting>
The <varname>build_exotic</varname> job reuses
<varname>build</varname> and overrides some of its arguments: it
adds a dependency on GCC 3.3, a pre-configure phase that runs
<command>gcc --version</command>, and adds the
<literal>--disable-nls</literal> configure flags.
</para>
<para>
This customization mechanism is very powerful. For instance, it
can be used to change the way Hello and <emphasis>all</emphasis>
its dependenciesincluding the C library and compiler used to
build itare built. See the Nixpkgs manual for more.
</para>
</section>
</chapter>
<!--
Local Variables:
indent-tabs-mode: nil
ispell-local-dictionary: "american"
End:
-->

20
doc/manual/src/SUMMARY.md Normal file
View File

@@ -0,0 +1,20 @@
# Hydra User's Guide
- [Introduction](introduction.md)
- [Installation](installation.md)
- [Configuration](configuration.md)
- [Creating and Managing Projects](projects.md)
- [Hydra jobs](./jobs.md)
- [Plugins](./plugins/README.md)
- [Declarative Projects](./plugins/declarative-projects.md)
- [RunCommand](./plugins/RunCommand.md)
- [Using the external API](api.md)
- [Webhooks](webhooks.md)
- [Webhook Authentication Migration Guide](webhook-migration-guide.md)
- [Monitoring Hydra](./monitoring/README.md)
## Developer's Guide
- [Hacking](hacking.md)
- [Hydra Notifications](notifications.md)
-----------
[About](about.md)

6
doc/manual/src/about.md Normal file
View File

@@ -0,0 +1,6 @@
# Authors
* Eelco Dolstra, Delft University of Technology, Department of Software Technology
* Rob Vermaas, Delft University of Technology, Department of Software Technology
* Eelco Visser, Delft University of Technology, Department of Software Technology
* Ludovic Courtès

249
doc/manual/src/api.md Normal file
View File

@@ -0,0 +1,249 @@
Using the external API
======================
To be able to create integrations with other services, Hydra exposes an
external API that you can manage projects with.
The API is accessed over HTTP(s) where all data is sent and received as
JSON.
Creating resources requires the caller to be authenticated, while
retrieving resources does not.
The API does not have a separate URL structure for it\'s endpoints.
Instead you request the pages of the web interface as `application/json`
to use the API.
List projects
-------------
To list all the `projects` of the Hydra install:
GET /
Accept: application/json
This will give you a list of `projects`, where each `project` contains
general information and a list of its `job sets`.
**Example**
curl -i -H 'Accept: application/json' \
https://hydra.nixos.org
**Note:** this response is truncated
GET https://hydra.nixos.org/
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"displayname": "Acoda",
"name": "acoda",
"description": "Acoda is a tool set for automatic data migration along an evolving data model",
"enabled": 0,
"owner": "sander",
"hidden": 1,
"jobsets": [
"trunk"
]
},
{
"displayname": "cabal2nix",
"name": "cabal2nix",
"description": "Convert Cabal files into Nix build instructions",
"enabled": 0,
"owner": "simons@cryp.to",
"hidden": 1,
"jobsets": [
"master"
]
}
]
Get a single project
--------------------
To get a single `project` by identifier:
GET /project/:project-identifier
Accept: application/json
**Example**
curl -i -H 'Accept: application/json' \
https://hydra.nixos.org/project/hydra
GET https://hydra.nixos.org/project/hydra
HTTP/1.1 200 OK
Content-Type: application/json
{
"description": "Hydra, the Nix-based continuous build system",
"hidden": 0,
"displayname": "Hydra",
"jobsets": [
"hydra-master",
"hydra-ant-logger-trunk",
"master",
"build-ng"
],
"name": "hydra",
"enabled": 1,
"owner": "eelco"
}
Get a single job set
--------------------
To get a single `job set` by identifier:
GET /jobset/:project-identifier/:jobset-identifier
Content-Type: application/json
**Example**
curl -i -H 'Accept: application/json' \
https://hydra.nixos.org/jobset/hydra/build-ng
GET https://hydra.nixos.org/jobset/hydra/build-ng
HTTP/1.1 200 OK
Content-Type: application/json
{
"errormsg": "evaluation failed due to signal 9 (Killed)",
"fetcherrormsg": null,
"nixexprpath": "release.nix",
"nixexprinput": "hydraSrc",
"emailoverride": "rob.vermaas@gmail.com, eelco.dolstra@logicblox.com",
"jobsetinputs": {
"officialRelease": {
"jobsetinputalts": [
"false"
]
},
"hydraSrc": {
"jobsetinputalts": [
"https://github.com/NixOS/hydra.git build-ng"
]
},
"nixpkgs": {
"jobsetinputalts": [
"https://github.com/NixOS/nixpkgs.git release-14.12"
]
}
},
"enabled": 0
}
List evaluations
----------------
To list the `evaluations` of a `job set` by identifier:
GET /jobset/:project-identifier/:jobset-identifier/evals
Content-Type: application/json
**Example**
curl -i -H 'Accept: application/json' \
https://hydra.nixos.org/jobset/hydra/build-ng/evals
**Note:** this response is truncated
GET https://hydra.nixos.org/jobset/hydra/build-ng/evals
HTTP/1.1 200 OK
Content-Type: application/json
{
"evals": [
{
"jobsetevalinputs": {
"nixpkgs": {
"dependency": null,
"type": "git",
"value": null,
"uri": "https://github.com/NixOS/nixpkgs.git",
"revision": "f60e48ce81b6f428d072d3c148f6f2e59f1dfd7a"
},
"hydraSrc": {
"dependency": null,
"type": "git",
"value": null,
"uri": "https://github.com/NixOS/hydra.git",
"revision": "48d6f0de2ab94f728d287b9c9670c4d237e7c0f6"
},
"officialRelease": {
"dependency": null,
"value": "false",
"type": "boolean",
"uri": null,
"revision": null
}
},
"hasnewbuilds": 1,
"builds": [
24670686,
24670684,
24670685,
24670687
],
"id": 1213758
}
],
"first": "?page=1",
"last": "?page=1"
}
Get a single build
------------------
To get a single `build` by its id:
GET /build/:build-id
Content-Type: application/json
**Example**
curl -i -H 'Accept: application/json' \
https://hydra.nixos.org/build/24670686
GET /build/24670686
HTTP/1.1 200 OK
Content-Type: application/json
{
"job": "tests.api.x86_64-linux",
"jobsetevals": [
1213758
],
"buildstatus": 0,
"buildmetrics": null,
"project": "hydra",
"system": "x86_64-linux",
"priority": 100,
"releasename": null,
"starttime": 1439402853,
"nixname": "vm-test-run-unnamed",
"timestamp": 1439388618,
"id": 24670686,
"stoptime": 1439403403,
"jobset": "build-ng",
"buildoutputs": {
"out": {
"path": "/nix/store/lzrxkjc35mhp8w7r8h82g0ljyizfchma-vm-test-run-unnamed"
}
},
"buildproducts": {
"1": {
"path": "/nix/store/lzrxkjc35mhp8w7r8h82g0ljyizfchma-vm-test-run-unnamed",
"defaultpath": "log.html",
"type": "report",
"sha256hash": null,
"filesize": null,
"name": "",
"subtype": "testlog"
}
},
"finished": 1
}

View File

@@ -0,0 +1,310 @@
Configuration
=============
This chapter is a collection of configuration snippets for different
scenarios.
The configuration is parsed by `Config::General` which has [a pretty
thorough documentation on their file format](https://metacpan.org/pod/Config::General#CONFIG-FILE-FORMAT).
Hydra calls the parser with the following options:
- `-UseApacheInclude => 1`
- `-IncludeAgain => 1`
- `-IncludeRelative => 1`
Including files
---------------
`hydra.conf` supports Apache-style includes. This is **IMPORTANT**
because that is how you keep your **secrets** out of the **Nix store**.
Hopefully this got your attention 😌
This:
```
<github_authorization>
NixOS = Bearer gha-secret😱secret😱secret😱
</github_authorization>
```
should **NOT** be in `hydra.conf`.
`hydra.conf` is rendered in the Nix store and is therefore world-readable.
Instead, the above should be written to a file outside the Nix store by
other means (manually, using Nixops' secrets feature, etc) and included
like so:
```
Include /run/keys/hydra/github_authorizations.conf
```
Serving behind reverse proxy
----------------------------
To serve hydra web server behind reverse proxy like *nginx* or *httpd*
some additional configuration must be made.
Edit your `hydra.conf` file in a similar way to this example:
```conf
using_frontend_proxy 1
base_uri example.com
```
`base_uri` should be your hydra servers proxied URL. If you are using
Hydra nixos module then setting `hydraURL` option should be enough.
You also need to configure your reverse proxy to pass `X-Request-Base`
to hydra, with the same value as `base_uri`.
This also covers the case of serving Hydra with a prefix path,
as in [http://example.com/hydra]().
For example if you are using nginx, then use configuration similar to
following:
server {
listen 433 ssl;
server_name example.com;
.. other configuration ..
location /hydra/ {
proxy_pass http://127.0.0.1:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Request-Base /hydra;
}
}
Note the trailing slash on the `proxy_pass` directive, which causes nginx to
strip off the `/hydra/` part of the URL before passing it to hydra.
Populating a Cache
------------------
A common use for Hydra is to pre-build and cache derivations which
take a long time to build. While it is possible to direcly access the
Hydra server's store over SSH, a more scalable option is to upload
built derivations to a remote store like an [S3-compatible object
store](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-help-stores.html#s3-binary-cache-store). Setting
the `store_uri` parameter will cause Hydra to sign and upload
derivations as they are built:
```
store_uri = s3://cache-bucket-name?compression=zstd&parallel-compression=true&write-nar-listing=1&ls-compression=br&log-compression=br&secret-key=/path/to/cache/private/key
```
This example uses [Zstandard](https://github.com/facebook/zstd)
compression on derivations to reduce CPU usage on the server, but
[Brotli](https://brotli.org/) compression for derivation listings and
build logs because it has better browser support.
See [`nix help
stores`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-help-stores.html)
for a description of the store URI format.
Statsd Configuration
--------------------
By default, Hydra will send stats to statsd at `localhost:8125`. Point Hydra to a different server via:
```
<statsd>
host = alternative.host
port = 18125
</statsd>
```
hydra-notify's Prometheus service
---------------------------------
hydra-notify supports running a Prometheus webserver for metrics. The
exporter does not run unless a listen address and port are specified
in the hydra configuration file, as below:
```conf
<hydra_notify>
<prometheus>
listen_address = 127.0.0.1
port = 9199
</prometheus>
</hydra_notify>
```
hydra-queue-runner's Prometheus service
---------------------------------------
hydra-queue-runner supports running a Prometheus webserver for metrics. The
exporter's address defaults to exposing on `127.0.0.1:9198`, but is also
configurable through the hydra configuration file and a command line argument,
as below. A port of `:0` will make the exposer choose a random, available port.
```conf
queue_runner_metrics_address = 127.0.0.1:9198
# or
queue_runner_metrics_address = [::]:9198
```
```shell
$ hydra-queue-runner --prometheus-address 127.0.0.1:9198
# or
$ hydra-queue-runner --prometheus-address [::]:9198
```
Using LDAP as authentication backend (optional)
-----------------------------------------------
Instead of using Hydra's built-in user management you can optionally
use LDAP to manage roles and users.
This is configured by defining the `<ldap>` block in the configuration file.
In this block it's possible to configure the authentication plugin in the
`<config>` block. All options are directly passed to `Catalyst::Authentication::Store::LDAP`.
The documentation for the available settings can be found
[here](https://metacpan.org/pod/Catalyst::Authentication::Store::LDAP#CONFIGURATION-OPTIONS).
Note that the bind password (if needed) should be supplied as an included file to
prevent it from leaking to the Nix store.
Roles can be assigned to users based on their LDAP group membership. For this
to work *use\_roles = 1* needs to be defined for the authentication plugin.
LDAP groups can then be mapped to Hydra roles using the `<role_mapping>` block.
Example configuration:
```
<ldap>
<config>
<credential>
class = Password
password_field = password
password_type = self_check
</credential>
<store>
class = LDAP
ldap_server = localhost
<ldap_server_options>
timeout = 30
</ldap_server_options>
binddn = "cn=root,dc=example"
include ldap-password.conf
start_tls = 0
<start_tls_options>
verify = none
</start_tls_options>
user_basedn = "ou=users,dc=example"
user_filter = "(&(objectClass=inetOrgPerson)(cn=%s))"
user_scope = one
user_field = cn
<user_search_options>
deref = always
</user_search_options>
# Important for role mappings to work:
use_roles = 1
role_basedn = "ou=groups,dc=example"
role_filter = "(&(objectClass=groupOfNames)(member=%s))"
role_scope = one
role_field = cn
role_value = dn
<role_search_options>
deref = always
</role_search_options>
</store>
</config>
<role_mapping>
# Make all users in the hydra_admin group Hydra admins
hydra_admin = admin
# Allow all users in the dev group to eval jobsets, restart jobs and cancel builds
dev = eval-jobset
dev = restart-jobs
dev = cancel-build
</role_mapping>
</ldap>
```
Then, place the password to your LDAP server in `/var/lib/hydra/ldap-password.conf`:
```
bindpw = the-ldap-password
```
### Debugging LDAP
Set the `debug` parameter under `ldap.config.ldap_server_options.debug`:
```
<ldap>
<config>
<store>
<ldap_server_options>
debug = 2
</ldap_server_options>
</store>
</config>
</ldap>
```
### Legacy LDAP Configuration
Hydra used to load the LDAP configuration from a YAML file in the
`HYDRA_LDAP_CONFIG` environment variable. This behavior is deperecated
and will be removed.
When Hydra uses the deprecated YAML file, Hydra applies the following
default role mapping:
```
<ldap>
<role_mapping>
hydra_admin = admin
hydra_bump-to-front = bump-to-front
hydra_cancel-build = cancel-build
hydra_create-projects = create-projects
hydra_restart-jobs = restart-jobs
</role_mapping>
</ldap>
```
Note that configuring both the LDAP parameters in the hydra.conf and via
the environment variable is a fatal error.
Webhook Authentication
---------------------
Hydra supports authenticating webhook requests from GitHub and Gitea to prevent unauthorized job evaluations.
Webhook secrets should be stored in separate files outside the Nix store for security using Config::General's include mechanism.
In your main `hydra.conf`:
```apache
<webhooks>
Include /var/lib/hydra/secrets/webhook-secrets.conf
</webhooks>
```
Then create `/var/lib/hydra/secrets/webhook-secrets.conf` with your actual secrets:
```apache
<github>
secret = your-github-webhook-secret
</github>
<gitea>
secret = your-gitea-webhook-secret
</gitea>
```
For multiple secrets (useful for rotation or multiple environments), use an array:
```apache
<github>
secret = your-github-webhook-secret-prod
secret = your-github-webhook-secret-staging
</github>
```
**Important**: The secrets file should have restricted permissions (e.g., 0600) to prevent unauthorized access.
See the [Webhooks documentation](webhooks.md) for detailed setup instructions.
Embedding Extra HTML
--------------------
Embed an analytics widget or other HTML in the `<head>` of each HTML document via:
```conf
tracker = <script src="...">
```

108
doc/manual/src/hacking.md Normal file
View File

@@ -0,0 +1,108 @@
# Hacking
This section provides some notes on how to hack on Hydra. To get the
latest version of Hydra from GitHub:
```console
$ git clone git://github.com/NixOS/hydra.git
$ cd hydra
```
To enter a shell in which all environment variables (such as `PERL5LIB`)
and dependencies can be found:
```console
$ nix develop
```
To build Hydra, you should then do:
```console
$ mesonConfigurePhase
$ ninja
```
You start a local database, the webserver, and other components with
foreman:
```console
$ ninja -C build
$ foreman start
```
The Hydra interface will be available on port 63333, with an admin user named "alice" with password "foobar"
You can run just the Hydra web server in your source tree as follows:
```console
$ ./src/script/hydra-server
```
You can run Hydra's test suite with the following:
```console
$ meson test
# to run as many tests as you have cores:
$ YATH_JOB_COUNT=$NIX_BUILD_CORES meson test
```
To run individual tests:
```console
# Run a specific test file
$ PERL5LIB=t/lib:$PERL5LIB perl t/test.pl t/Hydra/Controller/API/checks.t
# Run all tests in a directory
$ PERL5LIB=t/lib:$PERL5LIB perl t/test.pl t/Hydra/Controller/API/
```
**Warning**: Currently, the tests can fail
if run with high parallelism [due to an issue in
`Test::PostgreSQL`](https://github.com/TJC/Test-postgresql/issues/40)
causing database ports to collide.
## Working on the Manual
By default, `foreman start` runs mdbook in "watch" mode. mdbook listens
at [http://localhost:63332/](http://localhost:63332/), and
will reload the page every time you save.
## Building
To build Hydra and its dependencies:
```console
$ nix build .#packages.x86_64-linux.default
```
## Development Tasks
### Connecting to the database
Assuming you're running the default configuration with `foreman start`,
open an interactive session with Postgres via:
```console
$ psql --host localhost --port 64444 hydra
```
### Runinng the builder locally
For `hydra-queue-runner` to successfully build locally, your
development user will need to be "trusted" by your Nix store.
Add yourself to the `trusted_users` option of `/etc/nix/nix.conf`.
On NixOS:
```nix
{
nix.settings.trusted-users = [ "YOURUSER" ];
}
```
Off NixOS, change `/etc/nix/nix.conf`:
```conf
trusted-users = root YOURUSERNAME
```

View File

@@ -0,0 +1,165 @@
Installation
============
This chapter explains how to install Hydra on your own build farm
server.
Prerequisites
-------------
To install and use Hydra you need to have installed the following
dependencies:
- Nix
- PostgreSQL
- many Perl packages, notably Catalyst, EmailSender, and NixPerl (see
the [Hydra expression in
Nixpkgs](https://github.com/NixOS/hydra/blob/master/release.nix) for
the complete list)
At the moment, Hydra runs only on GNU/Linux (*i686-linux* and
*x86\_64\_linux*).
For small projects, Hydra can be run on any reasonably modern machine.
For individual projects you can even run Hydra on a laptop. However, the
charm of a buildfarm server is usually that it operates without
disturbing the developer\'s working environment and can serve releases
over the internet. In conjunction you should typically have your source
code administered in a version management system, such as subversion.
Therefore, you will probably want to install a server that is connected
to the internet. To scale up to large and/or many projects, you will
need at least a considerable amount of diskspace to store builds. Since
Hydra can schedule multiple simultaneous build jobs, it can be useful to
have a multi-core machine, and/or attach multiple build machines in a
network to the central Hydra server.
Of course we think it is a good idea to use the
[NixOS](http://nixos.org/nixos) GNU/Linux distribution for your
buildfarm server. But this is not a requirement. The Nix software
deployment system can be installed on any GNU/Linux distribution in
parallel to the regular package management system. Thus, you can use
Hydra on a Debian, Fedora, SuSE, or Ubuntu system.
Getting Nix
-----------
If your server runs NixOS you are all set to continue with installation
of Hydra. Otherwise you first need to install Nix. The latest stable
version can be found one [the Nix web
site](https://nixos.org/download/), along with a manual, which
includes installation instructions.
Installation
------------
The latest development snapshot of Hydra can be installed by visiting
the URL
[`http://hydra.nixos.org/view/hydra/unstable`](http://hydra.nixos.org/view/hydra/unstable)
and using the one-click install available at one of the build pages. You
can also install Hydra through the channel by performing the following
commands:
nix-channel --add http://hydra.nixos.org/jobset/hydra/master/channel/latest
nix-channel --update
nix-env -i hydra
Command completion should reveal a number of command-line tools from
Hydra, such as `hydra-queue-runner`.
Creating the database
---------------------
Hydra stores its results in a PostgreSQL database.
To setup a PostgreSQL database with *hydra* as database name and user
name, issue the following commands on the PostgreSQL server:
```console
createuser -S -D -R -P hydra
createdb -O hydra hydra
```
Note that *\$prefix* is the location of Hydra in the nix store.
Hydra uses an environment variable to know which database should be
used, and a variable which point to a location that holds some state. To
set these variables for a PostgreSQL database, add the following to the
file `~/.profile` of the user running the Hydra services.
```console
export HYDRA_DBI="dbi:Pg:dbname=hydra;host=dbserver.example.org;user=hydra;"
export HYDRA_DATA=/var/lib/hydra
```
You can provide the username and password in the file `~/.pgpass`, e.g.
```
dbserver.example.org:*:hydra:hydra:password
```
Make sure that the *HYDRA\_DATA* directory exists and is writable for
the user which will run the Hydra services.
Having set these environment variables, you can now initialise the
database by doing:
```console
hydra-init
```
To create projects, you need to create a user with *admin* privileges.
This can be done using the command `hydra-create-user`:
```console
$ hydra-create-user alice --full-name 'Alice Q. User' \
--email-address 'alice@example.org' --password-prompt --role admin
```
Additional users can be created through the web interface.
Upgrading
---------
If you\'re upgrading Hydra from a previous version, you should do the
following to perform any necessary database schema migrations:
```console
hydra-init
```
Getting Started
---------------
To start the Hydra web server, execute:
```console
hydra-server
```
When the server is started, you can browse to [http://localhost:3000/]()
to start configuring your Hydra instance.
The `hydra-server` command launches the web server. There are two other
processes that come into play:
- The
evaluator
is responsible for periodically evaluating job sets, checking out
their dependencies off their version control systems (VCS), and
queueing new builds if the result of the evaluation changed. It is
launched by the
hydra-evaluator
command.
- The
queue runner
launches builds (using Nix) as they are queued by the evaluator,
scheduling them onto the configured Nix hosts. It is launched using
the
hydra-queue-runner
command.
All three processes must be running for Hydra to be fully functional,
though it\'s possible to temporarily stop any one of them for
maintenance purposes, for instance.

View File

@@ -0,0 +1,173 @@
Introduction
============
About Hydra
-----------
Hydra is a tool for continuous integration testing and software release
that uses a purely functional language to describe build jobs and their
dependencies. Continuous integration is a simple technique to improve
the quality of the software development process. An automated system
continuously or periodically checks out the source code of a project,
builds it, runs tests, and produces reports for the developers. Thus,
various errors that might accidentally be committed into the code base
are automatically caught. Such a system allows more in-depth testing
than what developers could feasibly do manually:
- Portability testing
: The software may need to be built and tested on many different
platforms. It is infeasible for each developer to do this before
every commit.
- Likewise, many projects have very large test sets (e.g., regression
tests in a compiler, or stress tests in a DBMS) that can take hours
or days to run to completion.
- Many kinds of static and dynamic analyses can be performed as part
of the tests, such as code coverage runs and static analyses.
- It may also be necessary to build many different
variants
of the software. For instance, it may be necessary to verify that
the component builds with various versions of a compiler.
- Developers typically use incremental building to test their changes
(since a full build may take too long), but this is unreliable with
many build management tools (such as Make), i.e., the result of the
incremental build might differ from a full build.
- It ensures that the software can be built from the sources under
revision control. Users of version management systems such as CVS
and Subversion often forget to place source files under revision
control.
- The machines on which the continuous integration system runs ideally
provides a clean, well-defined build environment. If this
environment is administered through proper SCM techniques, then
builds produced by the system can be reproduced. In contrast,
developer work environments are typically not under any kind of SCM
control.
- In large projects, developers often work on a particular component
of the project, and do not build and test the composition of those
components (again since this is likely to take too long). To prevent
the phenomenon of \`\`big bang integration\'\', where components are
only tested together near the end of the development process, it is
important to test components together as soon as possible (hence
continuous integration
).
- It allows software to be
released
by automatically creating packages that users can download and
install. To do this manually represents an often prohibitive amount
of work, as one may want to produce releases for many different
platforms: e.g., installers for Windows and Mac OS X, RPM or Debian
packages for certain Linux distributions, and so on.
In its simplest form, a continuous integration tool sits in a loop
building and releasing software components from a version management
system. For each component, it performs the following tasks:
- It obtains the latest version of the component\'s source code from
the version management system.
- It runs the component\'s build process (which presumably includes
the execution of the component\'s test set).
- It presents the results of the build (such as error logs and
releases) to the developers, e.g., by producing a web page.
Examples of continuous integration tools include Jenkins, CruiseControl
Tinderbox, Sisyphus, Anthill and BuildBot. These tools have various
limitations.
- They do not manage the
build environment
. The build environment consists of the dependencies necessary to
perform a build action, e.g., compilers, libraries, etc. Setting up
the environment is typically done manually, and without proper SCM
control (so it may be hard to reproduce a build at a later time).
Manual management of the environment scales poorly in the number of
configurations that must be supported. For instance, suppose that we
want to build a component that requires a certain compiler X. We
then have to go to each machine and install X. If we later need a
newer version of X, the process must be repeated all over again. An
ever worse problem occurs if there are conflicting, mutually
exclusive versions of the dependencies. Thus, simply installing the
latest version is not an option. Of course, we can install these
components in different directories and manually pass the
appropriate paths to the build processes of the various components.
But this is a rather tiresome and error-prone process.
- They do not easily support
variability in software systems
. A system may have a great deal of build-time variability: optional
functionality, whether to build a debug or production version,
different versions of dependencies, and so on. (For instance, the
Linux kernel now has over 2,600 build-time configuration switches.)
It is therefore important that a continuous integration tool can
easily select and test different instances from the configuration
space of the system to reveal problems, such as erroneous
interactions between features. In a continuous integration setting,
it is also useful to test different combinations of versions of
subsystems, e.g., the head revision of a component against stable
releases of its dependencies, and vice versa, as this can reveal
various integration problems.
*Hydra*, is a continuous integration tool that solves these problems. It
is built on top of the [Nix package manager](http://nixos.org/nix/),
which has a purely functional language for describing package build
actions and their dependencies. This allows the build environment for
projects to be produced automatically and deterministically, and
variability in components to be expressed naturally using functions; and
as such is an ideal fit for a continuous build system.
About Us
--------
Hydra is the successor of the Nix Buildfarm, which was developed in
tandem with the Nix software deployment system. Nix was originally
developed at the Department of Information and Computing Sciences,
Utrecht University by the TraCE project (2003-2008). The project was
funded by the Software Engineering Research Program Jacquard to improve
the support for variability in software systems. Funding for the
development of Nix and Hydra is now provided by the NIRICT LaQuSo Build
Farm project.
About this Manual
-----------------
This manual tells you how to install the Hydra buildfarm software on
your own server and how to operate that server using its web interface.
License
-------
Hydra is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your
option) any later version.
Hydra is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the [GNU General Public
License](http://www.gnu.org/licenses/) for more details.
Hydra at `nixos.org`
--------------------
The `nixos.org` installation of Hydra runs at
[`http://hydra.nixos.org/`](http://hydra.nixos.org/). That installation
is used to build software components from the [Nix](http://nixos.org),
[NixOS](http://nixos.org/nixos), [GNU](http://www.gnu.org/),
[Stratego/XT](http://strategoxt.org), and related projects.
If you are one of the developers on those projects, it is likely that
you will be using the NixOS Hydra server in some way. If you need to
administer automatic builds for your project, you should pull the right
strings to get an account on the server. This manual will tell you how
to set up new projects and build jobs within those projects and write a
release.nix file to describe the build process of your project to Hydra.
You can skip the next chapter.
If your project does not yet have automatic builds within the NixOS
Hydra server, it may actually be eligible. We are in the process of
setting up a large buildfarm that should be able to support open source
and academic software projects. Get in touch.
Hydra on your own buildfarm
---------------------------
If you need to run your own Hydra installation,
[installation chapter](installation.md) explains how to download and install the
system on your own server.

21
doc/manual/src/jobs.md Normal file
View File

@@ -0,0 +1,21 @@
# Hydra Jobs
## Derivation Attributes
Hydra stores the following job attributes in its database:
* `nixName` - the Derivation's `name` attribute
* `system` - the Derivation's `system` attribute
* `drvPath` - the Derivation's path in the Nix store
* `outputs` - A JSON dictionary of output names and their store path.
### Meta fields
* `description` - `meta.description`, a string
* `license` - a comma separated list of license names from `meta.license`, expected to be a list of attribute sets with an attribute named `shortName`, ex: `[ { shortName = "licensename"} ]`.
* `homepage` - `meta.homepage`, a string
* `maintainers` - a comma separated list of maintainer email addresses from `meta.maintainers`, expected to be a list of attribute sets with an attribute named `email`, ex: `[ { email = "alice@example.com"; } ]`.
* `schedulingPriority` - `meta.schedulingPriority`, an integer. Default: 100. Slightly prioritizes this job over other jobs within this jobset.
* `timeout` - `meta.timeout`, an integer. Default: 36000. Number of seconds this job must complete within.
* `maxSilent` - `meta.maxSilent`, an integer. Default: 7200. Number of seconds of no output on stderr / stdout before considering the job failed.
* `isChannel` - `meta.isHydraChannel`, bool. Default: false. Deprecated.

View File

@@ -0,0 +1,33 @@
# Monitoring Hydra
## Webserver
The webserver exposes Prometheus metrics for the webserver itself at `/metrics`.
## Queue Runner
The queue runner's status is exposed at `/queue-runner-status`:
```console
$ curl --header "Accept: application/json" http://localhost:63333/queue-runner-status
... JSON payload ...
```
## Notification Daemon
The `hydra-notify` process can expose Prometheus metrics for plugin execution. See
[hydra-notify's Prometheus service](../configuration.md#hydra-notifys-prometheus-service)
for details on enabling and configuring the exporter.
The notification exporter exposes metrics on a per-plugin, per-event-type basis: execution
durations, frequency, successes, and failures.
### Diagnostic Dump
The notification daemon can also dump its metrics to stderr whether or not the exporter
is configured. This is particularly useful for cases where metrics data is needed but the
exporter was not enabled.
To trigger this diagnostic dump, send a Postgres notification with the
`hydra_notify_dump_metrics` channel and no payload. See
[Re-sending a notification](../notifications.md#re-sending-a-notification).

View File

@@ -0,0 +1,87 @@
# `hydra-notify` and Hydra's Notifications
Hydra uses a notification-based subsystem to implement some features and support plugin development. Notifications are sent to `hydra-notify`, which is responsible for dispatching each notification to each plugin.
Notifications are passed from `hydra-queue-runner` to `hydra-notify` through Postgres's `NOTIFY` and `LISTEN` feature.
## Notification Types
Note that the notification format is subject to change and should not be considered an API. Integrate with `hydra-notify` instead of listening directly.
### `cached_build_finished`
* **Payload:** Exactly two values, tab separated: The ID of the evaluation which contains the finished build, followed by the ID of the finished build.
* **When:** Issued directly after an evaluation completes, when that evaluation includes this finished build.
* **Delivery Semantics:** At most once per evaluation.
### `cached_build_queued`
* **Payload:** Exactly two values, tab separated: The ID of the evaluation which contains the finished build, followed by the ID of the queued build.
* **When:** Issued directly after an evaluation completes, when that evaluation includes this queued build.
* **Delivery Semantics:** At most once per evaluation.
### `build_queued`
* **Payload:** Exactly one value, the ID of the build.
* **When:** Issued after the transaction inserting the build in to the database is committed. One notification is sent per new build.
* **Delivery Semantics:** Ephemeral. `hydra-notify` must be running to react to this event. No record of this event is stored.
### `build_started`
* **Payload:** Exactly one value, the ID of the build.
* **When:** Issued directly before building happens, and only if the derivation's outputs cannot be substituted.
* **Delivery Semantics:** Ephemeral. `hydra-notify` must be running to react to this event. No record of this event is stored.
### `step_finished`
* **Payload:** Three values, tab separated: The ID of the build which the step is part of, the step number, and the path on disk to the log file.
* **When:** Issued directly after a step completes, regardless of success. Is not issued if the step's derivation's outputs can be substituted.
* **Delivery Semantics:** Ephemeral. `hydra-notify` must be running to react to this event. No record of this event is stored.
### `build_finished`
* **Payload:** At least one value, tab separated: The ID of the build which finished, followed by IDs of all of the builds which also depended upon this build.
* **When:** Issued directly after a build completes, regardless of success and substitutability.
* **Delivery Semantics:** At least once.
`hydra-notify` will call `buildFinished` for each plugin in two ways:
* The `builds` table's `notificationspendingsince` column stores when the build finished. On startup, `hydra-notify` will query all builds with a non-null `notificationspendingsince` value and treat each row as a received `build_finished` event.
* Additionally, `hydra-notify` subscribes to `build_finished` events and processes them in real time.
After processing, the row's `notificationspendingsince` column is set to null.
It is possible for subsequent deliveries of the same `build_finished` data to imply different outcomes. For example, if the build fails, is restarted, and then succeeds. In this scenario the `build_finished` events will be delivered at least twice, once for the failure and then once for the success.
### `eval_started`
* **Payload:** Exactly two values, tab separated: an opaque trace ID representing this evaluation, and the ID of the jobset.
* **When:** At the beginning of the evaluation phase for the jobset, before any work is done.
* **Delivery Semantics:** Ephemeral. `hydra-notify` must be running to react to this event. No record of this event is stored.
### `eval_added`
* **Payload:** Exactly three values, tab separated: an opaque trace ID representing this evaluation, the ID of the jobset, and the ID of the JobsetEval record.
* **When:** After the evaluator fetches inputs and completes the evaluation successfully.
* **Delivery Semantics:** Ephemeral. `hydra-notify` must be running to react to this event. No record of this event is stored.
### `eval_cached`
* **Payload:** Exactly three values: an opaque trace ID representing this evaluation, the ID of the jobset, and the ID of the previous identical evaluation.
* **When:** After the evaluator fetches inputs, if none of the inputs changed.
* **Delivery Semantics:** Ephemeral. `hydra-notify` must be running to react to this event. No record of this event is stored.
### `eval_failed`
* **Payload:** Exactly two values: an opaque trace ID representing this evaluation, and the ID of the jobset.
* **When:** After any fetching any input fails, or any other evaluation error occurs.
* **Delivery Semantics:** Ephemeral. `hydra-notify` must be running to react to this event. No record of this event is stored.
## Development Notes
### Re-sending a notification
Notifications can be experimentally re-sent on the command line with `psql`, with `NOTIFY $notificationname, '$payload'`.

View File

@@ -0,0 +1,278 @@
# Plugins
This chapter describes all plugins present in Hydra.
### Inputs
Hydra supports the following inputs:
- Bazaar input
- Darcs input
- Git input
- Mercurial input
- Path input
## Bitbucket pull requests
Create jobs based on open bitbucket pull requests.
### Configuration options
- `bitbucket_authorization.<owner>`
## Bitbucket status
Sets Bitbucket CI status.
### Configuration options
- `enable_bitbucket_status`
- `bitbucket.username`
- `bitbucket.password`
## CircleCI Notification
Sets CircleCI status.
### Configuration options
- `circleci.[].jobs`
- `circleci.[].vcstype`
- `circleci.[].token`
## Compress build logs
Compresses build logs after a build with bzip2 or zstd.
### Configuration options
- `compress_build_logs`
Enable log compression
- `compress_build_logs_compression`
Which compression format to use. Valid values are bzip2 (default) and zstd.
- `compress_build_logs_silent`
Whether to compress logs silently.
### Example
```xml
compress_build_logs = 1
```
## Coverity Scan
Uploads source code to [coverity scan](https://scan.coverity.com).
### Configuration options
- `coverityscan.[].jobs`
- `coverityscan.[].project`
- `coverityscan.[].email`
- `coverityscan.[].token`
- `coverityscan.[].scanurl`
## Email notification
Sends email notification if build status changes.
### Configuration options
- `email_notification`
## Gitea status
Sets Gitea CI status
### Configuration options
- `gitea_authorization.<repo-owner>`
## GitHub pulls
Create jobs based on open GitHub pull requests
### Configuration options
- `github_authorization.<repo-owner>`
## Github refs
Hydra plugin for retrieving the list of references (branches or tags) from
GitHub following a certain naming scheme.
### Configuration options
- `github_endpoint` (defaults to https://api.github.com)
- `github_authorization.<repo-owner>`
## Github status
Sets GitHub CI status.
### Configuration options
- `githubstatus.[].jobs`
Regular expression for jobs to match in the format `project:jobset:job`.
This field is required and has no default value.
- `githubstatus.[].excludeBuildFromContext`
Don't include the build's ID in the status.
- `githubstatus.[].context`
Context shown in the status
- `githubstatus.[].useShortContext`
Renames `continuous-integration/hydra` to `ci/hydra` and removes the PR suffix
from the name. Useful to see the full path in GitHub for long job names.
- `githubstatus.[].description`
Description shown in the status. Defaults to `Hydra build #<build-id> of
<jobname>`
- `githubstatus.[].inputs`
The input which corresponds to the github repo/rev whose
status we want to report. Can be repeated.
- `githubstatus.[].authorization`
Verbatim contents of the Authorization header. See
[GitHub documentation](https://developer.github.com/v3/#authentication) for
details. This field is only used if `github_authorization.<repo-owner>` is not set.
### Example
```xml
<githubstatus>
jobs = test:pr:build
## This example will match all jobs
#jobs = .*
inputs = src
authorization = Bearer gha-secret😱secret😱secret😱
excludeBuildFromContext = 1
</githubstatus>
```
## GitLab pulls
Create jobs based on open gitlab pull requests.
### Configuration options
- `gitlab_authorization.<projectId>`
## Gitlab status
Sets Gitlab CI status.
### Configuration options
- `gitlab_authorization.<projectId>`
## InfluxDB notification
Writes InfluxDB events when a builds finished.
### Configuration options
- `influxdb.url`
- `influxdb.db`
## RunCommand
Runs a shell command when the build is finished.
See [The RunCommand Plugin](./RunCommand.md) for more information.
### Configuration options:
- `runcommand.[].job`
Regular expression for jobs to match in the format `project:jobset:job`.
Defaults to `*:*:*`.
- `runcommand.[].command`
Command to run. Can use the `$HYDRA_JSON` environment variable to access
information about the build.
### Example
```xml
<runcommand>
job = myProject:*:*
command = cat $HYDRA_JSON > /tmp/hydra-output
</runcommand>
```
## S3 backup
Upload nars and narinfos to S3 storage.
### Configuration options
- `s3backup.[].jobs`
- `s3backup.[].compression_type`
- `s3backup.[].name`
- `s3backup.[].prefix`
## Slack notification
Sending Slack notifications about build results.
### Configuration options
- `slack.[].jobs`
- `slack.[].force`
- `slack.[].url`
## SoTest
Scheduling hardware tests to SoTest controller
This plugin submits tests to a SoTest controller for all builds that contain
two products matching the subtypes "sotest-binaries" and "sotest-config".
Build products are declared by the file "nix-support/hydra-build-products"
relative to the root of a build, in the following format:
```
file sotest-binaries /nix/store/…/binaries.zip
file sotest-config /nix/store/…/config.yaml
```
### Configuration options
- `sotest.[].uri`
URL of the controller, defaults to `https://opensource.sotest.io`
- `sotest.[].authfile`
File containing `username:password`
- `sotest.[].priority`
Optional priority setting.
### Example
```xml
<sotest>
uri = https://sotest.example
authfile = /var/lib/hydra/sotest.auth
priority = 1
</sotest>
```

View File

@@ -0,0 +1,83 @@
## The RunCommand Plugin
Hydra supports executing a program after certain builds finish.
This behavior is disabled by default.
Hydra executes these commands under the `hydra-notify` service.
### Static Commands
Configure specific commands to execute after the specified matching job finishes.
#### Configuration
- `runcommand.[].job`
A matcher for jobs to match in the format `project:jobset:job`. Defaults to `*:*:*`.
**Note:** This matcher format is not a regular expression.
The `*` is a wildcard for that entire section, partial matches are not supported.
- `runcommand.[].command`
Command to run. Can use the `$HYDRA_JSON` environment variable to access information about the build.
### Example
```xml
<runcommand>
job = myProject:*:*
command = cat $HYDRA_JSON > /tmp/hydra-output
</runcommand>
```
### Dynamic Commands
Hydra can optionally run RunCommand hooks defined dynamically by the jobset. In
order to enable dynamic commands, you must enable this feature in your
`hydra.conf`, *as well as* in the parent project and jobset configuration.
#### Behavior
Hydra will execute any program defined under the `runCommandHook` attribute set. These jobs must have a single output named `out`, and that output must be an executable file located directly at `$out`.
#### Security Properties
Safely deploying dynamic commands requires careful design of your Hydra jobs. Allowing arbitrary users to define attributes in your top level attribute set will allow that user to execute code on your Hydra.
If a jobset has dynamic commands enabled, you must ensure only trusted users can define top level attributes.
#### Configuration
- `dynamicruncommand.enable`
Set to 1 to enable dynamic RunCommand program execution.
#### Example
In your Hydra configuration, specify:
```xml
<dynamicruncommand>
enable = 1
</dynamicruncommand>
```
Then create a job named `runCommandHook.example` in your jobset:
```
{ pkgs, ... }: {
runCommandHook = {
recurseForDerivations = true;
example = pkgs.writeScript "run-me" ''
#!${pkgs.runtimeShell}
${pkgs.jq}/bin/jq . "$HYDRA_JSON"
'';
};
}
```
After the `runcommandHook.example` build finishes that script will execute.

View File

@@ -0,0 +1,146 @@
## Declarative Projects
Hydra supports declaratively configuring a project\'s jobsets. This
configuration can be done statically, or generated by a build job.
> **Note**
>
> Hydra will treat the project\'s declarative input as a static definition
> if and only if the spec file contains a dictionary of dictionaries. If
> the value of any key in the spec is not a dictionary, it will treat the
> spec as a generated declarative spec.
### Static, Declarative Projects
Hydra supports declarative projects, where jobsets are configured from a
static JSON document in a repository.
To configure a static declarative project, take the following steps:
1. Create a Hydra-fetchable source like a Git repository or local path.
2. In that source, create a file called `spec.json`, and add the
specification for all of the jobsets. Each key is jobset and each
value is a jobset\'s specification. For example:
``` {.json}
{
"nixpkgs": {
"enabled": 1,
"hidden": false,
"description": "Nixpkgs",
"nixexprinput": "nixpkgs",
"nixexprpath": "pkgs/top-level/release.nix",
"checkinterval": 300,
"schedulingshares": 100,
"enableemail": false,
"enable_dynamic_run_command": false,
"emailoverride": "",
"keepnr": 3,
"inputs": {
"nixpkgs": {
"type": "git",
"value": "git://github.com/NixOS/nixpkgs.git master",
"emailresponsible": false
}
}
},
"nixos": {
"enabled": 1,
"hidden": false,
"description": "NixOS: Small Evaluation",
"nixexprinput": "nixpkgs",
"nixexprpath": "nixos/release-small.nix",
"checkinterval": 300,
"schedulingshares": 100,
"enableemail": false,
"enable_dynamic_run_command": false,
"emailoverride": "",
"keepnr": 3,
"inputs": {
"nixpkgs": {
"type": "git",
"value": "git://github.com/NixOS/nixpkgs.git master",
"emailresponsible": false
}
}
}
}
```
3. Create a new project, and set the project\'s declarative input type,
declarative input value, and declarative spec file to point to the
source and JSON file you created in step 2.
Hydra will create a special jobset named `.jobsets`. When the `.jobsets`
jobset is evaluated, this static specification will be used for
configuring the rest of the project\'s jobsets.
### Generated, Declarative Projects
Hydra also supports generated declarative projects, where jobsets are
configured automatically from specification files instead of being
managed through the UI. A jobset specification is a JSON object
containing the configuration of the jobset, for example:
``` {.json}
{
"enabled": 1,
"hidden": false,
"description": "js",
"nixexprinput": "src",
"nixexprpath": "release.nix",
"checkinterval": 300,
"schedulingshares": 100,
"enableemail": false,
"enable_dynamic_run_command": false,
"emailoverride": "",
"keepnr": 3,
"inputs": {
"src": { "type": "git", "value": "git://github.com/shlevy/declarative-hydra-example.git", "emailresponsible": false },
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs.git release-16.03", "emailresponsible": false }
}
}
```
To configure a declarative project, take the following steps:
1. Create a jobset repository in the normal way (e.g. a git repo with a
`release.nix` file, any other needed helper files, and taking any
kind of hydra input), but without adding it to the UI. The nix
expression of this repository should contain a single job, named
`jobsets`. The output of the `jobsets` job should be a JSON file
containing an object of jobset specifications. Each member of the
object will become a jobset of the project, configured by the
corresponding jobset specification.
2. In some hydra-fetchable source (potentially, but not necessarily,
the same repo you created in step 1), create a JSON file containing
a jobset specification that points to the jobset repository you
created in the first step, specifying any needed inputs
(e.g. nixpkgs) as necessary.
3. In the project creation/edit page, set declarative input type,
declarative input value, and declarative spec file to point to the
source and JSON file you created in step 2.
Hydra will create a special jobset named `.jobsets`, which whenever
evaluated will go through the steps above in reverse order:
1. Hydra will fetch the input specified by the declarative input type
and value.
2. Hydra will use the configuration given in the declarative spec file
as the jobset configuration for this evaluation. In addition to any
inputs specified in the spec file, hydra will also pass the
`declInput` argument corresponding to the input fetched in step 1 and
the `projectName` argument containing the project\'s name.
3. As normal, hydra will build the jobs specified in the jobset
repository, which in this case is the single `jobsets` job. When
that job completes, hydra will read the created jobset
specifications and create corresponding jobsets in the project,
disabling any jobsets that used to exist but are not present in the
current spec.

413
doc/manual/src/projects.md Normal file
View File

@@ -0,0 +1,413 @@
Creating and Managing Projects
==============================
Once Hydra is installed and running, the next step is to add projects to
the build farm. We follow the example of the [Patchelf
project](http://nixos.org/patchelf.html), a software tool written in C
and using the GNU Build System (GNU Autoconf and GNU Automake).
Log in to the web interface of your Hydra installation using the user
name and password you inserted in the database (by default, Hydra\'s web
server listens on [`localhost:3000`](http://localhost:3000/)). Then
follow the \"Create Project\" link to create a new project.
Project Information
-------------------
A project definition consists of some general information and a set of
job sets. The general information identifies a project, its owner, and
current state of activity. Here\'s what we fill in for the patchelf
project:
Identifier: patchelf
The *identifier* is the identity of the project. It is used in URLs and
in the names of build results.
The identifier should be a unique name (it is the primary database key
for the project table in the database). If you try to create a project
with an already existing identifier you\'d get an error message from the
database. So try to create the project after entering just the general
information to figure out if you have chosen a unique name. Job sets can
be added once the project has been created.
Display name: Patchelf
The *display name* is used in menus.
Description: A tool for modifying ELF binaries
The *description* is used as short documentation of the nature of the
project.
Owner: eelco
The *owner* of a project can create and edit job sets.
Enabled: Yes
Only if the project is *enabled* are builds performed.
Once created there should be an entry for the project in the sidebar. Go
to the project page for the
[Patchelf](http://localhost:3000/project/patchelf) project.
Job Sets
--------
A project can consist of multiple *job sets* (hereafter *jobsets*),
separate tasks that can be built separately, but may depend on each
other (without cyclic dependencies, of course). Go to the
[Edit](http://localhost:3000/project/patchelf/edit) page of the Patchelf
project and \"Add a new jobset\" by providing the following
\"Information\":
Identifier: trunk
Description: Trunk
Nix expression: release.nix in input patchelfSrc
This states that in order to build the `trunk` jobset, the Nix
expression in the file `release.nix`, which can be obtained from input
`patchelfSrc`, should be evaluated. (We\'ll have a look at `release.nix`
later.)
To realize a job we probably need a number of inputs, which can be
declared in the table below. As many inputs as required can be added.
For patchelf we declare the following inputs.
patchelfSrc
'Git checkout' https://github.com/NixOS/patchelf
nixpkgs 'Git checkout' https://github.com/NixOS/nixpkgs
officialRelease Boolean false
system String value "i686-linux"
Building Jobs
-------------
Build Recipes
-------------
Build jobs and *build recipes* for a jobset are specified in a text file
written in the [Nix language](http://nixos.org/nix/). The recipe is
actually called a *Nix expression* in Nix parlance. By convention this
file is often called `release.nix`.
The `release.nix` file is typically kept under version control, and the
repository that contains it one of the build inputs of the
corresponding--often called `hydraConfig` by convention. The repository
for that file and the actual file name are specified on the web
interface of Hydra under the `Setup` tab of the jobset\'s overview page,
under the `Nix
expression` heading. See, for example, the [jobset overview
page](http://hydra.nixos.org/jobset/patchelf/trunk) of the PatchELF
project, and [the corresponding Nix
file](https://github.com/NixOS/patchelf/blob/master/release.nix).
Knowledge of the Nix language is recommended, but the example below
should already give a good idea of how it works:
let
pkgs = import <nixpkgs> {}; ①
jobs = rec { ②
tarball = ③
pkgs.releaseTools.sourceTarball { ④
name = "hello-tarball";
src = <hello>; ⑤
buildInputs = (with pkgs; [ gettext texLive texinfo ]);
};
build = ⑥
{ system ? builtins.currentSystem }: ⑦
let pkgs = import <nixpkgs> { inherit system; }; in
pkgs.releaseTools.nixBuild { ⑧
name = "hello";
src = jobs.tarball;
configureFlags = [ "--disable-silent-rules" ];
};
};
in
jobs ⑨
This file shows what a `release.nix` file for
[GNU Hello](http://www.gnu.org/software/hello/) would look like.
GNU Hello is representative of many GNU and non-GNU free software
projects:
- it uses the GNU Build System, namely GNU Autoconf, and GNU Automake;
for users, it means it can be installed using the
usual
./configure && make install
procedure
;
- it uses Gettext for internationalization;
- it has a Texinfo manual, which can be rendered as PDF with TeX.
The file defines a jobset consisting of two jobs: `tarball`, and
`build`. It contains the following elements (referenced from the figure
by numbers):
1. This defines a variable `pkgs` holding the set of packages provided
by [Nixpkgs](http://nixos.org/nixpkgs/).
Since `nixpkgs` appears in angle brackets, there must be a build
input of that name in the Nix search path. In this case, the web
interface should show a `nixpkgs` build input, which is a checkout
of the Nixpkgs source code repository; Hydra then adds this and
other build inputs to the Nix search path when evaluating
`release.nix`.
2. This defines a variable holding the two Hydra jobs--an *attribute
set* in Nix.
3. This is the definition of the first job, named `tarball`. The
purpose of this job is to produce a usable source code tarball.
4. The `tarball` job calls the `sourceTarball` function, which
(roughly) runs `autoreconf && ./configure &&
make dist` on the checkout. The `buildInputs` attribute
specifies additional software dependencies for the job.
> The package names used in `buildInputs`--e.g., `texLive`--are the
> names of the *attributes* corresponding to these packages in
> Nixpkgs, specifically in the
> [`all-packages.nix`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/all-packages.nix)
> file. See the section entitled "Package Naming" in the Nixpkgs
> manual for more information.
5. The `tarball` jobs expects a `hello` build input to be available in
the Nix search path. Again, this input is passed by Hydra and is
meant to be a checkout of GNU Hello\'s source code repository.
6. This is the definition of the `build` job, whose purpose is to build
Hello from the tarball produced above.
7. The `build` function takes one parameter, `system`, which should be
a string defining the Nix system type--e.g., `"x86_64-linux"`.
Additionally, it refers to `jobs.tarball`, seen above.
Hydra inspects the formal argument list of the function (here, the
`system` argument) and passes it the corresponding parameter
specified as a build input on Hydra\'s web interface. Here, `system`
is passed by Hydra when it calls `build`. Thus, it must be defined
as a build input of type string in Hydra, which could take one of
several values.
The question mark after `system` defines the default value for this
argument, and is only useful when debugging locally.
8. The `build` job calls the `nixBuild` function, which unpacks the
tarball, then runs `./configure && make
&& make check && make install`.
9. Finally, the set of jobs is returned to Hydra, as a Nix attribute
set.
Building from the Command Line
------------------------------
It is often useful to test a build recipe, for instance before it is
actually used by Hydra, when testing changes, or when debugging a build
issue. Since build recipes for Hydra jobsets are just plain Nix
expressions, they can be evaluated using the standard Nix tools.
To evaluate the `tarball` jobset of the above example, just
run:
```console
$ nix-build release.nix -A tarball
```
However, doing this with the example as is will probably
yield an error like this:
error: user-thrown exception: file `hello' was not found in the Nix search path (add it using $NIX_PATH or -I)
The error is self-explanatory. Assuming `$HOME/src/hello` points to a
checkout of Hello, this can be fixed this way:
```console
$ nix-build -I ~/src release.nix -A tarball
```
Similarly, the `build` jobset can be evaluated:
```console
$ nix-build -I ~/src release.nix -A build
```
The `build` job reuses the result of the `tarball` job, rebuilding it
only if it needs to.
Adding More Jobs
----------------
The example illustrates how to write the most basic
jobs, `tarball` and `build`. In practice, much more can be done by using
features readily provided by Nixpkgs or by creating new jobs as
customizations of existing jobs.
For instance, test coverage report for projects compiled with GCC can be
automatically generated using the `coverageAnalysis` function provided
by Nixpkgs instead of `nixBuild`. Back to our GNU Hello example, we can
define a `coverage` job that produces an HTML code coverage report
directly readable from the corresponding Hydra build page:
coverage =
{ system ? builtins.currentSystem }:
let pkgs = import nixpkgs { inherit system; }; in
pkgs.releaseTools.coverageAnalysis {
name = "hello";
src = jobs.tarball;
configureFlags = [ "--disable-silent-rules" ];
};
As can be seen, the only difference compared to `build` is the use of
`coverageAnalysis`.
Nixpkgs provides many more build tools, including the ability to run
build in virtual machines, which can themselves run another GNU/Linux
distribution, which allows for the creation of packages for these
distributions. Please see [the `pkgs/build-support/release`
directory](https://github.com/NixOS/nixpkgs/tree/master/pkgs/build-support/release)
of Nixpkgs for more. The NixOS manual also contains information about
whole-system testing in virtual machine.
Now, assume we want to build Hello with an old version of GCC, and with
different `configure` flags. A new `build_exotic` job can be written
that simply *overrides* the relevant arguments passed to `nixBuild`:
build_exotic =
{ system ? builtins.currentSystem }:
let
pkgs = import nixpkgs { inherit system; };
build = jobs.build { inherit system; };
in
pkgs.lib.overrideDerivation build (attrs: {
buildInputs = [ pkgs.gcc33 ];
preConfigure = "gcc --version";
configureFlags =
attrs.configureFlags ++ [ "--disable-nls" ];
});
The `build_exotic` job reuses `build` and overrides some of its
arguments: it adds a dependency on GCC 3.3, a pre-configure phase that
runs `gcc --version`, and adds the `--disable-nls` configure flags.
This customization mechanism is very powerful. For instance, it can be
used to change the way Hello and *all* its dependencies--including the C
library and compiler used to build it--are built. See the Nixpkgs manual
for more.
Declarative Projects
--------------------
see this [chapter](./plugins/declarative-projects.md)
Email Notifications
-------------------
Hydra can send email notifications when the status of a build changes.
This provides immediate feedback to maintainers or committers when a
change causes build failures.
The feature can be turned on by adding the following line to `hydra.conf`
``` conf
email_notification = 1
```
By default, Hydra only sends email notifications if a previously successful
build starts to fail. In order to force Hydra to send an email for each build
(including e.g. successful or cancelled ones), the environment variable
`HYDRA_FORCE_SEND_MAIL` can be declared:
``` nix
services.hydra-dev.extraEnv.HYDRA_FORCE_SEND_MAIL = "1";
```
SASL Authentication for the email address that's used to send notifications
can be configured like this:
``` conf
EMAIL_SENDER_TRANSPORT_sasl_username=hydra@example.org
EMAIL_SENDER_TRANSPORT_sasl_password=verysecret
EMAIL_SENDER_TRANSPORT_port=587
EMAIL_SENDER_TRANSPORT_ssl=starttls
```
Further information about these environment variables can be found at the
[MetaCPAN documentation of `Email::Sender::Manual::QuickStart`](https://metacpan.org/pod/Email::Sender::Manual::QuickStart#specifying-transport-in-the-environment).
It's recommended to not put this in `services.hydra-dev.extraEnv` as this would
leak the secrets into the Nix store. Instead, it should be written into an
environment file and configured like this:
``` nix
{ systemd.services.hydra-notify = {
serviceConfig.EnvironmentFile = "/etc/secrets/hydra-mail-cfg";
};
}
```
The simplest approach to enable Email Notifications is to use the ssmtp
package, which simply hands off the emails to another SMTP server. For
details on how to configure ssmtp, see the documentation for the
`networking.defaultMailServer` option. To use ssmtp for the Hydra email
notifications, add it to the path option of the Hydra services in your
`/etc/nixos/configuration.nix` file:
systemd.services.hydra-queue-runner.path = [ pkgs.ssmtp ];
systemd.services.hydra-server.path = [ pkgs.ssmtp ];
Gitea Integration
-----------------
Hydra can notify Git servers (such as [GitLab](https://gitlab.com/), [GitHub](https://github.com)
or [Gitea](https://gitea.io/en-us/)) about the result of a build from a Git checkout.
This section describes how it can be implemented for `gitea`, but the approach for `gitlab` is
analogous:
* [Obtain an API token for your user](https://docs.gitea.io/en-us/api-usage/#authentication)
* Add it to a file which only users in the hydra group can read like this: see [including files](configuration.md#including-files) for more information
```
<gitea_authorization>
your_username=your_token
</gitea_authorization>
```
* Include the file in your `hydra.conf` like this:
``` nix
{
services.hydra-dev.extraConfig = ''
Include /path/to/secret/file
'';
}
```
* For a jobset with a `Git`-input which points to a `gitea`-instance, add the following
additional inputs:
| Type | Name | Value |
| -------------- | ------------------- | ---------------------------------- |
| `String value` | `gitea_repo_name` | *Name of the repository to build* |
| `String value` | `gitea_repo_owner` | *Owner of the repository* |
| `String value` | `gitea_status_repo` | *Name of the `Git checkout` input* |
| `String value` | `gitea_http_url` | *Public URL of `gitea`*, optional |
Content-addressed derivations
-----------------------------
Hydra can to a certain extent use the [`ca-derivations` experimental Nix feature](https://github.com/NixOS/rfcs/pull/62).
To use it, make sure that the Nix version you use is at least as recent as the one used in hydra's flake.
Be warned that this support is still highly experimental, and anything beyond the basic functionality might be broken at that point.

View File

@@ -0,0 +1,168 @@
# Webhook Authentication Migration Guide
This guide helps Hydra administrators migrate from unauthenticated webhooks to authenticated webhooks to secure their Hydra instances against unauthorized job evaluations.
## Why Migrate?
Currently, Hydra's webhook endpoints (`/api/push-github` and `/api/push-gitea`) accept any POST request without authentication. This vulnerability allows:
- Anyone to trigger expensive job evaluations
- Potential denial of service through repeated requests
- Manipulation of build timing and scheduling
## Step-by-Step Migration for NixOS
### 1. Create Webhook Configuration
Create a webhook secrets configuration file with the generated secrets:
```bash
# Create the secrets configuration file with inline secret generation
cat > /var/lib/hydra/secrets/webhook-secrets.conf <<EOF
<github>
secret = $(openssl rand -hex 32)
</github>
<gitea>
secret = $(openssl rand -hex 32)
</gitea>
EOF
# Set secure permissions
chmod 0440 /var/lib/hydra/secrets/webhook-secrets.conf
chown hydra:hydra /var/lib/hydra/secrets/webhook-secrets.conf
```
**Important**: Save the generated secrets to configure them in GitHub/Gitea later. You can view them with:
```bash
cat /var/lib/hydra/secrets/webhook-secrets.conf
```
Then update your NixOS configuration to include the webhook configuration:
```nix
{
services.hydra-dev = {
enable = true;
hydraURL = "https://hydra.example.com";
notificationSender = "hydra@example.com";
extraConfig = ''
<webhooks>
Include /var/lib/hydra/secrets/webhook-secrets.conf
</webhooks>
'';
};
}
```
For multiple secrets (useful for rotation or multiple environments), update your webhook-secrets.conf:
```apache
<github>
secret = your-github-webhook-secret-prod
secret = your-github-webhook-secret-staging
</github>
<gitea>
secret = your-gitea-webhook-secret
</gitea>
```
### 2. Deploy Configuration
Apply the NixOS configuration:
```bash
nixos-rebuild switch
```
This will automatically restart Hydra services with the new configuration.
### 3. Verify Configuration
Check Hydra's logs to ensure secrets were loaded successfully:
```bash
journalctl -u hydra-server | grep -i webhook
```
You should not see warnings about webhook authentication not being configured.
### 4. Update Your Webhooks
#### GitHub
1. Navigate to your repository settings: `https://github.com/<owner>/<repo>/settings/hooks`
2. Edit your existing Hydra webhook
3. In the "Secret" field, paste the content of `/var/lib/hydra/secrets/github-webhook-secret`
4. Click "Update webhook"
5. GitHub will send a ping event to verify the configuration
#### Gitea
1. Navigate to your repository webhook settings
2. Edit your existing Hydra webhook
3. In the "Secret" field, paste the content of `/var/lib/hydra/secrets/gitea-webhook-secret`
4. Click "Update Webhook"
5. Use the "Test Delivery" button to verify the configuration
### 5. Test the Configuration
After updating each webhook:
1. Make a test commit to trigger the webhook
2. Check Hydra's logs for successful authentication
3. Verify the evaluation was triggered in Hydra's web interface
## Troubleshooting
### 401 Unauthorized Errors
If webhooks start failing with 401 errors:
- Verify the secret in the Git forge matches the file content exactly
- Check file permissions: `ls -la /var/lib/hydra/secrets/`
- Ensure no extra whitespace in secret files
- Check Hydra logs for specific error messages
### Webhook Still Unauthenticated
If you see warnings about unauthenticated webhooks after configuration:
- Verify the configuration syntax in your NixOS module
- Ensure the NixOS configuration was successfully applied
- Check that the webhook-secrets.conf file exists and is readable by the Hydra user
- Verify the Include path is correct in your hydra.conf
- Check the syntax of your webhook-secrets.conf file
### Testing Without Git Forge
You can test webhook authentication using curl:
```bash
# Read the secret
SECRET=$(cat /var/lib/hydra/secrets/github-webhook-secret)
# Create test payload
PAYLOAD='{"ref":"refs/heads/main","repository":{"clone_url":"https://github.com/test/repo.git"}}'
# Calculate signature
SIGNATURE="sha256=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)"
# Send authenticated request
curl -X POST https://your-hydra/api/push-github \
-H "Content-Type: application/json" \
-H "X-Hub-Signature-256: $SIGNATURE" \
-d "$PAYLOAD"
```
For Gitea (no prefix in signature):
```bash
# Read the secret
SECRET=$(cat /var/lib/hydra/secrets/gitea-webhook-secret)
# Create test payload
PAYLOAD='{"ref":"refs/heads/main","repository":{"clone_url":"https://gitea.example.com/test/repo.git"}}'
# Calculate signature
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)
# Send authenticated request
curl -X POST https://your-hydra/api/push-gitea \
-H "Content-Type: application/json" \
-H "X-Gitea-Signature: $SIGNATURE" \
-d "$PAYLOAD"
```

101
doc/manual/src/webhooks.md Normal file
View File

@@ -0,0 +1,101 @@
# Webhooks
Hydra can be notified by github or gitea with webhooks to trigger a new evaluation when a
jobset has a github repo in its input.
## Webhook Authentication
Hydra supports webhook signature verification for both GitHub and Gitea using HMAC-SHA256. This ensures that webhook
requests are coming from your configured Git forge and haven't been tampered with.
### Configuring Webhook Authentication
1. **Create webhook configuration**: Generate and store webhook secrets securely:
```bash
# Create directory and generate secrets in one step
mkdir -p /var/lib/hydra/secrets
cat > /var/lib/hydra/secrets/webhook-secrets.conf <<EOF
<github>
secret = $(openssl rand -hex 32)
</github>
<gitea>
secret = $(openssl rand -hex 32)
</gitea>
EOF
# Set secure permissions
chmod 0600 /var/lib/hydra/secrets/webhook-secrets.conf
chown hydra:hydra /var/lib/hydra/secrets/webhook-secrets.conf
```
2. **Configure Hydra**: Add the following to your `hydra.conf`:
```apache
<webhooks>
Include /var/lib/hydra/secrets/webhook-secrets.conf
</webhooks>
```
3. **Configure your Git forge**: View the generated secrets and configure them in GitHub/Gitea:
```bash
grep "secret =" /var/lib/hydra/secrets/webhook-secrets.conf
```
### Multiple Secrets Support
Hydra supports configuring multiple secrets for each platform, which is useful for:
- Zero-downtime secret rotation
- Supporting multiple environments (production/staging)
- Gradual migration of webhooks
To configure multiple secrets, use array syntax:
```apache
<github>
secret = current-webhook-secret
secret = previous-webhook-secret
</github>
```
## GitHub
To set up a webhook for a GitHub repository go to `https://github.com/<yourhandle>/<yourrepo>/settings`
and in the `Webhooks` tab click on `Add webhook`.
- In `Payload URL` fill in `https://<your-hydra-domain>/api/push-github`.
- In `Content type` switch to `application/json`.
- In the `Secret` field, enter the content of your GitHub webhook secret file (if authentication is configured).
- For `Which events would you like to trigger this webhook?` keep the default option for events on `Just the push event.`.
Then add the hook with `Add webhook`.
### Verifying GitHub Webhook Security
After configuration, GitHub will send webhook requests with an `X-Hub-Signature-256` header containing the HMAC-SHA256
signature of the request body. Hydra will verify this signature matches the configured secret.
## Gitea
To set up a webhook for a Gitea repository go to the settings of the repository in your Gitea instance
and in the `Webhooks` tab click on `Add Webhook` and choose `Gitea` in the drop down.
- In `Target URL` fill in `https://<your-hydra-domain>/api/push-gitea`.
- Keep HTTP method `POST`, POST Content Type `application/json` and Trigger On `Push Events`.
- In the `Secret` field, enter the content of your Gitea webhook secret file (if authentication is configured).
- Change the branch filter to match the git branch hydra builds.
Then add the hook with `Add webhook`.
### Verifying Gitea Webhook Security
After configuration, Gitea will send webhook requests with an `X-Gitea-Signature` header containing the HMAC-SHA256
signature of the request body. Hydra will verify this signature matches the configured secret.
## Troubleshooting
If you receive 401 Unauthorized errors:
- Verify the webhook secret in your Git forge matches the content of the secret file exactly
- Check that the secret file has proper permissions (should be 0600)
- Look at Hydra's logs for specific error messages
- Ensure the correct signature header is being sent by your Git forge
If you see warnings about webhook authentication not being configured:
- Configure webhook authentication as described above to secure your endpoints

View File

@@ -1,288 +0,0 @@
/* Copied from http://bakefile.sourceforge.net/, which appears
licensed under the GNU GPL. */
/***************************************************************************
Basic headers and text:
***************************************************************************/
body
{
font-family: sans-serif;
background: white;
margin: 2em 1em 2em 1em;
}
h1,h2,h3
{
color: #005aa0;
text-align: left;
}
h1 /* title */
{
font-size: 200%;
}
h2 /* chapters, appendices, subtitle */
{
font-size: 180%;
}
/* Extra space between chapters, appendices. */
div.chapter > div.titlepage h2, div.appendix > div.titlepage h2
{
margin-top: 1.5em;
}
div.section > div.titlepage h2 /* sections */
{
font-size: 150%;
margin-top: 1.5em;
}
h3 /* subsections */
{
font-size: 125%;
}
div.simplesect h2
{
font-size: 110%;
}
div.appendix h3
{
font-size: 150%;
margin-top: 1.5em;
}
div.refnamediv h2, div.refsynopsisdiv h2, div.refsection h2 /* refentry parts */
{
margin-top: 1.4em;
font-size: 125%;
}
div.refsection h3
{
font-size: 110%;
}
/***************************************************************************
Examples:
***************************************************************************/
div.example
{
border: 1px solid #6185a0;
padding: 6px 6px;
margin-left: 1.5em;
margin-right: 1.5em;
background: #f4f4f8;
}
div.example p.title
{
margin-top: 0em;
}
/***************************************************************************
Screen dumps:
***************************************************************************/
pre.screen, pre.programlisting
{
border: 1px solid #6185a0;
padding: 3px 3px;
margin-left: 1.5em;
margin-right: 1.5em;
color: #600000;
background: #f4f4f8;
font-family: monospace;
/* font-size: 90%; */
}
div.example pre.programlisting
{
border: 0px;
padding: 0 0;
margin: 0 0 0 0;
}
/***************************************************************************
Notes, warnings etc:
***************************************************************************/
.note, .warning
{
border: 1px solid #6185a0;
padding: 3px 3px;
margin-left: 1.5em;
margin-right: 1.5em;
margin-bottom: 1em;
padding: 0.3em 0.3em 0.3em 0.3em;
background: #fffff5;
}
div.note, div.warning
{
font-style: italic;
}
div.note h3, div.warning h3
{
color: red;
font-size: 100%;
// margin: 0 0 0 0;
padding-right: 0.5em;
display: inline;
}
div.note p, div.warning p
{
margin-bottom: 0em;
}
div.note h3 + p, div.warning h3 + p
{
display: inline;
}
div.note h3
{
color: blue;
font-size: 100%;
}
div.navfooter *
{
font-size: 90%;
}
/***************************************************************************
Links colors and highlighting:
***************************************************************************/
a:link { color: #0048b3; }
a:visited { color: #002a6a; }
a:hover { background: #ffffcd; }
/***************************************************************************
Table of contents:
***************************************************************************/
.toc
{
font-size: 90%;
}
/***************************************************************************
Special elements:
***************************************************************************/
tt, code
{
color: #400000;
}
.term
{
font-weight: bold;
}
div.variablelist dd p, div.glosslist dd p
{
margin-top: 0em;
}
div.variablelist dd, div.glosslist dd
{
margin-left: 1.5em;
}
div.glosslist dt
{
font-style: italic;
}
.default
{
font-style: italic;
}
.availability
{
font-style: italic;
}
.varname
{
color: #400000;
}
div.informaltable table
{
border: 1px solid #6185a0;
width: 100%;
}
div.informaltable td
{
border: 0;
padding: 5px;
}
div.informaltable td.default
{
text-align: right;
}
div.informaltable th
{
text-align: left;
color: #005aa0;
border: 0;
padding: 5px;
background: #fffff5;
font-weight: normal;
font-style: italic;
}
td.varname, td.tagname, td.paramname
{
font-weight: bold;
vertical-align: top;
}
div.epigraph
{
font-style: italic;
text-align: right;
}
table.productionset table.productionset
{
font-family: monospace;
}
strong.command
{
// font-family: monospace;
// font-style: italic;
// font-weight: normal;
color: #400000;
}
div.calloutlist td
{
padding-bottom: 1em;
}

13
examples/hello.nix Normal file
View File

@@ -0,0 +1,13 @@
#
# jobset example file. This file can be referenced as Nix expression
# in a jobset configuration along with inputs for nixpkgs and the
# repository containing this file.
#
{ ... }:
let
# <nixpkgs> is set to the value designated by the nixpkgs input of the
# jobset configuration.
pkgs = (import <nixpkgs> {});
in {
hello = pkgs.hello;
}

63
flake.lock generated Normal file
View File

@@ -0,0 +1,63 @@
{
"nodes": {
"nix": {
"flake": false,
"locked": {
"lastModified": 1768160797,
"narHash": "sha256-TVKn52SoKq8mMyW/x3NPPskGVurFdnGGV0DGvnL0gak=",
"owner": "NixOS",
"repo": "nix",
"rev": "fb562abba93fb15f66a71a9fc1d94bb1ea21a2d4",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "2.33-maintenance",
"repo": "nix",
"type": "github"
}
},
"nix-eval-jobs": {
"flake": false,
"locked": {
"lastModified": 1767025318,
"narHash": "sha256-i68miKHGdueWggcDAF+Kca9g6S3ipkW629XbMpQYfn0=",
"owner": "nix-community",
"repo": "nix-eval-jobs",
"rev": "79dd7adbb5f75b08fb4b9bddd712ebc52baa46bc",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "v2.33.0",
"repo": "nix-eval-jobs",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1768332487,
"narHash": "sha256-Q0bSMhDIhb/S7r+XRyuPy58kEXa0rmpw5j99ubJzovg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6b0609442afc4ce51ff1466e7db555c2e2fc28d4",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.11-small",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nix": "nix",
"nix-eval-jobs": "nix-eval-jobs",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

140
flake.nix Normal file
View File

@@ -0,0 +1,140 @@
{
description = "A Nix-based continuous build system";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11-small";
inputs.nix = {
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/v2.33.0";
# We want to control the deps precisely
flake = false;
};
outputs = { self, nixpkgs, nix, nix-eval-jobs, ... }:
let
systems = [ "x86_64-linux" "aarch64-linux" ];
forEachSystem = nixpkgs.lib.genAttrs systems;
in
rec {
# A Nixpkgs overlay that provides a 'hydra' package.
overlays.default = final: prev: {
nixDependenciesForHydra = final.lib.makeScope final.newScope
(import (nix + "/packaging/dependencies.nix") {
pkgs = final;
inherit (final) stdenv;
inputs = {};
});
nixComponentsForHydra = final.lib.makeScope final.nixDependenciesForHydra.newScope
(import (nix + "/packaging/components.nix") {
officialRelease = true;
inherit (final) lib;
pkgs = final;
src = nix;
maintainers = [ ];
});
nix-eval-jobs = final.callPackage nix-eval-jobs {
nixComponents = final.nixComponentsForHydra;
};
hydra = final.callPackage ./package.nix {
inherit (final.lib) fileset;
rawSrc = self;
nixComponents = final.nixComponentsForHydra;
};
};
hydraJobs = {
build = forEachSystem (system: packages.${system}.hydra);
buildNoTests = forEachSystem (system:
packages.${system}.hydra.overrideAttrs (_: {
doCheck = false;
})
);
manual = forEachSystem (system: let
pkgs = nixpkgs.legacyPackages.${system};
hydra = self.packages.${pkgs.stdenv.hostPlatform.system}.hydra;
in
pkgs.runCommand "hydra-manual-${hydra.version}" { }
''
mkdir -p $out/share
cp -prvd ${hydra.doc}/share/doc $out/share/
mkdir $out/nix-support
echo "doc manual $out/share/doc/hydra" >> $out/nix-support/hydra-build-products
'');
tests = import ./nixos-tests.nix {
inherit forEachSystem nixpkgs nixosModules;
};
container = nixosConfigurations.container.config.system.build.toplevel;
};
checks = forEachSystem (system: {
build = hydraJobs.build.${system};
install = hydraJobs.tests.install.${system};
validate-openapi = hydraJobs.tests.validate-openapi.${system};
});
packages = forEachSystem (system: let
inherit (nixpkgs) lib;
pkgs = nixpkgs.legacyPackages.${system};
nixDependencies = lib.makeScope pkgs.newScope
(import (nix + "/packaging/dependencies.nix") {
inherit pkgs;
inherit (pkgs) stdenv;
inputs = {};
});
nixComponents = lib.makeScope nixDependencies.newScope
(import (nix + "/packaging/components.nix") {
officialRelease = true;
inherit lib pkgs;
src = nix;
maintainers = [ ];
});
in {
nix-eval-jobs = pkgs.callPackage nix-eval-jobs {
inherit nixComponents;
};
hydra = pkgs.callPackage ./package.nix {
inherit (nixpkgs.lib) fileset;
inherit nixComponents;
inherit (self.packages.${system}) nix-eval-jobs;
rawSrc = self;
};
default = self.packages.${system}.hydra;
});
nixosModules = import ./nixos-modules {
inherit self;
};
nixosConfigurations.container = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules =
[
self.nixosModules.hydra
self.nixosModules.hydraTest
self.nixosModules.hydraProxy
{
system.configurationRevision = self.lastModifiedDate;
boot.isContainer = true;
networking.useDHCP = false;
networking.firewall.allowedTCPPorts = [ 80 ];
networking.hostName = "hydra";
services.hydra-dev.useSubstitutes = true;
}
];
};
};
}

8
foreman/start-evaluator.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/sh
export PATH=$(pwd)/src/script:$PATH
# wait for hydra-server to listen
while ! nc -z localhost 63333; do sleep 1; done
HYDRA_CONFIG=$(pwd)/.hydra-data/hydra.conf exec hydra-evaluator

33
foreman/start-hydra.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/bin/sh
export PATH=$(pwd)/src/script:$PATH
# wait for postgresql to listen
while ! pg_isready -h $(pwd)/.hydra-data/postgres -p 64444; do sleep 1; done
createdb -h $(pwd)/.hydra-data/postgres -p 64444 hydra
# create a db for the default user. Not sure why, but
# the terminal is otherwise spammed with:
#
# FATAL: database "USERNAME" does not exist
createdb -h $(pwd)/.hydra-data/postgres -p 64444 "$(whoami)" || true
hydra-init
hydra-create-user alice --password foobar --role admin
if [ ! -f ./.hydra-data/hydra.conf ]; then
echo "Creating a default hydra.conf"
cat << EOF > .hydra-data/hydra.conf
# test-time instances likely don't want to bootstrap nixpkgs from scratch
use-substitutes = true
<hydra_notify>
<prometheus>
listen_address = 127.0.0.1
port = 64445
</prometheus>
</hydra_notify>
EOF
fi
HYDRA_CONFIG=$(pwd)/.hydra-data/hydra.conf exec hydra-dev-server --port 63333 --restart --debug

6
foreman/start-manual.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
mdbook serve \
--port 63332 \
--dest-dir ./.hydra-data/manual \
./doc/manual/

8
foreman/start-notify.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/sh
export PATH=$(pwd)/src/script:$PATH
# wait for hydra-server to listen
while ! nc -z localhost 63333; do sleep 1; done
HYDRA_CONFIG=$(pwd)/.hydra-data/hydra.conf exec hydra-notify

4
foreman/start-postgres.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
initdb ./.hydra-data/postgres
exec postgres -D ./.hydra-data/postgres -k $(pwd)/.hydra-data/postgres -p 64444

6
foreman/start-queue-runner.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
# wait until hydra is listening on port 63333
while ! nc -z localhost 63333; do sleep 1; done
NIX_REMOTE_SYSTEMS="" HYDRA_CONFIG=$(pwd)/.hydra-data/hydra.conf exec hydra-queue-runner

71
gitea_hydra_server.py Normal file
View 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()

1267
hydra-api.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,229 +0,0 @@
{ config, pkgs, ... }:
with pkgs.lib;
let
cfg = config.services.hydra;
hydraConf = pkgs.writeScript "hydra.conf"
''
using_frontend_proxy 1
base_uri ${cfg.hydraURL}
notification_sender ${cfg.notificationSender}
max_servers 25
'';
env = ''export NIX_REMOTE=daemon ''
+ ''HYDRA_DBI="${cfg.dbi}" ''
+ ''HYDRA_CONFIG=${cfg.baseDir}/data/hydra.conf ''
+ ''HYDRA_DATA=${cfg.baseDir}/data ''
+ ''HYDRA_PORT="${toString cfg.port}" ''
+ (if cfg.logo != null
then ''HYDRA_LOGO="${cfg.logo}" ''
else "")
+ ''HYDRA_TRACKER="${cfg.tracker}" ;'';
in
{
###### interface
options = {
services.hydra = rec {
enable = mkOption {
default = false;
description = ''
Whether to run Hydra services.
'';
};
baseDir = mkOption {
default = "/home/${user.default}";
description = ''
The directory holding configuration, logs and temporary files.
'';
};
user = mkOption {
default = "hydra";
description = ''
The user the Hydra services should run as.
'';
};
dbi = mkOption {
default = "dbi:Pg:dbname=hydra;host=localhost;user=root;";
example = "dbi:SQLite:/home/hydra/db/hydra.sqlite";
description = ''
The DBI string for Hydra database connection.
'';
};
hydra = mkOption {
default = pkgs.hydra;
description = ''
Location of hydra
'';
};
hydraURL = mkOption {
default = "http://hydra.nixos.org";
description = ''
The base URL for the Hydra webserver instance. Used for links in emails.
'';
};
port = mkOption {
default = 3000;
description = ''
TCP port the web server should listen to.
'';
};
minimumDiskFree = mkOption {
default = 5;
description = ''
Threshold of minimum disk space (G) to determine if queue runner should run or not.
'';
};
minimumDiskFreeEvaluator = mkOption {
default = 2;
description = ''
Threshold of minimum disk space (G) to determine if evaluator should run or not.
'';
};
notificationSender = mkOption {
default = "e.dolstra@tudelft.nl";
description = ''
Sender email address used for email notifications.
'';
};
tracker = mkOption {
default = "";
description = ''
Piece of HTML that is included on all pages.
'';
};
logo = mkOption {
default = null;
description = ''
File name of an alternate logo to be displayed on the web pages.
'';
};
autoStart = mkOption {
default = true;
description = ''
If hydra upstart jobs should start automatically.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
environment.systemPackages = [ cfg.hydra ];
users.extraUsers = [
{ name = cfg.user;
description = "Hydra";
home = cfg.baseDir;
createHome = true;
useDefaultShell = true;
}
];
nix.gc.automatic = true;
# $3 / $4 don't always work depending on length of device name
nix.gc.options = ''--max-freed "$((200 * 1024**3 - 1024 * $(df /nix/store | tail -n 1 | awk '{ print $3 }')))"'';
nix.extraOptions = ''
gc-keep-outputs = true
gc-keep-derivations = true
# The default (`true') slows Nix down a lot since the build farm
# has so many GC roots.
gc-check-reachability = false
# Hydra needs caching of build failures.
build-cache-failure = true
build-poll-interval = 10
use-sqlite-wal = false
'';
jobs.hydra_init =
{ description = "hydra-init";
startOn = "started network-interfaces";
preStart = ''
mkdir -p ${cfg.baseDir}/data
chown ${cfg.user} ${cfg.baseDir}/data
ln -sf ${hydraConf} ${cfg.baseDir}/data/hydra.conf
'';
exec = ''
echo done
'';
};
jobs.hydra_server =
{ description = "hydra-server";
startOn = if cfg.autoStart then "started network-interfaces hydra-init" else "never";
exec = ''
${pkgs.su}/bin/su - ${cfg.user} -c '${env} ${cfg.hydra}/bin/hydra-server > ${cfg.baseDir}/data/server.log 2>&1'
'';
};
jobs.hydra_queue_runner =
{ description = "hydra-queue-runner";
startOn = if cfg.autoStart then "started network-interfaces hydra-init" else "never";
preStart = "${pkgs.su}/bin/su - ${cfg.user} -c '${env} ${cfg.hydra}/bin/hydra-queue-runner --unlock'";
exec = ''
${pkgs.su}/bin/su - ${cfg.user} -c '${env} nice -n 8 ${cfg.hydra}/bin/hydra-queue-runner > ${cfg.baseDir}/data/queue-runner.log 2>&1'
'';
};
jobs.hydra_evaluator =
{ description = "hydra-evaluator";
startOn = if cfg.autoStart then "started network-interfaces hydra-init" else "never";
exec = ''
${pkgs.su}/bin/su - ${cfg.user} -c '${env} nice -n 5 ${cfg.hydra}/bin/hydra-evaluator > ${cfg.baseDir}/data/evaluator.log 2>&1'
'';
};
services.cron.systemCronJobs =
let
# If there is less than ... GiB of free disk space, stop the queue
# to prevent builds from failing or aborting.
checkSpace = pkgs.writeScript "hydra-check-space"
''
#! /bin/sh
if [ $(($(stat -f -c '%a' /nix/store) * $(stat -f -c '%S' /nix/store))) -lt $((${toString cfg.minimumDiskFree} * 1024**3)) ]; then
stop hydra-queue-runner
fi
if [ $(($(stat -f -c '%a' /nix/store) * $(stat -f -c '%S' /nix/store))) -lt $((${toString cfg.minimumDiskFreeEvaluator} * 1024**3)) ]; then
stop hydra-evaluator
fi
'';
compressLogs = pkgs.writeScript "compress-logs" ''
#! /bin/sh -e
touch -d 'last month' r
find /nix/var/log/nix/drvs -type f -a ! -newer r -name '*.drv' | xargs bzip2 -v
'';
in
[ "*/5 * * * * root ${checkSpace} &> ${cfg.baseDir}/data/checkspace.log"
"15 5 * * * root ${compressLogs} &> ${cfg.baseDir}/data/compress.log"
"15 02 * * * ${cfg.user} ${env} ${cfg.hydra}/bin/hydra-update-gc-roots &> ${cfg.baseDir}/data/gc-roots.log"
];
};
}

26
meson.build Normal file
View File

@@ -0,0 +1,26 @@
project('hydra', 'cpp',
version: files('version.txt'),
license: 'GPL-3.0',
default_options: [
'debug=true',
'optimization=2',
'cpp_std=c++23',
],
)
nix_util_dep = dependency('nix-util', required: true)
nix_store_dep = dependency('nix-store', required: true)
nix_main_dep = dependency('nix-main', required: true)
pqxx_dep = dependency('libpqxx', required: true)
prom_cpp_core_dep = dependency('prometheus-cpp-core', required: true)
prom_cpp_pull_dep = dependency('prometheus-cpp-pull', required: true)
mdbook = find_program('mdbook', native: true)
perl = find_program('perl', native: true)
subdir('doc/manual')
subdir('nixos-modules')
subdir('src')
subdir('t')

47
nixos-modules/default.nix Normal file
View File

@@ -0,0 +1,47 @@
{ self }:
{
hydra = { pkgs, lib,... }: {
_file = ./default.nix;
imports = [ ./hydra.nix ];
services.hydra-dev.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.hydra;
};
hydraTest = { pkgs, ... }: {
services.hydra-dev.enable = true;
services.hydra-dev.hydraURL = "http://hydra.example.org";
services.hydra-dev.notificationSender = "admin@hydra.example.org";
systemd.services.hydra-send-stats.enable = false;
services.postgresql.enable = true;
# The following is to work around the following error from hydra-server:
# [error] Caught exception in engine "Cannot determine local time zone"
time.timeZone = "UTC";
nix.extraOptions = ''
allowed-uris = https://github.com/
'';
};
hydraProxy = {
services.httpd = {
enable = true;
adminAddr = "hydra-admin@example.org";
extraConfig = ''
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /apache-errors !
ErrorDocument 503 /apache-errors/503.html
ProxyPass / http://127.0.0.1:3000/ retry=5 disablereuse=on
ProxyPassReverse / http://127.0.0.1:3000/
'';
};
};
}

495
nixos-modules/hydra.nix Normal file
View File

@@ -0,0 +1,495 @@
{ config, pkgs, lib ? pkgs.lib, ... }:
with lib;
let
cfg = config.services.hydra-dev;
baseDir = "/var/lib/hydra";
hydraConf = pkgs.writeScript "hydra.conf" cfg.extraConfig;
hydraEnv =
{ HYDRA_DBI = cfg.dbi;
HYDRA_CONFIG = "${baseDir}/hydra.conf";
HYDRA_DATA = "${baseDir}";
};
env =
{ NIX_REMOTE = "daemon";
PGPASSFILE = "${baseDir}/pgpass";
NIX_REMOTE_SYSTEMS = concatStringsSep ":" cfg.buildMachinesFiles;
} // optionalAttrs (cfg.smtpHost != null) {
EMAIL_SENDER_TRANSPORT = "SMTP";
EMAIL_SENDER_TRANSPORT_host = cfg.smtpHost;
} // hydraEnv // cfg.extraEnv;
serverEnv = env //
{
COLUMNS = "80";
PGPASSFILE = "${baseDir}/pgpass-www"; # grrr
XDG_CACHE_HOME = "${baseDir}/www/.cache";
} // (optionalAttrs cfg.debugServer { DBIC_TRACE = "1"; });
localDB = "dbi:Pg:dbname=hydra;user=hydra;";
haveLocalDB = cfg.dbi == localDB;
in
{
###### interface
options = {
services.hydra-dev = rec {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to run Hydra services.
'';
};
dbi = mkOption {
type = types.str;
default = localDB;
example = "dbi:Pg:dbname=hydra;host=postgres.example.org;user=foo;";
description = ''
The DBI string for Hydra database connection.
NOTE: Attempts to set `application_name` will be overridden by
`hydra-TYPE` (where TYPE is e.g. `evaluator`, `queue-runner`,
etc.) in all hydra services to more easily distinguish where
queries are coming from.
'';
};
package = mkOption {
type = types.path;
description = "The Hydra package.";
};
hydraURL = mkOption {
type = types.str;
description = ''
The base URL for the Hydra webserver instance. Used for links in emails.
'';
};
listenHost = mkOption {
type = types.str;
default = "*";
example = "localhost";
description = ''
The hostname or address to listen on or <literal>*</literal> to listen
on all interfaces.
'';
};
port = mkOption {
type = types.int;
default = 3000;
description = ''
TCP port the web server should listen to.
'';
};
minimumDiskFree = mkOption {
type = types.int;
default = 0;
description = ''
Threshold of minimum disk space (GiB) to determine if the queue runner should run or not.
'';
};
minimumDiskFreeEvaluator = mkOption {
type = types.int;
default = 0;
description = ''
Threshold of minimum disk space (GiB) to determine if the evaluator should run or not.
'';
};
notificationSender = mkOption {
type = types.str;
description = ''
Sender email address used for email notifications.
'';
};
smtpHost = mkOption {
type = types.nullOr types.str;
default = null;
example = ["localhost"];
description = ''
Hostname of the SMTP server to use to send email.
'';
};
tracker = mkOption {
type = types.str;
default = "";
description = ''
Piece of HTML that is included on all pages.
'';
};
logo = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Path to a file containing the logo of your Hydra instance.
'';
};
debugServer = mkOption {
type = types.bool;
default = false;
description = "Whether to run the server in debug mode.";
};
extraConfig = mkOption {
type = types.lines;
description = "Extra lines for the Hydra configuration.";
};
extraEnv = mkOption {
type = types.attrsOf types.str;
default = {};
description = "Extra environment variables for Hydra.";
};
gcRootsDir = mkOption {
type = types.path;
default = "/nix/var/nix/gcroots/hydra";
description = "Directory that holds Hydra garbage collector roots.";
};
buildMachinesFiles = mkOption {
type = types.listOf types.path;
default = optional (config.nix.buildMachines != []) "/etc/nix/machines";
defaultText = literalExpression ''optional (config.nix.buildMachines != []) "/etc/nix/machines"'';
example = [ "/etc/nix/machines" "/var/lib/hydra/provisioner/machines" ];
description = "List of files containing build machines.";
};
useSubstitutes = mkOption {
type = types.bool;
default = false;
description = ''
Whether to use binary caches for downloading store paths. Note that
binary substitutions trigger (a potentially large number of) additional
HTTP requests that slow down the queue monitor thread significantly.
Also, this Hydra instance will serve those downloaded store paths to
its users with its own signature attached as if it had built them
itself, so don't enable this feature unless your active binary caches
are absolute trustworthy.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
systemd.tmpfiles.rules = [
"d ${baseDir} 0750 hydra hydra"
];
users.extraGroups.hydra = { };
users.extraUsers.hydra =
{ description = "Hydra";
group = "hydra";
home = baseDir;
isSystemUser = true;
useDefaultShell = true;
};
users.extraUsers.hydra-queue-runner =
{ description = "Hydra queue runner";
group = "hydra";
useDefaultShell = true;
isSystemUser = true;
home = "${baseDir}/queue-runner"; # really only to keep SSH happy
};
users.extraUsers.hydra-www =
{ description = "Hydra web server";
group = "hydra";
isSystemUser = true;
useDefaultShell = true;
};
nix.settings = {
trusted-users = [ "hydra-queue-runner" ];
keep-outputs = true;
keep-derivations = true;
};
services.hydra-dev.extraConfig =
''
using_frontend_proxy = 1
base_uri = ${cfg.hydraURL}
notification_sender = ${cfg.notificationSender}
max_servers = 25
compress_num_threads = 0
${optionalString (cfg.logo != null) ''
hydra_logo = ${cfg.logo}
''}
gc_roots_dir = ${cfg.gcRootsDir}
use-substitutes = ${if cfg.useSubstitutes then "1" else "0"}
${optionalString (cfg.tracker != null) (let
indentedTrackerData = lib.concatMapStringsSep "\n" (line: " ${line}") (lib.splitString "\n" cfg.tracker);
in ''
tracker = <<TRACKER
${indentedTrackerData}
TRACKER
'')}
'';
environment.systemPackages = [ cfg.package ];
environment.variables = hydraEnv;
systemd.services.hydra-init =
{ wantedBy = [ "multi-user.target" ];
requires = optional haveLocalDB "postgresql.service";
after = optional haveLocalDB "postgresql.service";
environment = env // {
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-init";
};
path = [ pkgs.util-linux ];
preStart = ''
ln -sf ${hydraConf} ${baseDir}/hydra.conf
mkdir -m 0700 -p ${baseDir}/www
chown hydra-www:hydra ${baseDir}/www
mkdir -m 0700 -p ${baseDir}/queue-runner
mkdir -m 0750 -p ${baseDir}/build-logs
mkdir -m 0750 -p ${baseDir}/runcommand-logs
chown hydra-queue-runner:hydra \
${baseDir}/queue-runner \
${baseDir}/build-logs \
${baseDir}/runcommand-logs
${optionalString haveLocalDB ''
if ! [ -e ${baseDir}/.db-created ]; then
runuser -u ${config.services.postgresql.superUser} -- ${config.services.postgresql.package}/bin/createuser hydra
runuser -u ${config.services.postgresql.superUser} -- ${config.services.postgresql.package}/bin/createdb -O hydra hydra
touch ${baseDir}/.db-created
fi
echo "create extension if not exists pg_trgm" | runuser -u ${config.services.postgresql.superUser} -- ${config.services.postgresql.package}/bin/psql hydra
''}
if [ ! -e ${cfg.gcRootsDir} ]; then
# Move legacy roots directory.
if [ -e /nix/var/nix/gcroots/per-user/hydra/hydra-roots ]; then
mv /nix/var/nix/gcroots/per-user/hydra/hydra-roots ${cfg.gcRootsDir}
fi
mkdir -p ${cfg.gcRootsDir}
fi
# Move legacy hydra-www roots.
if [ -e /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots ]; then
find /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots/ -type f \
| xargs -r mv -f -t ${cfg.gcRootsDir}/
rmdir /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots
fi
chown hydra:hydra ${cfg.gcRootsDir}
chmod 2775 ${cfg.gcRootsDir}
'';
serviceConfig.ExecStart = "${cfg.package}/bin/hydra-init";
serviceConfig.PermissionsStartOnly = true;
serviceConfig.User = "hydra";
serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = true;
};
systemd.services.hydra-server =
{ wantedBy = [ "multi-user.target" ];
requires = [ "hydra-init.service" ];
after = [ "hydra-init.service" ];
environment = serverEnv // {
HYDRA_DBI = "${serverEnv.HYDRA_DBI};application_name=hydra-server";
};
restartTriggers = [ hydraConf ];
serviceConfig =
{ ExecStart =
"@${cfg.package}/bin/hydra-server hydra-server -f -h '${cfg.listenHost}' "
+ "-p ${toString cfg.port} --max_spare_servers 5 --max_servers 25 "
+ "--max_requests 100 ${optionalString cfg.debugServer "-d"}";
User = "hydra-www";
PermissionsStartOnly = true;
Restart = "always";
};
};
systemd.services.hydra-queue-runner =
{ wantedBy = [ "multi-user.target" ];
requires = [ "hydra-init.service" ];
wants = [ "network-online.target" ];
after = [ "hydra-init.service" "network.target" "network-online.target" ];
path = [ cfg.package pkgs.hostname-debian pkgs.openssh pkgs.bzip2 config.nix.package ];
restartTriggers = [ hydraConf ];
environment = env // {
PGPASSFILE = "${baseDir}/pgpass-queue-runner"; # grrr
IN_SYSTEMD = "1"; # to get log severity levels
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-queue-runner";
};
serviceConfig =
{ ExecStart = "@${cfg.package}/bin/hydra-queue-runner hydra-queue-runner -v";
ExecStopPost = "${cfg.package}/bin/hydra-queue-runner --unlock";
User = "hydra-queue-runner";
Restart = "always";
# Ensure we can get core dumps.
LimitCORE = "infinity";
WorkingDirectory = "${baseDir}/queue-runner";
};
};
systemd.services.hydra-evaluator =
{ wantedBy = [ "multi-user.target" ];
requires = [ "hydra-init.service" ];
restartTriggers = [ hydraConf ];
after = [ "hydra-init.service" "network.target" ];
path = with pkgs; [ hostname-debian cfg.package ];
environment = env // {
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-evaluator";
};
serviceConfig =
{ ExecStart = "@${cfg.package}/bin/hydra-evaluator hydra-evaluator";
ExecStopPost = "${cfg.package}/bin/hydra-evaluator --unlock";
User = "hydra";
Restart = "always";
WorkingDirectory = baseDir;
};
};
systemd.services.hydra-update-gc-roots =
{ requires = [ "hydra-init.service" ];
after = [ "hydra-init.service" ];
environment = env // {
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-update-gc-roots";
};
serviceConfig =
{ ExecStart = "@${cfg.package}/bin/hydra-update-gc-roots hydra-update-gc-roots";
User = "hydra";
};
startAt = "2,14:15";
};
systemd.services.hydra-send-stats =
{ wantedBy = [ "multi-user.target" ];
after = [ "hydra-init.service" ];
environment = env // {
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-send-stats";
};
serviceConfig =
{ ExecStart = "@${cfg.package}/bin/hydra-send-stats hydra-send-stats";
User = "hydra";
};
};
systemd.services.hydra-notify =
{ wantedBy = [ "multi-user.target" ];
requires = [ "hydra-init.service" ];
after = [ "hydra-init.service" ];
restartTriggers = [ hydraConf ];
path = [ pkgs.zstd ];
environment = env // {
PGPASSFILE = "${baseDir}/pgpass-queue-runner"; # grrr
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-notify";
};
serviceConfig =
{ ExecStart = "@${cfg.package}/bin/hydra-notify hydra-notify";
# FIXME: run this under a less privileged user?
User = "hydra-queue-runner";
Restart = "always";
RestartSec = 5;
};
};
# If there is less than a certain amount of free disk space, stop
# the queue/evaluator to prevent builds from failing or aborting.
# Leaves a tag file indicating this reason; if the tag file exists
# and disk space is above the threshold + 10GB, the queue/evaluator will be
# restarted; starting it if it is already started is not harmful.
systemd.services.hydra-check-space =
{ script =
''
spaceleft=$(($(stat -f -c '%a' /nix/store) * $(stat -f -c '%S' /nix/store)))
spacestopstart() {
service=$1
minFreeGB=$2
if [ $spaceleft -lt $(($minFreeGB * 1024**3)) ]; then
if [ $(systemctl is-active $service) == active ]; then
echo "stopping $service due to lack of free space..."
systemctl stop $service
date > ${baseDir}/.$service-stopped-minspace
fi
else
if [ $spaceleft -gt $(( ($minFreeGB + 10) * 1024**3)) -a \
-r ${baseDir}/.$service-stopped-minspace ] ; then
rm ${baseDir}/.$service-stopped-minspace
echo "restarting $service due to newly available free space..."
systemctl start $service
fi
fi
}
spacestopstart hydra-queue-runner ${toString cfg.minimumDiskFree}
spacestopstart hydra-evaluator ${toString cfg.minimumDiskFreeEvaluator}
'';
startAt = "*:0/5";
};
# Periodically compress build logs. The queue runner compresses
# logs automatically after a step finishes, but this doesn't work
# if the queue runner is stopped prematurely.
systemd.services.hydra-compress-logs =
{ path = [ pkgs.bzip2 pkgs.zstd ];
script =
''
set -eou pipefail
compression=$(sed -nr 's/compress_build_logs_compression = ()/\1/p' ${baseDir}/hydra.conf)
if [[ $compression == "" || $compression == bzip2 ]]; then
compressionCmd=(bzip2)
elif [[ $compression == zstd ]]; then
compressionCmd=(zstd --rm)
fi
find ${baseDir}/build-logs -ignore_readdir_race -type f -name "*.drv" -mtime +3 -size +0c -print0 | xargs -0 -r "''${compressionCmd[@]}" --force --quiet
'';
startAt = "Sun 01:45";
};
services.postgresql.enable = mkIf haveLocalDB true;
services.postgresql.identMap = optionalString haveLocalDB
''
hydra-users hydra hydra
hydra-users hydra-queue-runner hydra
hydra-users hydra-www hydra
hydra-users root hydra
# The postgres user is used to create the pg_trgm extension for the hydra database
hydra-users postgres postgres
'';
services.postgresql.authentication = optionalString haveLocalDB
''
local hydra all ident map=hydra-users
'';
};
}

View File

@@ -0,0 +1,4 @@
install_data('hydra.nix',
install_dir: get_option('datadir') / 'nix',
rename: ['hydra-module.nix'],
)

306
nixos-tests.nix Normal file
View File

@@ -0,0 +1,306 @@
{ forEachSystem, nixpkgs, nixosModules }:
let
# NixOS configuration used for VM tests.
hydraServer =
{ pkgs, ... }:
{
imports = [
nixosModules.hydra
nixosModules.hydraTest
];
virtualisation.memorySize = 1024;
virtualisation.writableStore = true;
environment.systemPackages = [ pkgs.perlPackages.LWP pkgs.perlPackages.JSON ];
nix = {
# Without this nix tries to fetch packages from the default
# cache.nixos.org which is not reachable from this sandboxed NixOS test.
settings.substituters = [ ];
};
};
in
{
install = forEachSystem (system:
(import (nixpkgs + "/nixos/lib/testing-python.nix") { inherit system; }).simpleTest {
name = "hydra-install";
nodes.machine = hydraServer;
testScript =
''
machine.wait_for_job("hydra-init")
machine.wait_for_job("hydra-server")
machine.wait_for_job("hydra-evaluator")
machine.wait_for_job("hydra-queue-runner")
machine.wait_for_open_port(3000)
machine.succeed("curl --fail http://localhost:3000/")
'';
});
notifications = forEachSystem (system:
(import (nixpkgs + "/nixos/lib/testing-python.nix") { inherit system; }).simpleTest {
name = "hydra-notifications";
nodes.machine = {
imports = [ hydraServer ];
services.hydra-dev.extraConfig = ''
<influxdb>
url = http://127.0.0.1:8086
db = hydra
</influxdb>
'';
services.influxdb.enable = true;
};
testScript = { nodes, ... }: ''
machine.wait_for_job("hydra-init")
# Create an admin account and some other state.
machine.succeed(
"""
su - hydra -c "hydra-create-user root --email-address 'alice@example.org' --password foobar --role admin"
mkdir /run/jobset
chmod 755 /run/jobset
cp ${./t/jobs/api-test.nix} /run/jobset/default.nix
chmod 644 /run/jobset/default.nix
chown -R hydra /run/jobset
"""
)
# Wait until InfluxDB can receive web requests
machine.wait_for_job("influxdb")
machine.wait_for_open_port(8086)
# Create an InfluxDB database where hydra will write to
machine.succeed(
"curl -XPOST 'http://127.0.0.1:8086/query' "
+ "--data-urlencode 'q=CREATE DATABASE hydra'"
)
# Wait until hydra-server can receive HTTP requests
machine.wait_for_job("hydra-server")
machine.wait_for_open_port(3000)
# Setup the project and jobset
machine.succeed(
"su - hydra -c 'perl -I ${nodes.machine.services.hydra-dev.package.perlDeps}/lib/perl5/site_perl ${./t/setup-notifications-jobset.pl}' >&2"
)
# Wait until hydra has build the job and
# the InfluxDBNotification plugin uploaded its notification to InfluxDB
machine.wait_until_succeeds(
"curl -s -H 'Accept: application/csv' "
+ "-G 'http://127.0.0.1:8086/query?db=hydra' "
+ "--data-urlencode 'q=SELECT * FROM hydra_build_status' | grep success"
)
'';
});
gitea = forEachSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
(import (nixpkgs + "/nixos/lib/testing-python.nix") { inherit system; }).makeTest {
name = "hydra-gitea";
nodes.machine = { pkgs, ... }: {
imports = [ hydraServer ];
services.hydra-dev.extraConfig = ''
<gitea_authorization>
root=d7f16a3412e01a43a414535b16007c6931d3a9c7
</gitea_authorization>
'';
nixpkgs.config.permittedInsecurePackages = [ "gitea-1.19.4" ];
nix = {
settings.substituters = [ ];
};
services.gitea = {
enable = true;
database.type = "postgres";
settings = {
service.DISABLE_REGISTRATION = true;
server.HTTP_PORT = 3001;
};
};
services.openssh.enable = true;
environment.systemPackages = with pkgs; [ gitea git jq gawk ];
networking.firewall.allowedTCPPorts = [ 3000 ];
};
skipLint = true;
testScript =
let
scripts.mktoken = pkgs.writeText "token.sql" ''
INSERT INTO access_token (id, uid, name, created_unix, updated_unix, token_hash, token_salt, token_last_eight, scope) VALUES (1, 1, 'hydra', 1617107360, 1617107360, 'a930f319ca362d7b49a4040ac0af74521c3a3c3303a86f327b01994430672d33b6ec53e4ea774253208686c712495e12a486', 'XRjWE9YW0g', '31d3a9c7', 'all');
'';
scripts.git-setup = pkgs.writeShellScript "setup.sh" ''
set -x
mkdir -p /tmp/repo $HOME/.ssh
cat ${snakeoilKeypair.privkey} > $HOME/.ssh/privk
chmod 0400 $HOME/.ssh/privk
git -C /tmp/repo init
cp ${smallDrv} /tmp/repo/jobset.nix
git -C /tmp/repo add .
git config --global user.email test@localhost
git config --global user.name test
git -C /tmp/repo commit -m 'Initial import'
git -C /tmp/repo remote add origin gitea@machine:root/repo
GIT_SSH_COMMAND='ssh -i $HOME/.ssh/privk -o StrictHostKeyChecking=no' \
git -C /tmp/repo push origin master
git -C /tmp/repo log >&2
'';
scripts.hydra-setup = pkgs.writeShellScript "hydra.sh" ''
set -x
su -l hydra -c "hydra-create-user root --email-address \
'alice@example.org' --password foobar --role admin"
URL=http://localhost:3000
USERNAME="root"
PASSWORD="foobar"
PROJECT_NAME="trivial"
JOBSET_NAME="trivial"
mycurl() {
curl --referer $URL -H "Accept: application/json" \
-H "Content-Type: application/json" $@
}
cat >data.json <<EOF
{ "username": "$USERNAME", "password": "$PASSWORD" }
EOF
mycurl -X POST -d '@data.json' $URL/login -c hydra-cookie.txt
cat >data.json <<EOF
{
"displayname":"Trivial",
"enabled":"1",
"visible":"1"
}
EOF
mycurl --silent -X PUT $URL/project/$PROJECT_NAME \
-d @data.json -b hydra-cookie.txt
cat >data.json <<EOF
{
"description": "Trivial",
"checkinterval": "60",
"enabled": "1",
"visible": "1",
"keepnr": "1",
"enableemail": true,
"emailoverride": "hydra@localhost",
"type": 0,
"nixexprinput": "git",
"nixexprpath": "jobset.nix",
"inputs": {
"git": {"value": "http://localhost:3001/root/repo.git", "type": "git"},
"gitea_repo_name": {"value": "repo", "type": "string"},
"gitea_repo_owner": {"value": "root", "type": "string"},
"gitea_status_repo": {"value": "git", "type": "string"},
"gitea_http_url": {"value": "http://localhost:3001", "type": "string"}
}
}
EOF
mycurl --silent -X PUT $URL/jobset/$PROJECT_NAME/$JOBSET_NAME \
-d @data.json -b hydra-cookie.txt
'';
api_token = "d7f16a3412e01a43a414535b16007c6931d3a9c7";
snakeoilKeypair = {
privkey = pkgs.writeText "privkey.snakeoil" ''
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIHQf/khLvYrQ8IOika5yqtWvI0oquHlpRLTZiJy5dRJmoAoGCCqGSM49
AwEHoUQDQgAEKF0DYGbBwbj06tA3fd/+yP44cvmwmHBWXZCKbS+RQlAKvLXMWkpN
r1lwMyJZoSGgBHoUahoYjTh9/sJL7XLJtA==
-----END EC PRIVATE KEY-----
'';
pubkey = pkgs.lib.concatStrings [
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHA"
"yNTYAAABBBChdA2BmwcG49OrQN33f/sj+OHL5sJhwVl2Qim0vkUJQCry1zFpKTa"
"9ZcDMiWaEhoAR6FGoaGI04ff7CS+1yybQ= sakeoil"
];
};
smallDrv = pkgs.writeText "jobset.nix" ''
{ trivial = builtins.derivation {
name = "trivial";
system = "${system}";
builder = "/bin/sh";
allowSubstitutes = false;
preferLocalBuild = true;
args = ["-c" "echo success > $out; exit 0"];
};
}
'';
in
''
import json
machine.start()
machine.wait_for_unit("multi-user.target")
machine.wait_for_open_port(3000)
machine.wait_for_open_port(3001)
machine.succeed(
"su -l gitea -c 'GITEA_WORK_DIR=/var/lib/gitea gitea admin user create "
+ "--username root --password root --email test@localhost'"
)
machine.succeed("su -l postgres -c 'psql gitea < ${scripts.mktoken}'")
machine.succeed(
"curl --fail -X POST http://localhost:3001/api/v1/user/repos "
+ "-H 'Accept: application/json' -H 'Content-Type: application/json' "
+ f"-H 'Authorization: token ${api_token}'"
+ ' -d \'{"auto_init":false, "description":"string", "license":"mit", "name":"repo", "private":false}\'''
)
machine.succeed(
"curl --fail -X POST http://localhost:3001/api/v1/user/keys "
+ "-H 'Accept: application/json' -H 'Content-Type: application/json' "
+ f"-H 'Authorization: token ${api_token}'"
+ ' -d \'{"key":"${snakeoilKeypair.pubkey}","read_only":true,"title":"SSH"}\'''
)
machine.succeed(
"${scripts.git-setup}"
)
machine.succeed(
"${scripts.hydra-setup}"
)
machine.wait_until_succeeds(
'curl -Lf -s http://localhost:3000/build/1 -H "Accept: application/json" '
+ '| jq .buildstatus | xargs test 0 -eq'
)
data = machine.succeed(
'curl -Lf -s "http://localhost:3001/api/v1/repos/root/repo/statuses/$(cd /tmp/repo && git show | head -n1 | awk "{print \\$2}")" '
+ "-H 'Accept: application/json' -H 'Content-Type: application/json' "
+ f"-H 'Authorization: token ${api_token}'"
)
response = json.loads(data)
assert len(response) == 2, "Expected exactly three status updates for latest commit (queued, finished)!"
assert response[0]['status'] == "success", "Expected finished status to be success!"
assert response[1]['status'] == "pending", "Expected queued status to be pending!"
machine.shutdown()
'';
});
validate-openapi = forEachSystem (system:
let pkgs = nixpkgs.legacyPackages.${system}; in
pkgs.runCommand "validate-openapi"
{ buildInputs = [ pkgs.openapi-generator-cli ]; }
''
openapi-generator-cli validate -i ${./hydra-api.yaml}
touch $out
'');
}

285
package.nix Normal file
View File

@@ -0,0 +1,285 @@
{ stdenv
, lib
, fileset
, rawSrc
, buildEnv
, perlPackages
, nixComponents
, git
, makeWrapper
, meson
, ninja
, nukeReferences
, pkg-config
, mdbook
, unzip
, libpqxx
, top-git
, mercurial
, darcs
, subversion
, breezy
, openssl
, bzip2
, libxslt
, perl
, pixz
, boost
, postgresql_17
, nlohmann_json
, prometheus-cpp
, cacert
, foreman
, glibcLocales
, libressl
, openldap
, python3
, openssh
, coreutils
, findutils
, gzip
, xz
, gnutar
, gnused
, nix-eval-jobs
, rpm
, dpkg
, cdrkit
}:
let
perlDeps = buildEnv {
name = "hydra-perl-deps";
paths = lib.closePropagation
([
nixComponents.nix-perl-bindings
git
] ++ (with perlPackages; [
AuthenSASL
CatalystActionREST
CatalystAuthenticationStoreDBIxClass
CatalystAuthenticationStoreLDAP
CatalystDevel
CatalystPluginAccessLog
CatalystPluginAuthorizationRoles
CatalystPluginCaptcha
CatalystPluginPrometheusTiny
CatalystPluginSessionStateCookie
CatalystPluginSessionStoreFastMmap
CatalystPluginStackTrace
CatalystTraitForRequestProxyBase
CatalystViewDownload
CatalystViewJSON
CatalystViewTT
CatalystXRoleApplicator
CatalystXScriptServerStarman
CryptPassphrase
CryptPassphraseArgon2
CryptRandPasswd
DataDump
DateTime
DBDPg
DBDSQLite
DBIxClassHelpers
DigestSHA1
EmailMIME
EmailSender
FileCopyRecursive
FileLibMagic
FileSlurper
FileWhich
IOCompress
IPCRun
IPCRun3
JSON
JSONMaybeXS
JSONXS
ListSomeUtils
LWP
LWPProtocolHttps
ModulePluggable
NetAmazonS3
NetPrometheus
NetStatsd
NumberBytesHuman
PadWalker
ParallelForkManager
PerlCriticCommunity
PrometheusTinyShared
ReadonlyX
SetScalar
SQLSplitStatement
Starman
StringCompareConstantTime
SysHostnameLong
TermSizeAny
TermReadKey
Test2Harness
TestPostgreSQL
TextDiff
TextTable
UUID4Tiny
YAML
XMLSimple
]));
};
version = "${builtins.readFile ./version.txt}.${builtins.substring 0 8 (rawSrc.lastModifiedDate or "19700101")}.${rawSrc.shortRev or "DIRTY"}";
in
stdenv.mkDerivation (finalAttrs: {
pname = "hydra";
inherit version;
src = fileset.toSource {
root = ./.;
fileset = fileset.unions ([
./doc
./meson.build
./nixos-modules
./src
./t
./version.txt
./.perlcriticrc
]);
};
outputs = [ "out" "doc" ];
strictDeps = true;
nativeBuildInputs = [
makeWrapper
meson
ninja
nukeReferences
pkg-config
mdbook
nixComponents.nix-cli
perlDeps
perl
unzip
];
buildInputs = [
libpqxx
openssl
libxslt
nixComponents.nix-util
nixComponents.nix-store
nixComponents.nix-main
perlDeps
perl
boost
nlohmann_json
prometheus-cpp
];
nativeCheckInputs = [
bzip2
darcs
foreman
top-git
mercurial
subversion
breezy
openldap
postgresql_17
pixz
nix-eval-jobs
];
checkInputs = [
cacert
glibcLocales
libressl.nc
python3
nixComponents.nix-cli
];
hydraPath = lib.makeBinPath (
[
subversion
openssh
nixComponents.nix-cli
coreutils
findutils
pixz
gzip
bzip2
xz
gnutar
unzip
git
top-git
mercurial
darcs
gnused
breezy
nix-eval-jobs
] ++ lib.optionals stdenv.isLinux [ rpm dpkg cdrkit ]
);
OPENLDAP_ROOT = openldap;
mesonBuildType = "release";
postPatch = ''
patchShebangs .
'';
shellHook = ''
pushd $(git rev-parse --show-toplevel) >/dev/null
PATH=$(pwd)/build/src/hydra-evaluator:$(pwd)/src/script:$(pwd)/build/src/hydra-queue-runner:$PATH
PERL5LIB=$(pwd)/src/lib:$PERL5LIB
export HYDRA_HOME="$(pwd)/src/"
mkdir -p .hydra-data
export HYDRA_DATA="$(pwd)/.hydra-data"
export HYDRA_DBI='dbi:Pg:dbname=hydra;host=localhost;port=64444'
popd >/dev/null
'';
doCheck = true;
mesonCheckFlags = [ "--verbose" ];
preCheck = ''
export LOGNAME=''${LOGNAME:-foo}
# set $HOME for bzr so it can create its trace file
export HOME=$(mktemp -d)
'';
postInstall = ''
mkdir -p $out/nix-support
for i in $out/bin/*; do
read -n 4 chars < $i
if [[ $chars =~ ELF ]]; then continue; fi
wrapProgram $i \
--prefix PERL5LIB ':' $out/libexec/hydra/lib:$PERL5LIB \
--prefix PATH ':' $out/bin:$hydraPath \
--set HYDRA_RELEASE ${version} \
--set HYDRA_HOME $out/libexec/hydra \
--set NIX_RELEASE ${nixComponents.nix-cli.name or "unknown"} \
--set NIX_EVAL_JOBS_RELEASE ${nix-eval-jobs.name or "unknown"}
done
'';
dontStrip = true;
meta.description = "Build of Hydra on ${stdenv.system}";
passthru = {
inherit perlDeps;
nix = nixComponents.nix-cli;
};
})

View File

@@ -1,133 +0,0 @@
{ nixpkgs ? /etc/nixos/nixpkgs
, hydraSrc ? { outPath = ./.; revCount = 1234; gitTag = "abcdef"; }
, officialRelease ? false
}:
rec {
tarball =
with import nixpkgs { };
let nix = nixUnstable; in
releaseTools.makeSourceTarball {
name = "hydra-tarball";
src = hydraSrc;
inherit officialRelease;
version = builtins.readFile ./version;
buildInputs =
[ perl libxslt dblatex tetex nukeReferences pkgconfig boehmgc git ];
versionSuffix = if officialRelease then "" else "pre${toString hydraSrc.revCount}-${hydraSrc.gitTag}";
preConfigure = ''
# TeX needs a writable font cache.
export VARTEXFONTS=$TMPDIR/texfonts
'';
configureFlags =
[ "--with-nix=${nix}"
"--with-docbook-xsl=${docbook_xsl}/xml/xsl/docbook"
];
postDist = ''
make -C doc/manual install prefix="$out"
nuke-refs "$out/share/doc/hydra/manual.pdf"
echo "doc manual $out/share/doc/hydra manual.html" >> \
"$out/nix-support/hydra-build-products"
echo "doc-pdf manual $out/share/doc/hydra/manual.pdf" >> \
"$out/nix-support/hydra-build-products"
'';
};
build =
{ system ? "x86_64-linux" }:
let pkgs = import nixpkgs {inherit system;}; in
with pkgs;
let nix = nixUnstable; in
releaseTools.nixBuild {
name = "hydra";
src = tarball;
configureFlags = "--with-nix=${nix}";
buildInputs =
[ perl makeWrapper libtool nix unzip nukeReferences pkgconfig boehmgc sqlite git gitAndTools.topGit mercurial subversion bazaar ]
++ (import ./deps.nix) { inherit pkgs; };
hydraPath = stdenv.lib.concatStringsSep ":" (map (p: "${p}/bin") ( [
libxslt sqlite subversion openssh nix coreutils findutils
gzip bzip2 lzma gnutar unzip git gitAndTools.topGit mercurial gnused graphviz bazaar
] ++ ( if stdenv.isLinux then [rpm dpkg cdrkit] else [] )));
preConfigure = "patchShebangs .";
postInstall = ''
ensureDir $out/nix-support
nuke-refs $out/share/doc/hydra/manual/manual.pdf
for i in $out/bin/*; do
wrapProgram $i \
--prefix PERL5LIB ':' $out/libexec/hydra/lib:$PERL5LIB \
--prefix PATH ':' $out/bin:$hydraPath \
--set HYDRA_RELEASE ${tarball.version} \
--set HYDRA_HOME $out/libexec/hydra \
--set NIX_RELEASE ${nix.name}
done
''; # */
LOGNAME="$USER";
meta = {
description = "Build of Hydra on ${system}";
};
succeedOnFailure = true;
keepBuildDirectory = true;
};
tests =
{ nixos ? ../nixos, system ? "x86_64-linux" }:
let hydra = build { inherit system; }; in
with import "${nixos}/lib/testing.nix" { inherit nixpkgs system; };
{
install = simpleTest {
machine =
{ config, pkgs, ... }:
{ services.postgresql.enable = true;
environment.systemPackages = [ hydra ];
};
testScript =
''
$machine->waitForJob("postgresql");
# Initialise the database and the state.
$machine->mustSucceed
( "createdb -O root hydra",
, "psql hydra -f ${hydra}/share/hydra/sql/hydra-postgresql.sql"
, "mkdir /var/lib/hydra"
);
# Start the web interface.
#$machine->mustSucceed("HYDRA_DATA=/var/lib/hydra HYDRA_DBI='dbi:Pg:dbname=hydra;user=hydra;' hydra-server >&2 &");
#$machine->waitForOpenPort("3000");
'';
};
};
}

6
shell.nix Normal file
View File

@@ -0,0 +1,6 @@
# The `default.nix` in flake-compat reads `flake.nix` and `flake.lock` from `src` and
# returns an attribute set of the shape `{ defaultNix, shellNix }`
(import (fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz") {
src = ./.;
}).shellNix

View File

@@ -1,5 +1,7 @@
# IMPORTANT: if you delete this file your app will not work as
# expected. you have been warned
use strict;
use warnings;
use inc::Module::Install;
name 'Hydra';

View File

@@ -1,4 +0,0 @@
SUBDIRS = c sql script lib root xsl
BOOTCLEAN_SUBDIRS = $(SUBDIRS)
DIST_SUBDIRS = $(SUBDIRS)

View File

@@ -1,8 +0,0 @@
bin_PROGRAMS = hydra-eval-jobs
hydra_eval_jobs_SOURCES = hydra-eval-jobs.cc
hydra_eval_jobs_LDADD = -lmain -lexpr -L$(nix)/lib/nix $(BDW_GC_LIBS)
AM_CXXFLAGS = \
-I$(nix)/include/nix \
$(BDW_GC_CFLAGS)

View File

@@ -1,265 +0,0 @@
#include <map>
#include <iostream>
#include <gc/gc_allocator.h>
#include "shared.hh"
#include "store-api.hh"
#include "eval.hh"
#include "util.hh"
#include "xml-writer.hh"
#include "get-drvs.hh"
#include "common-opts.hh"
using namespace nix;
void printHelp()
{
std::cout << "Syntax: eval-jobs <expr>\n";
}
static Path gcRootsDir;
typedef std::map<Symbol, std::pair<unsigned int, Value *> > ArgsUsed;
typedef std::list<Value *, traceable_allocator<Value *> > ValueList;
typedef std::map<Symbol, ValueList> AutoArgs;
static void findJobs(EvalState & state, XMLWriter & doc,
const ArgsUsed & argsUsed, const AutoArgs & argsLeft,
Value & v, const string & attrPath);
static void tryJobAlts(EvalState & state, XMLWriter & doc,
const ArgsUsed & argsUsed, const AutoArgs & argsLeft,
const string & attrPath, Value & fun,
Formals::Formals_::iterator cur,
Formals::Formals_::iterator last,
const Bindings & actualArgs)
{
if (cur == last) {
Value v, * arg = state.allocValue();
state.mkAttrs(*arg, 0);
*arg->attrs = actualArgs;
mkApp(v, fun, *arg);
findJobs(state, doc, argsUsed, argsLeft, v, attrPath);
return;
}
AutoArgs::const_iterator a = argsLeft.find(cur->name);
if (a == argsLeft.end())
throw TypeError(format("job `%1%' requires an argument named `%2%'")
% attrPath % cur->name);
Formals::Formals_::iterator next = cur; ++next;
int n = 0;
foreach (ValueList::const_iterator, i, a->second) {
Bindings actualArgs2(actualArgs); // !!! inefficient
ArgsUsed argsUsed2(argsUsed);
AutoArgs argsLeft2(argsLeft);
actualArgs2.push_back(Attr(cur->name, *i));
actualArgs2.sort(); // !!! inefficient
argsUsed2[cur->name] = std::pair<unsigned int, Value *>(n, *i);
argsLeft2.erase(cur->name);
tryJobAlts(state, doc, argsUsed2, argsLeft2, attrPath, fun, next, last, actualArgs2);
++n;
}
}
static void showArgsUsed(XMLWriter & doc, const ArgsUsed & argsUsed)
{
foreach (ArgsUsed::const_iterator, i, argsUsed) {
XMLAttrs xmlAttrs2;
xmlAttrs2["name"] = i->first;
xmlAttrs2["value"] = (format("%1%") % *i->second.second).str();
xmlAttrs2["altnr"] = int2String(i->second.first);
doc.writeEmptyElement("arg", xmlAttrs2);
}
}
static string queryMetaFieldString(MetaInfo & meta, const string & name)
{
MetaValue value = meta[name];
if (value.type != MetaValue::tpString) return "";
return value.stringValue;
}
static int queryMetaFieldInt(MetaInfo & meta, const string & name, int def)
{
MetaValue value = meta[name];
if (value.type == MetaValue::tpInt) return value.intValue;
if (value.type == MetaValue::tpString) {
int n;
if (string2Int(value.stringValue, n)) return n;
}
return def;
}
static void findJobsWrapped(EvalState & state, XMLWriter & doc,
const ArgsUsed & argsUsed, const AutoArgs & argsLeft,
Value & v, const string & attrPath)
{
debug(format("at path `%1%'") % attrPath);
state.forceValue(v);
if (v.type == tAttrs) {
DrvInfo drv;
if (getDerivation(state, v, drv)) {
XMLAttrs xmlAttrs;
Path drvPath;
xmlAttrs["jobName"] = attrPath;
xmlAttrs["nixName"] = drv.name;
xmlAttrs["system"] = drv.system;
xmlAttrs["drvPath"] = drvPath = drv.queryDrvPath(state);
xmlAttrs["outPath"] = drv.queryOutPath(state);
MetaInfo meta = drv.queryMetaInfo(state);
xmlAttrs["description"] = queryMetaFieldString(meta, "description");
xmlAttrs["longDescription"] = queryMetaFieldString(meta, "longDescription");
xmlAttrs["license"] = queryMetaFieldString(meta, "license");
xmlAttrs["homepage"] = queryMetaFieldString(meta, "homepage");
int prio = queryMetaFieldInt(meta, "schedulingPriority", 100);
xmlAttrs["schedulingPriority"] = int2String(prio);
int timeout = queryMetaFieldInt(meta, "timeout", 36000);
xmlAttrs["timeout"] = int2String(timeout);
int maxsilent = queryMetaFieldInt(meta, "maxSilent", 3600);
xmlAttrs["maxSilent"] = int2String(maxsilent);
string maintainers;
MetaValue value = meta["maintainers"];
if (value.type == MetaValue::tpString)
maintainers = value.stringValue;
else if (value.type == MetaValue::tpStrings) {
foreach (Strings::const_iterator, i, value.stringValues) {
if (maintainers.size() != 0) maintainers += ", ";
maintainers += *i;
}
}
xmlAttrs["maintainers"] = maintainers;
/* Register the derivation as a GC root. !!! This
registers roots for jobs that we may have already
done. */
if (gcRootsDir != "") {
Path root = gcRootsDir + "/" + baseNameOf(drvPath);
if (!pathExists(root)) addPermRoot(*store, drvPath, root, false);
}
XMLOpenElement _(doc, "job", xmlAttrs);
showArgsUsed(doc, argsUsed);
}
else {
foreach (Bindings::iterator, i, *v.attrs)
findJobs(state, doc, argsUsed, argsLeft, *i->value,
(attrPath.empty() ? "" : attrPath + ".") + (string) i->name);
}
}
else if (v.type == tLambda && v.lambda.fun->matchAttrs) {
tryJobAlts(state, doc, argsUsed, argsLeft, attrPath, v,
v.lambda.fun->formals->formals.begin(),
v.lambda.fun->formals->formals.end(),
Bindings());
}
else if (v.type == tNull) {
// allow null values, meaning 'do nothing'
}
else
throw TypeError(format("unsupported value: %1%") % v);
}
static void findJobs(EvalState & state, XMLWriter & doc,
const ArgsUsed & argsUsed, const AutoArgs & argsLeft,
Value & v, const string & attrPath)
{
try {
findJobsWrapped(state, doc, argsUsed, argsLeft, v, attrPath);
} catch (EvalError & e) {
XMLAttrs xmlAttrs;
xmlAttrs["location"] = attrPath;
xmlAttrs["msg"] = e.msg();
XMLOpenElement _(doc, "error", xmlAttrs);
showArgsUsed(doc, argsUsed);
}
}
void run(Strings args)
{
EvalState state;
Path releaseExpr;
AutoArgs autoArgs;
/* Prevent undeclared dependencies in the evaluation via
$HYDRA_PATH. */
unsetenv("HYDRA_PATH");
for (Strings::iterator i = args.begin(); i != args.end(); ) {
string arg = *i++;
if (arg == "--arg" || arg == "--argstr") {
/* This is like --arg in nix-instantiate, except that it
supports multiple versions for the same argument.
That is, autoArgs is a mapping from variable names to
*lists* of values. */
if (i == args.end()) throw UsageError("missing argument");
string name = *i++;
if (i == args.end()) throw UsageError("missing argument");
string value = *i++;
Value * v = state.allocValue();
if (arg == "--arg")
state.eval(state.parseExprFromString(value, absPath(".")), *v);
else
mkString(*v, value);
autoArgs[state.symbols.create(name)].push_back(v);
}
else if (arg == "--gc-roots-dir") {
if (i == args.end()) throw UsageError("missing argument");
gcRootsDir = *i++;
}
else if (parseSearchPathArg(arg, i, args.end(), state))
;
else if (arg[0] == '-')
throw UsageError(format("unknown flag `%1%'") % arg);
else
releaseExpr = arg;
}
if (releaseExpr == "") throw UsageError("no expression specified");
if (gcRootsDir == "") printMsg(lvlError, "warning: `--gc-roots-dir' not specified");
store = openStore();
Expr * e = state.parseExprFromFile(releaseExpr);
Value v;
state.mkThunk_(v, e);
std::cout.setf(std::ios::unitbuf);
XMLWriter doc(true, std::cout);
XMLOpenElement root(doc, "jobs");
findJobs(state, doc, ArgsUsed(), autoArgs, v, "");
state.printStats();
}
string programId = "eval-jobs";

View File

@@ -0,0 +1,521 @@
#include "db.hh"
#include "hydra-config.hh"
#include <nix/util/pool.hh>
#include <nix/main/shared.hh>
#include <nix/util/signals.hh>
#include <algorithm>
#include <thread>
#include <cstring>
#include <optional>
#include <sys/types.h>
#include <sys/wait.h>
using namespace nix;
typedef std::pair<std::string, std::string> JobsetName;
class JobsetId {
public:
std::string project;
std::string jobset;
int id;
JobsetId(const std::string & project, const std::string & jobset, int id)
: project{ project }, jobset{ jobset }, id{ id }
{
}
friend bool operator== (const JobsetId & lhs, const JobsetId & rhs);
friend bool operator!= (const JobsetId & lhs, const JobsetId & rhs);
friend bool operator< (const JobsetId & lhs, const JobsetId & rhs);
friend bool operator== (const JobsetId & lhs, const JobsetName & rhs);
friend bool operator!= (const JobsetId & lhs, const JobsetName & rhs);
std::string display() const {
return boost::str(boost::format("%1%:%2% (jobset#%3%)") % project % jobset % id);
}
};
bool operator==(const JobsetId & lhs, const JobsetId & rhs)
{
return lhs.id == rhs.id;
}
bool operator!=(const JobsetId & lhs, const JobsetId & rhs)
{
return lhs.id != rhs.id;
}
bool operator<(const JobsetId & lhs, const JobsetId & rhs)
{
return lhs.id < rhs.id;
}
bool operator==(const JobsetId & lhs, const JobsetName & rhs)
{
return lhs.project == rhs.first && lhs.jobset == rhs.second;
}
bool operator!=(const JobsetId & lhs, const JobsetName & rhs)
{
return ! (lhs == rhs);
}
enum class EvaluationStyle
{
SCHEDULE = 1,
ONESHOT = 2,
ONE_AT_A_TIME = 3,
};
struct Evaluator
{
std::unique_ptr<HydraConfig> config;
nix::Pool<Connection> dbPool;
struct Jobset
{
JobsetId name;
std::optional<EvaluationStyle> evaluation_style;
time_t lastCheckedTime, triggerTime;
int checkInterval;
Pid pid;
};
typedef std::map<JobsetId, Jobset> Jobsets;
std::optional<JobsetName> evalOne;
const size_t maxEvals;
struct State
{
size_t runningEvals = 0;
Jobsets jobsets;
};
Sync<State> state_;
std::condition_variable childStarted;
std::condition_variable maybeDoWork;
const time_t notTriggered = std::numeric_limits<time_t>::max();
Evaluator()
: config(std::make_unique<HydraConfig>())
, maxEvals(std::max((size_t) 1, (size_t) config->getIntOption("max_concurrent_evals", 4)))
{ }
void readJobsets()
{
auto conn(dbPool.get());
pqxx::work txn(*conn);
auto res = txn.exec
("select j.id as id, project, j.name, lastCheckedTime, triggerTime, checkInterval, j.enabled as jobset_enabled "
"from Jobsets j "
"join Projects p on j.project = p.name "
"where j.enabled != 0 and p.enabled != 0");
auto state(state_.lock());
std::set<JobsetId> seen;
for (auto const & row : res) {
auto name = JobsetId{row["project"].as<std::string>(), row["name"].as<std::string>(), row["id"].as<int>()};
if (evalOne && name != *evalOne) continue;
auto res = state->jobsets.try_emplace(name, Jobset{name});
auto & jobset = res.first->second;
jobset.lastCheckedTime = row["lastCheckedTime"].as<time_t>(0);
jobset.triggerTime = row["triggerTime"].as<time_t>(notTriggered);
jobset.checkInterval = row["checkInterval"].as<time_t>();
switch (row["jobset_enabled"].as<int>(0)) {
case 1:
jobset.evaluation_style = EvaluationStyle::SCHEDULE;
break;
case 2:
jobset.evaluation_style = EvaluationStyle::ONESHOT;
break;
case 3:
jobset.evaluation_style = EvaluationStyle::ONE_AT_A_TIME;
break;
}
seen.insert(name);
}
if (evalOne && seen.empty()) {
printError("the specified jobset does not exist or is disabled");
std::_Exit(1);
}
for (auto i = state->jobsets.begin(); i != state->jobsets.end(); )
if (seen.count(i->first))
++i;
else {
printInfo("forgetting jobset %s", i->first.display());
i = state->jobsets.erase(i);
}
}
void startEval(State & state, Jobset & jobset)
{
time_t now = time(0);
printInfo("starting evaluation of jobset %s (last checked %d s ago)",
jobset.name.display(),
now - jobset.lastCheckedTime);
{
auto conn(dbPool.get());
pqxx::work txn(*conn);
txn.exec("update Jobsets set startTime = $1 where id = $2",
pqxx::params{now, jobset.name.id}).no_rows();
txn.commit();
}
assert(jobset.pid == -1);
jobset.pid = startProcess([&]() {
Strings args = { "hydra-eval-jobset", jobset.name.project, jobset.name.jobset };
execvp(args.front().c_str(), stringsToCharPtrs(args).data());
throw SysError("executing %1%", args.front());
});
state.runningEvals++;
childStarted.notify_one();
}
bool shouldEvaluate(Jobset & jobset)
{
if (jobset.pid != -1) {
// Already running.
debug("shouldEvaluate %s? no: already running",
jobset.name.display());
return false;
}
if (jobset.triggerTime != std::numeric_limits<time_t>::max()) {
// An evaluation of this Jobset is requested
debug("shouldEvaluate %s? yes: requested",
jobset.name.display());
return true;
}
if (jobset.checkInterval <= 0) {
// Automatic scheduling is disabled. We allow requested
// evaluations, but never schedule start one.
debug("shouldEvaluate %s? no: checkInterval <= 0",
jobset.name.display());
return false;
}
if (jobset.lastCheckedTime + jobset.checkInterval <= time(0)) {
// Time to schedule a fresh evaluation. If the jobset
// is a ONE_AT_A_TIME jobset, ensure the previous jobset
// has no remaining, unfinished work.
auto conn(dbPool.get());
pqxx::work txn(*conn);
if (jobset.evaluation_style == EvaluationStyle::ONE_AT_A_TIME) {
auto evaluation_res = txn.exec
("select id from JobsetEvals "
"where jobset_id = $1 "
"order by id desc limit 1"
,jobset.name.id
);
if (evaluation_res.empty()) {
// First evaluation, so allow scheduling.
debug("shouldEvaluate(one-at-a-time) %s? yes: no prior eval",
jobset.name.display());
return true;
}
auto evaluation_id = evaluation_res[0][0].as<int>();
auto unfinished_build_res = txn.exec
("select id from Builds "
"join JobsetEvalMembers "
" on (JobsetEvalMembers.build = Builds.id) "
"where JobsetEvalMembers.eval = $1 "
" and builds.finished = 0 "
" limit 1"
,evaluation_id
);
// If the previous evaluation has no unfinished builds
// schedule!
if (unfinished_build_res.empty()) {
debug("shouldEvaluate(one-at-a-time) %s? yes: no unfinished builds",
jobset.name.display());
return true;
} else {
debug("shouldEvaluate(one-at-a-time) %s:%s? no: at least one unfinished build",
jobset.name.display());
return false;
}
} else {
// EvaluationStyle::ONESHOT, EvaluationStyle::SCHEDULED
debug("shouldEvaluate(oneshot/scheduled) %s? yes: checkInterval elapsed",
jobset.name.display());
return true;
}
}
return false;
}
void startEvals(State & state)
{
std::vector<Jobsets::iterator> sorted;
/* Filter out jobsets that have been evaluated recently and have
not been triggered. */
for (auto i = state.jobsets.begin(); i != state.jobsets.end(); ++i)
if (evalOne ||
(i->second.evaluation_style && shouldEvaluate(i->second)))
sorted.push_back(i);
/* Put jobsets in order of ascending trigger time, last checked
time, and name. */
std::sort(sorted.begin(), sorted.end(),
[](const Jobsets::iterator & a, const Jobsets::iterator & b) {
return
a->second.triggerTime != b->second.triggerTime
? a->second.triggerTime < b->second.triggerTime
: a->second.lastCheckedTime != b->second.lastCheckedTime
? a->second.lastCheckedTime < b->second.lastCheckedTime
: a->first < b->first;
});
/* Start jobset evaluations up to the concurrency limit.*/
for (auto & i : sorted) {
if (state.runningEvals >= maxEvals) break;
startEval(state, i->second);
}
}
void loop()
{
auto state(state_.lock());
while (true) {
time_t now = time(0);
std::chrono::seconds sleepTime = std::chrono::seconds::max();
if (state->runningEvals < maxEvals) {
for (auto & i : state->jobsets)
if (i.second.pid == -1 &&
i.second.checkInterval > 0)
sleepTime = std::min(sleepTime, std::chrono::seconds(
std::max((time_t) 1, i.second.lastCheckedTime - now + i.second.checkInterval)));
}
debug("waiting for %d s", sleepTime.count());
if (sleepTime == std::chrono::seconds::max())
state.wait(maybeDoWork);
else
state.wait_for(maybeDoWork, sleepTime);
startEvals(*state);
}
}
/* A thread that listens to PostgreSQL notifications about jobset
changes, updates the jobsets map, and signals the main thread
to start evaluations. */
void databaseMonitor()
{
while (true) {
try {
auto conn(dbPool.get());
receiver jobsetsAdded(*conn, "jobsets_added");
receiver jobsetsDeleted(*conn, "jobsets_deleted");
receiver jobsetsChanged(*conn, "jobset_scheduling_changed");
while (true) {
/* Note: we read/notify before
await_notification() to ensure we don't miss a
state change. */
readJobsets();
maybeDoWork.notify_one();
conn->await_notification();
printInfo("received jobset event");
}
} catch (pqxx::broken_connection & e) {
printError("Database connection broken: %s", e.what());
std::_Exit(1);
} catch (std::exception & e) {
printError("exception in database monitor thread: %s", e.what());
sleep(30);
}
}
}
/* A thread that reaps child processes.*/
void reaper()
{
while (true) {
{
auto state(state_.lock());
while (!state->runningEvals)
state.wait(childStarted);
}
int status;
pid_t pid = waitpid(-1, &status, 0);
if (pid == -1) {
if (errno == EINTR) continue;
throw SysError("waiting for children");
}
{
auto state(state_.lock());
assert(state->runningEvals);
state->runningEvals--;
// FIXME: should use a map.
for (auto & i : state->jobsets) {
auto & jobset(i.second);
if (jobset.pid == pid) {
printInfo("evaluation of jobset %s %s",
jobset.name.display(), statusToString(status));
auto now = time(0);
jobset.triggerTime = notTriggered;
jobset.lastCheckedTime = now;
try {
auto conn(dbPool.get());
pqxx::work txn(*conn);
/* Clear the trigger time to prevent this
jobset from getting stuck in an endless
failing eval loop. */
txn.exec
("update Jobsets set triggerTime = null where id = $1 and startTime is not null and triggerTime <= startTime",
jobset.name.id).no_rows();
/* Clear the start time. */
txn.exec
("update Jobsets set startTime = null where id = $1",
jobset.name.id).no_rows();
if (!WIFEXITED(status) || WEXITSTATUS(status) > 1) {
txn.exec("update Jobsets set errorMsg = $1, lastCheckedTime = $2, errorTime = $2, fetchErrorMsg = null where id = $3",
pqxx::params{fmt("evaluation %s", statusToString(status)), now, jobset.name.id}).no_rows();
}
txn.commit();
} catch (std::exception & e) {
printError("exception setting jobset error: %s", e.what());
}
jobset.pid.release();
maybeDoWork.notify_one();
if (evalOne) std::_Exit(0);
break;
}
}
}
}
}
void unlock()
{
auto conn(dbPool.get());
pqxx::work txn(*conn);
txn.exec("update Jobsets set startTime = null").no_rows();
txn.commit();
}
void run()
{
unlock();
/* Can't be bothered to shut down cleanly. Goodbye! */
auto callback = createInterruptCallback([&]() { std::_Exit(1); });
std::thread reaperThread([&]() { reaper(); });
std::thread monitorThread([&]() { databaseMonitor(); });
while (true) {
try {
loop();
} catch (pqxx::broken_connection & e) {
printError("Database connection broken: %s", e.what());
std::_Exit(1);
} catch (std::exception & e) {
printError("exception in main loop: %s", e.what());
sleep(30);
}
}
}
};
int main(int argc, char * * argv)
{
return handleExceptions(argv[0], [&]() {
initNix();
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGHUP, SIG_DFL);
bool unlock = false;
Evaluator evaluator;
std::vector<std::string> args;
parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
if (*arg == "--unlock")
unlock = true;
else if (hasPrefix(*arg, "-"))
return false;
args.push_back(*arg);
return true;
});
if (unlock)
evaluator.unlock();
else {
if (!args.empty()) {
if (args.size() != 2) throw UsageError("Syntax: hydra-evaluator [<project> <jobset>]");
evaluator.evalOne = JobsetName(args[0], args[1]);
}
evaluator.run();
}
});
}

View File

@@ -0,0 +1,10 @@
hydra_evaluator = executable('hydra-evaluator',
'hydra-evaluator.cc',
dependencies: [
libhydra_dep,
nix_util_dep,
nix_main_dep,
pqxx_dep,
],
install: true,
)

View File

@@ -0,0 +1,646 @@
#include <algorithm>
#include <cmath>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <nix/store/build-result.hh>
#include <nix/store/path.hh>
#include <nix/store/legacy-ssh-store.hh>
#include <nix/store/serve-protocol.hh>
#include <nix/store/serve-protocol-impl.hh>
#include "state.hh"
#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>
#include <nix/util/finally.hh>
#include <nix/util/url.hh>
using namespace nix;
bool ::Machine::isLocalhost() const
{
return storeUri.params.empty() && std::visit(overloaded {
[](const StoreReference::Auto &) {
return true;
},
[](const StoreReference::Specified & s) {
return
(s.scheme == "local" || s.scheme == "unix") ||
((s.scheme == "ssh" || s.scheme == "ssh-ng") &&
s.authority == "localhost");
},
}, storeUri.variant);
}
namespace nix::build_remote {
static std::unique_ptr<SSHMaster::Connection> openConnection(
::Machine::ptr machine, SSHMaster & master)
{
Strings command = {"nix-store", "--serve", "--write"};
if (machine->isLocalhost()) {
command.push_back("--builders");
command.push_back("");
} else {
auto remoteStore = machine->storeUri.params.find("remote-store");
if (remoteStore != machine->storeUri.params.end()) {
command.push_back("--store");
command.push_back(escapeShellArgAlways(remoteStore->second));
}
}
auto ret = master.startCommand(std::move(command), {
"-a", "-oBatchMode=yes", "-oConnectTimeout=60", "-oTCPKeepAlive=yes"
});
// XXX: determine the actual max value we can use from /proc.
// FIXME: Should this be upstreamed into `startCommand` in Nix?
int pipesize = 1024 * 1024;
fcntl(ret->in.get(), F_SETPIPE_SZ, &pipesize);
fcntl(ret->out.get(), F_SETPIPE_SZ, &pipesize);
return ret;
}
static void copyClosureTo(
::Machine::Connection & conn,
Store & destStore,
const StorePathSet & paths,
SubstituteFlag useSubstitutes = NoSubstitute)
{
StorePathSet closure;
destStore.computeFSClosure(paths, closure);
/* Send the "query valid paths" command with the "lock" option
enabled. This prevents a race where the remote host
garbage-collect paths that are already there. Optionally, ask
the remote host to substitute missing paths. */
// FIXME: substitute output pollutes our build log
/* Get back the set of paths that are already valid on the remote
host. */
auto present = conn.queryValidPaths(
destStore, true, closure, useSubstitutes);
if (present.size() == closure.size()) return;
auto sorted = destStore.topoSortPaths(closure);
StorePathSet missing;
for (auto i = sorted.rbegin(); i != sorted.rend(); ++i)
if (!present.count(*i)) missing.insert(*i);
printMsg(lvlDebug, "sending %d missing paths", missing.size());
std::unique_lock<std::timed_mutex> sendLock(conn.machine->state->sendLock,
std::chrono::seconds(600));
conn.to << ServeProto::Command::ImportPaths;
exportPaths(destStore, missing, conn.to);
conn.to.flush();
if (readInt(conn.from) != 1)
throw Error("remote machine failed to import closure");
}
// FIXME: use Store::topoSortPaths().
static StorePaths reverseTopoSortPaths(const std::map<StorePath, UnkeyedValidPathInfo> & paths)
{
StorePaths sorted;
StorePathSet visited;
std::function<void(const StorePath & path)> dfsVisit;
dfsVisit = [&](const StorePath & path) {
if (!visited.insert(path).second) return;
auto info = paths.find(path);
auto references = info == paths.end() ? StorePathSet() : info->second.references;
for (auto & i : references)
/* Don't traverse into paths that don't exist. That can
happen due to substitutes for non-existent paths. */
if (i != path && paths.count(i))
dfsVisit(i);
sorted.push_back(path);
};
for (auto & i : paths)
dfsVisit(i.first);
return sorted;
}
static std::pair<Path, AutoCloseFD> openLogFile(const std::string & logDir, const StorePath & drvPath)
{
std::string base(drvPath.to_string());
auto logFile = logDir + "/" + std::string(base, 0, 2) + "/" + std::string(base, 2);
createDirs(dirOf(logFile));
AutoCloseFD logFD = open(logFile.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0666);
if (!logFD) throw SysError("creating log file %s", logFile);
return {std::move(logFile), std::move(logFD)};
}
static BasicDerivation sendInputs(
State & state,
Step & step,
Store & localStore,
Store & destStore,
::Machine::Connection & conn,
unsigned int & overhead,
counter & nrStepsWaiting,
counter & nrStepsCopyingTo
)
{
/* Replace the input derivations by their output paths to send a
minimal closure to the builder.
`tryResolve` currently does *not* rewrite input addresses, so it
is safe to do this in all cases. (It should probably have a mode
to do that, however, but we would not use it here.)
*/
BasicDerivation basicDrv = ({
auto maybeBasicDrv = step.drv->tryResolve(destStore, &localStore);
if (!maybeBasicDrv)
throw Error(
"the derivation '%s' cant be resolved. Its probably "
"missing some outputs",
localStore.printStorePath(step.drvPath));
*maybeBasicDrv;
});
/* Ensure that the inputs exist in the destination store. This is
a no-op for regular stores, but for the binary cache store,
this will copy the inputs to the binary cache from the local
store. */
if (&localStore != &destStore) {
copyClosure(localStore, destStore,
step.drv->inputSrcs,
NoRepair, NoCheckSigs, NoSubstitute);
}
{
auto mc1 = std::make_shared<MaintainCount<counter>>(nrStepsWaiting);
mc1.reset();
MaintainCount<counter> mc2(nrStepsCopyingTo);
printMsg(lvlDebug, "sending closure of %s to %s",
localStore.printStorePath(step.drvPath), conn.machine->storeUri.render());
auto now1 = std::chrono::steady_clock::now();
/* Copy the input closure. */
if (conn.machine->isLocalhost()) {
StorePathSet closure;
destStore.computeFSClosure(basicDrv.inputSrcs, closure);
copyPaths(destStore, localStore, closure, NoRepair, NoCheckSigs, NoSubstitute);
} else {
copyClosureTo(conn, destStore, basicDrv.inputSrcs, Substitute);
}
auto now2 = std::chrono::steady_clock::now();
overhead += std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
}
return basicDrv;
}
static BuildResult performBuild(
::Machine::Connection & conn,
Store & localStore,
StorePath drvPath,
const BasicDerivation & drv,
const ServeProto::BuildOptions & options,
counter & nrStepsBuilding
)
{
conn.putBuildDerivationRequest(localStore, drvPath, drv, options);
BuildResult result;
time_t startTime, stopTime;
startTime = time(0);
{
MaintainCount<counter> mc(nrStepsBuilding);
result = ServeProto::Serialise<BuildResult>::read(localStore, conn);
}
stopTime = time(0);
if (!result.startTime) {
// If the builder gave `startTime = 0`, use our measurements
// instead of the builder's.
//
// Note: this represents the duration of a single round, rather
// than all rounds.
result.startTime = startTime;
result.stopTime = stopTime;
}
// If the protocol was too old to give us `builtOutputs`, initialize
// it manually by introspecting the derivation.
if (GET_PROTOCOL_MINOR(conn.remoteVersion) < 6)
{
// If the remote is too old to handle CA derivations, we cant get this
// far anyways
assert(drv.type().hasKnownOutputPaths());
DerivationOutputsAndOptPaths drvOutputs = drv.outputsAndOptPaths(localStore);
// Since this a `BasicDerivation`, `staticOutputHashes` will not
// do any real work.
auto outputHashes = staticOutputHashes(localStore, drv);
if (auto * successP = result.tryGetSuccess()) {
for (auto & [outputName, output] : drvOutputs) {
auto outputPath = output.second;
// Weve 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 });
}
}
}
return result;
}
static void copyPathFromRemote(
::Machine::Connection & conn,
NarMemberDatas & narMembers,
Store & localStore,
Store & destStore,
const ValidPathInfo & info
)
{
/* Receive the NAR from the remote and add it to the
destination store. Meanwhile, extract all the info from the
NAR that getBuildOutput() needs. */
auto source2 = sinkToSource([&](Sink & sink)
{
/* Note: we should only send the command to dump the store
path to the remote if the NAR is actually going to get read
by the destination store, which won't happen if this path
is already valid on the destination store. Since this
lambda function only gets executed if someone tries to read
from source2, we will send the command from here rather
than outside the lambda. */
conn.to << ServeProto::Command::DumpStorePath << localStore.printStorePath(info.path);
conn.to.flush();
TeeSource tee(conn.from, sink);
extractNarData(tee, localStore.printStorePath(info.path), narMembers);
});
destStore.addToStore(info, *source2, NoRepair, NoCheckSigs);
}
static void copyPathsFromRemote(
::Machine::Connection & conn,
NarMemberDatas & narMembers,
Store & localStore,
Store & destStore,
const std::map<StorePath, UnkeyedValidPathInfo> & infos
)
{
auto pathsSorted = reverseTopoSortPaths(infos);
for (auto & path : pathsSorted) {
auto & info = infos.find(path)->second;
copyPathFromRemote(
conn, narMembers, localStore, destStore,
ValidPathInfo { path, info });
}
}
}
/* using namespace nix::build_remote; */
void RemoteResult::updateWithBuildResult(const nix::BuildResult & buildResult)
{
startTime = buildResult.startTime;
stopTime = buildResult.stopTime;
timesBuilt = buildResult.timesBuilt;
std::visit(overloaded{
[&](const BuildResult::Success & success) {
stepStatus = bsSuccess;
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. */
template <typename T>
class SemaphoreReleaser {
public:
SemaphoreReleaser(T* s) : sem(s) {}
~SemaphoreReleaser() { sem->release(); }
private:
T* sem;
};
void State::buildRemote(ref<Store> destStore,
std::unique_ptr<MachineReservation> reservation,
::Machine::ptr machine, Step::ptr step,
const ServeProto::BuildOptions & buildOptions,
RemoteResult & result, std::shared_ptr<ActiveStep> activeStep,
std::function<void(StepState)> updateStep,
NarMemberDatas & narMembers)
{
assert(BuildResult::Failure::TimedOut == 8);
auto [logFile, logFD] = build_remote::openLogFile(logDir, step->drvPath);
AutoDelete logFileDel(logFile, false);
result.logFile = logFile;
try {
updateStep(ssConnecting);
auto storeRef = machine->completeStoreReference();
auto * pSpecified = std::get_if<StoreReference::Specified>(&storeRef.variant);
if (!pSpecified || pSpecified->scheme != "ssh") {
throw Error("Currently, only (legacy-)ssh stores are supported!");
}
LegacySSHStoreConfig storeConfig {
pSpecified->scheme,
pSpecified->authority,
storeRef.params
};
auto master = storeConfig.createSSHMaster(
false, // no SSH master yet
logFD.get());
// FIXME: rewrite to use Store.
auto child = build_remote::openConnection(machine, master);
{
auto activeStepState(activeStep->state_.lock());
if (activeStepState->cancelled) throw Error("step cancelled");
activeStepState->pid = child->sshPid;
}
Finally clearPid([&]() {
auto activeStepState(activeStep->state_.lock());
activeStepState->pid = -1;
/* FIXME: there is a slight race here with step
cancellation in State::processQueueChange(), which
could call kill() on this pid after we've done waitpid()
on it. With pid wrap-around, there is a tiny
possibility that we end up killing another
process. Meh. */
});
::Machine::Connection conn {
{
.to = child->in.get(),
.from = child->out.get(),
/* Handshake. */
.remoteVersion = 0xdadbeef, // FIXME avoid dummy initialize
},
/*.machine =*/ machine,
};
Finally updateStats([&]() {
bytesReceived += conn.from.read;
bytesSent += conn.to.written;
});
constexpr ServeProto::Version our_version = 0x206;
try {
conn.remoteVersion = decltype(conn)::handshake(
conn.to,
conn.from,
our_version,
machine->storeUri.render());
} catch (EndOfFile & e) {
child->sshPid.wait();
std::string s = chomp(readFile(result.logFile));
throw Error("cannot connect to %1%: %2%", machine->storeUri.render(), s);
}
{
auto info(machine->state->connectInfo.lock());
info->consecutiveFailures = 0;
}
/* Gather the inputs. If the remote side is Nix <= 1.9, we have to
copy the entire closure of drvPath, as well as the required
outputs of the input derivations. On Nix > 1.9, we only need to
copy the immediate sources of the derivation and the required
outputs of the input derivations. */
updateStep(ssSendingInputs);
BasicDerivation resolvedDrv = build_remote::sendInputs(*this, *step, *localStore, *destStore, conn, result.overhead, nrStepsWaiting, nrStepsCopyingTo);
logFileDel.cancel();
/* Truncate the log to get rid of messages about substitutions
etc. on the remote system. */
if (lseek(logFD.get(), SEEK_SET, 0) != 0)
throw SysError("seeking to the start of log file %s", result.logFile);
if (ftruncate(logFD.get(), 0) == -1)
throw SysError("truncating log file %s", result.logFile);
logFD = -1;
/* Do the build. */
printMsg(lvlDebug, "building %s on %s",
localStore->printStorePath(step->drvPath),
machine->storeUri.render());
updateStep(ssBuilding);
auto buildResult = build_remote::performBuild(
conn,
*localStore,
step->drvPath,
resolvedDrv,
buildOptions,
nrStepsBuilding
);
result.updateWithBuildResult(buildResult);
if (result.stepStatus != bsSuccess) return;
result.errorMsg = "";
/* If the path was substituted or already valid, then we didn't
get a build log. */
if (result.isCached) {
printMsg(lvlInfo, "outputs of %s substituted or already valid on %s",
localStore->printStorePath(step->drvPath), machine->storeUri.render());
unlink(result.logFile.c_str());
result.logFile = "";
}
/* Throttle CPU-bound work. Opportunistically skip updating the current
* step, since this requires a DB roundtrip. */
if (!localWorkThrottler.try_acquire()) {
MaintainCount<counter> mc(nrStepsWaitingForDownloadSlot);
updateStep(ssWaitingForLocalSlot);
localWorkThrottler.acquire();
}
SemaphoreReleaser releaser(&localWorkThrottler);
/* Once we've started copying outputs, release the machine reservation
* so further builds can happen. We do not release the machine earlier
* to avoid situations where the queue runner is bottlenecked on
* copying outputs and we end up building too many things that we
* haven't been able to allow copy slots for. */
reservation.reset();
wakeDispatcher();
StorePathSet outputs;
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)) {
updateStep(ssReceivingOutputs);
MaintainCount<counter> mc(nrStepsCopyingFrom);
auto now1 = std::chrono::steady_clock::now();
auto infos = conn.queryPathInfos(*localStore, outputs);
size_t totalNarSize = 0;
for (auto & [_, info] : infos) totalNarSize += info.narSize;
if (totalNarSize > maxOutputSize) {
result.stepStatus = bsNarSizeLimitExceeded;
return;
}
/* Copy each path. */
printMsg(lvlDebug, "copying outputs of %s from %s (%d bytes)",
localStore->printStorePath(step->drvPath), machine->storeUri.render(), totalNarSize);
build_remote::copyPathsFromRemote(conn, narMembers, *localStore, *destStore, infos);
auto now2 = std::chrono::steady_clock::now();
result.overhead += std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
}
/* Register the outputs of the newly built drv */
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) {
auto outputHashes = staticOutputHashes(*localStore, *step->drv);
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);
}
}
}
/* Shut down the connection. */
child->in = -1;
child->sshPid.wait();
} catch (Error & e) {
/* Disable this machine until a certain period of time has
passed. This period increases on every consecutive
failure. However, don't count failures that occurred soon
after the last one (to take into account steps started in
parallel). */
auto info(machine->state->connectInfo.lock());
auto now = std::chrono::system_clock::now();
if (info->consecutiveFailures == 0 || info->lastFailure < now - std::chrono::seconds(30)) {
info->consecutiveFailures = std::min(info->consecutiveFailures + 1, (unsigned int) 4);
info->lastFailure = now;
int delta = retryInterval * std::pow(retryBackoff, info->consecutiveFailures - 1) + (rand() % 30);
printMsg(lvlInfo, "will disable machine %1% for %2%s", machine->storeUri.render(), delta);
info->disabledUntil = now + std::chrono::seconds(delta);
}
throw;
}
}

View File

@@ -0,0 +1,163 @@
#include "hydra-build-result.hh"
#include <nix/store/store-api.hh>
#include <nix/util/util.hh>
#include <nix/util/source-accessor.hh>
#include <regex>
using namespace nix;
BuildOutput getBuildOutput(
nix::ref<Store> store,
NarMemberDatas & narMembers,
const OutputPathMap derivationOutputs)
{
BuildOutput res;
/* Compute the closure size. */
StorePathSet outputs;
StorePathSet closure;
for (auto& [outputName, outputPath] : derivationOutputs) {
store->computeFSClosure(outputPath, closure);
outputs.insert(outputPath);
res.outputs.insert({outputName, outputPath});
}
for (auto & path : closure) {
auto info = store->queryPathInfo(path);
res.closureSize += info->narSize;
if (outputs.count(path)) res.size += info->narSize;
}
/* Fetch missing data. Usually buildRemote() will have extracted
this data from the incoming NARs. */
for (auto & output : outputs) {
auto outputS = store->printStorePath(output);
if (!narMembers.count(outputS)) {
printInfo("fetching NAR contents of '%s'...", outputS);
auto source = sinkToSource([&](Sink & sink)
{
store->narFromPath(output, sink);
});
extractNarData(*source, outputS, narMembers);
}
}
/* Get build products. */
bool explicitProducts = false;
std::regex regex(
"([a-zA-Z0-9_-]+)" // type (e.g. "doc")
"[[:space:]]+"
"([a-zA-Z0-9_-]+)" // subtype (e.g. "readme")
"[[:space:]]+"
"(\"[^\"]+\"|[^[:space:]<>\"]+)" // path (may be quoted)
"([[:space:]]+([^[:space:]<>]+))?" // entry point
, std::regex::extended);
for (auto & output : outputs) {
auto outputS = store->printStorePath(output);
if (narMembers.count(outputS + "/nix-support/failed"))
res.failed = true;
auto productsFile = narMembers.find(outputS + "/nix-support/hydra-build-products");
if (productsFile == narMembers.end() ||
productsFile->second.type != SourceAccessor::Type::tRegular)
continue;
assert(productsFile->second.contents);
explicitProducts = true;
for (auto & line : tokenizeString<Strings>(productsFile->second.contents.value(), "\n")) {
BuildProduct product;
std::smatch match;
if (!std::regex_match(line, match, regex)) continue;
product.type = match[1];
product.subtype = match[2];
std::string s(match[3]);
product.path = s[0] == '"' && s.back() == '"' ? std::string(s, 1, s.size() - 2) : s;
product.defaultPath = match[5];
/* Ensure that the path exists and points into the Nix
store. */
// FIXME: should we disallow products referring to other
// store paths, or that are outside the input closure?
if (product.path == "" || product.path[0] != '/') continue;
product.path = canonPath(product.path);
if (!store->isInStore(product.path)) continue;
auto file = narMembers.find(product.path);
if (file == narMembers.end()) continue;
product.name = product.path == store->printStorePath(output) ? "" : baseNameOf(product.path);
if (!std::regex_match(product.name, std::regex("[a-zA-Z0-9.@:_ -]*")))
product.name = "";
if (file->second.type == SourceAccessor::Type::tRegular) {
product.isRegular = true;
product.fileSize = file->second.fileSize.value();
product.sha256hash = file->second.sha256.value();
}
res.products.push_back(product);
}
}
/* If no build products were explicitly declared, then add all
outputs as a product of type "nix-build". */
if (!explicitProducts) {
for (auto & [name, output] : derivationOutputs) {
BuildProduct product;
product.path = store->printStorePath(output);
product.type = "nix-build";
product.subtype = name == "out" ? "" : name;
product.name = output.name();
auto file = narMembers.find(product.path);
assert(file != narMembers.end());
if (file->second.type == SourceAccessor::Type::tDirectory)
res.products.push_back(product);
}
}
/* Get the release name from $output/nix-support/hydra-release-name. */
for (auto & output : outputs) {
auto file = narMembers.find(store->printStorePath(output) + "/nix-support/hydra-release-name");
if (file == narMembers.end() ||
file->second.type != SourceAccessor::Type::tRegular)
continue;
auto contents = trim(file->second.contents.value());
if (std::regex_match(contents, std::regex("[a-zA-Z0-9.@:_-]+")))
res.releaseName = contents;
}
/* Get metrics. */
for (auto & output : outputs) {
auto file = narMembers.find(store->printStorePath(output) + "/nix-support/hydra-metrics");
if (file == narMembers.end() ||
file->second.type != SourceAccessor::Type::tRegular)
continue;
for (auto & line : tokenizeString<Strings>(file->second.contents.value(), "\n")) {
auto fields = tokenizeString<std::vector<std::string>>(line);
if (fields.size() < 2) continue;
if (!std::regex_match(fields[0], std::regex("[a-zA-Z0-9._-]+")))
continue;
BuildMetric metric;
metric.name = fields[0];
try {
metric.value = std::stod(fields[1]);
} catch (...) {
continue; // skip this metric
}
metric.unit = fields.size() >= 3 ? fields[2] : "";
if (!std::regex_match(metric.unit, std::regex("[a-zA-Z0-9._%-]+")))
metric.unit = "";
res.metrics[metric.name] = metric;
}
}
return res;
}

View File

@@ -0,0 +1,506 @@
#include <cmath>
#include "state.hh"
#include "hydra-build-result.hh"
#include <nix/util/finally.hh>
#include <nix/store/binary-cache-store.hh>
using namespace nix;
void setThreadName(const std::string & name)
{
#ifdef __linux__
pthread_setname_np(pthread_self(), std::string(name, 0, 15).c_str());
#endif
}
void State::builder(std::unique_ptr<MachineReservation> reservation)
{
setThreadName("bld~" + std::string(reservation->step->drvPath.to_string()));
StepResult res = sRetry;
nrStepsStarted++;
Step::wptr wstep = reservation->step;
{
auto activeStep = std::make_shared<ActiveStep>();
activeStep->step = reservation->step;
activeSteps_.lock()->insert(activeStep);
Finally removeActiveStep([&]() {
activeSteps_.lock()->erase(activeStep);
});
std::string machine = reservation->machine->storeUri.render();
try {
auto destStore = getDestStore();
// Might release the reservation.
res = doBuildStep(destStore, std::move(reservation), activeStep);
} catch (std::exception & e) {
printMsg(lvlError, "uncaught exception building %s on %s: %s",
localStore->printStorePath(activeStep->step->drvPath),
machine,
e.what());
}
}
/* If there was a temporary failure, retry the step after an
exponentially increasing interval. */
Step::ptr step = wstep.lock();
if (res != sDone && step) {
if (res == sRetry) {
auto step_(step->state.lock());
step_->tries++;
nrRetries++;
if (step_->tries > maxNrRetries) maxNrRetries = step_->tries; // yeah yeah, not atomic
int delta = retryInterval * std::pow(retryBackoff, step_->tries - 1) + (rand() % 10);
printMsg(lvlInfo, "will retry %s after %ss", localStore->printStorePath(step->drvPath), delta);
step_->after = std::chrono::system_clock::now() + std::chrono::seconds(delta);
}
makeRunnable(step);
}
}
State::StepResult State::doBuildStep(nix::ref<Store> destStore,
std::unique_ptr<MachineReservation> reservation,
std::shared_ptr<ActiveStep> activeStep)
{
auto step(reservation->step);
auto machine(reservation->machine);
{
auto step_(step->state.lock());
assert(step_->created);
assert(!step->finished);
}
/* There can be any number of builds in the database that depend
on this derivation. Arbitrarily pick one (though preferring a
build of which this is the top-level derivation) for the
purpose of creating build steps. We could create a build step
record for every build, but that could be very expensive
(e.g. a stdenv derivation can be a dependency of tens of
thousands of builds), so we don't.
We don't keep a Build::ptr here to allow
State::processQueueChange() to detect whether a step can be
cancelled (namely if there are no more Builds referring to
it). */
BuildID buildId;
std::optional<StorePath> buildDrvPath;
// Other fields set below
nix::ServeProto::BuildOptions buildOptions {
.maxLogSize = maxLogSize,
.nrRepeats = step->isDeterministic ? 1u : 0u,
.enforceDeterminism = step->isDeterministic,
.keepFailed = false,
};
auto conn(dbPool.get());
{
std::set<Build::ptr> dependents;
std::set<Step::ptr> steps;
getDependents(step, dependents, steps);
if (dependents.empty()) {
/* Apparently all builds that depend on this derivation
are gone (e.g. cancelled). So don't bother. This is
very unlikely to happen, because normally Steps are
only kept alive by being reachable from a
Build. However, it's possible that a new Build just
created a reference to this step. So to handle that
possibility, we retry this step (putting it back in
the runnable queue). If there are really no strong
pointers to the step, it will be deleted. */
printMsg(lvlInfo, "maybe cancelling build step %s", localStore->printStorePath(step->drvPath));
return sMaybeCancelled;
}
Build::ptr build;
for (auto build2 : dependents) {
if (build2->drvPath == step->drvPath) {
build = build2;
pqxx::work txn(*conn);
notifyBuildStarted(txn, build->id);
txn.commit();
}
{
auto i = jobsetRepeats.find(std::make_pair(build2->projectName, build2->jobsetName));
if (i != jobsetRepeats.end())
buildOptions.nrRepeats = std::max(buildOptions.nrRepeats, i->second);
}
}
if (!build) build = *dependents.begin();
buildId = build->id;
buildDrvPath = build->drvPath;
buildOptions.maxSilentTime = build->maxSilentTime;
buildOptions.buildTimeout = build->buildTimeout;
printInfo("performing step %s %d times on %s (needed by build %d and %d others)",
localStore->printStorePath(step->drvPath), buildOptions.nrRepeats + 1, machine->storeUri.render(), buildId, (dependents.size() - 1));
}
if (!buildOneDone)
buildOneDone = buildId == buildOne && step->drvPath == *buildDrvPath;
RemoteResult result;
BuildOutput res;
unsigned int stepNr = 0;
bool stepFinished = false;
Finally clearStep([&]() {
if (stepNr && !stepFinished) {
printError("marking step %d of build %d as orphaned", stepNr, buildId);
auto orphanedSteps_(orphanedSteps.lock());
orphanedSteps_->emplace(buildId, stepNr);
}
if (stepNr) {
/* Upload the log file to the binary cache. FIXME: should
be done on a worker thread. */
try {
auto store = destStore.dynamic_pointer_cast<BinaryCacheStore>();
if (uploadLogsToBinaryCache && store && pathExists(result.logFile)) {
store->upsertFile("log/" + std::string(step->drvPath.to_string()), readFile(result.logFile), "text/plain; charset=utf-8");
unlink(result.logFile.c_str());
}
} catch (...) {
ignoreExceptionInDestructor();
}
}
});
time_t stepStartTime = result.startTime = time(0);
/* If any of the outputs have previously failed, then don't bother
building again. */
if (checkCachedFailure(step, *conn))
result.stepStatus = bsCachedFailure;
else {
/* Create a build step record indicating that we started
building. */
{
auto mc = startDbUpdate();
pqxx::work txn(*conn);
stepNr = createBuildStep(txn, result.startTime, buildId, step, machine->storeUri.render(), bsBusy);
txn.commit();
}
auto updateStep = [&](StepState stepState) {
pqxx::work txn(*conn);
updateBuildStep(txn, buildId, stepNr, stepState);
txn.commit();
};
/* Do the build. */
NarMemberDatas narMembers;
try {
/* FIXME: referring builds may have conflicting timeouts. */
buildRemote(destStore, std::move(reservation), machine, step, buildOptions, result, activeStep, updateStep, narMembers);
} catch (Error & e) {
if (activeStep->state_.lock()->cancelled) {
printInfo("marking step %d of build %d as cancelled", stepNr, buildId);
result.stepStatus = bsCancelled;
result.canRetry = false;
} else {
result.stepStatus = bsAborted;
result.errorMsg = e.msg();
result.canRetry = true;
}
}
if (result.stepStatus == bsSuccess) {
updateStep(ssPostProcessing);
res = getBuildOutput(destStore, narMembers, destStore->queryDerivationOutputMap(step->drvPath, &*localStore));
}
}
time_t stepStopTime = time(0);
if (!result.stopTime) result.stopTime = stepStopTime;
/* For standard failures, we don't care about the error
message. */
if (result.stepStatus != bsAborted)
result.errorMsg = "";
/* Account the time we spent building this step by dividing it
among the jobsets that depend on it. */
{
auto step_(step->state.lock());
if (!step_->jobsets.empty()) {
// FIXME: loss of precision.
time_t charge = (result.stopTime - result.startTime) / step_->jobsets.size();
for (auto & jobset : step_->jobsets)
jobset->addStep(result.startTime, charge);
}
}
/* Finish the step in the database. */
if (stepNr) {
pqxx::work txn(*conn);
finishBuildStep(txn, result, buildId, stepNr, machine->storeUri.render());
txn.commit();
}
/* The step had a hopefully temporary failure (e.g. network
issue). Retry a number of times. */
if (result.canRetry) {
printMsg(lvlError, "possibly transient failure building %s on %s: %s",
localStore->printStorePath(step->drvPath), machine->storeUri.render(), result.errorMsg);
assert(stepNr);
bool retry;
{
auto step_(step->state.lock());
retry = step_->tries + 1 < maxTries;
}
if (retry) {
auto mc = startDbUpdate();
stepFinished = true;
if (buildOneDone) exit(1);
return sRetry;
}
}
if (result.stepStatus == bsSuccess) {
assert(stepNr);
for (auto & [outputName, optOutputPath] : destStore->queryPartialDerivationOutputMap(step->drvPath, &*localStore)) {
if (!optOutputPath)
throw Error(
"Missing output %s for derivation %d which was supposed to have succeeded",
outputName, localStore->printStorePath(step->drvPath));
addRoot(*optOutputPath);
}
/* Register success in the database for all Build objects that
have this step as the top-level step. Since the queue
monitor thread may be creating new referring Builds
concurrently, and updating the database may fail, we do
this in a loop, marking all known builds, repeating until
there are no unmarked builds.
*/
std::vector<BuildID> buildIDs;
while (true) {
/* Get the builds that have this one as the top-level. */
std::vector<Build::ptr> direct;
{
auto steps_(steps.lock());
auto step_(step->state.lock());
for (auto & b_ : step_->builds) {
auto b = b_.lock();
if (b && !b->finishedInDB) direct.push_back(b);
}
/* If there are no builds left to update in the DB,
then we're done (except for calling
finishBuildStep()). Delete the step from
steps. Since we've been holding the steps lock,
no new referrers can have been added in the
meantime or be added afterwards. */
if (direct.empty()) {
printMsg(lvlDebug, "finishing build step %s",
localStore->printStorePath(step->drvPath));
steps_->erase(step->drvPath);
}
}
/* Update the database. */
{
auto mc = startDbUpdate();
pqxx::work txn(*conn);
for (auto & b : direct) {
printInfo("marking build %1% as succeeded", b->id);
markSucceededBuild(txn, b, res, buildId != b->id || result.isCached,
result.startTime, result.stopTime);
}
txn.commit();
}
stepFinished = true;
if (direct.empty()) break;
/* Remove the direct dependencies from builds. This will
cause them to be destroyed. */
for (auto & b : direct) {
auto builds_(builds.lock());
b->finishedInDB = true;
builds_->erase(b->id);
buildIDs.push_back(b->id);
}
}
/* Send notification about the builds that have this step as
the top-level. */
{
pqxx::work txn(*conn);
for (auto id : buildIDs)
notifyBuildFinished(txn, id, {});
txn.commit();
}
/* Wake up any dependent steps that have no other
dependencies. */
{
auto step_(step->state.lock());
for (auto & rdepWeak : step_->rdeps) {
auto rdep = rdepWeak.lock();
if (!rdep) continue;
bool runnable = false;
{
auto rdep_(rdep->state.lock());
rdep_->deps.erase(step);
/* Note: if the step has not finished
initialisation yet, it will be made runnable in
createStep(), if appropriate. */
if (rdep_->deps.empty() && rdep_->created) runnable = true;
}
if (runnable) makeRunnable(rdep);
}
}
} else
failStep(*conn, step, buildId, result, machine, stepFinished);
// FIXME: keep stats about aborted steps?
nrStepsDone++;
totalStepTime += stepStopTime - stepStartTime;
totalStepBuildTime += result.stopTime - result.startTime;
machine->state->nrStepsDone++;
machine->state->totalStepTime += stepStopTime - stepStartTime;
machine->state->totalStepBuildTime += result.stopTime - result.startTime;
if (buildOneDone) exit(0); // testing hack; FIXME: this won't run plugins
return sDone;
}
void State::failStep(
Connection & conn,
Step::ptr step,
BuildID buildId,
const RemoteResult & result,
::Machine::ptr machine,
bool & stepFinished)
{
/* Register failure in the database for all Build objects that
directly or indirectly depend on this step. */
std::vector<BuildID> dependentIDs;
while (true) {
/* Get the builds and steps that depend on this step. */
std::set<Build::ptr> indirect;
{
auto steps_(steps.lock());
std::set<Step::ptr> steps;
getDependents(step, indirect, steps);
/* If there are no builds left, delete all referring
steps from steps. As for the success case, we can
be certain no new referrers can be added. */
if (indirect.empty()) {
for (auto & s : steps) {
printMsg(lvlDebug, "finishing build step %s",
localStore->printStorePath(s->drvPath));
steps_->erase(s->drvPath);
}
}
}
if (indirect.empty() && stepFinished) break;
/* Update the database. */
{
auto mc = startDbUpdate();
pqxx::work txn(conn);
/* Create failed build steps for every build that
depends on this, except when this step is cached
and is the top-level of that build (since then it's
redundant with the build's isCachedBuild field). */
for (auto & build : indirect) {
if ((result.stepStatus == bsCachedFailure && build->drvPath == step->drvPath) ||
((result.stepStatus != bsCachedFailure && result.stepStatus != bsUnsupported) && buildId == build->id) ||
build->finishedInDB)
continue;
createBuildStep(txn,
0, build->id, step, machine ? machine->storeUri.render() : "",
result.stepStatus, result.errorMsg, buildId == build->id ? 0 : buildId);
}
/* Mark all builds that depend on this derivation as failed. */
for (auto & build : indirect) {
if (build->finishedInDB) continue;
printError("marking build %1% as failed", build->id);
txn.exec("update Builds set finished = 1, buildStatus = $2, startTime = $3, stopTime = $4, isCachedBuild = $5, notificationPendingSince = $4 where id = $1 and finished = 0",
pqxx::params{build->id,
(int) (build->drvPath != step->drvPath && result.buildStatus() == bsFailed ? bsDepFailed : result.buildStatus()),
result.startTime,
result.stopTime,
result.stepStatus == bsCachedFailure ? 1 : 0}).no_rows();
nrBuildsDone++;
}
/* Remember failed paths in the database so that they
won't be built again. */
if (result.stepStatus != bsCachedFailure && result.canCache)
for (auto & i : step->drv->outputsAndOptPaths(*localStore))
if (i.second.second)
txn.exec("insert into FailedPaths values ($1)", pqxx::params{localStore->printStorePath(*i.second.second)}).no_rows();
txn.commit();
}
stepFinished = true;
/* Remove the indirect dependencies from builds. This
will cause them to be destroyed. */
for (auto & b : indirect) {
auto builds_(builds.lock());
b->finishedInDB = true;
builds_->erase(b->id);
dependentIDs.push_back(b->id);
if (!buildOneDone && buildOne == b->id) buildOneDone = true;
}
}
/* Send notification about this build and its dependents. */
{
pqxx::work txn(conn);
notifyBuildFinished(txn, buildId, dependentIDs);
txn.commit();
}
}
void State::addRoot(const StorePath & storePath)
{
auto root = rootsDir + "/" + std::string(storePath.to_string());
if (!pathExists(root)) writeFile(root, "");
}

View File

@@ -0,0 +1,478 @@
#include <algorithm>
#include <cmath>
#include <thread>
#include <unordered_map>
#include <unordered_set>
#include "state.hh"
using namespace nix;
void State::makeRunnable(Step::ptr step)
{
printMsg(lvlChatty, "step %s is now runnable", localStore->printStorePath(step->drvPath));
{
auto step_(step->state.lock());
assert(step_->created);
assert(!step->finished);
assert(step_->deps.empty());
step_->runnableSince = std::chrono::system_clock::now();
}
{
auto runnable_(runnable.lock());
runnable_->push_back(step);
}
wakeDispatcher();
}
void State::dispatcher()
{
printMsg(lvlDebug, "Waiting for the machines parsing to have completed at least once");
machinesReadyLock.lock();
while (true) {
try {
printMsg(lvlDebug, "dispatcher woken up");
nrDispatcherWakeups++;
auto t_before_work = std::chrono::steady_clock::now();
auto sleepUntil = doDispatch();
auto t_after_work = std::chrono::steady_clock::now();
prom.dispatcher_time_spent_running.Increment(
std::chrono::duration_cast<std::chrono::microseconds>(t_after_work - t_before_work).count());
dispatchTimeMs += std::chrono::duration_cast<std::chrono::milliseconds>(t_after_work - t_before_work).count();
/* Sleep until we're woken up (either because a runnable build
is added, or because a build finishes). */
{
auto dispatcherWakeup_(dispatcherWakeup.lock());
if (!*dispatcherWakeup_) {
debug("dispatcher sleeping for %1%s",
std::chrono::duration_cast<std::chrono::seconds>(sleepUntil - std::chrono::system_clock::now()).count());
dispatcherWakeup_.wait_until(dispatcherWakeupCV, sleepUntil);
}
*dispatcherWakeup_ = false;
}
auto t_after_sleep = std::chrono::steady_clock::now();
prom.dispatcher_time_spent_waiting.Increment(
std::chrono::duration_cast<std::chrono::microseconds>(t_after_sleep - t_after_work).count());
} catch (std::exception & e) {
printError("dispatcher: %s", e.what());
sleep(1);
}
}
printMsg(lvlError, "dispatcher exits");
}
system_time State::doDispatch()
{
/* Prune old historical build step info from the jobsets. */
{
auto jobsets_(jobsets.lock());
for (auto & jobset : *jobsets_) {
auto s1 = jobset.second->shareUsed();
jobset.second->pruneSteps();
auto s2 = jobset.second->shareUsed();
if (s1 != s2)
debug("pruned scheduling window of %1%:%2% from %3% to %4%",
jobset.first.first, jobset.first.second, s1, s2);
}
}
system_time now = std::chrono::system_clock::now();
/* Start steps until we're out of steps or slots. */
auto sleepUntil = system_time::max();
bool keepGoing;
/* Sort the runnable steps by priority. Priority is establised
as follows (in order of precedence):
- The global priority of the builds that depend on the
step. This allows admins to bump a build to the front of
the queue.
- The lowest used scheduling share of the jobsets depending
on the step.
- The local priority of the build, as set via the build's
meta.schedulingPriority field. Note that this is not
quite correct: the local priority should only be used to
establish priority between builds in the same jobset, but
here it's used between steps in different jobsets if they
happen to have the same lowest used scheduling share. But
that's not very likely.
- The lowest ID of the builds depending on the step;
i.e. older builds take priority over new ones.
FIXME: O(n lg n); obviously, it would be better to keep a
runnable queue sorted by priority. */
struct StepInfo
{
Step::ptr step;
bool alreadyScheduled = false;
/* The lowest share used of any jobset depending on this
step. */
double lowestShareUsed = 1e9;
/* Info copied from step->state to ensure that the
comparator is a partial ordering (see MachineInfo). */
int highestGlobalPriority;
int highestLocalPriority;
size_t numRequiredSystemFeatures;
size_t numRevDeps;
BuildID lowestBuildID;
StepInfo(Step::ptr step, Step::State & step_) : step(step)
{
for (auto & jobset : step_.jobsets)
lowestShareUsed = std::min(lowestShareUsed, jobset->shareUsed());
highestGlobalPriority = step_.highestGlobalPriority;
highestLocalPriority = step_.highestLocalPriority;
numRequiredSystemFeatures = step->requiredSystemFeatures.size();
numRevDeps = step_.rdeps.size();
lowestBuildID = step_.lowestBuildID;
}
};
std::vector<StepInfo> runnableSorted;
struct RunnablePerType
{
unsigned int count{0};
std::chrono::seconds waitTime{0};
};
std::unordered_map<std::string, RunnablePerType> runnablePerType;
{
auto runnable_(runnable.lock());
runnableSorted.reserve(runnable_->size());
for (auto i = runnable_->begin(); i != runnable_->end(); ) {
auto step = i->lock();
/* Remove dead steps. */
if (!step) {
i = runnable_->erase(i);
continue;
}
++i;
auto & r = runnablePerType[step->systemType];
r.count++;
/* Skip previously failed steps that aren't ready
to be retried. */
auto step_(step->state.lock());
r.waitTime += std::chrono::duration_cast<std::chrono::seconds>(now - step_->runnableSince);
if (step_->tries > 0 && step_->after > now) {
if (step_->after < sleepUntil)
sleepUntil = step_->after;
continue;
}
runnableSorted.emplace_back(step, *step_);
}
}
sort(runnableSorted.begin(), runnableSorted.end(),
[](const StepInfo & a, const StepInfo & b)
{
return
a.highestGlobalPriority != b.highestGlobalPriority ? a.highestGlobalPriority > b.highestGlobalPriority :
a.lowestShareUsed != b.lowestShareUsed ? a.lowestShareUsed < b.lowestShareUsed :
a.highestLocalPriority != b.highestLocalPriority ? a.highestLocalPriority > b.highestLocalPriority :
a.numRequiredSystemFeatures != b.numRequiredSystemFeatures ? a.numRequiredSystemFeatures > b.numRequiredSystemFeatures :
a.numRevDeps != b.numRevDeps ? a.numRevDeps > b.numRevDeps :
a.lowestBuildID < b.lowestBuildID;
});
do {
now = std::chrono::system_clock::now();
/* Copy the currentJobs field of each machine. This is
necessary to ensure that the sort comparator below is
an ordering. std::sort() can segfault if it isn't. Also
filter out temporarily disabled machines. */
struct MachineInfo
{
::Machine::ptr machine;
unsigned long currentJobs;
};
std::vector<MachineInfo> machinesSorted;
{
auto machines_(machines.lock());
for (auto & m : *machines_) {
auto info(m.second->state->connectInfo.lock());
if (!m.second->enabled) continue;
if (info->consecutiveFailures && info->disabledUntil > now) {
if (info->disabledUntil < sleepUntil)
sleepUntil = info->disabledUntil;
continue;
}
machinesSorted.push_back({m.second, m.second->state->currentJobs});
}
}
/* Sort the machines by a combination of speed factor and
available slots. Prioritise the available machines as
follows:
- First by load divided by speed factor, rounded to the
nearest integer. This causes fast machines to be
preferred over slow machines with similar loads.
- Then by speed factor.
- Finally by load. */
sort(machinesSorted.begin(), machinesSorted.end(),
[](const MachineInfo & a, const MachineInfo & b) -> bool
{
float ta = std::round(a.currentJobs / a.machine->speedFactor);
float tb = std::round(b.currentJobs / b.machine->speedFactor);
return
ta != tb ? ta < tb :
a.machine->speedFactor != b.machine->speedFactor ? a.machine->speedFactor > b.machine->speedFactor :
a.currentJobs > b.currentJobs;
});
/* Find a machine with a free slot and find a step to run
on it. Once we find such a pair, we restart the outer
loop because the machine sorting will have changed. */
keepGoing = false;
for (auto & mi : machinesSorted) {
if (mi.machine->state->currentJobs >= mi.machine->maxJobs) continue;
for (auto & stepInfo : runnableSorted) {
if (stepInfo.alreadyScheduled) continue;
auto & step(stepInfo.step);
/* Can this machine do this step? */
if (!mi.machine->supportsStep(step)) {
debug("machine '%s' does not support step '%s' (system type '%s')",
mi.machine->storeUri.render(), localStore->printStorePath(step->drvPath), step->drv->platform);
continue;
}
/* Let's do this step. Remove it from the runnable
list. FIXME: O(n). */
{
auto runnable_(runnable.lock());
bool removed = false;
for (auto i = runnable_->begin(); i != runnable_->end(); )
if (i->lock() == step) {
i = runnable_->erase(i);
removed = true;
break;
} else ++i;
assert(removed);
auto & r = runnablePerType[step->systemType];
assert(r.count);
r.count--;
}
stepInfo.alreadyScheduled = true;
/* Make a slot reservation and start a thread to
do the build. */
auto builderThread = std::thread(&State::builder, this,
std::make_unique<MachineReservation>(*this, step, mi.machine));
builderThread.detach(); // FIXME?
keepGoing = true;
break;
}
if (keepGoing) break;
}
/* Update the stats for the auto-scaler. */
{
auto machineTypes_(machineTypes.lock());
for (auto & i : *machineTypes_)
i.second.runnable = 0;
for (auto & i : runnablePerType) {
auto & j = (*machineTypes_)[i.first];
j.runnable = i.second.count;
j.waitTime = i.second.waitTime;
}
}
lastDispatcherCheck = std::chrono::system_clock::to_time_t(now);
} while (keepGoing);
abortUnsupported();
return sleepUntil;
}
void State::wakeDispatcher()
{
{
auto dispatcherWakeup_(dispatcherWakeup.lock());
*dispatcherWakeup_ = true;
}
dispatcherWakeupCV.notify_one();
}
void State::abortUnsupported()
{
/* Make a copy of 'runnable' and 'machines' so we don't block them
very long. */
auto runnable2 = *runnable.lock();
auto machines2 = *machines.lock();
system_time now = std::chrono::system_clock::now();
auto now2 = time(0);
std::unordered_set<Step::ptr> aborted;
size_t count = 0;
for (auto & wstep : runnable2) {
auto step(wstep.lock());
if (!step) continue;
bool supported = false;
for (auto & machine : machines2) {
if (machine.second->supportsStep(step)) {
step->state.lock()->lastSupported = now;
supported = true;
break;
}
}
if (!supported)
count++;
if (!supported
&& std::chrono::duration_cast<std::chrono::seconds>(now - step->state.lock()->lastSupported).count() >= maxUnsupportedTime)
{
printError("aborting unsupported build step '%s' (type '%s')",
localStore->printStorePath(step->drvPath),
step->systemType);
aborted.insert(step);
auto conn(dbPool.get());
std::set<Build::ptr> dependents;
std::set<Step::ptr> steps;
getDependents(step, dependents, steps);
/* Maybe the step got cancelled. */
if (dependents.empty()) continue;
/* Find the build that has this step as the top-level (if
any). */
Build::ptr build;
for (auto build2 : dependents) {
if (build2->drvPath == step->drvPath)
build = build2;
}
if (!build) build = *dependents.begin();
bool stepFinished = false;
failStep(
*conn, step, build->id,
RemoteResult {
.stepStatus = bsUnsupported,
.errorMsg = fmt("unsupported system type '%s'",
step->systemType),
.startTime = now2,
.stopTime = now2,
},
nullptr, stepFinished);
if (buildOneDone) exit(1);
}
}
/* Clean up 'runnable'. */
{
auto runnable_(runnable.lock());
for (auto i = runnable_->begin(); i != runnable_->end(); ) {
if (aborted.count(i->lock()))
i = runnable_->erase(i);
else
++i;
}
}
nrUnsupportedSteps = count;
}
void Jobset::addStep(time_t startTime, time_t duration)
{
auto steps_(steps.lock());
(*steps_)[startTime] = duration;
seconds += duration;
}
void Jobset::pruneSteps()
{
time_t now = time(0);
auto steps_(steps.lock());
while (!steps_->empty()) {
auto i = steps_->begin();
if (i->first > now - schedulingWindow) break;
seconds -= i->second;
steps_->erase(i);
}
}
State::MachineReservation::MachineReservation(State & state, Step::ptr step, ::Machine::ptr machine)
: state(state), step(step), machine(machine)
{
machine->state->currentJobs++;
{
auto machineTypes_(state.machineTypes.lock());
(*machineTypes_)[step->systemType].running++;
}
}
State::MachineReservation::~MachineReservation()
{
auto prev = machine->state->currentJobs--;
assert(prev);
if (prev == 1)
machine->state->idleSince = time(0);
{
auto machineTypes_(state.machineTypes.lock());
auto & machineType = (*machineTypes_)[step->systemType];
assert(machineType.running);
machineType.running--;
if (machineType.running == 0)
machineType.lastActive = std::chrono::system_clock::now();
}
}

View File

@@ -0,0 +1,47 @@
#pragma once
#include <memory>
#include <nix/util/hash.hh>
#include <nix/store/derivations.hh>
#include <nix/store/store-api.hh>
#include "nar-extractor.hh"
struct BuildProduct
{
nix::Path path, defaultPath;
std::string type, subtype, name;
bool isRegular = false;
std::optional<nix::Hash> sha256hash;
std::optional<off_t> fileSize;
BuildProduct() { }
};
struct BuildMetric
{
std::string name, unit;
double value;
};
struct BuildOutput
{
/* Whether this build has failed with output, i.e., the build
finished with exit code 0 but produced a file
$out/nix-support/failed. */
bool failed = false;
std::string releaseName;
uint64_t closureSize = 0, size = 0;
std::list<BuildProduct> products;
std::map<std::string, nix::StorePath> outputs;
std::map<std::string, BuildMetric> metrics;
};
BuildOutput getBuildOutput(
nix::ref<nix::Store> store,
NarMemberDatas & narMembers,
const nix::OutputPathMap derivationOutputs);

View File

@@ -0,0 +1,968 @@
#include <iostream>
#include <thread>
#include <optional>
#include <type_traits>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <prometheus/exposer.h>
#include <nlohmann/json.hpp>
#include <nix/util/signals.hh>
#include "state.hh"
#include "hydra-build-result.hh"
#include <nix/store/store-open.hh>
#include <nix/store/remote-store.hh>
#include <nix/store/globals.hh>
#include "hydra-config.hh"
#include <nix/store/s3-binary-cache-store.hh>
#include <nix/main/shared.hh>
using namespace nix;
using nlohmann::json;
std::string getEnvOrDie(const std::string & key)
{
auto value = getEnv(key);
if (!value) throw Error("environment variable '%s' is not set", key);
return *value;
}
State::PromMetrics::PromMetrics()
: registry(std::make_shared<prometheus::Registry>())
, queue_checks_started(
prometheus::BuildCounter()
.Name("hydraqueuerunner_queue_checks_started_total")
.Help("Number of times State::getQueuedBuilds() was started")
.Register(*registry)
.Add({})
)
, queue_build_loads(
prometheus::BuildCounter()
.Name("hydraqueuerunner_queue_build_loads_total")
.Help("Number of builds loaded")
.Register(*registry)
.Add({})
)
, queue_steps_created(
prometheus::BuildCounter()
.Name("hydraqueuerunner_queue_steps_created_total")
.Help("Number of steps created")
.Register(*registry)
.Add({})
)
, queue_checks_early_exits(
prometheus::BuildCounter()
.Name("hydraqueuerunner_queue_checks_early_exits_total")
.Help("Number of times State::getQueuedBuilds() yielded to potential bumps")
.Register(*registry)
.Add({})
)
, queue_checks_finished(
prometheus::BuildCounter()
.Name("hydraqueuerunner_queue_checks_finished_total")
.Help("Number of times State::getQueuedBuilds() was completed")
.Register(*registry)
.Add({})
)
, dispatcher_time_spent_running(
prometheus::BuildCounter()
.Name("hydraqueuerunner_dispatcher_time_spent_running")
.Help("Time (in micros) spent running the dispatcher")
.Register(*registry)
.Add({})
)
, dispatcher_time_spent_waiting(
prometheus::BuildCounter()
.Name("hydraqueuerunner_dispatcher_time_spent_waiting")
.Help("Time (in micros) spent waiting for the dispatcher to obtain work")
.Register(*registry)
.Add({})
)
, queue_monitor_time_spent_running(
prometheus::BuildCounter()
.Name("hydraqueuerunner_queue_monitor_time_spent_running")
.Help("Time (in micros) spent running the queue monitor")
.Register(*registry)
.Add({})
)
, queue_monitor_time_spent_waiting(
prometheus::BuildCounter()
.Name("hydraqueuerunner_queue_monitor_time_spent_waiting")
.Help("Time (in micros) spent waiting for the queue monitor to obtain work")
.Register(*registry)
.Add({})
)
{
}
State::State(std::optional<std::string> metricsAddrOpt)
: config(std::make_unique<HydraConfig>())
, maxUnsupportedTime(config->getIntOption("max_unsupported_time", 0))
, dbPool(config->getIntOption("max_db_connections", 128))
, localWorkThrottler(config->getIntOption("max_local_worker_threads", std::min(maxSupportedLocalWorkers, std::max(4u, std::thread::hardware_concurrency()) - 2)))
, maxOutputSize(config->getIntOption("max_output_size", 2ULL << 30))
, maxLogSize(config->getIntOption("max_log_size", 64ULL << 20))
, uploadLogsToBinaryCache(config->getBoolOption("upload_logs_to_binary_cache", false))
, rootsDir(config->getStrOption("gc_roots_dir", fmt("%s/gcroots/per-user/%s/hydra-roots", settings.nixStateDir, getEnvOrDie("LOGNAME"))))
, metricsAddr(config->getStrOption("queue_runner_metrics_address", std::string{"127.0.0.1:9198"}))
{
hydraData = getEnvOrDie("HYDRA_DATA");
logDir = canonPath(hydraData + "/build-logs");
if (metricsAddrOpt.has_value()) {
metricsAddr = metricsAddrOpt.value();
}
/* handle deprecated store specification */
if (config->getStrOption("store_mode") != "")
throw Error("store_mode in hydra.conf is deprecated, please use store_uri");
if (config->getStrOption("binary_cache_dir") != "")
printMsg(lvlError, "hydra.conf: binary_cache_dir is deprecated and ignored. use store_uri=file:// instead");
if (config->getStrOption("binary_cache_s3_bucket") != "")
printMsg(lvlError, "hydra.conf: binary_cache_s3_bucket is deprecated and ignored. use store_uri=s3:// instead");
if (config->getStrOption("binary_cache_secret_key_file") != "")
printMsg(lvlError, "hydra.conf: binary_cache_secret_key_file is deprecated and ignored. use store_uri=...?secret-key= instead");
createDirs(rootsDir);
}
nix::MaintainCount<counter> State::startDbUpdate()
{
if (nrActiveDbUpdates > 6)
printError("warning: %d concurrent database updates; PostgreSQL may be stalled", nrActiveDbUpdates.load());
return MaintainCount<counter>(nrActiveDbUpdates);
}
ref<Store> State::getDestStore()
{
return ref<Store>(_destStore);
}
void State::parseMachines(const std::string & contents)
{
Machines newMachines, oldMachines;
{
auto machines_(machines.lock());
oldMachines = *machines_;
}
for (auto && machine_ : nix::Machine::parseConfig({}, contents)) {
auto machine = std::make_shared<::Machine>(std::move(machine_));
/* Re-use the State object of the previous machine with the
same name. */
auto i = oldMachines.find(machine->storeUri.variant);
if (i == oldMachines.end())
printMsg(lvlChatty, "adding new machine %1%", machine->storeUri.render());
else
printMsg(lvlChatty, "updating machine %1%", machine->storeUri.render());
machine->state = i == oldMachines.end()
? std::make_shared<::Machine::State>()
: i->second->state;
newMachines[machine->storeUri.variant] = machine;
}
for (auto & m : oldMachines)
if (newMachines.find(m.first) == newMachines.end()) {
if (m.second->enabled)
printInfo("removing machine %1%", m.second->storeUri.render());
/* Add a disabled ::Machine object to make sure stats are
maintained. */
auto machine = std::make_shared<::Machine>(*(m.second));
machine->enabled = false;
newMachines[m.first] = machine;
}
static bool warned = false;
if (newMachines.empty() && !warned) {
printError("warning: no build machines are defined");
warned = true;
}
auto machines_(machines.lock());
*machines_ = newMachines;
wakeDispatcher();
}
void State::monitorMachinesFile()
{
std::string defaultMachinesFile = "/etc/nix/machines";
auto machinesFiles = tokenizeString<std::vector<Path>>(
getEnv("NIX_REMOTE_SYSTEMS").value_or(pathExists(defaultMachinesFile) ? defaultMachinesFile : ""), ":");
if (machinesFiles.empty()) {
parseMachines("localhost " +
(settings.thisSystem == "x86_64-linux" ? "x86_64-linux,i686-linux" : settings.thisSystem.get())
+ " - " + std::to_string(settings.maxBuildJobs) + " 1 "
+ concatStringsSep(",", StoreConfig::getDefaultSystemFeatures()));
machinesReadyLock.unlock();
return;
}
std::vector<struct stat> fileStats;
fileStats.resize(machinesFiles.size());
for (unsigned int n = 0; n < machinesFiles.size(); ++n) {
auto & st(fileStats[n]);
st.st_ino = st.st_mtime = 0;
}
auto readMachinesFiles = [&]() {
/* Check if any of the machines files changed. */
bool anyChanged = false;
for (unsigned int n = 0; n < machinesFiles.size(); ++n) {
Path machinesFile = machinesFiles[n];
struct stat st;
if (stat(machinesFile.c_str(), &st) != 0) {
if (errno != ENOENT)
throw SysError("getting stats about %s", machinesFile);
st.st_ino = st.st_mtime = 0;
}
auto & old(fileStats[n]);
if (old.st_ino != st.st_ino || old.st_mtime != st.st_mtime)
anyChanged = true;
old = st;
}
if (!anyChanged) return;
debug("reloading machines files");
std::string contents;
for (auto & machinesFile : machinesFiles) {
try {
contents += readFile(machinesFile);
contents += '\n';
} catch (SysError & e) {
if (e.errNo != ENOENT) throw;
}
}
parseMachines(contents);
};
auto firstParse = true;
while (true) {
try {
readMachinesFiles();
if (firstParse) {
machinesReadyLock.unlock();
firstParse = false;
}
// FIXME: use inotify.
sleep(30);
} catch (std::exception & e) {
printMsg(lvlError, "reloading machines file: %s", e.what());
sleep(5);
}
}
}
void State::clearBusy(Connection & conn, time_t stopTime)
{
pqxx::work txn(conn);
txn.exec("update BuildSteps set busy = 0, status = $1, stopTime = $2 where busy != 0",
pqxx::params{(int) bsAborted,
stopTime != 0 ? std::make_optional(stopTime) : std::nullopt}).no_rows();
txn.commit();
}
unsigned int State::allocBuildStep(pqxx::work & txn, BuildID buildId)
{
auto res = txn.exec("select max(stepnr) from BuildSteps where build = $1", buildId).one_row();
return res[0].is_null() ? 1 : res[0].as<int>() + 1;
}
unsigned int State::createBuildStep(pqxx::work & txn, time_t startTime, BuildID buildId, Step::ptr step,
const std::string & machine, BuildStatus status, const std::string & errorMsg, BuildID propagatedFrom)
{
restart:
auto stepNr = allocBuildStep(txn, buildId);
auto r = txn.exec("insert into BuildSteps (build, stepnr, type, drvPath, busy, startTime, system, status, propagatedFrom, errorMsg, stopTime, machine) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) on conflict do nothing",
pqxx::params{buildId,
stepNr,
0, // == build
localStore->printStorePath(step->drvPath),
status == bsBusy ? 1 : 0,
startTime != 0 ? std::make_optional(startTime) : std::nullopt,
step->drv->platform,
status != bsBusy ? std::make_optional((int) status) : std::nullopt,
propagatedFrom != 0 ? std::make_optional(propagatedFrom) : std::nullopt, // internal::params
errorMsg != "" ? std::make_optional(errorMsg) : std::nullopt,
startTime != 0 && status != bsBusy ? std::make_optional(startTime) : std::nullopt,
machine});
if (r.affected_rows() == 0) goto restart;
for (auto & [name, output] : getDestStore()->queryPartialDerivationOutputMap(step->drvPath, &*localStore))
txn.exec("insert into BuildStepOutputs (build, stepnr, name, path) values ($1, $2, $3, $4)",
pqxx::params{buildId, stepNr, name,
output
? std::optional { localStore->printStorePath(*output)}
: std::nullopt}).no_rows();
if (status == bsBusy)
txn.exec(fmt("notify step_started, '%d\t%d'", buildId, stepNr));
return stepNr;
}
void State::updateBuildStep(pqxx::work & txn, BuildID buildId, unsigned int stepNr, StepState stepState)
{
if (txn.exec("update BuildSteps set busy = $1 where build = $2 and stepnr = $3 and busy != 0 and status is null",
pqxx::params{(int) stepState,
buildId,
stepNr}).affected_rows() != 1)
throw Error("step %d of build %d is in an unexpected state", stepNr, buildId);
}
void State::finishBuildStep(pqxx::work & txn, const RemoteResult & result,
BuildID buildId, unsigned int stepNr, const std::string & machine)
{
assert(result.startTime);
assert(result.stopTime);
txn.exec("update BuildSteps set busy = 0, status = $1, errorMsg = $4, startTime = $5, stopTime = $6, machine = $7, overhead = $8, timesBuilt = $9, isNonDeterministic = $10 where build = $2 and stepnr = $3",
pqxx::params{(int) result.stepStatus, buildId, stepNr,
result.errorMsg != "" ? std::make_optional(result.errorMsg) : std::nullopt,
result.startTime, result.stopTime,
machine != "" ? std::make_optional(machine) : std::nullopt,
result.overhead != 0 ? std::make_optional(result.overhead) : std::nullopt,
result.timesBuilt > 0 ? std::make_optional(result.timesBuilt) : std::nullopt,
result.timesBuilt > 1 ? std::make_optional(result.isNonDeterministic) : std::nullopt}).no_rows();
assert(result.logFile.find('\t') == std::string::npos);
txn.exec(fmt("notify step_finished, '%d\t%d\t%s'",
buildId, stepNr, result.logFile));
if (result.stepStatus == bsSuccess) {
// Update the corresponding `BuildStepOutputs` row to add the output path
auto res = txn.exec("select drvPath from BuildSteps where build = $1 and stepnr = $2", pqxx::params{buildId, stepNr}).one_row();
assert(res.size());
StorePath drvPath = localStore->parseStorePath(res[0].as<std::string>());
// If we've finished building, all the paths should be known
for (auto & [name, output] : getDestStore()->queryDerivationOutputMap(drvPath, &*localStore))
txn.exec("update BuildStepOutputs set path = $4 where build = $1 and stepnr = $2 and name = $3",
pqxx::params{buildId, stepNr, name, localStore->printStorePath(output)}).no_rows();
}
}
int State::createSubstitutionStep(pqxx::work & txn, time_t startTime, time_t stopTime,
Build::ptr build, const StorePath & drvPath, const nix::Derivation drv, const std::string & outputName, const StorePath & storePath)
{
restart:
auto stepNr = allocBuildStep(txn, build->id);
auto r = txn.exec("insert into BuildSteps (build, stepnr, type, drvPath, busy, status, startTime, stopTime) values ($1, $2, $3, $4, $5, $6, $7, $8) on conflict do nothing",
pqxx::params{build->id,
stepNr,
1, // == substitution
(localStore->printStorePath(drvPath)),
0,
0,
startTime,
stopTime});
if (r.affected_rows() == 0) goto restart;
txn.exec("insert into BuildStepOutputs (build, stepnr, name, path) values ($1, $2, $3, $4)",
pqxx::params{build->id, stepNr, outputName,
localStore->printStorePath(storePath)}).no_rows();
return stepNr;
}
/* Get the steps and unfinished builds that depend on the given step. */
void getDependents(Step::ptr step, std::set<Build::ptr> & builds, std::set<Step::ptr> & steps)
{
std::function<void(Step::ptr)> visit;
visit = [&](Step::ptr step) {
if (steps.count(step)) return;
steps.insert(step);
std::vector<Step::wptr> rdeps;
{
auto step_(step->state.lock());
for (auto & build : step_->builds) {
auto build_ = build.lock();
if (build_ && !build_->finishedInDB) builds.insert(build_);
}
/* Make a copy of rdeps so that we don't hold the lock for
very long. */
rdeps = step_->rdeps;
}
for (auto & rdep : rdeps) {
auto rdep_ = rdep.lock();
if (rdep_) visit(rdep_);
}
};
visit(step);
}
void visitDependencies(std::function<void(Step::ptr)> visitor, Step::ptr start)
{
std::set<Step::ptr> queued;
std::queue<Step::ptr> todo;
todo.push(start);
while (!todo.empty()) {
auto step = todo.front();
todo.pop();
visitor(step);
auto state(step->state.lock());
for (auto & dep : state->deps)
if (queued.find(dep) == queued.end()) {
queued.insert(dep);
todo.push(dep);
}
}
}
void State::markSucceededBuild(pqxx::work & txn, Build::ptr build,
const BuildOutput & res, bool isCachedBuild, time_t startTime, time_t stopTime)
{
if (build->finishedInDB) return;
if (txn.exec("select 1 from Builds where id = $1 and finished = 0", pqxx::params{build->id}).empty()) return;
txn.exec("update Builds set finished = 1, buildStatus = $2, startTime = $3, stopTime = $4, size = $5, closureSize = $6, releaseName = $7, isCachedBuild = $8, notificationPendingSince = $4 where id = $1",
pqxx::params{build->id,
(int) (res.failed ? bsFailedWithOutput : bsSuccess),
startTime,
stopTime,
res.size,
res.closureSize,
res.releaseName != "" ? std::make_optional(res.releaseName) : std::nullopt,
isCachedBuild ? 1 : 0}).no_rows();
for (auto & [outputName, outputPath] : res.outputs) {
txn.exec("update BuildOutputs set path = $3 where build = $1 and name = $2",
pqxx::params{build->id,
outputName,
localStore->printStorePath(outputPath)}
).no_rows();
}
txn.exec("delete from BuildProducts where build = $1", pqxx::params{build->id}).no_rows();
unsigned int productNr = 1;
for (auto & product : res.products) {
txn.exec("insert into BuildProducts (build, productnr, type, subtype, fileSize, sha256hash, path, name, defaultPath) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
pqxx::params{build->id,
productNr++,
product.type,
product.subtype,
product.fileSize ? std::make_optional(*product.fileSize) : std::nullopt,
product.sha256hash ? std::make_optional(product.sha256hash->to_string(HashFormat::Base16, false)) : std::nullopt,
product.path,
product.name,
product.defaultPath}).no_rows();
}
txn.exec("delete from BuildMetrics where build = $1", pqxx::params{build->id}).no_rows();
for (auto & metric : res.metrics) {
txn.exec("insert into BuildMetrics (build, name, unit, value, project, jobset, job, timestamp) values ($1, $2, $3, $4, $5, $6, $7, $8)",
pqxx::params{build->id,
metric.second.name,
metric.second.unit != "" ? std::make_optional(metric.second.unit) : std::nullopt,
metric.second.value,
build->projectName,
build->jobsetName,
build->jobName,
build->timestamp}).no_rows();
}
nrBuildsDone++;
}
bool State::checkCachedFailure(Step::ptr step, Connection & conn)
{
pqxx::work txn(conn);
for (auto & i : step->drv->outputsAndOptPaths(*localStore))
if (i.second.second)
if (!txn.exec("select 1 from FailedPaths where path = $1", pqxx::params{localStore->printStorePath(*i.second.second)}).empty())
return true;
return false;
}
void State::notifyBuildStarted(pqxx::work & txn, BuildID buildId)
{
txn.exec(fmt("notify build_started, '%s'", buildId));
}
void State::notifyBuildFinished(pqxx::work & txn, BuildID buildId,
const std::vector<BuildID> & dependentIds)
{
auto payload = fmt("%d", buildId);
for (auto & d : dependentIds)
payload += fmt("\t%d", d);
// FIXME: apparently parameterized() doesn't support NOTIFY.
txn.exec(fmt("notify build_finished, '%s'", payload));
}
std::shared_ptr<PathLocks> State::acquireGlobalLock()
{
auto lockPath = std::filesystem::path(hydraData) / "queue-runner/lock";
createDirs(lockPath.parent_path());
auto lock = std::make_shared<PathLocks>();
if (!lock->lockPaths({lockPath}, "", false)) return 0;
return lock;
}
void State::dumpStatus(Connection & conn)
{
time_t now = time(0);
json statusJson = {
{"status", "up"},
{"time", time(0)},
{"uptime", now - startedAt},
{"pid", getpid()},
{"nrQueuedBuilds", builds.lock()->size()},
{"nrActiveSteps", activeSteps_.lock()->size()},
{"nrStepsBuilding", nrStepsBuilding.load()},
{"nrStepsCopyingTo", nrStepsCopyingTo.load()},
{"nrStepsWaitingForDownloadSlot", nrStepsWaitingForDownloadSlot.load()},
{"nrStepsCopyingFrom", nrStepsCopyingFrom.load()},
{"nrStepsWaiting", nrStepsWaiting.load()},
{"nrUnsupportedSteps", nrUnsupportedSteps.load()},
{"bytesSent", bytesSent.load()},
{"bytesReceived", bytesReceived.load()},
{"nrBuildsRead", nrBuildsRead.load()},
{"buildReadTimeMs", buildReadTimeMs.load()},
{"buildReadTimeAvgMs", nrBuildsRead == 0 ? 0.0 : (float) buildReadTimeMs / nrBuildsRead},
{"nrBuildsDone", nrBuildsDone.load()},
{"nrStepsStarted", nrStepsStarted.load()},
{"nrStepsDone", nrStepsDone.load()},
{"nrRetries", nrRetries.load()},
{"maxNrRetries", maxNrRetries.load()},
{"nrQueueWakeups", nrQueueWakeups.load()},
{"nrDispatcherWakeups", nrDispatcherWakeups.load()},
{"dispatchTimeMs", dispatchTimeMs.load()},
{"dispatchTimeAvgMs", nrDispatcherWakeups == 0 ? 0.0 : (float) dispatchTimeMs / nrDispatcherWakeups},
{"nrDbConnections", dbPool.count()},
{"nrActiveDbUpdates", nrActiveDbUpdates.load()},
};
{
{
auto steps_(steps.lock());
for (auto i = steps_->begin(); i != steps_->end(); )
if (i->second.lock()) ++i; else i = steps_->erase(i);
statusJson["nrUnfinishedSteps"] = steps_->size();
}
{
auto runnable_(runnable.lock());
for (auto i = runnable_->begin(); i != runnable_->end(); )
if (i->lock()) ++i; else i = runnable_->erase(i);
statusJson["nrRunnableSteps"] = runnable_->size();
}
if (nrStepsDone) {
statusJson["totalStepTime"] = totalStepTime.load();
statusJson["totalStepBuildTime"] = totalStepBuildTime.load();
statusJson["avgStepTime"] = (float) totalStepTime / nrStepsDone;
statusJson["avgStepBuildTime"] = (float) totalStepBuildTime / nrStepsDone;
}
{
auto machines_json = json::object();
auto machines_(machines.lock());
for (auto & i : *machines_) {
auto & m(i.second);
auto & s(m->state);
auto info(m->state->connectInfo.lock());
json machine = {
{"enabled", m->enabled},
{"systemTypes", m->systemTypes},
{"supportedFeatures", m->supportedFeatures},
{"mandatoryFeatures", m->mandatoryFeatures},
{"nrStepsDone", s->nrStepsDone.load()},
{"currentJobs", s->currentJobs.load()},
{"disabledUntil", std::chrono::system_clock::to_time_t(info->disabledUntil)},
{"lastFailure", std::chrono::system_clock::to_time_t(info->lastFailure)},
{"consecutiveFailures", info->consecutiveFailures},
};
if (s->currentJobs == 0)
machine["idleSince"] = s->idleSince.load();
if (m->state->nrStepsDone) {
machine["totalStepTime"] = s->totalStepTime.load();
machine["totalStepBuildTime"] = s->totalStepBuildTime.load();
machine["avgStepTime"] = (float) s->totalStepTime / s->nrStepsDone;
machine["avgStepBuildTime"] = (float) s->totalStepBuildTime / s->nrStepsDone;
}
machines_json[m->storeUri.render()] = machine;
}
statusJson["machines"] = machines_json;
}
{
auto jobsets_json = json::object();
auto jobsets_(jobsets.lock());
for (auto & jobset : *jobsets_) {
jobsets_json[jobset.first.first + ":" + jobset.first.second] = {
{"shareUsed", jobset.second->shareUsed()},
{"seconds", jobset.second->getSeconds()},
};
}
statusJson["jobsets"] = jobsets_json;
}
{
auto machineTypesJson = json::object();
auto machineTypes_(machineTypes.lock());
for (auto & i : *machineTypes_) {
auto machineTypeJson = machineTypesJson[i.first] = {
{"runnable", i.second.runnable},
{"running", i.second.running},
};
if (i.second.runnable > 0)
machineTypeJson["waitTime"] = i.second.waitTime.count() +
i.second.runnable * (time(0) - lastDispatcherCheck);
if (i.second.running == 0)
machineTypeJson["lastActive"] = std::chrono::system_clock::to_time_t(i.second.lastActive);
}
statusJson["machineTypes"] = machineTypesJson;
}
auto store = getDestStore();
auto & stats = store->getStats();
statusJson["store"] = {
{"narInfoRead", stats.narInfoRead.load()},
{"narInfoReadAverted", stats.narInfoReadAverted.load()},
{"narInfoMissing", stats.narInfoMissing.load()},
{"narInfoWrite", stats.narInfoWrite.load()},
{"narInfoCacheSize", stats.pathInfoCacheSize.load()},
{"narRead", stats.narRead.load()},
{"narReadBytes", stats.narReadBytes.load()},
{"narReadCompressedBytes", stats.narReadCompressedBytes.load()},
{"narWrite", stats.narWrite.load()},
{"narWriteAverted", stats.narWriteAverted.load()},
{"narWriteBytes", stats.narWriteBytes.load()},
{"narWriteCompressedBytes", stats.narWriteCompressedBytes.load()},
{"narWriteCompressionTimeMs", stats.narWriteCompressionTimeMs.load()},
{"narCompressionSavings",
stats.narWriteBytes
? 1.0 - (double) stats.narWriteCompressedBytes / stats.narWriteBytes
: 0.0},
{"narCompressionSpeed", // MiB/s
stats.narWriteCompressionTimeMs
? (double) stats.narWriteBytes / stats.narWriteCompressionTimeMs * 1000.0 / (1024.0 * 1024.0)
: 0.0},
};
#if NIX_WITH_S3_SUPPORT
auto s3Store = dynamic_cast<S3BinaryCacheStore *>(&*store);
if (s3Store) {
auto & s3Stats = s3Store->getS3Stats();
auto jsonS3 = statusJson["s3"] = {
{"put", s3Stats.put.load()},
{"putBytes", s3Stats.putBytes.load()},
{"putTimeMs", s3Stats.putTimeMs.load()},
{"putSpeed",
s3Stats.putTimeMs
? (double) s3Stats.putBytes / s3Stats.putTimeMs * 1000.0 / (1024.0 * 1024.0)
: 0.0},
{"get", s3Stats.get.load()},
{"getBytes", s3Stats.getBytes.load()},
{"getTimeMs", s3Stats.getTimeMs.load()},
{"getSpeed",
s3Stats.getTimeMs
? (double) s3Stats.getBytes / s3Stats.getTimeMs * 1000.0 / (1024.0 * 1024.0)
: 0.0},
{"head", s3Stats.head.load()},
{"costDollarApprox",
(s3Stats.get + s3Stats.head) / 10000.0 * 0.004
+ s3Stats.put / 1000.0 * 0.005 +
+ s3Stats.getBytes / (1024.0 * 1024.0 * 1024.0) * 0.09},
};
}
#endif
}
{
auto mc = startDbUpdate();
pqxx::work txn(conn);
// FIXME: use PostgreSQL 9.5 upsert.
txn.exec("delete from SystemStatus where what = 'queue-runner'").no_rows();
txn.exec("insert into SystemStatus values ('queue-runner', $1)", pqxx::params{statusJson.dump()}).no_rows();
txn.exec("notify status_dumped");
txn.commit();
}
}
void State::showStatus()
{
auto conn(dbPool.get());
receiver statusDumped(*conn, "status_dumped");
std::string status;
bool barf = false;
/* Get the last JSON status dump from the database. */
{
pqxx::work txn(*conn);
auto res = txn.exec("select status from SystemStatus where what = 'queue-runner'");
if (res.size()) status = res[0][0].as<std::string>();
}
if (status != "") {
/* If the status is not empty, then the queue runner is
running. Ask it to update the status dump. */
{
pqxx::work txn(*conn);
txn.exec("notify dump_status");
txn.commit();
}
/* Wait until it has done so. */
barf = conn->await_notification(5, 0) == 0;
/* Get the new status. */
{
pqxx::work txn(*conn);
auto res = txn.exec("select status from SystemStatus where what = 'queue-runner'");
if (res.size()) status = res[0][0].as<std::string>();
}
}
if (status == "") status = R"({"status":"down"})";
std::cout << status << "\n";
if (barf)
throw Error("queue runner did not respond; status information may be wrong");
}
void State::unlock()
{
auto lock = acquireGlobalLock();
if (!lock)
throw Error("hydra-queue-runner is currently running");
auto conn(dbPool.get());
clearBusy(*conn, 0);
{
pqxx::work txn(*conn);
txn.exec("delete from SystemStatus where what = 'queue-runner'").no_rows();
txn.commit();
}
}
void State::run(BuildID buildOne)
{
/* Can't be bothered to shut down cleanly. Goodbye! */
auto callback = createInterruptCallback([&]() { std::_Exit(0); });
startedAt = time(0);
this->buildOne = buildOne;
auto lock = acquireGlobalLock();
if (!lock)
throw Error("hydra-queue-runner is already running");
std::cout << "Starting the Prometheus exporter on " << metricsAddr << std::endl;
/* Set up simple exporter, to show that we're still alive. */
prometheus::Exposer promExposer{metricsAddr};
auto exposerPort = promExposer.GetListeningPorts().front();
promExposer.RegisterCollectable(prom.registry);
std::cout << "Started the Prometheus exporter, listening on "
<< metricsAddr << "/metrics (port " << exposerPort << ")"
<< std::endl;
Store::Config::Params localParams;
localParams["max-connections"] = "16";
localParams["max-connection-age"] = "600";
localStore = openStore(getEnv("NIX_REMOTE").value_or(""), localParams);
auto storeUri = config->getStrOption("store_uri");
_destStore = storeUri == "" ? localStore : openStore(storeUri);
useSubstitutes = config->getBoolOption("use-substitutes", false);
// FIXME: hacky mechanism for configuring determinism checks.
for (auto & s : tokenizeString<Strings>(config->getStrOption("xxx-jobset-repeats"))) {
auto s2 = tokenizeString<std::vector<std::string>>(s, ":");
if (s2.size() != 3) throw Error("bad value in xxx-jobset-repeats");
jobsetRepeats.emplace(std::make_pair(s2[0], s2[1]), std::stoi(s2[2]));
}
{
auto conn(dbPool.get());
clearBusy(*conn, 0);
dumpStatus(*conn);
}
machinesReadyLock.lock();
std::thread(&State::monitorMachinesFile, this).detach();
std::thread(&State::queueMonitor, this).detach();
std::thread(&State::dispatcher, this).detach();
/* Periodically clean up orphaned busy steps in the database. */
std::thread([&]() {
while (true) {
sleep(180);
std::set<std::pair<BuildID, int>> steps;
{
auto orphanedSteps_(orphanedSteps.lock());
if (orphanedSteps_->empty()) continue;
steps = *orphanedSteps_;
orphanedSteps_->clear();
}
try {
auto conn(dbPool.get());
pqxx::work txn(*conn);
for (auto & step : steps) {
printMsg(lvlError, "cleaning orphaned step %d of build %d", step.second, step.first);
txn.exec("update BuildSteps set busy = 0, status = $1 where build = $2 and stepnr = $3 and busy != 0",
pqxx::params{(int) bsAborted,
step.first,
step.second}).no_rows();
}
txn.commit();
} catch (std::exception & e) {
printMsg(lvlError, "cleanup thread: %s", e.what());
auto orphanedSteps_(orphanedSteps.lock());
orphanedSteps_->insert(steps.begin(), steps.end());
}
}
}).detach();
/* Make sure that old daemon connections are closed even when
we're not doing much. */
std::thread([&]() {
while (true) {
sleep(10);
try {
if (auto remoteStore = getDestStore().dynamic_pointer_cast<RemoteStore>())
remoteStore->flushBadConnections();
} catch (std::exception & e) {
printMsg(lvlError, "connection flush thread: %s", e.what());
}
}
}).detach();
/* Monitor the database for status dump requests (e.g. from
hydra-queue-runner --status). */
while (true) {
try {
auto conn(dbPool.get());
try {
receiver dumpStatus_(*conn, "dump_status");
while (true) {
conn->await_notification();
dumpStatus(*conn);
}
} catch (pqxx::broken_connection & connEx) {
printMsg(lvlError, "main thread: %s", connEx.what());
printMsg(lvlError, "main thread: Reconnecting in 10s");
conn.markBad();
sleep(10);
}
} catch (std::exception & e) {
printMsg(lvlError, "main thread: %s", e.what());
sleep(10); // probably a DB problem, so don't retry right away
}
}
}
int main(int argc, char * * argv)
{
return handleExceptions(argv[0], [&]() {
initNix();
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGHUP, SIG_DFL);
// FIXME: do this in the child environment in openConnection().
unsetenv("IN_SYSTEMD");
bool unlock = false;
bool status = false;
BuildID buildOne = 0;
std::optional<std::string> metricsAddrOpt = std::nullopt;
parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
if (*arg == "--unlock")
unlock = true;
else if (*arg == "--status")
status = true;
else if (*arg == "--build-one") {
if (auto b = string2Int<BuildID>(getArg(*arg, arg, end)))
buildOne = *b;
else
throw Error("--build-one requires a build ID");
} else if (*arg == "--prometheus-address") {
metricsAddrOpt = getArg(*arg, arg, end);
} else
return false;
return true;
});
settings.verboseBuild = true;
State state{metricsAddrOpt};
if (status)
state.showStatus();
else if (unlock)
state.unlock();
else
state.run(buildOne);
});
}

View File

@@ -0,0 +1,24 @@
srcs = files(
'builder.cc',
'build-remote.cc',
'build-result.cc',
'dispatcher.cc',
'hydra-queue-runner.cc',
'nar-extractor.cc',
'queue-monitor.cc',
)
hydra_queue_runner = executable('hydra-queue-runner',
'hydra-queue-runner.cc',
srcs,
dependencies: [
libhydra_dep,
nix_util_dep,
nix_store_dep,
nix_main_dep,
pqxx_dep,
prom_cpp_core_dep,
prom_cpp_pull_dep,
],
install: true,
)

View File

@@ -0,0 +1,103 @@
#include "nar-extractor.hh"
#include <nix/util/archive.hh>
#include <unordered_set>
using namespace nix;
struct NarMemberConstructor : CreateRegularFileSink
{
NarMemberData & curMember;
HashSink hashSink = HashSink { HashAlgorithm::SHA256 };
std::optional<uint64_t> expectedSize;
NarMemberConstructor(NarMemberData & curMember)
: curMember(curMember)
{ }
void isExecutable() override
{
}
void preallocateContents(uint64_t size) override
{
expectedSize = size;
}
void operator () (std::string_view data) override
{
assert(expectedSize);
*curMember.fileSize += data.size();
hashSink(data);
if (curMember.contents) {
curMember.contents->append(data);
}
assert(curMember.fileSize <= expectedSize);
if (curMember.fileSize == expectedSize) {
auto [hash, len] = hashSink.finish();
assert(curMember.fileSize == len);
curMember.sha256 = hash;
}
}
};
struct Extractor : FileSystemObjectSink
{
std::unordered_set<Path> filesToKeep {
"/nix-support/hydra-build-products",
"/nix-support/hydra-release-name",
"/nix-support/hydra-metrics",
};
NarMemberDatas & members;
std::filesystem::path prefix;
Path toKey(const CanonPath & path)
{
std::filesystem::path p = prefix;
// Conditional to avoid trailing slash
if (!path.isRoot()) p /= path.rel();
return p;
}
Extractor(NarMemberDatas & members, const Path & prefix)
: members(members), prefix(prefix)
{ }
void createDirectory(const CanonPath & path) override
{
members.insert_or_assign(toKey(path), NarMemberData { .type = SourceAccessor::Type::tDirectory });
}
void createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> func) override
{
NarMemberConstructor nmc {
members.insert_or_assign(toKey(path), NarMemberData {
.type = SourceAccessor::Type::tRegular,
.fileSize = 0,
.contents = filesToKeep.count(path.abs()) ? std::optional("") : std::nullopt,
}).first->second,
};
func(nmc);
}
void createSymlink(const CanonPath & path, const std::string & target) override
{
members.insert_or_assign(toKey(path), NarMemberData { .type = SourceAccessor::Type::tSymlink });
}
};
void extractNarData(
Source & source,
const Path & prefix,
NarMemberDatas & members)
{
Extractor extractor(members, prefix);
parseDump(extractor, source);
// Note: this point may not be reached if we're in a coroutine.
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include <nix/util/source-accessor.hh>
#include <nix/util/types.hh>
#include <nix/util/serialise.hh>
#include <nix/util/hash.hh>
struct NarMemberData
{
nix::SourceAccessor::Type type;
std::optional<uint64_t> fileSize;
std::optional<std::string> contents;
std::optional<nix::Hash> sha256;
};
typedef std::map<nix::Path, NarMemberData> NarMemberDatas;
/* Read a NAR from a source and get to some info about every file
inside the NAR. */
void extractNarData(
nix::Source & source,
const nix::Path & prefix,
NarMemberDatas & members);

View File

@@ -0,0 +1,759 @@
#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>
#include <cstring>
#include <signal.h>
using namespace nix;
void State::queueMonitor()
{
while (true) {
auto conn(dbPool.get());
try {
queueMonitorLoop(*conn);
} catch (pqxx::broken_connection & e) {
printMsg(lvlError, "queue monitor: %s", e.what());
printMsg(lvlError, "queue monitor: Reconnecting in 10s");
conn.markBad();
sleep(10);
} catch (std::exception & e) {
printError("queue monitor: %s", e.what());
sleep(10); // probably a DB problem, so don't retry right away
}
}
}
void State::queueMonitorLoop(Connection & conn)
{
receiver buildsAdded(conn, "builds_added");
receiver buildsRestarted(conn, "builds_restarted");
receiver buildsCancelled(conn, "builds_cancelled");
receiver buildsDeleted(conn, "builds_deleted");
receiver buildsBumped(conn, "builds_bumped");
receiver jobsetSharesChanged(conn, "jobset_shares_changed");
auto destStore = getDestStore();
bool quit = false;
while (!quit) {
auto t_before_work = std::chrono::steady_clock::now();
localStore->clearPathInfoCache();
bool done = getQueuedBuilds(conn, destStore);
if (buildOne && buildOneDone) quit = true;
auto t_after_work = std::chrono::steady_clock::now();
prom.queue_monitor_time_spent_running.Increment(
std::chrono::duration_cast<std::chrono::microseconds>(t_after_work - t_before_work).count());
/* Sleep until we get notification from the database about an
event. */
if (done && !quit) {
conn.await_notification();
nrQueueWakeups++;
} else
conn.get_notifs();
if (auto lowestId = buildsAdded.get()) {
printMsg(lvlTalkative, "got notification: new builds added to the queue");
}
if (buildsRestarted.get()) {
printMsg(lvlTalkative, "got notification: builds restarted");
}
if (buildsCancelled.get() || buildsDeleted.get() || buildsBumped.get()) {
printMsg(lvlTalkative, "got notification: builds cancelled or bumped");
processQueueChange(conn);
}
if (jobsetSharesChanged.get()) {
printMsg(lvlTalkative, "got notification: jobset shares changed");
processJobsetSharesChange(conn);
}
auto t_after_sleep = std::chrono::steady_clock::now();
prom.queue_monitor_time_spent_waiting.Increment(
std::chrono::duration_cast<std::chrono::microseconds>(t_after_sleep - t_after_work).count());
}
exit(0);
}
struct PreviousFailure : public std::exception {
Step::ptr step;
PreviousFailure(Step::ptr step) : step(step) { }
};
bool State::getQueuedBuilds(Connection & conn,
ref<Store> destStore)
{
prom.queue_checks_started.Increment();
printInfo("checking the queue for builds...");
/* Grab the queued builds from the database, but don't process
them yet (since we don't want a long-running transaction). */
std::vector<BuildID> newIDs;
std::unordered_map<BuildID, Build::ptr> newBuildsByID;
std::multimap<StorePath, BuildID> newBuildsByPath;
{
pqxx::work txn(conn);
auto res = txn.exec("select builds.id, builds.jobset_id, jobsets.project as project, "
"jobsets.name as jobset, job, drvPath, maxsilent, timeout, timestamp, "
"globalPriority, priority from Builds "
"inner join jobsets on builds.jobset_id = jobsets.id "
"where finished = 0 order by globalPriority desc, random()");
for (auto const & row : res) {
auto builds_(builds.lock());
BuildID id = row["id"].as<BuildID>();
if (buildOne && id != buildOne) continue;
if (builds_->count(id)) continue;
auto build = std::make_shared<Build>(
localStore->parseStorePath(row["drvPath"].as<std::string>()));
build->id = id;
build->jobsetId = row["jobset_id"].as<JobsetID>();
build->projectName = row["project"].as<std::string>();
build->jobsetName = row["jobset"].as<std::string>();
build->jobName = row["job"].as<std::string>();
build->maxSilentTime = row["maxsilent"].as<int>();
build->buildTimeout = row["timeout"].as<int>();
build->timestamp = row["timestamp"].as<time_t>();
build->globalPriority = row["globalPriority"].as<int>();
build->localPriority = row["priority"].as<int>();
build->jobset = createJobset(txn, build->projectName, build->jobsetName, build->jobsetId);
newIDs.push_back(id);
newBuildsByID[id] = build;
newBuildsByPath.emplace(std::make_pair(build->drvPath, id));
}
}
std::set<Step::ptr> newRunnable;
unsigned int nrAdded;
std::function<void(Build::ptr)> createBuild;
std::set<StorePath> finishedDrvs;
createBuild = [&](Build::ptr build) {
prom.queue_build_loads.Increment();
printMsg(lvlTalkative, "loading build %1% (%2%)", build->id, build->fullJobName());
nrAdded++;
newBuildsByID.erase(build->id);
if (!localStore->isValidPath(build->drvPath)) {
/* Derivation has been GC'ed prematurely. */
printError("aborting GC'ed build %1%", build->id);
if (!build->finishedInDB) {
auto mc = startDbUpdate();
pqxx::work txn(conn);
txn.exec("update Builds set finished = 1, buildStatus = $2, startTime = $3, stopTime = $3 where id = $1 and finished = 0",
pqxx::params{build->id,
(int) bsAborted,
time(0)}).no_rows();
txn.commit();
build->finishedInDB = true;
nrBuildsDone++;
}
return;
}
std::set<Step::ptr> newSteps;
Step::ptr step;
/* Create steps for this derivation and its dependencies. */
try {
step = createStep(destStore, conn, build, build->drvPath,
build, 0, finishedDrvs, newSteps, newRunnable);
} catch (PreviousFailure & ex) {
/* Some step previously failed, so mark the build as
failed right away. */
if (!buildOneDone && build->id == buildOne) buildOneDone = true;
printMsg(lvlError, "marking build %d as cached failure due to %s",
build->id, localStore->printStorePath(ex.step->drvPath));
if (!build->finishedInDB) {
auto mc = startDbUpdate();
pqxx::work txn(conn);
/* Find the previous build step record, first by
derivation path, then by output path. */
BuildID propagatedFrom = 0;
auto res = txn.exec("select max(build) from BuildSteps where drvPath = $1 and startTime != 0 and stopTime != 0 and status = 1",
pqxx::params{localStore->printStorePath(ex.step->drvPath)}).one_row();
if (!res[0].is_null()) propagatedFrom = res[0].as<BuildID>();
if (!propagatedFrom) {
for (auto & [outputName, optOutputPath] : destStore->queryPartialDerivationOutputMap(ex.step->drvPath, &*localStore)) {
constexpr std::string_view common = "select max(s.build) from BuildSteps s join BuildStepOutputs o on s.build = o.build where startTime != 0 and stopTime != 0 and status = 1";
auto res = optOutputPath
? txn.exec(
std::string { common } + " and path = $1",
pqxx::params{localStore->printStorePath(*optOutputPath)})
: txn.exec(
std::string { common } + " and drvPath = $1 and name = $2",
pqxx::params{localStore->printStorePath(ex.step->drvPath), outputName});
if (!res[0][0].is_null()) {
propagatedFrom = res[0][0].as<BuildID>();
break;
}
}
}
createBuildStep(txn, 0, build->id, ex.step, "", bsCachedFailure, "", propagatedFrom);
txn.exec("update Builds set finished = 1, buildStatus = $2, startTime = $3, stopTime = $3, isCachedBuild = 1, notificationPendingSince = $3 "
"where id = $1 and finished = 0",
pqxx::params{build->id,
(int) (ex.step->drvPath == build->drvPath ? bsFailed : bsDepFailed),
time(0)}).no_rows();
notifyBuildFinished(txn, build->id, {});
txn.commit();
build->finishedInDB = true;
nrBuildsDone++;
}
return;
}
/* Some of the new steps may be the top level of builds that
we haven't processed yet. So do them now. This ensures that
if build A depends on build B with top-level step X, then X
will be "accounted" to B in doBuildStep(). */
for (auto & r : newSteps) {
auto i = newBuildsByPath.find(r->drvPath);
if (i == newBuildsByPath.end()) continue;
auto j = newBuildsByID.find(i->second);
if (j == newBuildsByID.end()) continue;
createBuild(j->second);
}
/* If we didn't get a step, it means the step's outputs are
all valid. So we mark this as a finished, cached build. */
if (!step) {
BuildOutput res = getBuildOutputCached(conn, destStore, build->drvPath);
for (auto & i : destStore->queryDerivationOutputMap(build->drvPath, &*localStore))
addRoot(i.second);
{
auto mc = startDbUpdate();
pqxx::work txn(conn);
time_t now = time(0);
if (!buildOneDone && build->id == buildOne) buildOneDone = true;
printMsg(lvlInfo, "marking build %1% as succeeded (cached)", build->id);
markSucceededBuild(txn, build, res, true, now, now);
notifyBuildFinished(txn, build->id, {});
txn.commit();
}
build->finishedInDB = true;
return;
}
/* Note: if we exit this scope prior to this, the build and
all newly created steps are destroyed. */
{
auto builds_(builds.lock());
if (!build->finishedInDB) // FIXME: can this happen?
(*builds_)[build->id] = build;
build->toplevel = step;
}
build->propagatePriorities();
printMsg(lvlChatty, "added build %1% (top-level step %2%, %3% new steps)",
build->id, localStore->printStorePath(step->drvPath), newSteps.size());
};
/* Now instantiate build steps for each new build. The builder
threads can start building the runnable build steps right away,
even while we're still processing other new builds. */
system_time start = std::chrono::system_clock::now();
for (auto id : newIDs) {
auto i = newBuildsByID.find(id);
if (i == newBuildsByID.end()) continue;
auto build = i->second;
auto now1 = std::chrono::steady_clock::now();
newRunnable.clear();
nrAdded = 0;
try {
createBuild(build);
} catch (Error & e) {
e.addTrace({}, HintFmt("while loading build %d: ", build->id));
throw;
}
auto now2 = std::chrono::steady_clock::now();
buildReadTimeMs += std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
/* Add the new runnable build steps to runnable and wake up
the builder threads. */
printMsg(lvlChatty, "got %1% new runnable steps from %2% new builds", newRunnable.size(), nrAdded);
for (auto & r : newRunnable)
makeRunnable(r);
if (buildOne && newRunnable.size() == 0) buildOneDone = true;
nrBuildsRead += nrAdded;
/* Stop after a certain time to allow priority bumps to be
processed. */
if (std::chrono::system_clock::now() > start + std::chrono::seconds(60)) {
prom.queue_checks_early_exits.Increment();
break;
}
}
prom.queue_checks_finished.Increment();
return newBuildsByID.empty();
}
void Build::propagatePriorities()
{
/* Update the highest global priority and lowest build ID fields
of each dependency. This is used by the dispatcher to start
steps in order of descending global priority and ascending
build ID. */
visitDependencies([&](const Step::ptr & step) {
auto step_(step->state.lock());
step_->highestGlobalPriority = std::max(step_->highestGlobalPriority, globalPriority);
step_->highestLocalPriority = std::max(step_->highestLocalPriority, localPriority);
step_->lowestBuildID = std::min(step_->lowestBuildID, id);
step_->jobsets.insert(jobset);
}, toplevel);
}
void State::processQueueChange(Connection & conn)
{
/* Get the current set of queued builds. */
std::map<BuildID, int> currentIds;
{
pqxx::work txn(conn);
auto res = txn.exec("select id, globalPriority from Builds where finished = 0");
for (auto const & row : res)
currentIds[row["id"].as<BuildID>()] = row["globalPriority"].as<BuildID>();
}
{
auto builds_(builds.lock());
for (auto i = builds_->begin(); i != builds_->end(); ) {
auto b = currentIds.find(i->first);
if (b == currentIds.end()) {
printInfo("discarding cancelled build %1%", i->first);
i = builds_->erase(i);
// FIXME: ideally we would interrupt active build steps here.
continue;
}
if (i->second->globalPriority < b->second) {
printInfo("priority of build %1% increased", i->first);
i->second->globalPriority = b->second;
i->second->propagatePriorities();
}
++i;
}
}
{
auto activeSteps(activeSteps_.lock());
for (auto & activeStep : *activeSteps) {
std::set<Build::ptr> dependents;
std::set<Step::ptr> steps;
getDependents(activeStep->step, dependents, steps);
if (!dependents.empty()) continue;
{
auto activeStepState(activeStep->state_.lock());
if (activeStepState->cancelled) continue;
activeStepState->cancelled = true;
if (activeStepState->pid != -1) {
printInfo("killing builder process %d of build step %s",
activeStepState->pid,
localStore->printStorePath(activeStep->step->drvPath));
if (kill(activeStepState->pid, SIGINT) == -1)
printError("error killing build step %s: %s",
localStore->printStorePath(activeStep->step->drvPath),
strerror(errno));
}
}
}
}
}
std::map<DrvOutput, std::optional<StorePath>> State::getMissingRemotePaths(
ref<Store> destStore,
const std::map<DrvOutput, std::optional<StorePath>> & paths)
{
Sync<std::map<DrvOutput, std::optional<StorePath>>> missing_;
ThreadPool tp;
for (auto & [output, maybeOutputPath] : paths) {
if (!maybeOutputPath) {
auto missing(missing_.lock());
missing->insert({output, maybeOutputPath});
} else {
tp.enqueue([&] {
if (!destStore->isValidPath(*maybeOutputPath)) {
auto missing(missing_.lock());
missing->insert({output, maybeOutputPath});
}
});
}
}
tp.process();
auto missing(missing_.lock());
return *missing;
}
Step::ptr State::createStep(ref<Store> destStore,
Connection & conn, Build::ptr build, const StorePath & drvPath,
Build::ptr referringBuild, Step::ptr referringStep, std::set<StorePath> & finishedDrvs,
std::set<Step::ptr> & newSteps, std::set<Step::ptr> & newRunnable)
{
if (finishedDrvs.find(drvPath) != finishedDrvs.end()) return 0;
/* Check if the requested step already exists. If not, create a
new step. In any case, make the step reachable from
referringBuild or referringStep. This is done atomically (with
steps locked), to ensure that this step can never become
reachable from a new build after doBuildStep has removed it
from steps. */
Step::ptr step;
bool isNew = false;
{
auto steps_(steps.lock());
/* See if the step already exists in steps and is not
stale. */
auto prev = steps_->find(drvPath);
if (prev != steps_->end()) {
step = prev->second.lock();
/* Since step is a strong pointer, the referred Step
object won't be deleted after this. */
if (!step) steps_->erase(drvPath); // remove stale entry
}
/* If it doesn't exist, create it. */
if (!step) {
step = std::make_shared<Step>(drvPath);
isNew = true;
}
auto step_(step->state.lock());
assert(step_->created != isNew);
if (referringBuild)
step_->builds.push_back(referringBuild);
if (referringStep)
step_->rdeps.push_back(referringStep);
steps_->insert_or_assign(drvPath, step);
}
if (!isNew) return step;
prom.queue_steps_created.Increment();
printMsg(lvlDebug, "considering derivation %1%", localStore->printStorePath(drvPath));
/* Initialize the step. Note that the step may be visible in
steps before this point, but that doesn't matter because
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));
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 = drvOptions.willBuildLocally(*localStore, *step->drv);
step->isDeterministic = getOr(step->drv->env, "isDetermistic", "0") == "1";
step->systemType = step->drv->platform;
{
StringSet features = step->requiredSystemFeatures = drvOptions.getRequiredSystemFeatures(*step->drv);
if (step->preferLocalBuild)
features.insert("local");
if (!features.empty()) {
step->systemType += ":";
step->systemType += concatStringsSep(",", features);
}
}
/* If this derivation failed previously, give up. */
if (checkCachedFailure(step, conn))
throw PreviousFailure{step};
/* Are all outputs valid? */
auto outputHashes = staticOutputHashes(*localStore, *(step->drv));
std::map<DrvOutput, std::optional<StorePath>> paths;
for (auto & [outputName, maybeOutputPath] : destStore->queryPartialDerivationOutputMap(drvPath, &*localStore)) {
auto outputHash = outputHashes.at(outputName);
paths.insert({{outputHash, outputName}, maybeOutputPath});
}
auto missing = getMissingRemotePaths(destStore, paths);
bool valid = missing.empty();
/* Try to copy the missing paths from the local store or from
substitutes. */
if (!missing.empty()) {
size_t avail = 0;
for (auto & [i, pathOpt] : missing) {
// If we don't know the output path from the destination
// store, see if the local store can tell us.
if (/* localStore != destStore && */ !pathOpt && experimentalFeatureSettings.isEnabled(Xp::CaDerivations))
if (auto maybeRealisation = localStore->queryRealisation(i))
pathOpt = maybeRealisation->outPath;
if (!pathOpt) {
// No hope of getting the store object if we don't know
// the path.
continue;
}
auto & path = *pathOpt;
if (/* localStore != destStore && */ localStore->isValidPath(path))
avail++;
else if (useSubstitutes) {
SubstitutablePathInfos infos;
localStore->querySubstitutablePathInfos({{path, {}}}, infos);
if (infos.size() == 1)
avail++;
}
}
if (missing.size() == avail) {
valid = true;
for (auto & [i, pathOpt] : missing) {
// If we found everything, then we should know the path
// to every missing store object now.
assert(pathOpt);
auto & path = *pathOpt;
try {
time_t startTime = time(0);
if (localStore->isValidPath(path))
printInfo("copying output %1% of %2% from local store",
localStore->printStorePath(path),
localStore->printStorePath(drvPath));
else {
printInfo("substituting output %1% of %2%",
localStore->printStorePath(path),
localStore->printStorePath(drvPath));
localStore->ensurePath(path);
// FIXME: should copy directly from substituter to destStore.
}
copyClosure(*localStore, *destStore,
StorePathSet { path },
NoRepair, CheckSigs, NoSubstitute);
time_t stopTime = time(0);
{
auto mc = startDbUpdate();
pqxx::work txn(conn);
createSubstitutionStep(txn, startTime, stopTime, build, drvPath, *(step->drv), "out", path);
txn.commit();
}
} catch (Error & e) {
printError("while copying/substituting output %s of %s: %s",
localStore->printStorePath(path),
localStore->printStorePath(drvPath),
e.what());
valid = false;
break;
}
}
}
}
// FIXME: check whether all outputs are in the binary cache.
if (valid) {
finishedDrvs.insert(drvPath);
return 0;
}
/* No, we need to build. */
printMsg(lvlDebug, "creating build step %1%", localStore->printStorePath(drvPath));
/* Create steps for the dependencies. */
for (auto & i : step->drv->inputDrvs.map) {
auto dep = createStep(destStore, conn, build, i.first, 0, step, finishedDrvs, newSteps, newRunnable);
if (dep) {
auto step_(step->state.lock());
step_->deps.insert(dep);
}
}
/* If the step has no (remaining) dependencies, make it
runnable. */
{
auto step_(step->state.lock());
assert(!step_->created);
step_->created = true;
if (step_->deps.empty())
newRunnable.insert(step);
}
newSteps.insert(step);
return step;
}
Jobset::ptr State::createJobset(pqxx::work & txn,
const std::string & projectName, const std::string & jobsetName, const JobsetID jobsetID)
{
auto p = std::make_pair(projectName, jobsetName);
{
auto jobsets_(jobsets.lock());
auto i = jobsets_->find(p);
if (i != jobsets_->end()) return i->second;
}
auto res = txn.exec("select schedulingShares from Jobsets where id = $1",
pqxx::params{jobsetID}).one_row();
auto shares = res["schedulingShares"].as<unsigned int>();
auto jobset = std::make_shared<Jobset>();
jobset->setShares(shares);
/* Load the build steps from the last 24 hours. */
auto res2 = txn.exec("select s.startTime, s.stopTime from BuildSteps s join Builds b on build = id "
"where s.startTime is not null and s.stopTime > $1 and jobset_id = $2",
pqxx::params{time(0) - Jobset::schedulingWindow * 10,
jobsetID});
for (auto const & row : res2) {
time_t startTime = row["startTime"].as<time_t>();
time_t stopTime = row["stopTime"].as<time_t>();
jobset->addStep(startTime, stopTime - startTime);
}
auto jobsets_(jobsets.lock());
// Can't happen because only this thread adds to "jobsets".
assert(jobsets_->find(p) == jobsets_->end());
(*jobsets_)[p] = jobset;
return jobset;
}
void State::processJobsetSharesChange(Connection & conn)
{
/* Get the current set of jobsets. */
pqxx::work txn(conn);
auto res = txn.exec("select project, name, schedulingShares from Jobsets");
for (auto const & row : res) {
auto jobsets_(jobsets.lock());
auto i = jobsets_->find(std::make_pair(row["project"].as<std::string>(), row["name"].as<std::string>()));
if (i == jobsets_->end()) continue;
i->second->setShares(row["schedulingShares"].as<unsigned int>());
}
}
BuildOutput State::getBuildOutputCached(Connection & conn, nix::ref<nix::Store> destStore, const nix::StorePath & drvPath)
{
auto derivationOutputs = destStore->queryDerivationOutputMap(drvPath, &*localStore);
{
pqxx::work txn(conn);
for (auto & [name, output] : derivationOutputs) {
auto r = txn.exec("select id, buildStatus, releaseName, closureSize, size from Builds b "
"join BuildOutputs o on b.id = o.build "
"where finished = 1 and (buildStatus = 0 or buildStatus = 6) and path = $1",
pqxx::params{localStore->printStorePath(output)});
if (r.empty()) continue;
BuildID id = r[0][0].as<BuildID>();
printInfo("reusing build %d", id);
BuildOutput res;
res.failed = r[0][1].as<int>() == bsFailedWithOutput;
res.releaseName = r[0][2].is_null() ? "" : r[0][2].as<std::string>();
res.closureSize = r[0][3].is_null() ? 0 : r[0][3].as<uint64_t>();
res.size = r[0][4].is_null() ? 0 : r[0][4].as<uint64_t>();
auto products = txn.exec("select type, subtype, fileSize, sha256hash, path, name, defaultPath from BuildProducts where build = $1 order by productnr",
pqxx::params{id});
for (auto row : products) {
BuildProduct product;
product.type = row[0].as<std::string>();
product.subtype = row[1].as<std::string>();
if (row[2].is_null())
product.isRegular = false;
else {
product.isRegular = true;
product.fileSize = row[2].as<off_t>();
}
if (!row[3].is_null())
product.sha256hash = Hash::parseAny(row[3].as<std::string>(), HashAlgorithm::SHA256);
if (!row[4].is_null())
product.path = row[4].as<std::string>();
product.name = row[5].as<std::string>();
if (!row[6].is_null())
product.defaultPath = row[6].as<std::string>();
res.products.emplace_back(product);
}
auto metrics = txn.exec("select name, unit, value from BuildMetrics where build = $1",
pqxx::params{id});
for (auto row : metrics) {
BuildMetric metric;
metric.name = row[0].as<std::string>();
metric.unit = row[1].is_null() ? "" : row[1].as<std::string>();
metric.value = row[2].as<double>();
res.metrics.emplace(metric.name, metric);
}
return res;
}
}
NarMemberDatas narMembers;
return getBuildOutput(destStore, narMembers, derivationOutputs);
}

View File

@@ -0,0 +1,596 @@
#pragma once
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <map>
#include <memory>
#include <queue>
#include <regex>
#include <semaphore>
#include <prometheus/counter.h>
#include <prometheus/gauge.h>
#include <prometheus/registry.h>
#include "db.hh"
#include <nix/store/derivations.hh>
#include <nix/store/derivation-options.hh>
#include <nix/store/pathlocks.hh>
#include <nix/util/pool.hh>
#include <nix/store/build-result.hh>
#include <nix/store/store-api.hh>
#include <nix/util/sync.hh>
#include "nar-extractor.hh"
#include <nix/store/serve-protocol.hh>
#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;
typedef unsigned int JobsetID;
typedef std::chrono::time_point<std::chrono::system_clock> system_time;
typedef std::atomic<unsigned long> counter;
typedef enum {
bsSuccess = 0,
bsFailed = 1,
bsDepFailed = 2, // builds only
bsAborted = 3,
bsCancelled = 4,
bsFailedWithOutput = 6, // builds only
bsTimedOut = 7,
bsCachedFailure = 8, // steps only
bsUnsupported = 9,
bsLogLimitExceeded = 10,
bsNarSizeLimitExceeded = 11,
bsNotDeterministic = 12,
bsBusy = 100, // not stored
} BuildStatus;
typedef enum {
ssPreparing = 1,
ssConnecting = 10,
ssSendingInputs = 20,
ssBuilding = 30,
ssWaitingForLocalSlot = 35,
ssReceivingOutputs = 40,
ssPostProcessing = 50,
} StepState;
struct RemoteResult
{
BuildStatus stepStatus = bsAborted;
bool canRetry = false; // for bsAborted
bool isCached = false; // for bsSucceed
bool canCache = false; // for bsFailed
std::string errorMsg; // for bsAborted
unsigned int timesBuilt = 0;
bool isNonDeterministic = false;
time_t startTime = 0, stopTime = 0;
unsigned int overhead = 0;
nix::Path logFile;
BuildStatus buildStatus() const
{
return stepStatus == bsCachedFailure ? bsFailed : stepStatus;
}
void updateWithBuildResult(const nix::BuildResult &);
};
struct Step;
struct BuildOutput;
class Jobset
{
public:
typedef std::shared_ptr<Jobset> ptr;
typedef std::weak_ptr<Jobset> wptr;
static const time_t schedulingWindow = 24 * 60 * 60;
private:
std::atomic<time_t> seconds{0};
std::atomic<unsigned int> shares{1};
/* The start time and duration of the most recent build steps. */
nix::Sync<std::map<time_t, time_t>> steps;
public:
double shareUsed()
{
return (double) seconds / shares;
}
void setShares(int shares_)
{
assert(shares_ > 0);
shares = shares_;
}
time_t getSeconds() { return seconds; }
void addStep(time_t startTime, time_t duration);
void pruneSteps();
};
struct Build
{
typedef std::shared_ptr<Build> ptr;
typedef std::weak_ptr<Build> wptr;
BuildID id;
nix::StorePath drvPath;
std::map<std::string, nix::StorePath> outputs;
JobsetID jobsetId;
std::string projectName, jobsetName, jobName;
time_t timestamp;
unsigned int maxSilentTime, buildTimeout;
int localPriority, globalPriority;
std::shared_ptr<Step> toplevel;
Jobset::ptr jobset;
std::atomic_bool finishedInDB{false};
Build(nix::StorePath && drvPath) : drvPath(std::move(drvPath))
{ }
std::string fullJobName()
{
return projectName + ":" + jobsetName + ":" + jobName;
}
void propagatePriorities();
};
struct Step
{
typedef std::shared_ptr<Step> ptr;
typedef std::weak_ptr<Step> wptr;
nix::StorePath drvPath;
std::unique_ptr<nix::Derivation> drv;
nix::StringSet requiredSystemFeatures;
bool preferLocalBuild;
bool isDeterministic;
std::string systemType; // concatenation of drv.platform and requiredSystemFeatures
struct State
{
/* Whether the step has finished initialisation. */
bool created = false;
/* The build steps on which this step depends. */
std::set<Step::ptr> deps;
/* The build steps that depend on this step. */
std::vector<Step::wptr> rdeps;
/* Builds that have this step as the top-level derivation. */
std::vector<Build::wptr> builds;
/* Jobsets to which this step belongs. Used for determining
scheduling priority. */
std::set<Jobset::ptr> jobsets;
/* Number of times we've tried this step. */
unsigned int tries = 0;
/* Point in time after which the step can be retried. */
system_time after;
/* The highest global priority of any build depending on this
step. */
int highestGlobalPriority{0};
/* The highest local priority of any build depending on this
step. */
int highestLocalPriority{0};
/* The lowest ID of any build depending on this step. */
BuildID lowestBuildID{std::numeric_limits<BuildID>::max()};
/* The time at which this step became runnable. */
system_time runnableSince;
/* The time that we last saw a machine that supports this
step. */
system_time lastSupported = std::chrono::system_clock::now();
};
std::atomic_bool finished{false}; // debugging
nix::Sync<State> state;
Step(const nix::StorePath & drvPath) : drvPath(drvPath)
{ }
~Step()
{
//printMsg(lvlError, format("destroying step %1%") % drvPath);
}
};
void getDependents(Step::ptr step, std::set<Build::ptr> & builds, std::set<Step::ptr> & steps);
/* Call visitor for a step and all its dependencies. */
void visitDependencies(std::function<void(Step::ptr)> visitor, Step::ptr step);
struct Machine : nix::Machine
{
typedef std::shared_ptr<Machine> ptr;
struct State {
typedef std::shared_ptr<State> ptr;
counter currentJobs{0};
counter nrStepsDone{0};
counter totalStepTime{0}; // total time for steps, including closure copying
counter totalStepBuildTime{0}; // total build time for steps
std::atomic<time_t> idleSince{0};
struct ConnectInfo
{
system_time lastFailure, disabledUntil;
unsigned int consecutiveFailures;
};
nix::Sync<ConnectInfo> connectInfo;
/* Mutex to prevent multiple threads from sending data to the
same machine (which would be inefficient). */
std::timed_mutex sendLock;
};
State::ptr state;
bool supportsStep(Step::ptr step)
{
/* Check that this machine is of the type required by the
step. */
if (!systemTypes.count(step->drv->platform == "builtin" ? nix::settings.thisSystem : step->drv->platform))
return false;
/* Check that the step requires all mandatory features of this
machine. (Thus, a machine with the mandatory "benchmark"
feature will *only* execute steps that require
"benchmark".) The "preferLocalBuild" bit of a step is
mapped to the "local" feature; thus machines that have
"local" as a mandatory feature will only do
preferLocalBuild steps. */
for (auto & f : mandatoryFeatures)
if (!step->requiredSystemFeatures.count(f)
&& !(f == "local" && step->preferLocalBuild))
return false;
/* Check that the machine supports all features required by
the step. */
for (auto & f : step->requiredSystemFeatures)
if (!supportedFeatures.count(f)) return false;
return true;
}
bool isLocalhost() const;
// A connection to a machine
struct Connection : nix::ServeProto::BasicClientConnection {
// Backpointer to the machine
ptr machine;
};
};
class HydraConfig;
class State
{
private:
std::unique_ptr<HydraConfig> config;
// FIXME: Make configurable.
const unsigned int maxTries = 5;
const unsigned int retryInterval = 60; // seconds
const float retryBackoff = 3.0;
const unsigned int maxParallelCopyClosure = 4;
/* Time in seconds before unsupported build steps are aborted. */
const unsigned int maxUnsupportedTime = 0;
nix::Path hydraData, logDir;
bool useSubstitutes = false;
/* The queued builds. */
typedef std::map<BuildID, Build::ptr> Builds;
nix::Sync<Builds> builds;
/* The jobsets. */
typedef std::map<std::pair<std::string, std::string>, Jobset::ptr> Jobsets;
nix::Sync<Jobsets> jobsets;
/* All active or pending build steps (i.e. dependencies of the
queued builds). Note that these are weak pointers. Steps are
kept alive by being reachable from Builds or by being in
progress. */
typedef std::map<nix::StorePath, Step::wptr> Steps;
nix::Sync<Steps> steps;
/* Build steps that have no unbuilt dependencies. */
typedef std::list<Step::wptr> Runnable;
nix::Sync<Runnable> runnable;
/* CV for waking up the dispatcher. */
nix::Sync<bool> dispatcherWakeup;
std::condition_variable dispatcherWakeupCV;
/* PostgreSQL connection pool. */
nix::Pool<Connection> dbPool;
/* The build machines. */
std::mutex machinesReadyLock;
typedef std::map<nix::StoreReference::Variant, Machine::ptr> Machines;
nix::Sync<Machines> machines; // FIXME: use atomic_shared_ptr
/* Throttler for CPU-bound local work. */
static constexpr unsigned int maxSupportedLocalWorkers = 1024;
std::counting_semaphore<maxSupportedLocalWorkers> localWorkThrottler;
/* Various stats. */
time_t startedAt;
counter nrBuildsRead{0};
counter buildReadTimeMs{0};
counter nrBuildsDone{0};
counter nrStepsStarted{0};
counter nrStepsDone{0};
counter nrStepsBuilding{0};
counter nrStepsCopyingTo{0};
counter nrStepsWaitingForDownloadSlot{0};
counter nrStepsCopyingFrom{0};
counter nrStepsWaiting{0};
counter nrUnsupportedSteps{0};
counter nrRetries{0};
counter maxNrRetries{0};
counter totalStepTime{0}; // total time for steps, including closure copying
counter totalStepBuildTime{0}; // total build time for steps
counter nrQueueWakeups{0};
counter nrDispatcherWakeups{0};
counter dispatchTimeMs{0};
counter bytesSent{0};
counter bytesReceived{0};
counter nrActiveDbUpdates{0};
/* Specific build to do for --build-one (testing only). */
BuildID buildOne;
bool buildOneDone = false;
/* Statistics per machine type for the Hydra auto-scaler. */
struct MachineType
{
unsigned int runnable{0}, running{0};
system_time lastActive;
std::chrono::seconds waitTime; // time runnable steps have been waiting
};
nix::Sync<std::map<std::string, MachineType>> machineTypes;
struct MachineReservation
{
State & state;
Step::ptr step;
Machine::ptr machine;
MachineReservation(State & state, Step::ptr step, Machine::ptr machine);
~MachineReservation();
};
struct ActiveStep
{
Step::ptr step;
struct State
{
pid_t pid = -1;
bool cancelled = false;
};
nix::Sync<State> state_;
};
nix::Sync<std::set<std::shared_ptr<ActiveStep>>> activeSteps_;
std::atomic<time_t> lastDispatcherCheck{0};
std::shared_ptr<nix::Store> localStore;
std::shared_ptr<nix::Store> _destStore;
size_t maxOutputSize;
size_t maxLogSize;
/* Steps that were busy while we encounted a PostgreSQL
error. These need to be cleared at a later time to prevent them
from showing up as busy until the queue runner is restarted. */
nix::Sync<std::set<std::pair<BuildID, int>>> orphanedSteps;
/* How often the build steps of a jobset should be repeated in
order to detect non-determinism. */
std::map<std::pair<std::string, std::string>, size_t> jobsetRepeats;
bool uploadLogsToBinaryCache;
/* Where to store GC roots. Defaults to
/nix/var/nix/gcroots/per-user/$USER/hydra-roots, overridable
via gc_roots_dir. */
nix::Path rootsDir;
std::string metricsAddr;
struct PromMetrics
{
std::shared_ptr<prometheus::Registry> registry;
prometheus::Counter& queue_checks_started;
prometheus::Counter& queue_build_loads;
prometheus::Counter& queue_steps_created;
prometheus::Counter& queue_checks_early_exits;
prometheus::Counter& queue_checks_finished;
prometheus::Counter& dispatcher_time_spent_running;
prometheus::Counter& dispatcher_time_spent_waiting;
prometheus::Counter& queue_monitor_time_spent_running;
prometheus::Counter& queue_monitor_time_spent_waiting;
PromMetrics();
};
PromMetrics prom;
public:
State(std::optional<std::string> metricsAddrOpt);
private:
nix::MaintainCount<counter> startDbUpdate();
/* Return a store object to store build results. */
nix::ref<nix::Store> getDestStore();
void clearBusy(Connection & conn, time_t stopTime);
void parseMachines(const std::string & contents);
/* Thread to reload /etc/nix/machines periodically. */
void monitorMachinesFile();
unsigned int allocBuildStep(pqxx::work & txn, BuildID buildId);
unsigned int createBuildStep(pqxx::work & txn, time_t startTime, BuildID buildId, Step::ptr step,
const std::string & machine, BuildStatus status, const std::string & errorMsg = "",
BuildID propagatedFrom = 0);
void updateBuildStep(pqxx::work & txn, BuildID buildId, unsigned int stepNr, StepState stepState);
void finishBuildStep(pqxx::work & txn, const RemoteResult & result, BuildID buildId, unsigned int stepNr,
const std::string & machine);
int createSubstitutionStep(pqxx::work & txn, time_t startTime, time_t stopTime,
Build::ptr build, const nix::StorePath & drvPath, const nix::Derivation drv, const std::string & outputName, const nix::StorePath & storePath);
void updateBuild(pqxx::work & txn, Build::ptr build, BuildStatus status);
void queueMonitor();
void queueMonitorLoop(Connection & conn);
/* Check the queue for new builds. */
bool getQueuedBuilds(Connection & conn, nix::ref<nix::Store> destStore);
/* Handle cancellation, deletion and priority bumps. */
void processQueueChange(Connection & conn);
BuildOutput getBuildOutputCached(Connection & conn, nix::ref<nix::Store> destStore,
const nix::StorePath & drvPath);
/* Returns paths missing from the remote store. Paths are processed in
* parallel to work around the possible latency of remote stores. */
std::map<nix::DrvOutput, std::optional<nix::StorePath>> getMissingRemotePaths(
nix::ref<nix::Store> destStore,
const std::map<nix::DrvOutput, std::optional<nix::StorePath>> & paths);
Step::ptr createStep(nix::ref<nix::Store> store,
Connection & conn, Build::ptr build, const nix::StorePath & drvPath,
Build::ptr referringBuild, Step::ptr referringStep, std::set<nix::StorePath> & finishedDrvs,
std::set<Step::ptr> & newSteps, std::set<Step::ptr> & newRunnable);
void failStep(
Connection & conn,
Step::ptr step,
BuildID buildId,
const RemoteResult & result,
Machine::ptr machine,
bool & stepFinished);
Jobset::ptr createJobset(pqxx::work & txn,
const std::string & projectName, const std::string & jobsetName, const JobsetID);
void processJobsetSharesChange(Connection & conn);
void makeRunnable(Step::ptr step);
/* The thread that selects and starts runnable builds. */
void dispatcher();
system_time doDispatch();
void wakeDispatcher();
void abortUnsupported();
void builder(std::unique_ptr<MachineReservation> reservation);
/* Perform the given build step. Return true if the step is to be
retried. */
enum StepResult { sDone, sRetry, sMaybeCancelled };
StepResult doBuildStep(nix::ref<nix::Store> destStore,
std::unique_ptr<MachineReservation> reservation,
std::shared_ptr<ActiveStep> activeStep);
void buildRemote(nix::ref<nix::Store> destStore,
std::unique_ptr<MachineReservation> reservation,
Machine::ptr machine, Step::ptr step,
const nix::ServeProto::BuildOptions & buildOptions,
RemoteResult & result, std::shared_ptr<ActiveStep> activeStep,
std::function<void(StepState)> updateStep,
NarMemberDatas & narMembers);
void markSucceededBuild(pqxx::work & txn, Build::ptr build,
const BuildOutput & res, bool isCachedBuild, time_t startTime, time_t stopTime);
bool checkCachedFailure(Step::ptr step, Connection & conn);
void notifyBuildStarted(pqxx::work & txn, BuildID buildId);
void notifyBuildFinished(pqxx::work & txn, BuildID buildId,
const std::vector<BuildID> & dependentIds);
/* Acquire the global queue runner lock, or null if somebody else
has it. */
std::shared_ptr<nix::PathLocks> acquireGlobalLock();
void dumpStatus(Connection & conn);
void addRoot(const nix::StorePath & storePath);
void runMetricsExporter();
public:
void showStatus();
void unlock();
void run(BuildID buildOne = 0);
};

View File

@@ -2,11 +2,12 @@ package Hydra;
use strict;
use warnings;
use Hydra::Helper::Nix;
use parent 'Catalyst';
use Moose;
use Hydra::Plugin;
use Hydra::Model::DB;
use Hydra::Config qw(getLDAPConfigAmbient);
use Catalyst::Runtime '5.70';
use parent qw/Catalyst/;
use Catalyst qw/ConfigLoader
Static::Simple
StackTrace
@@ -15,43 +16,89 @@ use Catalyst qw/ConfigLoader
Session
Session::Store::FastMmap
Session::State::Cookie
AccessLog
/;
Captcha
PrometheusTiny/,
'-Log=warn,fatal,error';
use CatalystX::RoleApplicator;
use Path::Class 'file';
our $VERSION = '0.01';
__PACKAGE__->config(
name => 'Hydra',
default_view => "TT",
session => {
storage => getHydraPath . "/session_data"
},
authentication => {
'Plugin::Authentication' => {
default_realm => "dbic",
realms => {
dbic => {
credential => {
class => "Password",
password_field => "password",
password_type => "hashed",
password_hash_type => "SHA-1",
},
store => {
class => "DBIx::Class",
user_class => "DB::Users",
role_relation => "userroles",
role_field => "role",
},
dbic => {
credential => {
class => "Password",
password_field => "password",
password_type => "self_check",
},
store => {
class => "DBIx::Class",
user_class => "DB::Users",
role_relation => "userroles",
role_field => "role",
},
},
ldap => getLDAPConfigAmbient()->{'config'}
},
'Plugin::ConfigLoader' => {
driver => {
'General' => \%Hydra::Config::configGeneralOpts
}
},
'Plugin::PrometheusTiny' => {
include_action_labels => 1,
},
'Plugin::Static::Simple' => {
send_etag => 1,
expires => 3600
},
'View::JSON' => {
expose_stash => qr/^json/,
expose_stash => 'json'
},
'Plugin::Session' => {
expires => 3600 * 24 * 2,
expires => 3600 * 24 * 7,
storage => Hydra::Model::DB::getHydraPath . "/www/session_data",
unlink_on_exit => 0
},
'Plugin::Captcha' => {
session_name => 'hydra-captcha',
new => {
width => 270,
height => 80,
ptsize => 20,
lines => 30,
thickness => 1,
rndmax => 5,
scramble => 1,
#send_ctobg => 1,
bgcolor => '#ffffff',
font => __PACKAGE__->path_to("ttf/StayPuft.ttf"),
},
create => [ qw/ttf circle/ ],
particle => [ 3500 ],
out => { force => 'jpeg' }
},
);
__PACKAGE__->apply_request_class_roles(qw/Catalyst::TraitFor::Request::ProxyBase/);
my $plugins;
has 'hydra_plugins' => (
is => 'ro',
default => sub { return $plugins; }
);
after setup_finalize => sub {
my $class = shift;
$plugins = [Hydra::Plugin->instantiate(db => $class->model('DB'), config => $class->config)];
};
__PACKAGE__->setup();
1;

View File

@@ -7,44 +7,6 @@ use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
sub getJobStatus {
my ($self, $c) = @_;
my $maintainer = $c->request->params->{"maintainer"};
my $latest = $c->stash->{jobStatus}->search(
defined $maintainer ? { maintainers => { like => "%$maintainer%" } } : {},
{ '+select' => ["me.statusChangeId", "me.statusChangeTime"]
, '+as' => ["statusChangeId", "statusChangeTime"]
, order_by => "coalesce(statusChangeTime, 0) desc"
});
return $latest;
}
sub jobstatus : Chained('get_builds') PathPart Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'jobstatus.tt';
$c->stash->{latestBuilds} = [getJobStatus($self, $c)->all];
}
# A convenient way to see all the errors - i.e. things demanding
# attention - at a glance.
sub errors : Chained('get_builds') PathPart Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'errors.tt';
$c->stash->{brokenJobsets} =
[$c->stash->{allJobsets}->search({errormsg => {'!=' => ''}})]
if defined $c->stash->{allJobsets};
$c->stash->{brokenJobs} =
[$c->stash->{allJobs}->search({errormsg => {'!=' => ''}})]
if defined $c->stash->{allJobs};
$c->stash->{brokenBuilds} =
[getJobStatus($self, $c)->search({buildStatus => {'!=' => 0}})];
}
sub all : Chained('get_builds') PathPart {
my ($self, $c) = @_;
@@ -54,37 +16,32 @@ sub all : Chained('get_builds') PathPart {
my $resultsPerPage = 20;
my $nrBuilds = $c->stash->{allBuilds}->search({finished => 1})->count;
$c->stash->{baseUri} = $c->uri_for($self->action_for("all"), $c->req->captures);
$c->stash->{page} = $page;
$c->stash->{resultsPerPage} = $resultsPerPage;
$c->stash->{totalBuilds} = $nrBuilds;
$c->stash->{total} = $c->stash->{allBuilds}->search({finished => 1})->count
unless defined $c->stash->{total};
$c->stash->{builds} = [ $c->stash->{allBuilds}->search(
{ finished => 1 },
{ order_by => "timestamp DESC"
{ order_by => "stoptime DESC"
, columns => [@buildListColumns]
, rows => $resultsPerPage
, page => $page }) ];
}
sub nix : Chained('get_builds') PathPart('channel') CaptureArgs(1) {
my ($self, $c, $channelName) = @_;
eval {
if ($channelName eq "latest") {
$c->stash->{channelName} = $c->stash->{channelBaseName} . "-latest";
$c->stash->{channelBuilds} = $c->stash->{latestSucceeded}
->search_literal("exists (select 1 from buildproducts where build = me.id and type = 'nix-build')")
->search({}, { columns => [@buildListColumns, 'drvpath', 'outpath', 'description', 'homepage'] });
}
else {
notFound($c, "Unknown channel `$channelName'.");
}
};
error($c, $@) if $@;
sub nix : Chained('get_builds') PathPart('channel/latest') CaptureArgs(0) {
my ($self, $c) = @_;
$c->stash->{channelName} = $c->stash->{channelBaseName} . "-latest";
$c->stash->{channelBuilds} = $c->stash->{latestSucceeded}
->search_literal("exists (select 1 from buildproducts where build = me.id and type = 'nix-build')")
->search({}, { columns => [@buildListColumns, 'drvpath', 'description', 'homepage']
, join => ["buildoutputs"]
, order_by => ["me.id", "buildoutputs.name"]
, '+select' => ['buildoutputs.path', 'buildoutputs.name'], '+as' => ['outpath', 'outname'] });
}
@@ -92,12 +49,12 @@ sub nix : Chained('get_builds') PathPart('channel') CaptureArgs(1) {
sub latest : Chained('get_builds') PathPart('latest') {
my ($self, $c, @rest) = @_;
my ($latest) = $c->stash->{allBuilds}->search(
{finished => 1, buildstatus => 0}, {order_by => ["isCurrent DESC", "timestamp DESC"]});
my $latest = $c->stash->{allBuilds}->find(
{ finished => 1, buildstatus => 0 }, { order_by => ["id DESC"], rows => 1 });
notFound($c, "There is no successful build to redirect to.") unless defined $latest;
$c->res->redirect($c->uri_for($c->controller('Build')->action_for("view_build"), [$latest->id], @rest));
$c->res->redirect($c->uri_for($c->controller('Build')->action_for("build"), [$latest->id], @rest));
}
@@ -106,13 +63,31 @@ sub latest_for : Chained('get_builds') PathPart('latest-for') {
my ($self, $c, $system, @rest) = @_;
notFound($c, "You need to specify a platform type in the URL.") unless defined $system;
my ($latest) = $c->stash->{allBuilds}->search(
{finished => 1, buildstatus => 0, system => $system}, {order_by => ["isCurrent DESC", "timestamp DESC"]});
my $latest = $c->stash->{allBuilds}->find(
{ finished => 1, buildstatus => 0, system => $system }, { order_by => ["id DESC"], rows => 1 });
notFound($c, "There is no successful build for platform `$system' to redirect to.") unless defined $latest;
$c->res->redirect($c->uri_for($c->controller('Build')->action_for("view_build"), [$latest->id], @rest));
$c->res->redirect($c->uri_for($c->controller('Build')->action_for("build"), [$latest->id], @rest));
}
# Redirect to the latest successful build in a finished evaluation
# (i.e. an evaluation that has no unfinished builds).
sub latest_finished : Chained('get_builds') PathPart('latest-finished') {
my ($self, $c, @rest) = @_;
my $latest = $c->stash->{allBuilds}->find(
{ finished => 1, buildstatus => 0 },
{ order_by => ["id DESC"], rows => 1, join => ["jobsetevalmembers"]
, where => \
"not exists (select 1 from jobsetevalmembers m2 join builds b2 on jobsetevalmembers.eval = m2.eval and m2.build = b2.id and b2.finished = 0)"
});
notFound($c, "There is no successful build to redirect to.") unless defined $latest;
$c->res->redirect($c->uri_for($c->controller('Build')->action_for("build"), [$latest->id], @rest));
}

View File

@@ -2,8 +2,8 @@ package Hydra::Base::Controller::NixChannel;
use strict;
use warnings;
use base 'Catalyst::Controller';
use Nix::Store;
use base 'Hydra::Base::Controller::REST';
use List::SomeUtils qw(any);
use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
@@ -11,26 +11,40 @@ use Hydra::Helper::CatalystUtils;
sub getChannelData {
my ($c, $checkValidity) = @_;
requireLocalStore($c);
my @storePaths = ();
foreach my $build ($c->stash->{channelBuilds}->all) {
next if $checkValidity && !isValidPath($build->outpath);
#if (isValidPath($build->drvpath)) {
# # Adding `drvpath' implies adding `outpath' because of the
# # `--include-outputs' flag passed to `nix-store'.
# push @storePaths, $build->drvpath;
#} else {
# push @storePaths, $build->outpath;
#}
push @storePaths, $build->outpath;
$c->stash->{nixPkgs} = [];
my @builds = $c->stash->{channelBuilds}->all;
for (my $n = 0; $n < scalar @builds; ) {
# Since channelData is a join of Builds and BuildOutputs, we
# need to gather the rows that belong to a single build.
my $build = $builds[$n++];
my @outputs = ($build);
push @outputs, $builds[$n++] while $n < scalar @builds && $builds[$n]->id == $build->id;
@outputs = grep { $_->get_column("outpath") } @outputs;
my $outputs = {};
foreach my $output (@outputs) {
my $outPath = $output->get_column("outpath");
next if $checkValidity && !$MACHINE_LOCAL_STORE->isValidPath($outPath);
$outputs->{$output->get_column("outname")} = $outPath;
push @storePaths, $outPath;
# Put the system type in the manifest (for top-level
# paths) as a hint to the binary patch generator. (It
# shouldn't try to generate patches between builds for
# different systems.) It would be nice if Nix stored this
# info for every path but it doesn't.
$c->stash->{systemForPath}->{$outPath} = $build->system;
}
next if !%$outputs;
my $pkgName = $build->nixname . "-" . $build->system . "-" . $build->id;
$c->stash->{nixPkgs}->{"${pkgName}.nixpkg"} = {build => $build, name => $pkgName};
# Put the system type in the manifest (for top-level paths) as
# a hint to the binary patch generator. (It shouldn't try to
# generate patches between builds for different systems.) It
# would be nice if Nix stored this info for every path but it
# doesn't.
$c->stash->{systemForPath}->{$build->outpath} = $build->system;
};
push @{$c->stash->{nixPkgs}}, { build => $build, name => $pkgName, outputs => $outputs };
}
$c->stash->{storePaths} = [@storePaths];
}
@@ -38,10 +52,15 @@ sub getChannelData {
sub closure : Chained('nix') PathPart {
my ($self, $c) = @_;
requireLocalStore($c);
$c->stash->{current_view} = 'NixClosure';
getChannelData($c, 1);
# FIXME: get the closure of the selected path only.
# !!! quick hack; this is to make HEAD requests return the right
# MIME type. This is set in the view as well, but the view isn't
# called for HEAD requests. There should be a cleaner solution...
@@ -51,38 +70,26 @@ sub closure : Chained('nix') PathPart {
sub manifest : Chained('nix') PathPart("MANIFEST") Args(0) {
my ($self, $c) = @_;
requireLocalStore($c);
$c->stash->{current_view} = 'NixManifest';
$c->stash->{narBase} = $c->uri_for($c->controller('Root')->action_for("nar"));
getChannelData($c, 1);
}
sub pkg : Chained('nix') PathPart Args(1) {
my ($self, $c, $pkgName) = @_;
if (!$c->stash->{build}) {
$pkgName =~ /-(\d+)\.nixpkg$/ or notFound($c, "Bad package name.");
$c->stash->{build} = $c->stash->{channelBuilds}->find({ id => $1 })
|| notFound($c, "No such package in this channel.");
}
if (!isValidPath($c->stash->{build}->outpath)) {
$c->response->status(410); # "Gone"
error($c, "Build " . $c->stash->{build}->id . " is no longer available.");
}
$c->stash->{manifestUri} = $c->uri_for($self->action_for("manifest"), $c->req->captures);
$c->stash->{current_view} = 'NixPkg';
$c->response->content_type('application/nix-package');
sub nixexprs : Chained('nix') PathPart('nixexprs.tar.bz2') Args(0) {
my ($self, $c) = @_;
requireLocalStore($c);
$c->stash->{current_view} = 'NixExprs';
getChannelData($c, 1);
}
sub nixexprs : Chained('nix') PathPart('nixexprs.tar.bz2') Args(0) {
sub binary_cache_url : Chained('nix') PathPart('binary-cache-url') Args(0) {
my ($self, $c) = @_;
$c->stash->{current_view} = 'NixExprs';
getChannelData($c, 1);
$c->stash->{'plain'} = { data => $c->uri_for('/') };
$c->response->content_type('text/plain');
$c->forward('Hydra::View::Plain');
}
@@ -102,12 +109,14 @@ sub sortPkgs {
sub channel_contents : Chained('nix') PathPart('') Args(0) {
my ($self, $c) = @_;
requireLocalStore($c);
# Optimistically assume that none of the packages have been
# garbage-collected. That should be true for the "latest"
# channel.
getChannelData($c, 0);
$c->stash->{genericChannel} = 1;
$c->stash->{template} = 'channel-contents.tt';
$c->stash->{nixPkgs} = [sortPkgs (values %{$c->stash->{nixPkgs}})];
$c->stash->{nixPkgs} = [sortPkgs @{$c->stash->{nixPkgs}}];
}

View File

@@ -0,0 +1,22 @@
package Hydra::Base::Controller::REST;
use strict;
use warnings;
use base 'Catalyst::Controller::REST';
# Hack: Erase the map set by C::C::REST
__PACKAGE__->config( map => undef );
__PACKAGE__->config(
map => {
'application/json' => 'JSON',
'text/x-json' => 'JSON',
'text/html' => [ 'View', 'TT' ]
},
default => 'text/html',
'stash_key' => 'resource',
);
sub begin { my ( $self, $c ) = @_; $c->forward('Hydra::Controller::Root::begin'); }
sub end { my ( $self, $c ) = @_; $c->forward('Hydra::Controller::Root::end'); }
1;

View File

@@ -0,0 +1,46 @@
use utf8;
package Hydra::Component::ToJSON;
use strict;
use warnings;
use base 'DBIx::Class';
use JSON::MaybeXS;
sub TO_JSON {
my $self = shift;
if ($self->can("as_json")) {
return $self->as_json();
}
my $hint = $self->json_hint;
my %json = ();
foreach my $column (@{$hint->{columns}}) {
$json{$column} = $self->get_column($column);
}
foreach my $column (@{$hint->{string_columns}}) {
$json{$column} = $self->get_column($column) // "";
}
foreach my $column (@{$hint->{boolean_columns}}) {
$json{$column} = $self->get_column($column) ? JSON::MaybeXS::true : JSON::MaybeXS::false;
}
foreach my $relname (keys %{$hint->{relations}}) {
my $key = $hint->{relations}->{$relname};
$json{$relname} = [ map { $_->$key } $self->$relname ];
}
foreach my $relname (keys %{$hint->{eager_relations}}) {
my $key = $hint->{eager_relations}->{$relname};
$json{$relname} = { map { $_->$key => $_ } $self->$relname };
}
return \%json;
}
1;

168
src/lib/Hydra/Config.pm Normal file
View File

@@ -0,0 +1,168 @@
package Hydra::Config;
use strict;
use warnings;
use Config::General;
use List::SomeUtils qw(none);
use YAML qw(LoadFile);
our @ISA = qw(Exporter);
our @EXPORT = qw(
getHydraConfig
getLDAPConfig
getLDAPConfigAmbient
);
our %configGeneralOpts = (-UseApacheInclude => 1, -IncludeAgain => 1, -IncludeRelative => 1);
my $hydraConfigCache;
sub getHydraConfig {
return $hydraConfigCache if defined $hydraConfigCache;
my $conf;
if ($ENV{"HYDRA_CONFIG"}) {
$conf = $ENV{"HYDRA_CONFIG"};
} else {
require Hydra::Model::DB;
$conf = Hydra::Model::DB::getHydraPath() . "/hydra.conf"
};
if (-f $conf) {
$hydraConfigCache = loadConfig($conf);
} else {
$hydraConfigCache = {};
}
return $hydraConfigCache;
}
sub loadConfig {
my ($sourceFile) = @_;
my %opts = (%configGeneralOpts, -ConfigFile => $sourceFile);
return { Config::General->new(%opts)->getall };
}
sub is_ldap_in_legacy_mode {
my ($config, %env) = @_;
my $legacy_defined = defined $env{"HYDRA_LDAP_CONFIG"};
if (defined $config->{"ldap"}) {
if ($legacy_defined) {
die "The legacy environment variable HYDRA_LDAP_CONFIG is set, but config is also specified in hydra.conf. Please unset the environment variable.";
}
return 0;
} elsif ($legacy_defined) {
warn "Hydra is configured to use LDAP via the HYDRA_LDAP_CONFIG, a deprecated method. Please see the docs about configuring LDAP in the hydra.conf.";
return 1;
} else {
return 0;
}
}
sub getLDAPConfigAmbient {
return getLDAPConfig(getHydraConfig(), %ENV);
}
sub getLDAPConfig {
my ($config, %env) = @_;
my $ldap_config;
if (is_ldap_in_legacy_mode($config, %env)) {
$ldap_config = get_legacy_ldap_config($env{"HYDRA_LDAP_CONFIG"});
} else {
$ldap_config = $config->{"ldap"};
}
$ldap_config->{"role_mapping"} = normalize_ldap_role_mappings($ldap_config->{"role_mapping"});
return $ldap_config;
}
sub get_legacy_ldap_config {
my ($ldap_yaml_file) = @_;
return {
config => LoadFile($ldap_yaml_file),
role_mapping => {
"hydra_admin" => [ "admin" ],
"hydra_bump-to-front" => [ "bump-to-front" ],
"hydra_cancel-build" => [ "cancel-build" ],
"hydra_create-projects" => [ "create-projects" ],
"hydra_eval-jobset" => [ "eval-jobset" ],
"hydra_restart-jobs" => [ "restart-jobs" ],
},
};
}
sub normalize_ldap_role_mappings {
my ($input_map) = @_;
my $mapping = {};
my @errors;
for my $group (keys %{$input_map}) {
my $input = $input_map->{$group};
if (ref $input eq "ARRAY") {
$mapping->{$group} = $input;
} elsif (ref $input eq "") {
$mapping->{$group} = [ $input ];
} else {
push @errors, "On group '$group': the value is of type ${\ref $input}. Only strings and lists are acceptable.";
$mapping->{$group} = [ ];
}
eval {
validate_roles($mapping->{$group});
};
if ($@) {
push @errors, "On group '$group': $@";
}
}
if (@errors) {
die "Failed to normalize LDAP role mappings:\n" . (join "\n", @errors);
}
return $mapping;
}
sub validate_roles {
my ($roles) = @_;
my @invalid;
my $valid = valid_roles();
for my $role (@$roles) {
if (none { $_ eq $role } @$valid) {
push @invalid, "'$role'";
}
}
if (@invalid) {
die "Invalid roles: ${\join ', ', @invalid}. Valid roles are: ${\join ', ', @$valid}.";
}
return 1;
}
sub valid_roles {
return [
"admin",
"bump-to-front",
"cancel-build",
"create-projects",
"eval-jobset",
"restart-jobs",
];
}
1;

View File

@@ -1,19 +1,20 @@
package Hydra::Controller::API;
use utf8;
use strict;
use warnings;
use base 'Catalyst::Controller';
use base 'Hydra::Base::Controller::REST';
use Hydra::Helper::Nix;
use Hydra::Helper::AddBuilds;
use Hydra::Helper::CatalystUtils;
use Hydra::Controller::Project;
use JSON::Any;
use JSON::MaybeXS;
use DateTime;
use Digest::SHA qw(sha256_hex);
use Text::Diff;
use File::Slurp;
# !!! Rewrite this to use View::JSON.
use IPC::Run qw(run);
use Digest::SHA qw(hmac_sha256_hex);
use String::Compare::ConstantTime qw(equals);
use IPC::Run3;
sub api : Chained('/') PathPart('api') CaptureArgs(0) {
@@ -22,38 +23,12 @@ sub api : Chained('/') PathPart('api') CaptureArgs(0) {
}
sub projectToHash {
my ($project) = @_;
return {
name => $project->name,
description => $project->description
};
}
sub projects : Chained('api') PathPart('projects') Args(0) {
my ($self, $c) = @_;
my @projects = $c->model('DB::Projects')->search({hidden => 0}, {order_by => 'name'});
my @list;
foreach my $p (@projects) {
push @list, projectToHash($p);
}
$c->stash->{'plain'} = {
data => scalar (JSON::Any->objToJson(\@list))
};
$c->forward('Hydra::View::Plain');
}
sub buildToHash {
my ($build) = @_;
my $result = {
id => $build->id,
project => $build->get_column("project"),
jobset => $build->get_column("jobset"),
project => $build->jobset->get_column("project"),
jobset => $build->jobset->get_column("name"),
job => $build->get_column("job"),
system => $build->system,
nixname => $build->nixname,
@@ -61,13 +36,12 @@ sub buildToHash {
timestamp => $build->timestamp
};
if($build->finished) {
if($build->finished) {
$result->{'buildstatus'} = $build->get_column("buildstatus");
} else {
$result->{'busy'} = $build->get_column("busy");
$result->{'priority'} = $build->get_column("priority");
}
return $result;
};
@@ -81,20 +55,26 @@ sub latestbuilds : Chained('api') PathPart('latestbuilds') Args(0) {
my $jobset = $c->request->params->{jobset};
my $job = $c->request->params->{job};
my $system = $c->request->params->{system};
my $filter = {finished => 1};
$filter->{project} = $project if ! $project eq "";
$filter->{jobset} = $jobset if ! $jobset eq "";
$filter->{job} = $job if !$job eq "";
$filter->{system} = $system if !$system eq "";
my @latest = $c->model('DB::Builds')->search($filter, {rows => $nr, order_by => ["timestamp DESC"] });
$filter->{"jobset.project"} = $project if ! $project eq "";
$filter->{"jobset.name"} = $jobset if ! $jobset eq "";
$filter->{job} = $job if !$job eq "";
$filter->{system} = $system if !$system eq "";
my @latest = $c->model('DB::Builds')->search(
$filter,
{
rows => $nr,
order_by => ["id DESC"],
join => [ "jobset" ]
});
my @list;
push @list, buildToHash($_) foreach @latest;
$c->stash->{'plain'} = {
data => scalar (JSON::Any->objToJson(\@list))
$c->stash->{'plain'} = {
data => scalar (encode_json(\@list))
};
$c->forward('Hydra::View::Plain');
}
@@ -103,14 +83,21 @@ sub latestbuilds : Chained('api') PathPart('latestbuilds') Args(0) {
sub jobsetToHash {
my ($jobset) = @_;
return {
project => $jobset->project->name,
name => $jobset->name,
project => $jobset->get_column('project'),
name => $jobset->name,
nrscheduled => $jobset->get_column("nrscheduled"),
nrsucceeded => $jobset->get_column("nrsucceeded"),
nrfailed => $jobset->get_column("nrfailed"),
nrtotal => $jobset->get_column("nrtotal")
nrtotal => $jobset->get_column("nrtotal"),
lastcheckedtime => $jobset->lastcheckedtime,
starttime => $jobset->starttime,
checkinterval => $jobset->checkinterval,
triggertime => $jobset->triggertime,
fetcherrormsg => $jobset->fetcherrormsg,
errortime => $jobset->errortime,
haserrormsg => defined($jobset->errormsg) && $jobset->errormsg ne "" ? JSON::MaybeXS::true : JSON::MaybeXS::false
};
}
}
sub jobsets : Chained('api') PathPart('jobsets') Args(0) {
@@ -123,12 +110,12 @@ sub jobsets : Chained('api') PathPart('jobsets') Args(0) {
or notFound($c, "Project $projectName doesn't exist.");
my @jobsets = jobsetOverview($c, $project);
my @list;
push @list, jobsetToHash($_) foreach @jobsets;
$c->stash->{'plain'} = {
data => scalar (JSON::Any->objToJson(\@list))
$c->stash->{'plain'} = {
data => scalar (encode_json(\@list))
};
$c->forward('Hydra::View::Plain');
}
@@ -140,13 +127,13 @@ sub queue : Chained('api') PathPart('queue') Args(0) {
my $nr = $c->request->params->{nr};
error($c, "Parameter not defined!") if !defined $nr;
my @builds = $c->model('DB::Builds')->search({finished => 0}, {rows => $nr, order_by => ["busy DESC", "priority DESC", "timestamp"]});
my @builds = $c->model('DB::Builds')->search({finished => 0}, {rows => $nr, order_by => ["priority DESC", "id"]});
my @list;
push @list, buildToHash($_) foreach @builds;
$c->stash->{'plain'} = {
data => scalar (JSON::Any->objToJson(\@list))
$c->stash->{'plain'} = {
data => scalar (encode_json(\@list))
};
$c->forward('Hydra::View::Plain');
}
@@ -155,18 +142,8 @@ sub queue : Chained('api') PathPart('queue') Args(0) {
sub nrqueue : Chained('api') PathPart('nrqueue') Args(0) {
my ($self, $c) = @_;
my $nrQueuedBuilds = $c->model('DB::Builds')->search({finished => 0})->count();
$c->stash->{'plain'} = {
data => "$nrQueuedBuilds"
};
$c->forward('Hydra::View::Plain');
}
sub nrrunning : Chained('api') PathPart('nrrunning') Args(0) {
my ($self, $c) = @_;
my $nrRunningBuilds = $c->model('DB::Builds')->search({finished => 0, busy => 1 })->count();
$c->stash->{'plain'} = {
data => "$nrRunningBuilds"
data => "$nrQueuedBuilds"
};
$c->forward('Hydra::View::Plain');
}
@@ -176,7 +153,7 @@ sub nrbuilds : Chained('api') PathPart('nrbuilds') Args(0) {
my ($self, $c) = @_;
my $nr = $c->request->params->{nr};
my $period = $c->request->params->{period};
error($c, "Parameter not defined!") if !defined $nr || !defined $period;
my $base;
@@ -186,49 +163,69 @@ sub nrbuilds : Chained('api') PathPart('nrbuilds') Args(0) {
my $system = $c->request->params->{system};
my $filter = {finished => 1};
$filter->{project} = $project if ! $project eq "";
$filter->{jobset} = $jobset if ! $jobset eq "";
$filter->{job} = $job if !$job eq "";
$filter->{system} = $system if !$system eq "";
$filter->{"jobset.project"} = $project if ! $project eq "";
$filter->{"jobset.name"} = $jobset if ! $jobset eq "";
$filter->{job} = $job if !$job eq "";
$filter->{system} = $system if !$system eq "";
$base = 60*60 if($period eq "hour");
$base = 24*60*60 if($period eq "day");
my @stats = $c->model('DB::Builds')->search($filter, {select => [{ count => "*" }], as => ["nr"], group_by => ["timestamp - timestamp % $base"], order_by => "timestamp - timestamp % $base DESC", rows => $nr});
my @stats = $c->model('DB::Builds')->search(
$filter,
{
select => [{ count => "*" }],
as => ["nr"],
group_by => ["timestamp - timestamp % $base"],
order_by => "timestamp - timestamp % $base DESC",
rows => $nr,
join => [ "jobset" ]
}
);
my @arr;
push @arr, int($_->get_column("nr")) foreach @stats;
@arr = reverse(@arr);
$c->stash->{'plain'} = {
data => scalar (JSON::Any->objToJson(\@arr))
$c->stash->{'plain'} = {
data => scalar (encode_json(\@arr))
};
$c->forward('Hydra::View::Plain');
}
sub scmdiff : Chained('api') PathPart('scmdiff') Args(0) {
sub scmdiff : Path('/api/scmdiff') Args(0) {
my ($self, $c) = @_;
my $uri = $c->request->params->{uri};
my $type = $c->request->params->{type};
my $rev1 = $c->request->params->{rev1};
my $rev2 = $c->request->params->{rev2};
my $branch;
die("invalid revisions: [$rev1] [$rev2]") if $rev1 !~ m/^[a-zA-Z0-9_.]+$/ || $rev2 !~ m/^[a-zA-Z0-9_.]+$/;
# FIXME: injection danger.
my $diff = "";
if ($type eq "hg") {
my $clonePath = scmPath . "/" . sha256_hex($uri);
die if ! -d $clonePath;
$branch = `(cd $clonePath; hg log --template '{branch}' -r $rev2)`;
$diff .= `(cd $clonePath; hg log -r $rev1 -r $rev2 -b $branch)`;
$diff .= `(cd $clonePath; hg diff -r $rev1:$rev2)`;
my $clonePath = getSCMCacheDir . "/hg/" . sha256_hex($uri);
die "repository '$uri' is not in the SCM cache\n" if ! -d $clonePath;
my $out;
run(["hg", "log", "-R", $clonePath, "-r", "reverse($rev1::$rev2) and not($rev1)"], \undef, \$out)
or die "hg log failed";
$diff .= $out;
run(["hg", "diff", "-R", $clonePath, "-r", "$rev1::$rev2"], \undef, \$out)
or die "hg diff failed";
$diff .= $out;
} elsif ($type eq "git") {
my $clonePath = scmPath . "/" . sha256_hex($uri);
my $clonePath = getSCMCacheDir . "/git/" . sha256_hex($uri);
die if ! -d $clonePath;
$diff .= `(cd $clonePath; git log $rev1..$rev2)`;
$diff .= `(cd $clonePath; git diff $rev1..$rev2)`;
my ($stdout1, $stderr1);
run3(['git', '--git-dir', '.git', '-C', $clonePath, 'log', "$rev1..$rev2"], \undef, \$stdout1, \$stderr1);
$diff .= $stdout1 if $? == 0;
my ($stdout2, $stderr2);
run3(['git', '--git-dir', '.git', '-C', $clonePath, 'diff', "$rev1..$rev2"], \undef, \$stdout2, \$stderr2);
$diff .= $stdout2 if $? == 0;
}
$c->stash->{'plain'} = { data => (scalar $diff) || " " };
@@ -236,41 +233,163 @@ sub scmdiff : Chained('api') PathPart('scmdiff') Args(0) {
}
sub readNormalizedLog {
my ($file) = @_;
my $pipe = (-f "$file.bz2" ? "cat $file.bz2 | bzip2 -d" : "cat $file");
my $res = `$pipe`;
$res =~ s/\/nix\/store\/[a-z0-9]*-/\/nix\/store\/...-/g;
$res =~ s/nix-build-[a-z0-9]*-/nix-build-...-/g;
$res =~ s/[0-9]{2}:[0-9]{2}:[0-9]{2}/00:00:00/g;
return $res;
sub triggerJobset {
my ($self, $c, $jobset, $force) = @_;
print STDERR "triggering jobset ", $jobset->get_column('project') . ":" . $jobset->name, "\n";
$c->model('DB')->schema->txn_do(sub {
$jobset->update({ triggertime => time });
$jobset->update({ forceeval => 1 }) if $force;
});
push @{$c->{stash}->{json}->{jobsetsTriggered}}, $jobset->get_column('project') . ":" . $jobset->name;
}
sub logdiff : Chained('api') PathPart('logdiff') Args(2) {
my ($self, $c, $buildid1, $buildid2) = @_;
sub push : Chained('api') PathPart('push') Args(0) {
my ($self, $c) = @_;
my $diff = "";
requirePost($c);
my $build1 = getBuild($c, $buildid1);
notFound($c, "Build with ID $buildid1 doesn't exist.")
if !defined $build1;
my $build2 = getBuild($c, $buildid2);
notFound($c, "Build with ID $buildid2 doesn't exist.")
if !defined $build2;
$c->{stash}->{json}->{jobsetsTriggered} = [];
if (-f $build1->logfile && -f $build2->logfile) {
my $logtext1 = readNormalizedLog($build1->logfile);
my $logtext2 = readNormalizedLog($build2->logfile);
$diff = diff \$logtext1, \$logtext2;
my $force = exists $c->request->query_params->{force};
my @jobsets = split /,/, ($c->request->query_params->{jobsets} // "");
foreach my $s (@jobsets) {
my ($p, $j) = parseJobsetName($s);
my $jobset = $c->model('DB::Jobsets')->find($p, $j);
requireEvalJobsetPrivileges($c, $jobset->project);
next unless defined $jobset && ($force || ($jobset->project->enabled && $jobset->enabled));
triggerJobset($self, $c, $jobset, $force);
}
my @repos = split /,/, ($c->request->query_params->{repos} // "");
foreach my $r (@repos) {
my @jobsets = $c->model('DB::Jobsets')->search(
{ 'project.enabled' => 1, 'me.enabled' => 1 },
{
join => 'project',
where => \ [ 'exists (select 1 from JobsetInputAlts where project = me.project and jobset = me.name and value = ?)', [ 'value', $r ] ],
order_by => 'me.id DESC'
});
foreach my $jobset (@jobsets) {
requireEvalJobsetPrivileges($c, $jobset->project);
triggerJobset($self, $c, $jobset, $force)
}
}
$self->status_ok(
$c,
entity => { jobsetsTriggered => $c->stash->{json}->{jobsetsTriggered} }
);
}
sub verifyWebhookSignature {
my ($c, $platform, $header_name, $signature_prefix) = @_;
# Get secrets from config
my $webhook_config = $c->config->{webhooks} // {};
my $platform_config = $webhook_config->{$platform} // {};
my $secrets = $platform_config->{secret};
# Normalize to array
$secrets = [] unless defined $secrets;
$secrets = [$secrets] unless ref($secrets) eq 'ARRAY';
# Trim whitespace from secrets
my @secrets = grep { defined && length } map { s/^\s+|\s+$//gr } @$secrets;
if (@secrets) {
my $signature = $c->request->header($header_name);
if (!$signature) {
$c->log->warn("Webhook authentication failed for $platform: Missing signature from IP " . $c->request->address);
$c->response->status(401);
$c->stash->{json} = { error => "Missing webhook signature" };
$c->forward('View::JSON');
return 0;
}
# Get the raw body content from the buffered PSGI input
# For JSON requests, Catalyst will have already read and buffered the body
my $input = $c->request->env->{'psgi.input'};
$input->seek(0, 0);
local $/;
my $payload = <$input>;
$input->seek(0, 0); # Reset for any other consumers
unless (defined $payload && length $payload) {
$c->log->warn("Webhook authentication failed for $platform: Empty request body from IP " . $c->request->address);
$c->response->status(400);
$c->stash->{json} = { error => "Empty request body" };
$c->forward('View::JSON');
return 0;
}
my $valid = 0;
for my $secret (@secrets) {
my $expected = $signature_prefix . hmac_sha256_hex($payload, $secret);
if (equals($signature, $expected)) {
$valid = 1;
last;
}
}
if (!$valid) {
$c->log->warn("Webhook authentication failed for $platform: Invalid signature from IP " . $c->request->address);
$c->response->status(401);
$c->stash->{json} = { error => "Invalid webhook signature" };
$c->forward('View::JSON');
return 0;
}
return 1;
} else {
$c->response->status(404);
$c->log->warn("Webhook authentication failed for $platform: Unable to validate signature from IP " . $c->request->address . " because no secrets are configured");
$c->response->status(401);
$c->stash->{json} = { error => "Invalid webhook signature" };
$c->forward('View::JSON');
return 0;
}
}
$c->response->content_type('text/x-diff');
$c->stash->{'plain'} = { data => (scalar $diff) || " " };
$c->forward('Hydra::View::Plain');
sub push_github : Chained('api') PathPart('push-github') Args(0) {
my ($self, $c) = @_;
$c->{stash}->{json}->{jobsetsTriggered} = [];
return unless verifyWebhookSignature($c, 'github', 'X-Hub-Signature-256', 'sha256=');
my $in = $c->request->{data};
my $owner = ($in->{repository}->{owner}->{name} // $in->{repository}->{owner}->{login}) or die;
my $repo = $in->{repository}->{name} or die;
print STDERR "got push from GitHub repository $owner/$repo\n";
triggerJobset($self, $c, $_, 0) foreach $c->model('DB::Jobsets')->search(
{ 'project.enabled' => 1, 'me.enabled' => 1 },
{ join => 'project'
, where => \ [ 'me.flake like ? or exists (select 1 from JobsetInputAlts where project = me.project and jobset = me.name and value like ?)', [ 'flake', "%github%$owner/$repo%"], [ 'value', "%github.com%$owner/$repo%" ] ]
});
$c->response->body("");
}
sub push_gitea : Chained('api') PathPart('push-gitea') Args(0) {
my ($self, $c) = @_;
$c->{stash}->{json}->{jobsetsTriggered} = [];
# Note: Gitea doesn't use sha256= prefix
return unless verifyWebhookSignature($c, 'gitea', 'X-Gitea-Signature', '');
my $in = $c->request->{data};
my $url = $in->{repository}->{clone_url} or die;
$url =~ s/.git$//;
print STDERR "got push from Gitea repository $url\n";
triggerJobset($self, $c, $_, 0) foreach $c->model('DB::Jobsets')->search(
{ 'project.enabled' => 1, 'me.enabled' => 1 },
{ join => 'project'
, where => \ [ 'me.flake like ? or exists (select 1 from JobsetInputAlts where project = me.project and jobset = me.name and value like ?)', [ 'flake', "%$url%"], [ 'value', "%$url%" ] ]
});
$c->response->body("");
}

View File

@@ -5,42 +5,9 @@ use warnings;
use base 'Catalyst::Controller';
use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
use Hydra::Helper::AddBuilds;
use Data::Dump qw(dump);
use Digest::SHA1 qw(sha1_hex);
use Crypt::RandPasswd;
use Sys::Hostname::Long;
use Email::Simple;
use Email::Sender::Simple qw(sendmail);
use Email::Sender::Transport::SMTP;
use Config::General;
sub nixMachines {
my ($c) = @_;
my $result = "# GENERATED BY HYDRA\n";
foreach my $machine ($c->model("DB::BuildMachines")->all) {
if($machine->enabled) {
$result = $result . $machine->username . '@'. $machine->hostname . ' ';
foreach my $system ($machine->buildmachinesystemtypes) {
$result = $result . $system->system .',';
}
chop $result;
$result = $result . ' '. $machine->ssh_key . ' ' . $machine->maxconcurrent . ' '. $machine->speedfactor . ' ' . $machine->options . "\n";
}
}
return $result;
}
sub saveNixMachines {
my ($c) = @_;
die("File not writable: /etc/nix.machines") if ! -w "/etc/nix.machines" ;
open (NIXMACHINES, '>/etc/nix.machines') or die("Could not write to /etc/nix.machines");
print NIXMACHINES nixMachines($c);
close (NIXMACHINES);
}
sub admin : Chained('/') PathPart('admin') CaptureArgs(0) {
my ($self, $c) = @_;
@@ -48,293 +15,51 @@ sub admin : Chained('/') PathPart('admin') CaptureArgs(0) {
$c->stash->{admin} = 1;
}
sub index : Chained('admin') PathPart('') Args(0) {
my ($self, $c) = @_;
$c->stash->{machines} = [$c->model('DB::BuildMachines')->search(
{},
{ order_by => ["enabled DESC", "hostname"]
, '+select' => ["(select bs.stoptime from buildsteps as bs where bs.machine = (me.username || '\@' || me.hostname) and not bs.stoptime is null order by bs.stoptime desc limit 1)"]
, '+as' => ['idle']
})];
$c->stash->{steps} = [ $c->model('DB::BuildSteps')->search(
{ finished => 0, 'me.busy' => 1, 'build.busy' => 1, },
{ join => [ 'build' ]
, order_by => [ 'machine', 'stepnr' ]
} ) ];
$c->stash->{template} = 'admin.tt';
}
sub updateUser {
my ($c, $user) = @_;
my $username = trim $c->request->params->{"username"};
my $fullname = trim $c->request->params->{"fullname"};
my $emailaddress = trim $c->request->params->{"emailaddress"};
my $emailonerror = trim $c->request->params->{"emailonerror"};
my $roles = $c->request->params->{"roles"} ;
$user->update(
{ fullname => $fullname
, emailaddress => $emailaddress
, emailonerror => $emailonerror
});
$user->userroles->delete_all;
if(ref($roles) eq 'ARRAY') {
for my $s (@$roles) {
$user->userroles->create({ role => $s}) ;
}
} else {
$user->userroles->create({ role => $roles}) if defined $roles ;
}
}
sub user : Chained('admin') PathPart('user') CaptureArgs(1) {
my ($self, $c, $username) = @_;
requireAdmin($c);
my $user = $c->model('DB::Users')->find($username)
or notFound($c, "User $username doesn't exist.");
$c->stash->{user} = $user;
}
sub users : Chained('admin') PathPart('users') Args(0) {
my ($self, $c) = @_;
$c->stash->{users} = [$c->model('DB::Users')->search({}, {order_by => "username"})];
$c->stash->{template} = 'users.tt';
}
sub user_edit : Chained('user') PathPart('edit') Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'user.tt';
$c->stash->{edit} = 1;
}
sub user_edit_submit : Chained('user') PathPart('submit') Args(0) {
my ($self, $c) = @_;
requirePost($c);
txn_do($c->model('DB')->schema, sub {
updateUser($c, $c->stash->{user}) ;
});
$c->res->redirect("/admin/users");
}
sub sendemail {
my ($to, $subject, $body) = @_;
my $url = hostname_long;
my $sender = ($ENV{'USER'} || "hydra") . "@" . $url;
my $email = Email::Simple->create(
header => [
To => $to,
From => "Hydra <$sender>",
Subject => $subject
],
body => $body
);
sendmail($email);
}
sub reset_password : Chained('user') PathPart('reset-password') Args(0) {
my ($self, $c) = @_;
my %config = new Config::General(getHydraConf)->getall;
# generate password
my $password = Crypt::RandPasswd->word(8,10);
# calculate hash
my $hashed = sha1_hex($password);
$c->stash->{user}-> update({ password => $hashed}) ;
# send email
sendemail(
$c->stash->{user}->emailaddress,
"New password for Hydra",
"Hi,\n\n".
"Your password has been reset. Your new password is '$password'.\n".
"You can change your password at http://".$config{'base_uri'}."/change-password .\n".
"With regards, Hydra\n"
);
$c->res->redirect("/admin/users");
}
sub machines : Chained('admin') PathPart('machines') Args(0) {
my ($self, $c) = @_;
$c->stash->{machines} = [$c->model('DB::BuildMachines')->search({}, {order_by => "hostname"})];
$c->stash->{systems} = [$c->model('DB::SystemTypes')->search({}, {select => ["system"], order_by => "system" })];
$c->stash->{nixMachines} = nixMachines($c);
$c->stash->{nixMachinesWritable} = (-e "/etc/nix.machines" && -w "/etc/nix.machines");
$c->stash->{machines} = getMachines;
$c->stash->{template} = 'machines.tt';
}
sub machine : Chained('admin') PathPart('machine') CaptureArgs(1) {
my ($self, $c, $machineName) = @_;
requireAdmin($c);
my $machine = $c->model('DB::BuildMachines')->find($machineName)
or notFound($c, "Machine $machineName doesn't exist.");
$c->stash->{machine} = $machine;
}
sub machine_edit : Chained('machine') PathPart('edit') Args(0) {
sub clear_queue_non_current : Chained('admin') PathPart('clear-queue-non-current') Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'machine.tt';
$c->stash->{systemtypes} = [$c->model('DB::SystemTypes')->search({}, {order_by => "system"})];
$c->stash->{edit} = 1;
}
sub machine_edit_submit : Chained('machine') PathPart('submit') Args(0) {
my ($self, $c) = @_;
requirePost($c);
txn_do($c->model('DB')->schema, sub {
updateMachine($c, $c->stash->{machine}) ;
});
saveNixMachines($c);
$c->res->redirect("/admin/machines");
}
sub updateMachine {
my ($c, $machine) = @_;
my $hostname = trim $c->request->params->{"hostname"};
my $username = trim $c->request->params->{"username"};
my $maxconcurrent = trim $c->request->params->{"maxconcurrent"};
my $speedfactor = trim $c->request->params->{"speedfactor"};
my $ssh_key = trim $c->request->params->{"ssh_key"};
my $options = trim $c->request->params->{"options"};
my $systems = $c->request->params->{"systems"} ;
error($c, "Invalid or empty username.") if $username eq "";
error($c, "Max concurrent builds should be an integer > 0.") if $maxconcurrent eq "" || ! $maxconcurrent =~ m/[0-9]+/;
error($c, "Speed factor should be an integer > 0.") if $speedfactor eq "" || ! $speedfactor =~ m/[0-9]+/;
error($c, "Invalid or empty SSH key.") if $ssh_key eq "";
$machine->update(
{ username => $username
, maxconcurrent => $maxconcurrent
, speedfactor => $speedfactor
, ssh_key => $ssh_key
, options => $options
my $builds = $c->model('DB::Builds')->search_rs(
{ id => { -in => \ "select id from Builds where id in ((select id from Builds where finished = 0) except (select build from JobsetEvalMembers where eval in (select max(id) from JobsetEvals where hasNewBuilds = 1 group by jobset_id)))" }
});
$machine->buildmachinesystemtypes->delete_all;
if(ref($systems) eq 'ARRAY') {
for my $s (@$systems) {
$machine->buildmachinesystemtypes->create({ system => $s}) ;
}
} else {
$machine->buildmachinesystemtypes->create({ system => $systems}) ;
}
my $n = cancelBuilds($c->model('DB')->schema, $builds);
$c->flash->{successMsg} = "$n builds have been cancelled.";
$c->res->redirect($c->request->referer // "/");
}
sub create_machine : Chained('admin') PathPart('create-machine') Args(0) {
sub clearfailedcache : Chained('admin') PathPart('clear-failed-cache') Args(0) {
my ($self, $c) = @_;
requireAdmin($c);
$c->stash->{template} = 'machine.tt';
$c->stash->{systemtypes} = [$c->model('DB::SystemTypes')->search({}, {order_by => "system"})];
$c->stash->{edit} = 1;
$c->stash->{create} = 1;
$c->model('DB::FailedPaths')->delete;
$c->res->redirect($c->request->referer // "/");
}
sub create_machine_submit : Chained('admin') PathPart('create-machine/submit') Args(0) {
sub clearvcscache : Chained('admin') PathPart('clear-vcs-cache') Args(0) {
my ($self, $c) = @_;
requireAdmin($c);
my $hostname = trim $c->request->params->{"hostname"};
error($c, "Invalid or empty hostname.") if $hostname eq "";
txn_do($c->model('DB')->schema, sub {
my $machine = $c->model('DB::BuildMachines')->create(
{ hostname => $hostname });
updateMachine($c, $machine);
});
saveNixMachines($c);
$c->res->redirect("/admin/machines");
$c->model('DB::CachedPathInputs')->delete;
$c->model('DB::CachedGitInputs')->delete;
$c->model('DB::CachedSubversionInputs')->delete;
$c->model('DB::CachedBazaarInputs')->delete;
$c->flash->{successMsg} = "VCS caches have been cleared.";
$c->res->redirect($c->request->referer // "/");
}
sub machine_delete : Chained('machine') PathPart('delete') Args(0) {
my ($self, $c) = @_;
requirePost($c);
txn_do($c->model('DB')->schema, sub {
$c->stash->{machine}->delete;
});
saveNixMachines($c);
$c->res->redirect("/admin/machines");
}
sub machine_enable : Chained('machine') PathPart('enable') Args(0) {
my ($self, $c) = @_;
$c->stash->{machine}->update({ enabled => 1});
saveNixMachines($c);
$c->res->redirect("/admin/machines");
}
sub machine_disable : Chained('machine') PathPart('disable') Args(0) {
my ($self, $c) = @_;
$c->stash->{machine}->update({ enabled => 0});
saveNixMachines($c);
$c->res->redirect("/admin/machines");
}
sub clear_queue_non_current : Chained('admin') Path('clear-queue-non-current') Args(0) {
my ($self, $c) = @_;
# !!! Mark the builds as cancelled instead.
$c->model('DB::Builds')->search({finished => 0, iscurrent => 0, busy => 0})->delete_all;
$c->res->redirect("/admin");
}
sub clear_queue : Chained('admin') Path('clear-queue') Args(0) {
my ($self, $c) = @_;
# !!! Mark the builds as cancelled instead.
$c->model('DB::Builds')->search({finished => 0, busy => 0})->delete_all;
$c->res->redirect("/admin");
}
sub clearfailedcache : Chained('admin') Path('clear-failed-cache') Args(0) {
my ($self, $c) = @_;
my $r = `nix-store --clear-failed-paths '*'`;
$c->res->redirect("/admin");
}
sub clearvcscache : Chained('admin') Path('clear-vcs-cache') Args(0) {
my ($self, $c) = @_;
print "Clearing path cache\n";
$c->model('DB::CachedPathInputs')->delete_all;
print "Clearing git cache\n";
$c->model('DB::CachedGitInputs')->delete_all;
print "Clearing subversion cache\n";
$c->model('DB::CachedSubversionInputs')->delete_all;
print "Clearing bazaar cache\n";
$c->model('DB::CachedBazaarInputs')->delete_all;
$c->res->redirect("/admin");
}
sub managenews : Chained('admin') Path('news') Args(0) {
sub managenews : Chained('admin') PathPart('news') Args(0) {
my ($self, $c) = @_;
$c->stash->{newsItems} = [$c->model('DB::NewsItems')->search({}, {order_by => 'createtime DESC'})];
@@ -342,7 +67,8 @@ sub managenews : Chained('admin') Path('news') Args(0) {
$c->stash->{template} = 'news.tt';
}
sub news_submit : Chained('admin') Path('news/submit') Args(0) {
sub news_submit : Chained('admin') PathPart('news/submit') Args(0) {
my ($self, $c) = @_;
requirePost($c);
@@ -359,10 +85,11 @@ sub news_submit : Chained('admin') Path('news/submit') Args(0) {
$c->res->redirect("/admin/news");
}
sub news_delete : Chained('admin') Path('news/delete') Args(1) {
sub news_delete : Chained('admin') PathPart('news/delete') Args(1) {
my ($self, $c, $id) = @_;
txn_do($c->model('DB')->schema, sub {
$c->model('DB')->schema->txn_do(sub {
my $newsItem = $c->model('DB::NewsItems')->find($id)
or notFound($c, "Newsitem with id $id doesn't exist.");
$newsItem->delete;
@@ -371,20 +98,5 @@ sub news_delete : Chained('admin') Path('news/delete') Args(1) {
$c->res->redirect("/admin/news");
}
sub force_eval : Chained('admin') Path('eval') Args(2) {
my ($self, $c, $projectName, $jobsetName) = @_;
my $project = $c->model('DB::Projects')->find($projectName)
or notFound($c, "Project $projectName doesn't exist.");
$c->stash->{project} = $project;
$c->stash->{jobset_} = $project->jobsets->search({name => $jobsetName});
$c->stash->{jobset} = $c->stash->{jobset_}->single
or notFound($c, "Jobset $jobsetName doesn't exist.");
(my $res, my $stdout, my $stderr) = captureStdoutStderr(60, ("hydra-evaluator", $projectName, $jobsetName));
$c->res->redirect("/project/$projectName");
}
1;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
package Hydra::Controller::Channel;
use strict;
use warnings;
use base 'Hydra::Base::Controller::REST';
sub channel : Chained('/') PathPart('channel/custom') CaptureArgs(3) {
my ($self, $c, $projectName, $jobsetName, $channelName) = @_;
$c->stash->{project} = $c->model('DB::Projects')->find($projectName);
notFound($c, "Project $projectName doesn't exist.")
if !$c->stash->{project};
$c->stash->{jobset} = $c->stash->{project}->jobsets->find({
name => $jobsetName
});
notFound($c, "Jobset $jobsetName doesn't exist.")
if !$c->stash->{jobset};
my $lastSuccessful = $c->model('DB::Builds')->find(
{ 'eval.hasnewbuilds' => 1
, jobset_id => $c->stash->{jobset}->id,
, job => $channelName
, buildstatus => 0
},
{ rows => 1, order_by => "eval.id desc"
, join => { jobsetevalmembers => 'eval' }
}
);
notFound($c, "Channel $channelName either doesn't exist ".
"or was never built successfully.")
if !$lastSuccessful;
$c->stash->{lastSuccessful} = $lastSuccessful;
}
sub overview : Chained('channel') PathPart('') Args(0) {
my ($self, $c) = @_;
$c->stash->{constituents} = [
$c->stash->{lastSuccessful}->constituents_->search(
{}, {order_by => ["job"]}
)
];
$c->stash->{genericChannel} = 0;
$c->stash->{template} = 'channel-contents.tt';
}
sub nixexprs : Chained('channel') PathPart('') Args(1) {
my ($self, $c, $productName) = @_;
my $product = $c->stash->{lastSuccessful}->buildproducts->find(
{ type => "channel", name => $productName }
);
my $url = $c->uri_for(
$c->controller("Build")->action_for("download"),
[$c->stash->{lastSuccessful}->id],
$product->productnr,
$productName
);
$c->res->redirect($url);
}
sub binary_cache_url : Chained('channel') PathPart('binary-cache-url') Args(0) {
my ($self, $c) = @_;
$c->stash->{'plain'} = { data => $c->uri_for('/') };
$c->response->content_type('text/plain');
$c->forward('Hydra::View::Plain');
}
1;

View File

@@ -1,61 +1,248 @@
package Hydra::Controller::Job;
use utf8;
use strict;
use warnings;
use base 'Hydra::Base::Controller::ListBuilds';
use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
use JSON::MaybeXS;
use Net::Prometheus;
sub job : Chained('/') PathPart('job') CaptureArgs(3) {
my ($self, $c, $projectName, $jobsetName, $jobName) = @_;
$c->stash->{job_} = $c->model('DB::Jobs')->search({project => $projectName, jobset => $jobsetName, name => $jobName});
$c->stash->{job} = $c->stash->{job_}->single
or notFound($c, "Job $projectName:$jobsetName:$jobName doesn't exist.");
$c->stash->{project} = $c->stash->{job}->project;
$c->stash->{jobset} = $c->stash->{job}->jobset;
$c->stash->{jobset} = $c->model('DB::Jobsets')->find({ project => $projectName, name => $jobsetName });
if (!$c->stash->{jobset}) {
my $rename = $c->model('DB::JobsetRenames')->find({ project => $projectName, from_ => $jobsetName });
notFound($c, "Jobset $jobsetName doesn't exist.") unless defined $rename;
# Return a permanent redirect to the new jobset name.
my @captures = @{$c->req->captures};
$captures[1] = $rename->to_;
$c->res->redirect($c->uri_for($c->action, \@captures, $c->req->params), 301);
$c->detach;
}
$c->stash->{job} = $jobName;
$c->stash->{project} = $c->stash->{jobset}->project;
}
sub shield :Chained('job') PathPart('shield') Args(0) {
my ($self, $c) = @_;
my $job = $c->stash->{job};
my $lastBuild = $c->stash->{jobset}->builds->find(
{ job => $job, finished => 1 },
{ order_by => 'id DESC', rows => 1, columns => [@buildListColumns] }
);
notFound($c, "No latest build for job $job.") unless defined $lastBuild;
my $color =
$lastBuild->buildstatus == 0 ? "green" :
$lastBuild->buildstatus == 4 ? "yellow" :
"red";
my $message =
$lastBuild->buildstatus == 0 ? "passing" :
$lastBuild->buildstatus == 4 ? "cancelled" :
"failing";
$c->response->content_type('application/json');
$c->stash->{'plain'} = {
data => scalar (encode_json(
{
schemaVersion => 1,
label => "hydra build",
color => $color,
message => $message,
}))
};
$c->forward('Hydra::View::Plain');
}
sub prometheus : Chained('job') PathPart('prometheus') Args(0) {
my ($self, $c) = @_;
my $prometheus = Net::Prometheus->new;
my $lastBuild = $c->stash->{jobset}->builds->find(
{ job => $c->stash->{job}, finished => 1 },
{ order_by => 'id DESC', rows => 1, columns => ["stoptime", "buildstatus", "closuresize", "size"] }
);
$prometheus->new_counter(
name => "hydra_job_completion_time",
help => "The most recent job's completion time",
labels => [ "project", "jobset", "job" ]
)->labels(
$c->stash->{project}->name,
$c->stash->{jobset}->name,
$c->stash->{job},
)->inc($lastBuild->stoptime);
$prometheus->new_gauge(
name => "hydra_job_failed",
help => "Record if the most recent version of this job failed (1 means failed)",
labels => [ "project", "jobset", "job" ]
)->labels(
$c->stash->{project}->name,
$c->stash->{jobset}->name,
$c->stash->{job},
)->inc($lastBuild->buildstatus > 0);
$prometheus->new_gauge(
name => "hydra_build_closure_size",
help => "Closure size of the last job's build in bytes",
labels => [ "project", "jobset", "job" ]
)->labels(
$c->stash->{project}->name,
$c->stash->{jobset}->name,
$c->stash->{job},
)->inc($lastBuild->closuresize);
$prometheus->new_gauge(
name => "hydra_build_output_size",
help => "Output size of the last job's build in bytes",
labels => [ "project", "jobset", "job" ]
)->labels(
$c->stash->{project}->name,
$c->stash->{jobset}->name,
$c->stash->{job},
)->inc($lastBuild->size);
$c->stash->{'plain'} = { data => $prometheus->render };
$c->forward('Hydra::View::Plain');
}
sub overview : Chained('job') PathPart('') Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'job.tt';
#getBuildStats($c, scalar $c->stash->{job}->builds);
$c->stash->{lastBuilds} =
[ $c->stash->{jobset}->builds->search({ job => $c->stash->{job}, finished => 1 },
{ order_by => 'id DESC', rows => 10, columns => [@buildListColumns] }) ];
$c->stash->{currentBuilds} = [$c->stash->{job}->builds->search({finished => 1, iscurrent => 1}, { order_by => 'system' })];
$c->stash->{queuedBuilds} = [
$c->stash->{jobset}->builds->search(
{ job => $c->stash->{job}, finished => 0 },
{ order_by => ["priority DESC", "id"] }
) ];
$c->stash->{lastBuilds} =
[ $c->stash->{job}->builds->search({ finished => 1 },
{ order_by => 'timestamp DESC', rows => 10, columns => [@buildListColumns] }) ];
# If this is an aggregate job, then get its constituents.
my @constituents = $c->model('DB::Builds')->search(
{ aggregate => { -in => $c->stash->{jobset}->builds->search({ job => $c->stash->{job} }, { columns => ["id"], order_by => "id desc", rows => 15 })->as_query } },
{ join => 'aggregateconstituents_constituents',
columns => ['id', 'job', 'finished', 'buildstatus'],
+select => ['aggregateconstituents_constituents.aggregate'],
+as => ['aggregate']
});
$c->stash->{runningBuilds} = [
$c->stash->{job}->builds->search(
{ busy => 1 },
{ join => ['project']
, order_by => ["priority DESC", "timestamp"]
, '+select' => ['project.enabled']
, '+as' => ['enabled']
}
) ];
my $aggregates = {};
my %constituentJobs;
foreach my $build (@constituents) {
$aggregates->{$build->get_column('aggregate')}->{constituents}->{$build->job} =
{ id => $build->id, finished => $build->finished, buildstatus => $build->buildstatus };
$constituentJobs{$build->job} = 1;
}
$c->stash->{systems} = [$c->stash->{job}->builds->search({iscurrent => 1}, {select => ["system"], distinct => 1})];
foreach my $agg (keys %$aggregates) {
# FIXME: could be done in one query.
$aggregates->{$agg}->{build} =
$c->model('DB::Builds')->find({id => $agg}, {columns => [@buildListColumns]}) or die;
}
$c->stash->{aggregates} = $aggregates;
$c->stash->{constituentJobs} = [sort (keys %constituentJobs)];
$c->stash->{starred} = $c->user->starredjobs(
{ project => $c->stash->{project}->name
, jobset => $c->stash->{jobset}->name
, job => $c->stash->{job}
})->count == 1 if $c->user_exists;
}
sub metrics_tab : Chained('job') PathPart('metric-tab') Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'job-metrics-tab.tt';
$c->stash->{metrics} = [ $c->stash->{jobset}->buildmetrics->search(
{ job => $c->stash->{job} }, { select => ["name"], distinct => 1, order_by => "name", }) ];
}
sub build_times : Chained('job') PathPart('build-times') Args(0) {
my ($self, $c) = @_;
my @res = $c->stash->{jobset}->builds->search(
{ job => $c->stash->{job}, finished => 1, buildstatus => 0, closuresize => { '!=', 0 } },
{ join => "actualBuildStep"
, "+select" => ["actualBuildStep.stoptime - actualBuildStep.starttime"]
, "+as" => ["actualBuildTime"],
, order_by => "id" });
$self->status_ok($c, entity => [ map { { id => $_->id, timestamp => $_ ->timestamp, value => $_->get_column('actualBuildTime') } } @res ]);
}
sub closure_sizes : Chained('job') PathPart('closure-sizes') Args(0) {
my ($self, $c) = @_;
my @res = $c->stash->{jobset}->builds->search(
{ job => $c->stash->{job}, finished => 1, buildstatus => 0, closuresize => { '!=', 0 } },
{ order_by => "id", columns => [ "id", "timestamp", "closuresize" ] });
$self->status_ok($c, entity => [ map { { id => $_->id, timestamp => $_ ->timestamp, value => $_->closuresize } } @res ]);
}
sub output_sizes : Chained('job') PathPart('output-sizes') Args(0) {
my ($self, $c) = @_;
my @res = $c->stash->{jobset}->builds->search(
{ job => $c->stash->{job}, finished => 1, buildstatus => 0, size => { '!=', 0 } },
{ order_by => "id", columns => [ "id", "timestamp", "size" ] });
$self->status_ok($c, entity => [ map { { id => $_->id, timestamp => $_ ->timestamp, value => $_->size } } @res ]);
}
sub metric : Chained('job') PathPart('metric') Args(1) {
my ($self, $c, $metricName) = @_;
$c->stash->{template} = 'metric.tt';
$c->stash->{metricName} = $metricName;
my @res = $c->stash->{jobset}->buildmetrics->search(
{ job => $c->stash->{job}, name => $metricName },
{ order_by => "timestamp", columns => [ "build", "name", "timestamp", "value", "unit" ] });
$self->status_ok($c, entity => [ map { { id => $_->get_column("build"), timestamp => $_ ->timestamp, value => $_->value, unit => $_->unit } } @res ]);
}
# Hydra::Base::Controller::ListBuilds needs this.
sub get_builds : Chained('job') PathPart('') CaptureArgs(0) {
my ($self, $c) = @_;
$c->stash->{allBuilds} = $c->stash->{job}->builds;
$c->stash->{jobStatus} = $c->model('DB')->resultset('JobStatusForJob')
->search({}, {bind => [$c->stash->{project}->name, $c->stash->{jobset}->name, $c->stash->{job}->name]});
$c->stash->{allJobs} = $c->stash->{job_};
$c->stash->{allBuilds} = $c->stash->{jobset}->builds->search({ job => $c->stash->{job} });
$c->stash->{latestSucceeded} = $c->model('DB')->resultset('LatestSucceededForJob')
->search({}, {bind => [$c->stash->{project}->name, $c->stash->{jobset}->name, $c->stash->{job}->name]});
->search({}, {bind => [$c->stash->{jobset}->id, $c->stash->{job}]});
$c->stash->{channelBaseName} =
$c->stash->{project}->name . "-" . $c->stash->{jobset}->name . "-" . $c->stash->{job}->name;
$c->stash->{project}->name . "-" . $c->stash->{jobset}->name . "-" . $c->stash->{job};
}
sub star : Chained('job') PathPart('star') Args(0) {
my ($self, $c) = @_;
requirePost($c);
requireUser($c);
my $args =
{ project => $c->stash->{project}->name
, jobset => $c->stash->{jobset}->name
, job => $c->stash->{job}
};
if ($c->request->params->{star} eq "1") {
$c->user->starredjobs->update_or_create($args);
} else {
$c->user->starredjobs->find($args)->delete;
}
$c->stash->{resource}->{success} = 1;
}

View File

@@ -1,5 +1,6 @@
package Hydra::Controller::Jobset;
use utf8;
use strict;
use warnings;
use base 'Hydra::Base::Controller::ListBuilds';
@@ -7,178 +8,176 @@ use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
sub jobset : Chained('/') PathPart('jobset') CaptureArgs(2) {
sub jobsetChain :Chained('/') :PathPart('jobset') :CaptureArgs(2) {
my ($self, $c, $projectName, $jobsetName) = @_;
my $project = $c->model('DB::Projects')->find($projectName)
or notFound($c, "Project $projectName doesn't exist.");
my $project = $c->model('DB::Projects')->find($projectName);
notFound($c, "Project $projectName doesn't exist.") if !$project;
$c->stash->{project} = $project;
$c->stash->{jobset_} = $project->jobsets->search({name => $jobsetName});
$c->stash->{jobset} = $c->stash->{jobset_}->single
or notFound($c, "Jobset $jobsetName doesn't exist.");
$c->stash->{jobset} = $project->jobsets->find({ name => $jobsetName });
if (!$c->stash->{jobset} && !($c->action->name eq "jobset" and $c->request->method eq "PUT")) {
my $rename = $project->jobsetrenames->find({ from_ => $jobsetName });
notFound($c, "Jobset $jobsetName doesn't exist.") unless defined $rename;
# Return a permanent redirect to the new jobset name.
my @captures = @{$c->req->captures};
$captures[1] = $rename->to_;
$c->res->redirect($c->uri_for($c->action, \@captures, $c->req->params), 301);
$c->detach;
}
$c->stash->{params}->{name} //= $jobsetName;
}
sub jobsetIndex {
my ($self, $c, $forceStatus) = @_;
sub jobset :Chained('jobsetChain') :PathPart('') :Args(0) :ActionClass('REST::ForBrowsers') { }
sub jobset_GET {
my ($self, $c) = @_;
$c->stash->{template} = 'jobset.tt';
#getBuildStats($c, scalar $c->stash->{jobset}->builds);
$c->stash->{evals} = getEvals($c, scalar $c->stash->{jobset}->jobsetevals, 0, 10);
my $projectName = $c->stash->{project}->name;
my $jobsetName = $c->stash->{jobset}->name;
$c->stash->{latestEval} = $c->stash->{jobset}->jobsetevals->search({ hasnewbuilds => 1 }, { rows => 1, order_by => ["id desc"] })->single;
# Get the active / inactive jobs in this jobset.
my @jobs = $c->stash->{jobset}->jobs->search(
{ },
{ select => [
"name",
\ ("exists (select 1 from builds where project = '$projectName' and jobset = '$jobsetName' and job = me.name and isCurrent = 1) as active")
]
, as => ["name", "active"]
, order_by => ["name"] });
$c->stash->{totalShares} = getTotalShares($c->model('DB')->schema);
$c->stash->{activeJobs} = [];
$c->stash->{inactiveJobs} = [];
foreach my $job (@jobs) {
if ($job->get_column('active')) {
push @{$c->stash->{activeJobs}}, $job->name;
} else {
push @{$c->stash->{inactiveJobs}}, $job->name;
}
}
$c->stash->{emailNotification} = $c->config->{email_notification} // 0;
$c->stash->{systems} =
[ $c->stash->{jobset}->builds->search({ iscurrent => 1 }, { select => ["system"], distinct => 1, order_by => "system" }) ];
# status per system
my @systems = ();
foreach my $system (@{$c->stash->{systems}}) {
push(@systems, $system->system);
}
if($forceStatus || scalar(@{$c->stash->{activeJobs}}) <= 50) {
my @select = ();
my @as = ();
push(@select, "job"); push(@as, "job");
foreach my $system (@systems) {
push(@select, "(select buildstatus from Builds b where b.id = (select max(id) from Builds t where t.project = me.project and t.jobset = me.jobset and t.job = me.job and t.system = '$system' and t.iscurrent = 1 ))");
push(@as, $system);
push(@select, "(select b.id from Builds b where b.id = (select max(id) from Builds t where t.project = me.project and t.jobset = me.jobset and t.job = me.job and t.system = '$system' and t.iscurrent = 1 ))");
push(@as, "$system-build");
}
$c->stash->{activeJobsStatus} =
[ $c->model('DB')->resultset('ActiveJobsForJobset')->search(
{},
{ bind => [$c->stash->{project}->name, $c->stash->{jobset}->name]
, select => \@select
, as => \@as
, order_by => ["job"]
})];
}
# Last builds for jobset.
$c->stash->{lastBuilds} =
[ $c->stash->{jobset}->builds->search({ finished => 1 },
{ order_by => "timestamp DESC", rows => 5, columns => [@buildListColumns] }) ];
$self->status_ok($c, entity => $c->stash->{jobset});
}
sub index : Chained('jobset') PathPart('') Args(0) {
sub jobset_PUT {
my ($self, $c) = @_;
jobsetIndex($self, $c, 0);
requireProjectOwner($c, $c->stash->{project});
if (length($c->stash->{project}->declfile)) {
error($c, "can't modify jobset of declarative project", 403);
}
if (defined $c->stash->{jobset}) {
$c->model('DB')->schema->txn_do(sub {
updateJobset($c, $c->stash->{jobset});
});
my $uri = $c->uri_for($self->action_for("jobset"), [$c->stash->{project}->name, $c->stash->{jobset}->name]) . "#tabs-configuration";
$self->status_ok($c, entity => { redirect => "$uri" });
$c->flash->{successMsg} = "The jobset configuration has been updated.";
}
else {
my $jobset;
$c->model('DB')->schema->txn_do(sub {
# Note: $jobsetName is validated in updateProject, which will
# abort the transaction if the name isn't valid.
$jobset = $c->stash->{project}->jobsets->create(
{name => ".tmp", nixexprinput => "", nixexprpath => "", emailoverride => ""});
updateJobset($c, $jobset);
});
my $uri = $c->uri_for($self->action_for("jobset"), [$c->stash->{project}->name, $jobset->name]);
$self->status_created($c,
location => "$uri",
entity => { name => $jobset->name, uri => "$uri", redirect => "$uri", type => "jobset" });
}
}
sub jobset_DELETE {
my ($self, $c) = @_;
#requireProjectOwner($c, $c->stash->{project});
requireAdmin($c);
if (length($c->stash->{project}->declfile)) {
error($c, "can't modify jobset of declarative project", 403);
}
$c->model('DB')->schema->txn_do(sub {
$c->stash->{jobset}->jobsetevals->delete;
$c->stash->{jobset}->builds->delete;
$c->stash->{jobset}->delete;
});
my $uri = $c->uri_for($c->controller('Project')->action_for("project"), [$c->stash->{project}->name]);
$self->status_ok($c, entity => { redirect => "$uri" });
$c->flash->{successMsg} = "The jobset has been deleted.";
}
sub indexWithStatus : Chained('jobset') PathPart('') Args(1) {
my ($self, $c, $forceStatus) = @_;
jobsetIndex($self, $c, 1);
sub jobs_tab : Chained('jobsetChain') PathPart('jobs-tab') Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'jobset-jobs-tab.tt';
$c->stash->{filter} = $c->request->params->{filter} // "";
my $filter = "%" . $c->stash->{filter} . "%";
my ($evals, $builds) = searchBuildsAndEvalsForJobset(
$c->stash->{jobset},
{ job => { ilike => $filter }, ischannel => 0 },
10000
);
if ($c->request->params->{showInactive}) {
$c->stash->{showInactive} = 1;
foreach my $job ($c->stash->{jobset}->jobs->search({ name => { ilike => $filter } })) {
next if defined $builds->{$job->name};
$c->stash->{inactiveJobs}->{$job->name} = $builds->{$job->name} = 1;
}
}
$c->stash->{evals} = $evals;
my @jobs = sort (keys %$builds);
$c->stash->{nrJobs} = scalar @jobs;
splice @jobs, 250 if $c->stash->{filter} eq "";
$c->stash->{jobs} = [@jobs];
}
sub channels_tab : Chained('jobsetChain') PathPart('channels-tab') Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'jobset-channels-tab.tt';
my ($evals, $builds) = searchBuildsAndEvalsForJobset(
$c->stash->{jobset},
{ ischannel => 1 }
);
$c->stash->{evals} = $evals;
my @channels = sort (keys %$builds);
$c->stash->{channels} = [@channels];
}
# Hydra::Base::Controller::ListBuilds needs this.
sub get_builds : Chained('jobset') PathPart('') CaptureArgs(0) {
sub get_builds : Chained('jobsetChain') PathPart('') CaptureArgs(0) {
my ($self, $c) = @_;
$c->stash->{allBuilds} = $c->stash->{jobset}->builds;
$c->stash->{jobStatus} = $c->model('DB')->resultset('JobStatusForJobset')
->search({}, {bind => [$c->stash->{project}->name, $c->stash->{jobset}->name]});
$c->stash->{allJobsets} = $c->stash->{jobset_};
$c->stash->{allJobs} = $c->stash->{jobset}->jobs;
$c->stash->{latestSucceeded} = $c->model('DB')->resultset('LatestSucceededForJobset')
->search({}, {bind => [$c->stash->{project}->name, $c->stash->{jobset}->name]});
->search({}, {bind => [$c->stash->{jobset}->id]});
$c->stash->{channelBaseName} =
$c->stash->{project}->name . "-" . $c->stash->{jobset}->name;
}
sub edit : Chained('jobset') PathPart Args(0) {
sub edit : Chained('jobsetChain') PathPart Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
$c->stash->{template} = 'jobset.tt';
$c->stash->{edit} = 1;
}
sub submit : Chained('jobset') PathPart Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
requirePost($c);
txn_do($c->model('DB')->schema, sub {
updateJobset($c, $c->stash->{jobset});
});
$c->res->redirect($c->uri_for($self->action_for("index"),
[$c->stash->{project}->name, $c->stash->{jobset}->name]));
}
sub hide : Chained('jobset') PathPart Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
txn_do($c->model('DB')->schema, sub {
$c->stash->{jobset}->update({ hidden => 1, enabled => 0 });
});
$c->res->redirect($c->uri_for($c->controller('Project')->action_for("view"),
[$c->stash->{project}->name]));
}
sub unhide : Chained('jobset') PathPart Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
txn_do($c->model('DB')->schema, sub {
$c->stash->{jobset}->update({ hidden => 0 });
});
$c->res->redirect($c->uri_for($c->controller('Project')->action_for("view"),
[$c->stash->{project}->name]));
}
sub delete : Chained('jobset') PathPart Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
requirePost($c);
txn_do($c->model('DB')->schema, sub {
$c->stash->{jobset}->delete;
});
$c->res->redirect($c->uri_for($c->controller('Project')->action_for("view"),
[$c->stash->{project}->name]));
$c->stash->{template} = 'edit-jobset.tt';
$c->stash->{edit} = !defined $c->stash->{params}->{cloneJobset};
$c->stash->{cloneJobset} = defined $c->stash->{params}->{cloneJobset};
$c->stash->{totalShares} = getTotalShares($c->model('DB')->schema);
$c->stash->{emailNotification} = $c->config->{email_notification} // 0;
}
@@ -186,148 +185,208 @@ sub nixExprPathFromParams {
my ($c) = @_;
# The Nix expression path must be relative and can't contain ".." elements.
my $nixExprPath = trim $c->request->params->{"nixexprpath"};
error($c, "Invalid Nix expression path: $nixExprPath") if $nixExprPath !~ /^$relPathRE$/;
my $nixExprPath = trim $c->stash->{params}->{"nixexprpath"};
error($c, "Invalid Nix expression path $nixExprPath.") if $nixExprPath !~ /^$relPathRE$/;
my $nixExprInput = trim $c->request->params->{"nixexprinput"};
error($c, "Invalid Nix expression input name: $nixExprInput") unless $nixExprInput =~ /^\w+$/;
my $nixExprInput = trim $c->stash->{params}->{"nixexprinput"};
error($c, "Invalid Nix expression input name $nixExprInput.") unless $nixExprInput =~ /^[[:alpha:]][\w-]*$/;
return ($nixExprPath, $nixExprInput);
}
sub checkInput {
my ($c, $baseName) = @_;
sub checkInputValue {
my ($c, $name, $type, $value) = @_;
$value = trim $value unless $type eq "string";
my $inputName = trim $c->request->params->{"input-$baseName-name"};
error($c, "Invalid input name: $inputName") unless $inputName =~ /^[[:alpha:]]\w*$/;
error($c, "The value $value of input $name is not a Boolean (true or false).") if
$type eq "boolean" && !($value eq "true" || $value eq "false");
my $inputType = trim $c->request->params->{"input-$baseName-type"};
error($c, "Invalid input type: $inputType") unless
$inputType eq "svn" || $inputType eq "svn-checkout" || $inputType eq "hg" || $inputType eq "tarball" ||
$inputType eq "string" || $inputType eq "path" || $inputType eq "boolean" || $inputType eq "bzr" || $inputType eq "bzr-checkout" ||
$inputType eq "git" || $inputType eq "build" || $inputType eq "sysbuild" ;
error($c, "The value $value of input $name does not specify a Hydra evaluation. "
. "It should be either the number of a specific evaluation, the name of "
. "a jobset (given as <project>:<jobset>), or the name of a job (<project>:<jobset>:<job>).")
if $type eq "eval" && $value !~ /^\d+$/
&& $value !~ /^$projectNameRE:$jobsetNameRE$/
&& $value !~ /^$projectNameRE:$jobsetNameRE:$jobNameRE$/;
return ($inputName, $inputType);
return $value;
}
sub checkInputValue {
my ($c, $type, $value) = @_;
$value = trim $value;
error($c, "Invalid Boolean value: $value") if
$type eq "boolean" && !($value eq "true" || $value eq "false");
return $value;
sub knownInputTypes {
my ($c) = @_;
my @keys = keys %{$c->stash->{inputTypes}};
my $types = "";
my $counter = 0;
foreach my $key (@keys) {
$types = $types . "and $key" if ++$counter == scalar(@keys);
$types = $types . "$key, " if $counter != scalar(@keys);
}
return $types;
}
sub updateJobset {
my ($c, $jobset) = @_;
my $jobsetName = trim $c->request->params->{"name"};
error($c, "Invalid jobset name: $jobsetName") unless $jobsetName =~ /^[[:alpha:]][\w\-]*$/;
my $oldName = $jobset->name;
my $jobsetName = $c->stash->{params}->{name};
error($c, "Invalid jobset identifier $jobsetName.") if $jobsetName !~ /^$jobsetNameRE$/;
my ($nixExprPath, $nixExprInput) = nixExprPathFromParams $c;
error($c, "Cannot rename jobset to $jobsetName since that identifier is already taken.")
if $jobsetName ne $oldName && defined $c->stash->{project}->jobsets->find({ name => $jobsetName });
my $type = int($c->stash->{params}->{"type"} // 0);
my ($nixExprPath, $nixExprInput);
my $flake;
if ($type == 0) {
($nixExprPath, $nixExprInput) = nixExprPathFromParams $c;
} elsif ($type == 1) {
$flake = trim($c->stash->{params}->{"flake"});
error($c, "Invalid flake URI $flake.") if $flake !~ /^[a-zA-Z]/;
} else {
error($c, "Invalid jobset type.");
}
my $enabled = int($c->stash->{params}->{enabled});
die if $enabled < 0 || $enabled > 3;
my $shares = int($c->stash->{params}->{schedulingshares} // 1);
error($c, "The number of scheduling shares must be positive.") if $shares <= 0;
my $checkinterval = int(trim($c->stash->{params}->{checkinterval}));
my $enable_dynamic_run_command = defined $c->stash->{params}->{enable_dynamic_run_command} ? 1 : 0;
if ($enable_dynamic_run_command
&& !($c->config->{dynamicruncommand}->{enable}
&& $jobset->project->enable_dynamic_run_command))
{
badRequest($c, "Dynamic RunCommand is not enabled by the server or the parent project.");
}
$jobset->update(
{ name => $jobsetName
, description => trim($c->request->params->{"description"})
, description => trim($c->stash->{params}->{"description"})
, nixexprpath => $nixExprPath
, nixexprinput => $nixExprInput
, enabled => trim($c->request->params->{enabled}) eq "1" ? 1 : 0
, enableemail => trim($c->request->params->{enableemail}) eq "1" ? 1 : 0
, emailoverride => trim($c->request->params->{emailoverride}) || ""
, keepnr => trim($c->request->params->{keepnr}) || 3
, enabled => $enabled
, enableemail => defined $c->stash->{params}->{enableemail} ? 1 : 0
, enable_dynamic_run_command => $enable_dynamic_run_command
, emailoverride => trim($c->stash->{params}->{emailoverride}) || ""
, hidden => defined $c->stash->{params}->{visible} ? 0 : 1
, keepnr => int(trim($c->stash->{params}->{keepnr} // "0"))
, checkinterval => $checkinterval
, triggertime => ($enabled && $checkinterval > 0) ? $jobset->triggertime // time() : undef
, schedulingshares => $shares
, type => $type
, flake => $flake
});
my %inputNames;
$jobset->project->jobsetrenames->search({ from_ => $jobsetName })->delete;
$jobset->project->jobsetrenames->create({ from_ => $oldName, to_ => $jobsetName })
if $oldName ne ".tmp" && $jobsetName ne $oldName;
# Process the inputs of this jobset.
foreach my $param (keys %{$c->request->params}) {
next unless $param =~ /^input-(\w+)-name$/;
my $baseName = $1;
next if $baseName eq "template";
# Set the inputs of this jobset.
$jobset->jobsetinputs->delete;
my ($inputName, $inputType) = checkInput($c, $baseName);
if ($type == 0) {
foreach my $name (keys %{$c->stash->{params}->{inputs}}) {
my $inputData = $c->stash->{params}->{inputs}->{$name};
my $type = $inputData->{type};
my $value = $inputData->{value};
my $emailresponsible = defined $inputData->{emailresponsible} ? 1 : 0;
my $types = knownInputTypes($c);
$inputNames{$inputName} = 1;
badRequest($c, "Invalid input name $name.") unless $name =~ /^[[:alpha:]][\w-]*$/;
badRequest($c, "Invalid input type $type; valid types: $types.") unless defined $c->stash->{inputTypes}->{$type};
my $input;
if ($baseName =~ /^\d+$/) { # numeric base name is auto-generated, i.e. a new entry
$input = $jobset->jobsetinputs->create(
{ name => $inputName
, type => $inputType
my $input = $jobset->jobsetinputs->create(
{ name => $name,
type => $type,
emailresponsible => $emailresponsible
});
} else { # it's an existing input
$input = ($jobset->jobsetinputs->search({name => $baseName}))[0];
die unless defined $input;
$input->update({name => $inputName, type => $inputType});
}
# Update the values for this input. Just delete all the
# current ones, then create the new values.
$input->jobsetinputalts->delete_all;
my $values = $c->request->params->{"input-$baseName-values"};
$values = [] unless defined $values;
$values = [$values] unless ref($values) eq 'ARRAY';
my $altnr = 0;
foreach my $value (@{$values}) {
$value = checkInputValue($c, $inputType, $value);
$input->jobsetinputalts->create({altnr => $altnr++, value => $value});
$value = checkInputValue($c, $name, $type, $value);
$input->jobsetinputalts->create({altnr => 0, value => $value});
}
}
}
# Get rid of deleted inputs.
my @inputs = $jobset->jobsetinputs->all;
foreach my $input (@inputs) {
$input->delete unless defined $inputNames{$input->name};
sub clone : Chained('jobsetChain') PathPart('clone') Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
$c->stash->{template} = 'edit-jobset.tt';
$c->stash->{cloneJobset} = 1;
$c->stash->{totalShares} = getTotalShares($c->model('DB')->schema);
}
sub evals :Chained('jobsetChain') :PathPart('evals') :Args(0) :ActionClass('REST') { }
sub evals_GET {
my ($self, $c) = @_;
$c->stash->{template} = 'evals.tt';
my $page = int($c->req->param('page') || "1") || 1;
my $resultsPerPage = 20;
my $evals = $c->stash->{jobset}->jobsetevals;
$c->stash->{page} = $page;
$c->stash->{resultsPerPage} = $resultsPerPage;
$c->stash->{total} = $evals->search({hasnewbuilds => 1})->count;
my $offset = ($page - 1) * $resultsPerPage;
$c->stash->{evals} = getEvals($c, $evals, $offset, $resultsPerPage);
my %entity = (
evals => [ map { $_->{eval} } @{$c->stash->{evals}} ],
first => "?page=1",
last => "?page=" . POSIX::ceil($c->stash->{total}/$resultsPerPage)
);
if ($page > 1) {
$entity{previous} = "?page=" . ($page - 1);
}
if ($page < POSIX::ceil($c->stash->{total}/$resultsPerPage)) {
$entity{next} = "?page=" . ($page + 1);
}
$self->status_ok(
$c,
entity => \%entity
);
}
sub errors :Chained('jobsetChain') :PathPart('errors') :Args(0) :ActionClass('REST') { }
sub clone : Chained('jobset') PathPart('clone') Args(0) {
sub errors_GET {
my ($self, $c) = @_;
my $jobset = $c->stash->{jobset};
requireProjectOwner($c, $jobset->project);
$c->stash->{template} = 'eval-error.tt';
$c->stash->{template} = 'clone-jobset.tt';
my $jobsetName = $c->stash->{params}->{name};
$c->stash->{jobset} = $c->stash->{project}->jobsets->find(
{ name => $jobsetName },
{ '+columns' => { 'errormsg' => 'errormsg' } }
);
$self->status_ok($c, entity => $c->stash->{jobset});
}
sub clone_submit : Chained('jobset') PathPart('clone/submit') Args(0) {
my ($self, $c) = @_;
my $jobset = $c->stash->{jobset};
requireProjectOwner($c, $jobset->project);
requirePost($c);
my $newjobsetName = trim $c->request->params->{"newjobset"};
error($c, "Invalid jobset name: $newjobsetName") unless $newjobsetName =~ /^[[:alpha:]][\w\-]*$/;
my $newjobset;
txn_do($c->model('DB')->schema, sub {
$newjobset = $jobset->project->jobsets->create(
{ name => $newjobsetName
, description => $jobset->description
, nixexprpath => $jobset->nixexprpath
, nixexprinput => $jobset->nixexprinput
, enabled => 0
, enableemail => $jobset->enableemail
, emailoverride => $jobset->emailoverride || ""
});
foreach my $input ($jobset->jobsetinputs) {
my $newinput = $newjobset->jobsetinputs->create({name => $input->name, type => $input->type});
foreach my $inputalt ($input->jobsetinputalts) {
$newinput->jobsetinputalts->create({altnr => $inputalt->altnr, value => $inputalt->value});
}
}
});
$c->res->redirect($c->uri_for($c->controller('Jobset')->action_for("edit"), [$jobset->project->name, $newjobsetName]));
# Redirect to the latest finished evaluation of this jobset.
sub latest_eval : Chained('jobsetChain') PathPart('latest-eval') {
my ($self, $c, @args) = @_;
my $eval = getLatestFinishedEval($c->stash->{jobset})
or notFound($c, "No evaluation found.");
$c->res->redirect($c->uri_for($c->controller('JobsetEval')->action_for("view"), [$eval->id], @args, $c->req->params));
}
1;

View File

@@ -0,0 +1,212 @@
package Hydra::Controller::JobsetEval;
use utf8;
use strict;
use warnings;
use base 'Hydra::Base::Controller::NixChannel';
use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
use Hydra::Helper::BuildDiff;
use List::SomeUtils qw(uniq);
sub evalChain : Chained('/') PathPart('eval') CaptureArgs(1) {
my ($self, $c, $evalId) = @_;
my $eval = $c->model('DB::JobsetEvals')->find($evalId)
or notFound($c, "Evaluation $evalId doesn't exist.");
$c->stash->{eval} = $eval;
$c->stash->{jobset} = $eval->jobset;
$c->stash->{project} = $eval->jobset->project;
}
sub view :Chained('evalChain') :PathPart('') :Args(0) :ActionClass('REST') { }
sub view_GET {
my ($self, $c) = @_;
$c->stash->{template} = 'jobset-eval.tt';
my $eval = $c->stash->{eval};
$c->stash->{filter} = $c->request->params->{filter} // "";
my $filter = $c->stash->{filter} eq "" ? {} : { job => { ilike => "%" . $c->stash->{filter} . "%" } };
my $compare = $c->req->params->{compare};
my $eval2;
# Allow comparing this evaluation against the previous evaluation
# (default), an arbitrary evaluation, or the latest completed
# evaluation of another jobset.
if (defined $compare) {
if ($compare =~ /^\d+$/) {
$eval2 = $c->model('DB::JobsetEvals')->find($compare)
or notFound($c, "Evaluation $compare doesn't exist.");
} elsif ($compare =~ /^-(\d+)$/) {
my $t = int($1);
$eval2 = $c->stash->{jobset}->jobsetevals->find(
{ hasnewbuilds => 1, timestamp => {'<=', $eval->timestamp - $t} },
{ order_by => "timestamp desc", rows => 1});
} elsif (defined $compare && $compare =~ /^($jobsetNameRE)$/) {
my $j = $c->stash->{project}->jobsets->find({name => $compare})
or notFound($c, "Jobset $compare doesn't exist.");
$eval2 = getLatestFinishedEval($j);
} else {
notFound($c, "Unknown comparison source $compare.");
}
} else {
($eval2) = $eval->jobset->jobsetevals->search(
{ hasnewbuilds => 1, id => { '<', $eval->id } },
{ order_by => "id DESC", rows => 1 });
}
$c->stash->{otherEval} = $eval2 if defined $eval2;
my @builds = $eval->builds->search($filter, { columns => [@buildListColumns] });
my @builds2 = defined $eval2 ? $eval2->builds->search($filter, { columns => [@buildListColumns] }) : ();
my $diff = buildDiff([@builds], [@builds2]);
$c->stash->{stillSucceed} = $diff->{stillSucceed};
$c->stash->{stillFail} = $diff->{stillFail};
$c->stash->{nowSucceed} = $diff->{nowSucceed};
$c->stash->{nowFail} = $diff->{nowFail};
$c->stash->{new} = $diff->{new};
$c->stash->{removed} = $diff->{removed};
$c->stash->{unfinished} = $diff->{unfinished};
$c->stash->{aborted} = $diff->{aborted};
$c->stash->{totalAborted} = $diff->{totalAborted};
$c->stash->{totalFailed} = $diff->{totalFailed};
$c->stash->{totalQueued} = $diff->{totalQueued};
$c->stash->{full} = ($c->req->params->{full} || "0") eq "1";
$self->status_ok(
$c,
entity => $eval
);
}
sub errors :Chained('evalChain') :PathPart('errors') :Args(0) :ActionClass('REST') { }
sub errors_GET {
my ($self, $c) = @_;
$c->stash->{template} = 'eval-error.tt';
$c->stash->{eval} = $c->model('DB::JobsetEvals')->find($c->stash->{eval}->id, { prefetch => 'evaluationerror' });
$self->status_ok($c, entity => $c->stash->{eval});
}
sub create_jobset : Chained('evalChain') PathPart('create-jobset') Args(0) {
my ($self, $c) = @_;
my $eval = $c->stash->{eval};
requireProjectOwner($c, $c->stash->{project});
$c->stash->{template} = 'edit-jobset.tt';
$c->stash->{createFromEval} = 1;
}
sub cancel : Chained('evalChain') PathPart('cancel') Args(0) {
my ($self, $c) = @_;
requireCancelBuildPrivileges($c, $c->stash->{project});
my $n = cancelBuilds($c->model('DB')->schema, $c->stash->{eval}->builds->search_rs({}));
$c->flash->{successMsg} = "$n builds have been cancelled.";
$c->res->redirect($c->uri_for($c->controller('JobsetEval')->action_for('view'), $c->req->captures));
}
sub restart {
my ($self, $c, $condition) = @_;
requireRestartPrivileges($c, $c->stash->{project});
my $builds = $c->stash->{eval}->builds->search_rs({ finished => 1, buildstatus => $condition });
my $n = restartBuilds($c->model('DB')->schema, $builds);
$c->flash->{successMsg} = "$n builds have been restarted.";
$c->res->redirect($c->uri_for($c->controller('JobsetEval')->action_for('view'), $c->req->captures));
}
sub restart_aborted : Chained('evalChain') PathPart('restart-aborted') Args(0) {
my ($self, $c) = @_;
restart($self, $c, { -in => [3, 4, 9] });
}
sub restart_failed : Chained('evalChain') PathPart('restart-failed') Args(0) {
my ($self, $c) = @_;
restart($self, $c, { 'not in' => [0] });
}
sub bump : Chained('evalChain') PathPart('bump') Args(0) {
my ($self, $c) = @_;
requireBumpPrivileges($c, $c->stash->{project}); # FIXME: require admin?
my $builds = $c->stash->{eval}->builds->search({ finished => 0 });
my $n = $builds->count();
$c->model('DB')->schema->txn_do(sub {
$builds->update({globalpriority => time()});
});
$c->flash->{successMsg} = "$n builds have been bumped to the front of the queue.";
$c->res->redirect($c->uri_for($c->controller('JobsetEval')->action_for('view'), $c->req->captures));
}
# Hydra::Base::Controller::NixChannel needs this.
sub nix : Chained('evalChain') PathPart('channel') CaptureArgs(0) {
my ($self, $c) = @_;
$c->stash->{channelName} = $c->stash->{project}->name . "-" . $c->stash->{jobset}->name . "-latest";
$c->stash->{channelBuilds} = $c->stash->{eval}->builds
->search_literal("exists (select 1 from buildproducts where build = build.id and type = 'nix-build')")
->search({ finished => 1, buildstatus => 0 },
{ columns => [@buildListColumns, 'drvpath', 'description', 'homepage']
, join => ["buildoutputs"]
, order_by => ["build.id", "buildoutputs.name"]
, '+select' => ['buildoutputs.path', 'buildoutputs.name'], '+as' => ['outpath', 'outname'] });
}
sub job : Chained('evalChain') PathPart('job') {
my ($self, $c, $job, @rest) = @_;
my $build = $c->stash->{eval}->builds->find({job => $job});
notFound($c, "This evaluation has no job with the specified name.") unless defined $build;
$c->res->redirect($c->uri_for($c->controller('Build')->action_for("build"), [$build->id], @rest));
}
# Return the store paths of all succeeded builds of type 'nix-build'
# (i.e. regular packages). Used by the NixOS channel scripts.
sub store_paths : Chained('evalChain') PathPart('store-paths') Args(0) {
my ($self, $c) = @_;
my @builds = $c->stash->{eval}->builds
->search_literal("exists (select 1 from buildproducts where build = build.id and type = 'nix-build')")
->search({ finished => 1, buildstatus => 0 },
{ columns => [], join => ["buildoutputs"]
, '+select' => ['buildoutputs.path'], '+as' => ['outpath'] });
$self->status_ok(
$c,
entity => [uniq(sort map {$_->get_column('outpath')} @builds)]
);
}
# Return full info about all the builds in this evaluation.
sub all_builds : Chained('evalChain') PathPart('builds') Args(0) {
my ($self, $c) = @_;
my @builds = $c->stash->{eval}->builds;
$self->status_ok(
$c,
entity => [@builds],
);
}
1;

View File

@@ -1,5 +1,6 @@
package Hydra::Controller::Project;
use utf8;
use strict;
use warnings;
use base 'Hydra::Base::Controller::ListBuilds';
@@ -7,96 +8,102 @@ use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
sub project : Chained('/') PathPart('project') CaptureArgs(1) {
sub projectChain :Chained('/') :PathPart('project') :CaptureArgs(1) {
my ($self, $c, $projectName) = @_;
my $project = $c->model('DB::Projects')->find($projectName)
or notFound($c, "Project $projectName doesn't exist.");
$c->stash->{params}->{name} //= $projectName;
$c->stash->{project} = $project;
my $isCreate = $c->action->name eq "project" && $c->request->method eq "PUT";
$c->stash->{project} = $c->model('DB::Projects')->find($projectName);
$c->stash->{isProjectOwner} = !$isCreate && isProjectOwner($c, $c->stash->{project});
notFound($c, "Project $projectName doesn't exist.")
if !$c->stash->{project} && !$isCreate;
}
sub view : Chained('project') PathPart('') Args(0) {
sub project :Chained('projectChain') :PathPart('') :Args(0) :ActionClass('REST::ForBrowsers') { }
sub project_GET {
my ($self, $c) = @_;
$c->stash->{template} = 'project.tt';
#getBuildStats($c, scalar $c->stash->{project}->builds);
$c->stash->{views} = [$c->stash->{project}->views->all];
$c->stash->{jobsets} = [jobsetOverview($c, $c->stash->{project})];
$self->status_ok($c, entity => $c->stash->{project});
}
sub project_PUT {
my ($self, $c) = @_;
sub edit : Chained('project') PathPart Args(0) {
if (defined $c->stash->{project}) {
requireProjectOwner($c, $c->stash->{project});
$c->model('DB')->schema->txn_do(sub {
updateProject($c, $c->stash->{project});
});
my $uri = $c->uri_for($self->action_for("project"), [$c->stash->{project}->name]) . "#tabs-configuration";
$self->status_ok($c, entity => { redirect => "$uri" });
$c->flash->{successMsg} = "The project configuration has been updated.";
}
else {
requireMayCreateProjects($c);
my $project;
$c->model('DB')->schema->txn_do(sub {
# Note: $projectName is validated in updateProject,
# which will abort the transaction if the name isn't
# valid. Idem for the owner.
my $owner = $c->user->username;
$project = $c->model('DB::Projects')->create(
{ name => ".tmp", displayname => "", owner => $owner });
updateProject($c, $project);
});
my $uri = $c->uri_for($self->action_for("project"), [$project->name]);
$self->status_created($c,
location => "$uri",
entity => { name => $project->name, uri => "$uri", redirect => "$uri", type => "project" });
}
}
sub project_DELETE {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
$c->stash->{template} = 'project.tt';
$c->stash->{edit} = 1;
}
sub submit : Chained('project') PathPart Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
requirePost($c);
txn_do($c->model('DB')->schema, sub {
updateProject($c, $c->stash->{project});
});
$c->res->redirect($c->uri_for($self->action_for("view"), [$c->stash->{project}->name]));
}
sub hide : Chained('project') PathPart Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
txn_do($c->model('DB')->schema, sub {
$c->stash->{project}->update({ hidden => 1, enabled => 0 });
});
$c->res->redirect($c->uri_for("/"));
}
sub unhide : Chained('project') PathPart Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
txn_do($c->model('DB')->schema, sub {
$c->stash->{project}->update({ hidden => 0 });
});
$c->res->redirect($c->uri_for("/"));
}
sub delete : Chained('project') PathPart Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
requirePost($c);
txn_do($c->model('DB')->schema, sub {
$c->model('DB')->schema->txn_do(sub {
$c->stash->{project}->builds->delete;
$c->stash->{project}->jobsets->delete;
$c->stash->{project}->delete;
});
$c->res->redirect($c->uri_for("/"));
my $uri = $c->res->redirect($c->uri_for("/"));
$self->status_ok($c, entity => { redirect => "$uri" });
$c->flash->{successMsg} = "The project has been deleted.";
}
sub edit : Chained('projectChain') PathPart Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
$c->stash->{template} = 'edit-project.tt';
$c->stash->{edit} = 1;
}
sub requireMayCreateProjects {
my ($c) = @_;
requireLogin($c) if !$c->user_exists;
error($c, "Only administrators or authorised users can perform this operation.")
requireUser($c);
accessDenied($c, "Only administrators or authorised users can perform this operation.")
unless $c->check_user_roles('admin') || $c->check_user_roles('create-projects');
}
@@ -106,172 +113,88 @@ sub create : Path('/create-project') {
requireMayCreateProjects($c);
$c->stash->{template} = 'project.tt';
$c->stash->{template} = 'edit-project.tt';
$c->stash->{create} = 1;
$c->stash->{edit} = 1;
}
sub create_submit : Path('/create-project/submit') {
my ($self, $c) = @_;
requireMayCreateProjects($c);
my $projectName = trim $c->request->params->{name};
txn_do($c->model('DB')->schema, sub {
# Note: $projectName is validated in updateProject,
# which will abort the transaction if the name isn't
# valid. Idem for the owner.
my $owner = $c->check_user_roles('admin')
? trim $c->request->params->{owner} : $c->user->username;
my $project = $c->model('DB::Projects')->create(
{name => $projectName, displayname => "", owner => $owner});
updateProject($c, $project);
});
$c->res->redirect($c->uri_for($self->action_for("view"), [$projectName]));
}
sub create_jobset : Chained('project') PathPart('create-jobset') Args(0) {
sub create_jobset : Chained('projectChain') PathPart('create-jobset') Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
$c->stash->{template} = 'jobset.tt';
$c->stash->{template} = 'edit-jobset.tt';
$c->stash->{create} = 1;
$c->stash->{edit} = 1;
}
sub create_jobset_submit : Chained('project') PathPart('create-jobset/submit') Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
my $jobsetName = trim $c->request->params->{name};
txn_do($c->model('DB')->schema, sub {
# Note: $jobsetName is validated in updateProject, which will
# abort the transaction if the name isn't valid.
my $jobset = $c->stash->{project}->jobsets->create(
{name => $jobsetName, nixexprinput => "", nixexprpath => "", emailoverride => ""});
Hydra::Controller::Jobset::updateJobset($c, $jobset);
});
$c->res->redirect($c->uri_for($c->controller('Jobset')->action_for("index"),
[$c->stash->{project}->name, $jobsetName]));
$c->stash->{totalShares} = getTotalShares($c->model('DB')->schema);
$c->stash->{emailNotification} = $c->config->{email_notification} // 0;
}
sub updateProject {
my ($c, $project) = @_;
my $projectName = trim $c->request->params->{name};
error($c, "Invalid project name: " . ($projectName || "(empty)")) unless $projectName =~ /^[[:alpha:]][\w\-]*$/;
my $displayName = trim $c->request->params->{displayname};
error($c, "Invalid display name: $displayName") if $displayName eq "";
my $owner = $project->owner;
if ($c->check_user_roles('admin')) {
$owner = trim $c->request->params->{owner};
error($c, "Invalid owner: $owner")
unless defined $c->model('DB::Users')->find({username => $owner});
if ($c->check_user_roles('admin') and defined $c->stash->{params}->{owner}) {
$owner = trim $c->stash->{params}->{owner};
badRequest($c, "The user name $owner does not exist.")
unless defined $c->model('DB::Users')->find($owner);
}
my $projectName = $c->stash->{params}->{name};
error($c, "Invalid project identifier $projectName.") if $projectName !~ /^$projectNameRE$/;
error($c, "Cannot rename project to $projectName since that identifier is already taken.")
if $projectName ne $project->name && defined $c->model('DB::Projects')->find($projectName);
my $displayName = trim $c->stash->{params}->{displayname};
error($c, "You must specify a display name.") if $displayName eq "";
my $enable_dynamic_run_command = defined $c->stash->{params}->{enable_dynamic_run_command} ? 1 : 0;
if ($enable_dynamic_run_command && !$c->config->{dynamicruncommand}->{enable}) {
badRequest($c, "Dynamic RunCommand is not enabled by the server.");
}
$project->update(
{ name => $projectName
, displayname => $displayName
, description => trim($c->request->params->{description})
, homepage => trim($c->request->params->{homepage})
, enabled => trim($c->request->params->{enabled}) eq "1" ? 1 : 0
, description => trim($c->stash->{params}->{description})
, homepage => trim($c->stash->{params}->{homepage})
, enabled => defined $c->stash->{params}->{enabled} ? 1 : 0
, hidden => defined $c->stash->{params}->{visible} ? 0 : 1
, owner => $owner
, enable_dynamic_run_command => $enable_dynamic_run_command
, declfile => trim($c->stash->{params}->{declarative}->{file})
, decltype => trim($c->stash->{params}->{declarative}->{type})
, declvalue => trim($c->stash->{params}->{declarative}->{value})
});
if (length($project->declfile)) {
# This logic also exists in the DeclarativeJobets tests.
# TODO: refactor and deduplicate.
$project->jobsets->update_or_create(
{ name=> ".jobsets"
, nixexprinput => ""
, nixexprpath => ""
, emailoverride => ""
, triggertime => time
});
} else {
$project->jobsets->search({ name => ".jobsets" })->delete;
$project->update(
{ decltype => ""
, declvalue => ""
});
}
}
# Hydra::Base::Controller::ListBuilds needs this.
sub get_builds : Chained('project') PathPart('') CaptureArgs(0) {
sub get_builds : Chained('projectChain') PathPart('') CaptureArgs(0) {
my ($self, $c) = @_;
$c->stash->{allBuilds} = $c->stash->{project}->builds;
$c->stash->{jobStatus} = $c->model('DB')->resultset('JobStatusForProject')
->search({}, {bind => [$c->stash->{project}->name]});
$c->stash->{allJobsets} = $c->stash->{project}->jobsets;
$c->stash->{allJobs} = $c->stash->{project}->jobs;
$c->stash->{latestSucceeded} = $c->model('DB')->resultset('LatestSucceededForProject')
->search({}, {bind => [$c->stash->{project}->name]});
$c->stash->{channelBaseName} = $c->stash->{project}->name;
}
sub create_view_submit : Chained('project') PathPart('create-view/submit') Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
my $viewName = $c->request->params->{name};
my $view;
txn_do($c->model('DB')->schema, sub {
# Note: $viewName is validated in updateView, which will abort
# the transaction if the name isn't valid.
$view = $c->stash->{project}->views->create({name => $viewName});
Hydra::Controller::View::updateView($c, $view);
});
$c->res->redirect($c->uri_for($c->controller('View')->action_for('view_view'),
[$c->stash->{project}->name, $view->name]));
}
sub create_view : Chained('project') PathPart('create-view') Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
$c->stash->{template} = 'edit-view.tt';
$c->stash->{create} = 1;
}
sub releases : Chained('project') PathPart('releases') Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'releases.tt';
$c->stash->{releases} = [$c->stash->{project}->releases->search({},
{order_by => ["timestamp DESC"]})];
}
sub create_release : Chained('project') PathPart('create-release') Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
$c->stash->{template} = 'edit-release.tt';
$c->stash->{create} = 1;
}
sub create_release_submit : Chained('project') PathPart('create-release/submit') Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
my $releaseName = $c->request->params->{name};
my $release;
txn_do($c->model('DB')->schema, sub {
# Note: $releaseName is validated in updateRelease, which will
# abort the transaction if the name isn't valid.
$release = $c->stash->{project}->releases->create(
{ name => $releaseName
, timestamp => time
});
Hydra::Controller::Release::updateRelease($c, $release);
});
$c->res->redirect($c->uri_for($c->controller('Release')->action_for('view'),
[$c->stash->{project}->name, $release->name]));
}
1;

View File

@@ -1,79 +0,0 @@
package Hydra::Controller::Release;
use strict;
use warnings;
use base 'Catalyst::Controller';
use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
sub release : Chained('/') PathPart('release') CaptureArgs(2) {
my ($self, $c, $projectName, $releaseName) = @_;
$c->stash->{project} = $c->model('DB::Projects')->find($projectName)
or notFound($c, "Project $projectName doesn't exist.");
$c->stash->{release} = $c->stash->{project}->releases->find({name => $releaseName})
or notFound($c, "Release $releaseName doesn't exist.");
}
sub view : Chained('release') PathPart('') Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'release.tt';
$c->stash->{members} = [$c->stash->{release}->releasemembers->search({},
{order_by => ["description"]})];
}
sub updateRelease {
my ($c, $release) = @_;
my $releaseName = trim $c->request->params->{name};
error($c, "Invalid release name: $releaseName")
unless $releaseName =~ /^$relNameRE$/;
$release->update(
{ name => $releaseName
, description => trim $c->request->params->{description}
});
$release->releasemembers->delete_all;
foreach my $param (keys %{$c->request->params}) {
next unless $param =~ /^member-(\d+)-description$/;
my $buildId = $1;
my $description = trim $c->request->params->{"member-$buildId-description"};
$release->releasemembers->create({ build => $buildId, description => $description });
}
}
sub edit : Chained('release') PathPart('edit') Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
$c->stash->{template} = 'edit-release.tt';
}
sub submit : Chained('release') PathPart('submit') Args(0) {
my ($self, $c) = @_;
requireProjectOwner($c, $c->stash->{project});
if (($c->request->params->{action} || "") eq "delete") {
txn_do($c->model('DB')->schema, sub {
$c->stash->{release}->delete;
});
$c->res->redirect($c->uri_for($c->controller('Project')->action_for('releases'),
[$c->stash->{project}->name]));
} else {
txn_do($c->model('DB')->schema, sub {
updateRelease($c, $c->stash->{release});
});
$c->res->redirect($c->uri_for($self->action_for("view"),
[$c->stash->{project}->name, $c->stash->{release}->name]));
}
}
1;

View File

@@ -1,105 +1,288 @@
package Hydra::Controller::Root;
use utf8;
use strict;
use warnings;
use base 'Hydra::Base::Controller::ListBuilds';
use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
use Digest::SHA1 qw(sha1_hex);
use Hydra::View::TT;
use Nix::Store;
use Nix::Config;
use Number::Bytes::Human qw(format_bytes);
use Encode;
use File::Basename;
use JSON::MaybeXS;
use HTML::Entities;
use IPC::Run3;
use List::Util qw[min max];
use List::SomeUtils qw{any};
use Net::Prometheus;
use Types::Standard qw/StrMatch/;
use WWW::Form::UrlEncoded::PP qw();
use constant NARINFO_REGEX => qr{^([a-z0-9]{32})\.narinfo$};
# e.g.: https://hydra.example.com/realisations/sha256:a62128132508a3a32eef651d6467695944763602f226ac630543e947d9feb140!out.doi
use constant REALISATIONS_REGEX => qr{^(sha256:[a-z0-9]{64}![a-z]+)\.doi$};
# Put this controller at top-level.
__PACKAGE__->config->{namespace} = '';
sub noLoginNeeded {
my ($c) = @_;
my $hostname = $c->request->headers->header('X-Forwarded-For') || $c->request->hostname;
my $readonly_ips = $c->config->{readonly_ips} // "";
my $whitelisted = any { $_ eq $hostname } split(/,/, $readonly_ips);
return $whitelisted ||
$c->request->path eq "api/push-github" ||
$c->request->path eq "api/push-gitea" ||
$c->request->path eq "google-login" ||
$c->request->path eq "github-redirect" ||
$c->request->path eq "github-login" ||
$c->request->path eq "login" ||
$c->request->path eq "logo" ||
$c->request->path =~ /^static\//;
}
sub begin :Private {
my ($self, $c, @args) = @_;
$c->stash->{curUri} = $c->request->uri;
$c->stash->{version} = $ENV{"HYDRA_RELEASE"} || "<devel>";
$c->stash->{nixVersion} = $ENV{"NIX_RELEASE"} || "<devel>";
$c->stash->{nixEvalJobsVersion} = $ENV{"NIX_EVAL_JOBS_RELEASE"} || "<devel>";
$c->stash->{curTime} = time;
$c->stash->{logo} = $ENV{"HYDRA_LOGO"} ? "/logo" : "/static/images/hydra.png" ;
$c->stash->{tracker} = $ENV{"HYDRA_TRACKER"} ;
$c->stash->{logo} = defined $c->config->{hydra_logo} ? "/logo" : "";
$c->stash->{tracker} = defined $c->config->{tracker} ? $c->config->{tracker} : "";
$c->stash->{flashMsg} = $c->flash->{flashMsg};
$c->stash->{successMsg} = $c->flash->{successMsg};
$c->stash->{localStore} = isLocalStore;
$c->stash->{isPrivateHydra} = $c->config->{private} // "0" ne "0";
if ($c->stash->{isPrivateHydra} && ! noLoginNeeded($c)) {
requireUser($c);
}
if (scalar(@args) == 0 || $args[0] ne "static") {
$c->stash->{nrRunningBuilds} = $c->model('DB::Builds')->search({ finished => 0, busy => 1 }, {})->count();
$c->stash->{nrQueuedBuilds} = $c->model('DB::Builds')->search({ finished => 0 })->count();
$c->stash->{nrRunningBuilds} = dbh($c)->selectrow_array(
"select count(distinct build) from buildsteps where busy != 0");
$c->stash->{nrQueuedBuilds} = $c->model('DB::Builds')->search({ finished => 0 })->count();
}
# Gather the supported input types.
$c->stash->{inputTypes} = {
'string' => 'String value',
'boolean' => 'Boolean',
'nix' => 'Nix expression',
'build' => 'Previous Hydra build',
'sysbuild' => 'Previous Hydra build (same system)',
'eval' => 'Previous Hydra evaluation'
};
$_->supportedInputTypes($c->stash->{inputTypes}) foreach @{$c->hydra_plugins};
# XSRF protection: require POST requests to have the same origin.
if ($c->req->method eq "POST" && $c->req->path ne "api/push-github" && $c->req->path ne "api/push-gitea") {
my $referer = $c->req->header('Referer');
$referer //= $c->req->header('Origin');
my $base = $c->req->base;
die unless $base =~ /\/$/;
$referer .= "/";
error($c, "POST requests should come from $base.")
unless defined $referer && substr($referer, 0, length $base) eq $base;
}
$c->forward('deserialize');
$c->stash->{params} = $c->request->data or $c->request->params;
unless (defined $c->stash->{params} and %{$c->stash->{params}}) {
$c->stash->{params} = $c->request->params;
}
# Set the Vary header to "Accept" to ensure that browsers don't
# mix up HTML and JSON responses.
$c->response->headers->header('Vary', 'Accept');
}
sub deserialize :ActionClass('Deserialize') { }
sub index :Path :Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'overview.tt';
$c->stash->{projects} = [$c->model('DB::Projects')->search(isAdmin($c) ? {} : {hidden => 0}, {order_by => 'name'})];
$c->stash->{projects} = [$c->model('DB::Projects')->search({}, {order_by => ['enabled DESC', 'name']})];
$c->stash->{newsItems} = [$c->model('DB::NewsItems')->search({}, { order_by => ['createtime DESC'], rows => 5 })];
# $c->stash->{nrbuilds} = [nrbuildsQuery($c, 30, "day", "", "", "", "")];
# <img src="http://chart.apis.google.com/chart?cht=bvg&chtt=Nr%20builds%20over%20the%20last%2030%20days&chs=300x100&chd=t:1785,881,2863,2828,1472,2847,1449,5634,1625,1200,1576,700,839,8533,1439,361,991,1337,1234,1322,1883,2146,1553,883,378,1395,1204,527,1147,124&chco=BBCEBB&chds=0,8533&chbh=a&chxt=y&chxr=0,0,8533"/>
$self->status_ok($c,
entity => $c->stash->{projects}
);
}
sub login :Local {
my ($self, $c) = @_;
sub queue :Local :Args(0) :ActionClass('REST') { }
my $username = $c->request->params->{username} || "";
my $password = $c->request->params->{password} || "";
if ($username eq "" && $password eq "" && ! defined $c->flash->{referer}) {
my $baseurl = $c->uri_for('/');
my $refurl = $c->request->referer;
$c->flash->{referer} = $refurl if $refurl =~ m/^($baseurl)/;
}
if ($username && $password) {
if ($c->authenticate({username => $username, password => $password})) {
$c->response->redirect($c->flash->{referer} || $c->uri_for('/'));
$c->flash->{referer} = undef;
return;
}
$c->stash->{errorMsg} = "Bad username or password.";
}
$c->stash->{template} = 'login.tt';
}
sub logout :Local {
my ($self, $c) = @_;
$c->logout;
$c->response->redirect($c->request->referer || $c->uri_for('/'));
}
sub queue :Local {
sub queue_GET {
my ($self, $c) = @_;
$c->stash->{template} = 'queue.tt';
$c->stash->{queue} = [$c->model('DB::Builds')->search(
{finished => 0}, { join => ['project'], order_by => ["priority DESC", "timestamp"], columns => [@buildListColumns], '+select' => ['project.enabled'], '+as' => ['enabled'] })];
$c->stash->{flashMsg} = $c->flash->{buildMsg};
$c->stash->{flashMsg} //= $c->flash->{buildMsg};
$self->status_ok(
$c,
entity => [$c->model('DB::Builds')->search(
{ finished => 0 },
{ order_by => ["globalpriority desc", "id"],
, columns => [@buildListColumns]
})]
);
}
sub timeline :Local {
sub queue_summary :Local :Path('queue-summary') :Args(0) {
my ($self, $c) = @_;
my $pit = time();
$c->stash->{pit} = $pit;
$pit = $pit-(24*60*60)-1;
$c->stash->{template} = 'queue-summary.tt';
$c->stash->{template} = 'timeline.tt';
$c->stash->{builds} = [ $c->model('DB::Builds')->search
( { finished => 1, stoptime => { '>' => $pit } }
, { order_by => ["starttime"] }
) ];
$c->stash->{queued} = dbh($c)->selectall_arrayref(
"select jobsets.project as project, jobsets.name as jobset, count(*) as queued, min(timestamp) as oldest, max(timestamp) as newest from Builds " .
"join Jobsets jobsets on jobsets.id = builds.jobset_id " .
"where finished = 0 group by jobsets.project, jobsets.name order by queued desc",
{ Slice => {} });
$c->stash->{systems} = dbh($c)->selectall_arrayref(
"select system, count(*) as c from Builds where finished = 0 group by system order by c desc",
{ Slice => {} });
}
sub status :Local {
sub status :Local :Args(0) :ActionClass('REST') { }
sub status_GET {
my ($self, $c) = @_;
$c->stash->{steps} = [ $c->model('DB::BuildSteps')->search(
{ 'me.busy' => 1, 'build.finished' => 0, 'build.busy' => 1 },
{ join => [ 'build' ]
, order_by => [ 'machine' ]
} ) ];
$self->status_ok(
$c,
entity => [$c->model('DB::Builds')->search(
{ "buildsteps.busy" => { '!=', 0 } },
{ order_by => ["globalpriority DESC", "id"],
join => "buildsteps",
columns => [@buildListColumns, 'buildsteps.drvpath', 'buildsteps.type']
})]
);
}
sub queue_runner_status :Local :Path('queue-runner-status') :Args(0) :ActionClass('REST') { }
sub queue_runner_status_GET {
my ($self, $c) = @_;
#my $status = from_json($c->model('DB::SystemStatus')->find('queue-runner')->status);
my ($stdout, $stderr);
run3(['hydra-queue-runner', '--status'], \undef, \$stdout, \$stderr);
my $status;
if ($? != 0) {
$status = { status => "unknown" };
} else {
$status = decode_json($stdout);
}
my $json = JSON->new->pretty()->canonical();
$c->stash->{template} = 'queue-runner-status.tt';
$c->stash->{status} = $json->encode($status);
$self->status_ok($c, entity => $status);
}
sub machines :Local Args(0) {
my ($self, $c) = @_;
my $machines = getMachines;
# Add entry for localhost. The implicit addition is not needed with queue runner v2
if (not $c->config->{'queue_runner_endpoint'}) {
$machines->{''} //= {};
}
delete $machines->{'localhost'};
my $status = $c->model('DB::SystemStatus')->find("queue-runner");
if ($status) {
my $ms = decode_json($status->status)->{"machines"};
foreach my $name (keys %{$ms}) {
$name = "" if $name eq "localhost";
my $outName = $name;
$outName = "" if $name eq "ssh://localhost";
$machines->{$outName} //= {disabled => 1};
$machines->{$outName}->{nrStepsDone} = $ms->{$name}->{nrStepsDone};
$machines->{$outName}->{avgStepBuildTime} = $ms->{$name}->{avgStepBuildTime} // 0;
}
}
$c->stash->{machines} = $machines;
$c->stash->{steps} = dbh($c)->selectall_arrayref(
"select build, stepnr, s.system as system, s.drvpath as drvpath, machine, s.starttime as starttime, jobsets.project as project, jobsets.name as jobset, job, s.busy as busy " .
"from BuildSteps s " .
"join Builds b on s.build = b.id " .
"join Jobsets jobsets on jobsets.id = b.jobset_id " .
"where busy != 0 order by machine, stepnr",
{ Slice => {} });
$c->stash->{template} = 'machine-status.tt';
$c->stash->{human_bytes} = sub {
my ($bytes) = @_;
return format_bytes($bytes, si => 1);
};
$c->stash->{pretty_load} = sub {
my ($load) = @_;
return sprintf('%.2f', $load);
};
$c->stash->{pretty_percent} = sub {
my ($percent) = @_;
my $ret = sprintf('%.2f', $percent);
return ('&nbsp;' x (6 - length($ret))) . encode_entities($ret);
};
$self->status_ok($c, entity => $c->stash->{machines});
}
sub prometheus :Local Args(0) {
my ($self, $c) = @_;
my $machines = getMachines;
my $client = Net::Prometheus->new;
my $duration = $client->new_histogram(
name => "hydra_machine_build_duration",
help => "How long builds are taking per server. Note: counts are gauges, NOT counters.",
labels => [ "machine" ],
buckets => [
60,
600,
1800,
3600,
7200,
21600,
43200,
86400,
172800,
259200,
345600,
518400,
604800,
691200
]
);
my $steps = dbh($c)->selectall_arrayref(
"select machine, s.starttime as starttime " .
"from BuildSteps s join Builds b on s.build = b.id " .
"where busy != 0 order by machine, stepnr",
{ Slice => {} });
foreach my $step (@$steps) {
my $name = $step->{machine} ? Hydra::View::TT->stripSSHUser(undef, $step->{machine}) : "";
$name = "localhost" unless $name;
$duration->labels($name)->observe(time - $step->{starttime});
}
$c->stash->{'plain'} = { data => $client->render };
$c->forward('Hydra::View::Plain');
}
@@ -107,58 +290,15 @@ sub status :Local {
sub get_builds : Chained('/') PathPart('') CaptureArgs(0) {
my ($self, $c) = @_;
$c->stash->{allBuilds} = $c->model('DB::Builds');
$c->stash->{jobStatus} = $c->model('DB')->resultset('JobStatus');
$c->stash->{allJobsets} = $c->model('DB::Jobsets');
$c->stash->{allJobs} = $c->model('DB::Jobs');
$c->stash->{latestSucceeded} = $c->model('DB')->resultset('LatestSucceeded');
$c->stash->{channelBaseName} = "everything";
$c->stash->{total} = $c->model('DB::NrBuilds')->find('finished')->count;
}
sub robots_txt : Path('robots.txt') {
my ($self, $c) = @_;
sub uri_for {
my ($controller, $action, @args) = @_;
return $c->uri_for($c->controller($controller)->action_for($action), @args)->path;
}
sub channelUris {
my ($controller, $bindings) = @_;
return
( uri_for($controller, 'closure', $bindings, "*")
, uri_for($controller, 'manifest', $bindings)
, uri_for($controller, 'pkg', $bindings, "*")
, uri_for($controller, 'nixexprs', $bindings)
, uri_for($controller, 'channel_contents', $bindings)
);
}
# Put actions that are expensive or not useful for indexing in
# robots.txt. Note: wildcards are not universally supported in
# robots.txt, but apparently Google supports them.
my @rules =
( uri_for('Build', 'buildtimedeps', ["*"])
, uri_for('Build', 'runtimedeps', ["*"])
, uri_for('Build', 'deps', ["*"])
, uri_for('Build', 'view_nixlog', ["*"], "*")
, uri_for('Build', 'view_log', ["*"], "*")
, uri_for('Build', 'view_log', ["*"])
, uri_for('Build', 'download', ["*"], "*")
, uri_for('Root', 'nar', [], "*")
, uri_for('Root', 'status', [])
, uri_for('Root', 'all', [])
, uri_for('API', 'scmdiff', [])
, uri_for('API', 'logdiff', [],"*", "*")
, uri_for('Project', 'all', ["*"])
, channelUris('Root', ["*"])
, channelUris('Project', ["*", "*"])
, channelUris('Jobset', ["*", "*", "*"])
, channelUris('Job', ["*", "*", "*", "*"])
, channelUris('Build', ["*"])
);
$c->stash->{'plain'} = { data => "User-agent: *\n" . join('', map { "Disallow: $_\n" } @rules) };
$c->stash->{'plain'} = { data => "User-agent: *\nDisallow: /*\n" };
$c->forward('Hydra::View::Plain');
}
@@ -172,62 +312,300 @@ sub default :Path {
sub end : ActionClass('RenderView') {
my ($self, $c) = @_;
if (scalar @{$c->error}) {
$c->stash->{template} = 'error.tt';
if (defined $c->stash->{json}) {
if (scalar @{$c->error}) {
# FIXME: dunno why we need to do decode_utf8 here.
$c->stash->{json}->{error} = join "\n", map { decode_utf8($_); } @{$c->error};
$c->clear_errors;
}
$c->forward('View::JSON');
}
elsif (scalar @{$c->error}) {
$c->stash->{resource} = { error => join "\n", @{$c->error} };
if ($c->stash->{lazy}) {
$c->response->headers->header('X-Hydra-Lazy', 'Yes');
$c->stash->{template} = 'lazy_error.tt';
}
else {
$c->stash->{template} = 'error.tt';
}
$c->stash->{errors} = $c->error;
$c->response->status(500) if $c->response->status == 200;
if ($c->response->status >= 300) {
$c->stash->{httpStatus} =
$c->response->status . " " . HTTP::Status::status_message($c->response->status);
}
$c->clear_errors;
}
$c->forward('serialize') if defined $c->stash->{resource};
}
sub serialize : ActionClass('Serialize') { }
sub nar :Local :Args(1) {
my ($self, $c, $path) = @_;
$path = ($ENV{NIX_STORE_DIR} || "/nix/store")."/$path";
die if $path =~ /\//;
if (!isValidPath($path)) {
$c->response->status(410); # "Gone"
error($c, "Path " . $path . " is no longer available.");
if (!isLocalStore) {
notFound($c, "There is no binary cache here.");
}
$c->stash->{current_view} = 'NixNAR';
$c->stash->{storePath} = $path;
else {
$path = $Nix::Config::storeDir . "/$path";
gone($c, "Path " . $path . " is no longer available.") unless $MACHINE_LOCAL_STORE->isValidPath($path);
$c->stash->{current_view} = 'NixNAR';
$c->stash->{storePath} = $path;
}
}
sub change_password : Path('change-password') : Args(0) {
sub nix_cache_info :Path('nix-cache-info') :Args(0) {
my ($self, $c) = @_;
requireLogin($c) if !$c->user_exists;
if (!isLocalStore) {
notFound($c, "There is no binary cache here.");
}
$c->stash->{template} = 'change-password.tt';
else {
$c->response->content_type('text/plain');
$c->stash->{plain}->{data} =
"StoreDir: $Nix::Config::storeDir\n" .
"WantMassQuery: 0\n" .
# Give Hydra binary caches a very low priority (lower than the
# static binary cache http://nixos.org/binary-cache).
"Priority: 100\n";
setCacheHeaders($c, 24 * 60 * 60);
$c->forward('Hydra::View::Plain');
}
}
sub change_password_submit : Path('change-password/submit') : Args(0) {
my ($self, $c) = @_;
requireLogin($c) if !$c->user_exists;
sub realisations :Path('realisations') :Args(StrMatch[REALISATIONS_REGEX]) {
my ($self, $c, $realisation) = @_;
my $password = $c->request->params->{"password"};
my $password_check = $c->request->params->{"password_check"};
print STDERR "$password \n";
print STDERR "$password_check \n";
error($c, "Passwords did not match, go back and try again!") if $password ne $password_check;
if (!isLocalStore) {
notFound($c, "There is no binary cache here.");
}
my $hashed = sha1_hex($password);
$c->user->update({ password => $hashed}) ;
else {
my ($rawDrvOutput) = $realisation =~ REALISATIONS_REGEX;
my $rawRealisation = $MACHINE_LOCAL_STORE->queryRawRealisation($rawDrvOutput);
$c->res->redirect("/");
if (!$rawRealisation) {
$c->response->status(404);
$c->response->content_type('text/plain');
$c->stash->{plain}->{data} = "does not exist\n";
$c->forward('Hydra::View::Plain');
setCacheHeaders($c, 60 * 60);
return;
}
$c->response->content_type('text/plain');
$c->stash->{plain}->{data} = $rawRealisation;
$c->forward('Hydra::View::Plain');
}
}
sub narinfo :Path :Args(StrMatch[NARINFO_REGEX]) {
my ($self, $c, $narinfo) = @_;
if (!isLocalStore) {
notFound($c, "There is no binary cache here.");
}
else {
my ($hash) = $narinfo =~ NARINFO_REGEX;
die("Hash length was not 32") if length($hash) != 32;
my $path = $MACHINE_LOCAL_STORE->queryPathFromHashPart($hash);
if (!$path) {
$c->response->status(404);
$c->response->content_type('text/plain');
$c->stash->{plain}->{data} = "does not exist\n";
$c->forward('Hydra::View::Plain');
setCacheHeaders($c, 60 * 60);
return;
}
$c->stash->{storePath} = $path;
$c->forward('Hydra::View::NARInfo');
}
}
sub logo :Local {
my ($self, $c) = @_;
my $path = $ENV{"HYDRA_LOGO"} or die("Logo not set!");
my $path = $c->config->{hydra_logo} // die("Logo not set!");
$c->serve_static_file($path);
}
sub evals :Local Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'evals.tt';
my $page = int($c->req->param('page') || "1") || 1;
my $resultsPerPage = 20;
my $evals = $c->model('DB::JobsetEvals');
$c->stash->{page} = $page;
$c->stash->{resultsPerPage} = $resultsPerPage;
$c->stash->{total} = $evals->search({hasnewbuilds => 1})->count;
$c->stash->{evals} = getEvals($c, $evals, ($page - 1) * $resultsPerPage, $resultsPerPage);
$self->status_ok($c, entity => $c->stash->{evals});
}
sub steps :Local Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'steps.tt';
my $page = int($c->req->param('page') || "1") || 1;
my $resultsPerPage = 20;
$c->stash->{page} = $page;
$c->stash->{resultsPerPage} = $resultsPerPage;
$c->stash->{steps} = [ $c->model('DB::BuildSteps')->search(
{ starttime => { '!=', undef },
stoptime => { '!=', undef }
},
{ order_by => [ "stoptime desc" ],
rows => $resultsPerPage,
offset => ($page - 1) * $resultsPerPage
}) ];
$c->stash->{total} = approxTableSize($c, "IndexBuildStepsOnStopTime");
}
sub search :Local Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'search.tt';
my $query = trim $c->request->params->{"query"};
error($c, "Query is empty.") if $query eq "";
error($c, "Invalid character in query.")
unless $query =~ /^[a-zA-Z0-9_\-\/.]+$/;
my $limit = int(trim ($c->request->params->{"limit"} || "10"));
$c->stash->{limit} = min(50, max(1, $limit));
$c->model('DB')->schema->txn_do(sub {
$c->model('DB')->schema->storage->dbh->do("SET LOCAL statement_timeout = 20000");
$c->stash->{projects} = [ $c->model('DB::Projects')->search(
{ -and =>
[ { -or => [ name => { ilike => "%$query%" }, displayName => { ilike => "%$query%" }, description => { ilike => "%$query%" } ] }
, { hidden => 0 }
]
},
{ order_by => ["name"] } ) ];
$c->stash->{jobsets} = [ $c->model('DB::Jobsets')->search(
{ -and =>
[ { -or => [ "me.name" => { ilike => "%$query%" }, "me.description" => { ilike => "%$query%" } ] }
, { "project.hidden" => 0, "me.hidden" => 0 }
]
},
{ order_by => ["project", "name"], join => ["project"] } ) ];
$c->stash->{jobs} = [ $c->model('DB::Builds')->search(
{ "job" => { ilike => "%$query%" }
, "project.hidden" => 0
, "jobset.hidden" => 0
, iscurrent => 1
},
{
order_by => ["jobset.project", "jobset.name", "job"],
join => { "jobset" => "project" },
rows => $c->stash->{limit} + 1
} )
];
# Perform build search in separate queries to prevent seq scan on buildoutputs table.
$c->stash->{builds} = [ $c->model('DB::Builds')->search(
{ "buildoutputs.path" => { ilike => "%$query%" } },
{ order_by => ["id desc"], join => ["buildoutputs"]
, rows => $c->stash->{limit}
} ) ];
$c->stash->{buildsdrv} = [ $c->model('DB::Builds')->search(
{ "drvpath" => { ilike => "%$query%" } },
{ order_by => ["id desc"]
, rows => $c->stash->{limit}
} ) ];
$c->stash->{resource} = { projects => $c->stash->{projects},
jobsets => $c->stash->{jobsets},
builds => $c->stash->{builds},
buildsdrv => $c->stash->{buildsdrv} };
});
}
sub serveLogFile {
my ($c, $logPath, $tail) = @_;
$c->stash->{logPath} = $logPath;
$c->stash->{tail} = $tail;
$c->forward('Hydra::View::NixLog');
}
sub log :Local :Args(1) {
my ($self, $c, $drvPath) = @_;
$drvPath = "/nix/store/$drvPath";
my $tail = $c->request->params->{"tail"};
die if defined $tail && $tail !~ /^[0-9]+$/;
my $logFile = findLog($c, $drvPath);
if (defined $logFile) {
serveLogFile($c, $logFile, $tail);
return;
}
my $logPrefix = $c->config->{log_prefix};
if (defined $logPrefix) {
$c->res->redirect($logPrefix . "log/" . WWW::Form::UrlEncoded::PP::url_encode(basename($drvPath)));
} else {
notFound($c, "The build log of $drvPath is not available.");
}
}
sub runcommandlog :Local :Args(1) {
my ($self, $c, $uuid) = @_;
my $tail = $c->request->params->{"tail"};
die if defined $tail && $tail !~ /^[0-9]+$/;
my $runlog = $c->model('DB')->resultset('RunCommandLogs')->find({ uuid => $uuid })
or notFound($c, "The RunCommand log is not available.");
my $logFile = constructRunCommandLogPath($runlog);
if (-f $logFile) {
serveLogFile($c, $logFile, $tail);
return;
} else {
notFound($c, "The RunCommand log is not available.");
}
}
1;

Some files were not shown because too many files have changed in this diff Show More