1 | # CircleCI build environment looks like it has a zillion and a half cores. |
---|
2 | # Don't let Nix autodetect this high core count because it blows up memory |
---|
3 | # usage and fails the test run. Pick a number of cores that suits the build |
---|
4 | # environment we're paying for (the free one!). |
---|
5 | DEPENDENCY_CORES=3 |
---|
6 | |
---|
7 | # Once dependencies are built, we can allow some more concurrency for our own |
---|
8 | # test suite. |
---|
9 | UNITTEST_CORES=8 |
---|
10 | |
---|
11 | # Run a command, enabling cache writes to cachix if possible. The command is |
---|
12 | # accepted as a variable number of positional arguments (like argv). |
---|
13 | function cache_if_able() { |
---|
14 | # Dump some info about our build environment. |
---|
15 | describe_build |
---|
16 | |
---|
17 | if is_cache_writeable; then |
---|
18 | # If the cache is available we'll use it. This lets fork owners set |
---|
19 | # up their own caching if they want. |
---|
20 | echo "Cachix credentials present; will attempt to write to cache." |
---|
21 | |
---|
22 | # The `cachix watch-exec ...` does our cache population. When it sees |
---|
23 | # something added to the store (I guess) it pushes it to the named |
---|
24 | # cache. |
---|
25 | cachix watch-exec "${CACHIX_NAME}" -- "$@" |
---|
26 | else |
---|
27 | if is_cache_required; then |
---|
28 | echo "Required credentials (CACHIX_AUTH_TOKEN) are missing." |
---|
29 | return 1 |
---|
30 | else |
---|
31 | echo "Cachix credentials missing; will not attempt cache writes." |
---|
32 | "$@" |
---|
33 | fi |
---|
34 | fi |
---|
35 | } |
---|
36 | |
---|
37 | function is_cache_writeable() { |
---|
38 | # We can only *push* to the cache if we have a CACHIX_AUTH_TOKEN. in-repo |
---|
39 | # jobs will get this from CircleCI configuration but jobs from forks may |
---|
40 | # not. |
---|
41 | [ -v CACHIX_AUTH_TOKEN ] |
---|
42 | } |
---|
43 | |
---|
44 | function is_cache_required() { |
---|
45 | # If we're building in tahoe-lafs/tahoe-lafs then we must use the cache. |
---|
46 | # If we're building anything from a fork then we're allowed to not have |
---|
47 | # the credentials. |
---|
48 | is_upstream |
---|
49 | } |
---|
50 | |
---|
51 | # Return success if the origin of this build is the tahoe-lafs/tahoe-lafs |
---|
52 | # repository itself (and so we expect to have cache credentials available), |
---|
53 | # failure otherwise. |
---|
54 | # |
---|
55 | # See circleci.txt for notes about how this determination is made. |
---|
56 | function is_upstream() { |
---|
57 | # CIRCLE_PROJECT_USERNAME is set to the org the build is happening for. |
---|
58 | # If a PR targets a fork of the repo then this is set to something other |
---|
59 | # than "tahoe-lafs". |
---|
60 | [ "$CIRCLE_PROJECT_USERNAME" == "tahoe-lafs" ] && |
---|
61 | |
---|
62 | # CIRCLE_BRANCH is set to the real branch name for in-repo PRs and |
---|
63 | # "pull/NNNN" for pull requests from forks. |
---|
64 | # |
---|
65 | # CIRCLE_PULL_REQUESTS is set to a comma-separated list of the full |
---|
66 | # URLs of the PR pages which share an underlying branch, with one of |
---|
67 | # them ended with that same "pull/NNNN" for PRs from forks. |
---|
68 | ! any_element_endswith "/$CIRCLE_BRANCH" "," "$CIRCLE_PULL_REQUESTS" |
---|
69 | } |
---|
70 | |
---|
71 | # Return success if splitting $3 on $2 results in an array with any element |
---|
72 | # that ends with $1, failure otherwise. |
---|
73 | function any_element_endswith() { |
---|
74 | suffix=$1 |
---|
75 | shift |
---|
76 | |
---|
77 | sep=$1 |
---|
78 | shift |
---|
79 | |
---|
80 | haystack=$1 |
---|
81 | shift |
---|
82 | |
---|
83 | IFS="${sep}" read -r -a elements <<< "$haystack" |
---|
84 | for elem in "${elements[@]}"; do |
---|
85 | if endswith "$suffix" "$elem"; then |
---|
86 | return 0 |
---|
87 | fi |
---|
88 | done |
---|
89 | return 1 |
---|
90 | } |
---|
91 | |
---|
92 | # Return success if $2 ends with $1, failure otherwise. |
---|
93 | function endswith() { |
---|
94 | suffix=$1 |
---|
95 | shift |
---|
96 | |
---|
97 | haystack=$1 |
---|
98 | shift |
---|
99 | |
---|
100 | case "$haystack" in |
---|
101 | *${suffix}) |
---|
102 | return 0 |
---|
103 | ;; |
---|
104 | |
---|
105 | *) |
---|
106 | return 1 |
---|
107 | ;; |
---|
108 | esac |
---|
109 | } |
---|
110 | |
---|
111 | function describe_build() { |
---|
112 | echo "Building PR for user/org: ${CIRCLE_PROJECT_USERNAME}" |
---|
113 | echo "Building branch: ${CIRCLE_BRANCH}" |
---|
114 | if is_upstream; then |
---|
115 | echo "Upstream build." |
---|
116 | else |
---|
117 | echo "Non-upstream build." |
---|
118 | fi |
---|
119 | if is_cache_required; then |
---|
120 | echo "Cache is required." |
---|
121 | else |
---|
122 | echo "Cache not required." |
---|
123 | fi |
---|
124 | if is_cache_writeable; then |
---|
125 | echo "Cache is writeable." |
---|
126 | else |
---|
127 | echo "Cache not writeable." |
---|
128 | fi |
---|
129 | } |
---|
130 | |
---|
131 | # Inspect the flake input metadata for an input of a given name and return the |
---|
132 | # revision at which that input is pinned. If the input does not exist then |
---|
133 | # return garbage (probably "null"). |
---|
134 | read_input_revision() { |
---|
135 | input_name=$1 |
---|
136 | shift |
---|
137 | |
---|
138 | nix flake metadata --json | jp --unquoted 'locks.nodes."'"$input_name"'".locked.rev' |
---|
139 | } |
---|
140 | |
---|
141 | # Return a flake reference that refers to a certain revision of nixpkgs. The |
---|
142 | # certain revision is the revision to which the specified input is pinned. |
---|
143 | nixpkgs_flake_reference() { |
---|
144 | input_name=$1 |
---|
145 | shift |
---|
146 | |
---|
147 | echo "github:NixOS/nixpkgs?rev=$(read_input_revision $input_name)" |
---|
148 | } |
---|