diff --git a/lib/flakeModule.nix b/lib/flakeModule.nix index 8bafe41..3ba1e7e 100644 --- a/lib/flakeModule.nix +++ b/lib/flakeModule.nix @@ -244,19 +244,105 @@ ); in { name = "gitlab-ci:pipeline:${pipeline_name}:job:${key}"; - value = pkgs.writeShellScriptBin "gitlab-ci-job:${key}" '' - # set up deps and environment variables containing store paths - . ${jobsMappedForDeps."gitlab-ci:pipeline:${pipeline_name}:job-deps:${key}"} - # normal environment variables - ${variableExports} - # run before_script, script and after_script - echo -e "\e[32mRunning before_script...\e[0m" - ${lib.concatLines (job.before_script or [])} - echo -e "\e[32mRunning script...\e[0m" - ${lib.concatLines job.script} - echo -e "\e[32mRunning after_script...\e[0m" - ${lib.concatLines (job.after_script or [])} - ''; + value = let + actualJobScript = pkgs.writeShellScript "gitlab-ci-job:${key}:raw" '' + # set up deps and environment variables containing store paths + . ${jobsMappedForDeps."gitlab-ci:pipeline:${pipeline_name}:job-deps:${key}"} + # normal environment variables + ${variableExports} + # run before_script, script and after_script + echo -e "\e[32mRunning before_script...\e[0m" + set -x + ${lib.concatLines (job.before_script or [])} + { set +x; } 2>/dev/null + echo -e "\e[32mRunning script...\e[0m" + set -x + ${lib.concatLines job.script} + { set +x; } 2>/dev/null + echo -e "\e[32mRunning after_script...\e[0m" + set -x + ${lib.concatLines (job.after_script or [])} + { set +x; } 2>/dev/null + ''; + sandboxHelper = pkgs.writeShellScriptBin "gitlab-ci-job-sandbox-helper" '' + echo -e "\e[32mSetting up...\e[0m" + + actualJobScript=$1 + shift + + INCLUDE_DIRTY=false + NO_SANDBOX=false + KEEP_TMP=false + KEEP_ENV="" + # parse flags + while [[ $# -gt 0 ]]; do + case "$1" in + --include-dirty) + INCLUDE_DIRTY=true + shift + ;; + --no-sandbox) + NO_SANDBOX=true + shift + ;; + --keep-tmp) + KEEP_TMP=true + shift + ;; + --keep-env) + KEEP_ENV="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" >&2 + exit 1 + ;; + esac + done + + if [ "$NO_SANDBOX" = false ]; then + echo "Running with simple sandboxing" + if [ "$KEEP_TMP" = false ]; then + trap "rm -rf '$TMPDIR'" EXIT + else + echo "Temp dir will be preserved at: $TMPDIR" + fi + + # check if dirty + DIRTY_PATCH="" + if ! git diff --quiet && ! git diff --staged --quiet; then + echo "Warning: working tree is dirty." + DIRTY_PATCH=$(mktemp -t "nix-gitlab-ci.XXX.patch") + git diff --staged > "$DIRTY_PATCH" + trap "rm -f '$DIRTY_PATCH'" EXIT + fi + TMPDIR=$(mktemp -dt "nix-gitlab-ci.XXX") + git clone . $TMPDIR + pushd $TMPDIR >/dev/null + if [[ ! -z "$DIRTY_PATCH" && "$INCLUDE_DIRTY" = true ]]; then + echo "Copying dirty changes..." + git apply "$DIRTY_PATCH" 2>/dev/null || echo "Failed to copy dirty changes" + fi + + echo "Running job in $TMPDIR" + env -i $( + if [[ -n "$KEEP_ENV" ]]; then + IFS=',' read -ra VARS <<< "$KEEP_ENV" + for var in "''${VARS[@]}"; do + printf '%s=%q ' "$var" "''${!var}" + done + fi + ) bash $actualJobScript + popd >/dev/null + else + exec $actualJobScript + fi + ''; + in + # this way the sandbox helper just needs to be built once + pkgs.writeShellScriptBin "gitlab-ci-job:${key}" '' + exec ${lib.getExe sandboxHelper} ${actualJobScript} $@ + ''; }) jobs; # build the deps specific for this job before anything, this way the deps should be fetched from the cache