channel updates: make sequential
Create a sequential ordering with systemd After-relationships between each channel's update job. Then, remove individual timers and create one timer for all the jobs. Fixes #79
Graham Christensen committed
Mar 15, 2019 at 22:57 UTC
5c3362dd5757ba1e7c0bf553b1d42de8420a2067
2 files changed
+124
-39
lib/service-order.nix
new
+61
@@ -0,0 +1,61 @@
1
+# Ordering Services
2
+#
3
+# Given a set of services, make them run one at a time in a specific
4
+# order, on a timer.
5
+{ lib }:
6
+{
7
+ # Given a list of systemd service, give each one an After
8
+ # attribute, so they start in a specific order. The returned
9
+ # list can be converted in to a systemd.services attrset with
10
+ # `lib.listToAttrs`.
11
+ #
12
+ # Example:
13
+ #
14
+ # mkOrderedChain [
15
+ # { name = "foo"; value = { script = "true"; }; }
16
+ # { name = "bar"; value = { script = "true"; }; }
17
+ # ]
18
+ #
19
+ # => [
20
+ # {
21
+ # name = "foo";
22
+ # value = {
23
+ # script = "true";
24
+ # unitConfig = { After = []; };
25
+ # };
26
+ # }
27
+ # {
28
+ # name = "bar";
29
+ # value = {
30
+ # script = "true";
31
+ # unitConfig = { After = [ "bar" ]; };
32
+ # };
33
+ # }
34
+ #
35
+ mkOrderedChain = jobs: let
36
+ unitConfigFrom = job: job.unitConfig or {};
37
+ afterFrom = job: (unitConfigFrom job).After or [];
38
+ previousFrom = collector:
39
+ if collector ? previous
40
+ then [collector.previous]
41
+ else [];
42
+
43
+ ordered = builtins.foldl'
44
+ (collector: item: {
45
+ services = collector.services
46
+ ++ [{
47
+ inherit (item) name;
48
+ value = item.value // {
49
+ unitConfig = (unitConfigFrom item.value) //
50
+ {
51
+ After = (afterFrom item.value) ++
52
+ (previousFrom collector);
53
+ };
54
+ };
55
+ }];
56
+ previous = "${item.name}.service";
57
+ })
58
+ { services = []; }
59
+ jobs;
60
+ in ordered.services;
61
+}
modules/hydra-mirror.nix
+63
-39
@@ -1,54 +1,78 @@
1
-{ config, lib, pkgs, ... }:
2
-
3
-with lib;
1
+{ lib, pkgs, ... }:
2
3
let
4
+ channels = {
5
+ # Channel name https://hydra.nixos.org/job/<value>/latest-finished
6
+ "nixos-unstable" = "nixos/trunk-combined/tested";
7
+ "nixos-unstable-small" = "nixos/unstable-small/tested";
8
+ "nixpkgs-unstable" = "nixpkgs/trunk/unstable";
9
+
10
+ "nixos-19.03" = "nixos/release-19.03/tested";
11
+ "nixos-19.03-small" = "nixos/release-19.03-small/tested";
12
+ "nixpkgs-19.03-darwin" = "nixpkgs/nixpkgs-19.03-darwin/darwin-tested";
13
+
14
+ "nixos-18.09" = "nixos/release-18.09/tested";
15
+ "nixos-18.09-small" = "nixos/release-18.09-small/tested";
16
+ "nixpkgs-18.09-darwin" = "nixpkgs/nixpkgs-18.09-darwin/darwin-tested";
17
+
18
+ "nixos-18.03" = "nixos/release-18.03/tested";
19
+ "nixos-18.03-small" = "nixos/release-18.03-small/tested";
20
+ "nixpkgs-18.03-darwin" = "nixpkgs/nixpkgs-18.03-darwin/darwin-tested";
21
+ };
22
23
channelScripts = import <nixos-channel-scripts> { inherit pkgs; };
24
+ orderLib = import ../lib/service-order.nix { inherit lib; };
25
26
makeUpdateChannel = channelName: mainJob:
10
- { timers."update-${channelName}" =
11
- { wantedBy = [ "timers.target" ];
12
- timerConfig.OnUnitInactiveSec = 600;
13
- timerConfig.OnBootSec = 900;
14
- timerConfig.AccuracySec = 300;
15
- };
16
-
17
- services."update-${channelName}" =
18
- { description = "Update Channel ${channelName}";
19
- after = [ "networking.target" ];
20
- path = [ channelScripts ];
21
- script =
22
- ''
23
- # FIXME: use IAM role.
24
- export AWS_ACCESS_KEY_ID=$(sed 's/aws_access_key_id=\(.*\)/\1/ ; t; d' ~/.aws/credentials)
25
- export AWS_SECRET_ACCESS_KEY=$(sed 's/aws_secret_access_key=\(.*\)/\1/ ; t; d' ~/.aws/credentials)
26
- exec mirror-nixos-branch ${channelName} https://hydra.nixos.org/job/${mainJob}/latest-finished
27
- ''; # */
28
- serviceConfig.User = "hydra-mirror";
29
- environment.TMPDIR = "/scratch/hydra-mirror";
30
- environment.GC_INITIAL_HEAP_SIZE = "4g";
27
+ {
28
+ name = "update-${channelName}";
29
+ value = {
30
+ description = "Update Channel ${channelName}";
31
+ path = [ channelScripts ];
32
+ script =
33
+ ''
34
+ # FIXME: use IAM role.
35
+ export AWS_ACCESS_KEY_ID=$(sed 's/aws_access_key_id=\(.*\)/\1/ ; t; d' ~/.aws/credentials)
36
+ export AWS_SECRET_ACCESS_KEY=$(sed 's/aws_secret_access_key=\(.*\)/\1/ ; t; d' ~/.aws/credentials)
37
+ exec mirror-nixos-branch ${channelName} https://hydra.nixos.org/job/${mainJob}/latest-finished
38
+ '';
39
+ serviceConfig.User = "hydra-mirror";
40
+ unitConfig.After = [ "networking.target" ];
41
+ environment.TMPDIR = "/scratch/hydra-mirror";
42
+ environment.GC_INITIAL_HEAP_SIZE = "4g";
43
};
44
};
45
46
+ updateJobs = orderLib.mkOrderedChain
47
+ (lib.mapAttrsToList makeUpdateChannel channels);
48
+
49
in
50
51
{
52
imports = [ ./hydra-mirror-user.nix ];
53
39
- systemd =
40
- fold recursiveUpdate {} [
41
- (makeUpdateChannel "nixos-19.03" "nixos/release-19.03/tested")
42
- (makeUpdateChannel "nixos-19.03-small" "nixos/release-19.03-small/tested")
43
- (makeUpdateChannel "nixos-18.09" "nixos/release-18.09/tested")
44
- (makeUpdateChannel "nixos-18.09-small" "nixos/release-18.09-small/tested")
45
- (makeUpdateChannel "nixos-18.03" "nixos/release-18.03/tested")
46
- (makeUpdateChannel "nixos-18.03-small" "nixos/release-18.03-small/tested")
47
- (makeUpdateChannel "nixos-unstable" "nixos/trunk-combined/tested")
48
- (makeUpdateChannel "nixos-unstable-small" "nixos/unstable-small/tested")
49
- (makeUpdateChannel "nixpkgs-19.03-darwin" "nixpkgs/nixpkgs-19.03-darwin/darwin-tested")
50
- (makeUpdateChannel "nixpkgs-18.09-darwin" "nixpkgs/nixpkgs-18.09-darwin/darwin-tested")
51
- (makeUpdateChannel "nixpkgs-18.03-darwin" "nixpkgs/nixpkgs-18.03-darwin/darwin-tested")
52
- (makeUpdateChannel "nixpkgs-unstable" "nixpkgs/trunk/unstable")
53
- ];
54
+ systemd.services = (lib.listToAttrs updateJobs) // {
55
+ "update-all-channels" = {
56
+ description = "Start all channel updates.";
57
+ unitConfig = {
58
+ After = builtins.map
59
+ (service: "${service.name}.service")
60
+ updateJobs;
61
+ Wants = builtins.map
62
+ (service: "${service.name}.service")
63
+ updateJobs;
64
+ };
65
+ script = "true";
66
+ };
67
+ };
68
+
69
+ systemd.timers."update-all-channels" = {
70
+ description = "Start all channel updates.";
71
+ wantedBy = [ "timers.target" ];
72
+ timerConfig = {
73
+ OnUnitInactiveSec = 600;
74
+ OnBootSec = 900;
75
+ AccuracySec = 300;
76
+ };
77
+ };
78
}