#!/usr/bin/env bash job_artifacts() ( set -euo pipefail nix-build-and-cache packages ) job_ci() ( set -euo pipefail nix-build-and-cache ci direnv exec . engage ) job_pages() ( set -euo pipefail nix build .#website-root cp --recursive --dereference result public chmod u+w -R public ) bail() ( set -euo pipefail git show --shortstat echo echo "Failure caused by the above commit" exit 1 ) mark_commit_passed() ( set -euo pipefail mkdir -p ".gitlab-ci.d/passed/$1" touch ".gitlab-ci.d/passed/$1/$(git rev-parse HEAD)" ) commit_passed() ( set -euo pipefail [[ -f ".gitlab-ci.d/passed/$1/$(git rev-parse HEAD)" ]] ) run() ( set -euo pipefail if [[ -z "${1+x}" ]]; then echo "You must supply a job to run. Available jobs:" declare -F | rg \ --only-matching \ --color never \ --replace '* $1' \ '^declare -f job_(.*)$' exit 1 fi job="$1" cd "$(git rev-parse --show-toplevel)" if [[ -z "${CI_MERGE_REQUEST_DIFF_BASE_SHA+x}" ]]; then echo "Running against latest commit only..." job_"$job" || bail else echo "Running against all commits since this branch's base..." readarray -t commits < \ <(git rev-list --reverse "$CI_MERGE_REQUEST_DIFF_BASE_SHA..HEAD") for commit in "${commits[@]}"; do git checkout "$commit" if commit_passed "$job"; then echo "Skipping commit because it already passed: $commit" continue fi job_"$job" || bail mark_commit_passed "$job" done fi ) run "$@"