# CircleCI build environment looks like it has a zillion and a half cores. # Don't let Nix autodetect this high core count because it blows up memory # usage and fails the test run. Pick a number of cores that suits the build # environment we're paying for (the free one!). DEPENDENCY_CORES=3 # Once dependencies are built, we can allow some more concurrency for our own # test suite. UNITTEST_CORES=8 # Run a command, enabling cache writes to cachix if possible. The command is # accepted as a variable number of positional arguments (like argv). function cache_if_able() { # Dump some info about our build environment. describe_build if is_cache_writeable; then # If the cache is available we'll use it. This lets fork owners set # up their own caching if they want. echo "Cachix credentials present; will attempt to write to cache." # The `cachix watch-exec ...` does our cache population. When it sees # something added to the store (I guess) it pushes it to the named # cache. cachix watch-exec "${CACHIX_NAME}" -- "$@" else if is_cache_required; then echo "Required credentials (CACHIX_AUTH_TOKEN) are missing." return 1 else echo "Cachix credentials missing; will not attempt cache writes." "$@" fi fi } function is_cache_writeable() { # We can only *push* to the cache if we have a CACHIX_AUTH_TOKEN. in-repo # jobs will get this from CircleCI configuration but jobs from forks may # not. [ -v CACHIX_AUTH_TOKEN ] } function is_cache_required() { # If we're building in tahoe-lafs/tahoe-lafs then we must use the cache. # If we're building anything from a fork then we're allowed to not have # the credentials. is_upstream } # Return success if the origin of this build is the tahoe-lafs/tahoe-lafs # repository itself (and so we expect to have cache credentials available), # failure otherwise. # # See circleci.txt for notes about how this determination is made. function is_upstream() { # CIRCLE_PROJECT_USERNAME is set to the org the build is happening for. # If a PR targets a fork of the repo then this is set to something other # than "tahoe-lafs". [ "$CIRCLE_PROJECT_USERNAME" == "tahoe-lafs" ] && # CIRCLE_BRANCH is set to the real branch name for in-repo PRs and # "pull/NNNN" for pull requests from forks. # # CIRCLE_PULL_REQUESTS is set to a comma-separated list of the full # URLs of the PR pages which share an underlying branch, with one of # them ended with that same "pull/NNNN" for PRs from forks. ! any_element_endswith "/$CIRCLE_BRANCH" "," "$CIRCLE_PULL_REQUESTS" } # Return success if splitting $3 on $2 results in an array with any element # that ends with $1, failure otherwise. function any_element_endswith() { suffix=$1 shift sep=$1 shift haystack=$1 shift IFS="${sep}" read -r -a elements <<< "$haystack" for elem in "${elements[@]}"; do if endswith "$suffix" "$elem"; then return 0 fi done return 1 } # Return success if $2 ends with $1, failure otherwise. function endswith() { suffix=$1 shift haystack=$1 shift case "$haystack" in *${suffix}) return 0 ;; *) return 1 ;; esac } function describe_build() { echo "Building PR for user/org: ${CIRCLE_PROJECT_USERNAME}" echo "Building branch: ${CIRCLE_BRANCH}" if is_upstream; then echo "Upstream build." else echo "Non-upstream build." fi if is_cache_required; then echo "Cache is required." else echo "Cache not required." fi if is_cache_writeable; then echo "Cache is writeable." else echo "Cache not writeable." fi } # Inspect the flake input metadata for an input of a given name and return the # revision at which that input is pinned. If the input does not exist then # return garbage (probably "null"). read_input_revision() { input_name=$1 shift nix flake metadata --json | jp --unquoted 'locks.nodes."'"$input_name"'".locked.rev' } # Return a flake reference that refers to a certain revision of nixpkgs. The # certain revision is the revision to which the specified input is pinned. nixpkgs_flake_reference() { input_name=$1 shift echo "github:NixOS/nixpkgs?rev=$(read_input_revision $input_name)" }