mirror of
https://gitlab.com/TECHNOFAB/nix-gitlab-ci.git
synced 2026-02-02 03:15:09 +01:00
chore: split everything up into their own files & add a bunch of tests
This commit is contained in:
parent
b309fb59db
commit
2f197d2c50
20 changed files with 704 additions and 310 deletions
8
lib/default.nix
Normal file
8
lib/default.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
args: {
|
||||
helpers = import ./helpers.nix args;
|
||||
jobDeps = import ./jobDeps.nix args;
|
||||
jobRun = import ./jobRun.nix args;
|
||||
jobPatch = import ./jobPatch.nix args;
|
||||
pipeline = import ./pipeline.nix args;
|
||||
utils = import ./utils.nix args;
|
||||
}
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
{
|
||||
description = "Nix-CI lib";
|
||||
description = "Nix-GitLab-CI lib";
|
||||
|
||||
outputs = {...} @ inputs:
|
||||
{
|
||||
flakeModule = import ./flakeModule.nix;
|
||||
}
|
||||
// (import ./utils.nix);
|
||||
outputs = {...}: {
|
||||
flakeModule = import ./flakeModule.nix;
|
||||
lib = import ./default.nix;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,22 +9,12 @@
|
|||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) isAttrs filterAttrs mapAttrs types mkOption toList;
|
||||
cilib = import ./. {inherit lib pkgs;};
|
||||
inherit (cilib.pipeline) mkPipeline;
|
||||
inherit (lib) types mkOption;
|
||||
|
||||
cfg = config.ci.config;
|
||||
|
||||
stdenvMinimal = pkgs.stdenvNoCC.override {
|
||||
cc = null;
|
||||
preHook = "";
|
||||
allowedRequisites = null;
|
||||
initialPath = [pkgs.coreutils pkgs.findutils];
|
||||
extraNativeBuildInputs = [];
|
||||
};
|
||||
|
||||
filterAttrsRec = pred: v:
|
||||
if isAttrs v
|
||||
then filterAttrs pred (mapAttrs (path: filterAttrsRec pred) v)
|
||||
else v;
|
||||
|
||||
subType = options: types.submodule {inherit options;};
|
||||
mkNullOption = type:
|
||||
mkOption {
|
||||
|
|
@ -168,228 +158,15 @@
|
|||
};
|
||||
};
|
||||
|
||||
config.legacyPackages = let
|
||||
# NOTE: json is also valid yaml and this removes dependency on jq
|
||||
# and/or remarshal (used in pkgs.formats.json and pkgs.formats.yaml
|
||||
# respectively)
|
||||
toYaml = name: value: builtins.toFile name (builtins.toJSON value);
|
||||
mapAttrs = cb: set: builtins.listToAttrs (builtins.map (key: cb key (builtins.getAttr key set)) (builtins.attrNames set));
|
||||
prepend = key: arr: job:
|
||||
job
|
||||
// lib.optionalAttrs job.nix.enable {
|
||||
${key} =
|
||||
arr
|
||||
++ (job.${key} or []);
|
||||
};
|
||||
append = key: arr: job:
|
||||
job
|
||||
// lib.optionalAttrs job.nix.enable {
|
||||
${key} = (job.${key} or []) ++ arr;
|
||||
};
|
||||
prependToBeforeScript = prepend "before_script";
|
||||
appendToAfterScript = append "after_script";
|
||||
|
||||
# filter job's variables to either only those containing store paths
|
||||
# or those that do not
|
||||
filterJobVariables = nix: job:
|
||||
lib.concatMapAttrs (
|
||||
name: value:
|
||||
lib.optionalAttrs ((lib.hasInfix "/nix/store/" value) == nix) {
|
||||
${name} = value;
|
||||
}
|
||||
)
|
||||
(job.variables or {});
|
||||
in
|
||||
lib.fold (pipeline: acc: acc // pipeline) {} (map (
|
||||
pipeline_name: let
|
||||
pipeline = config.pipelines."${pipeline_name}";
|
||||
jobs = filterAttrsRec (n: v: v != null) pipeline.jobs;
|
||||
rest = filterAttrsRec (n: v: v != null) (builtins.removeAttrs pipeline ["jobs" "config"]);
|
||||
# this allows us to nix build this to get all the mentioned dependencies from the binary cache
|
||||
# pro: we don't have to download everything, just the deps for the current job
|
||||
# before, we just allowed pkgs inside the script string directly, but now with the ability to source this file
|
||||
# we can support different architectures between runners (eg. the arch of the initial runner does not matter)
|
||||
jobsMappedForDeps =
|
||||
mapAttrs (key: job: let
|
||||
variablesWithStorePaths = filterJobVariables true job;
|
||||
variableExports = lib.concatLines (
|
||||
lib.mapAttrsToList (name: value: "export ${name}=\"${value}\"") variablesWithStorePaths
|
||||
);
|
||||
in {
|
||||
name = "gitlab-ci:pipeline:${pipeline_name}:job-deps:${key}";
|
||||
value = stdenvMinimal.mkDerivation {
|
||||
name = "gitlab-ci-job-deps-${key}";
|
||||
dontUnpack = true;
|
||||
installPhase = let
|
||||
script = ''
|
||||
export PATH="${lib.makeBinPath job.nix.deps}:$PATH";
|
||||
# variables containing nix derivations:
|
||||
${variableExports}
|
||||
'';
|
||||
in
|
||||
# sh
|
||||
''
|
||||
echo '${script}' > $out
|
||||
chmod +x $out
|
||||
'';
|
||||
};
|
||||
})
|
||||
jobs;
|
||||
# allows the user to directly run the script
|
||||
jobsMappedForScript =
|
||||
mapAttrs (key: job: let
|
||||
variablesWithoutStorePaths = filterJobVariables false job;
|
||||
variableExports = lib.concatLines (
|
||||
lib.mapAttrsToList (name: value: "export ${name}=\"${value}\"") variablesWithoutStorePaths
|
||||
);
|
||||
in {
|
||||
name = "gitlab-ci:pipeline:${pipeline_name}:job:${key}";
|
||||
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
|
||||
jobsPatched =
|
||||
mapAttrs (key: job: {
|
||||
name = key;
|
||||
value = assert lib.assertMsg (builtins.elem job.stage (rest.stages or [])) "stage '${job.stage}' of job '${key}' does not exist";
|
||||
builtins.removeAttrs (
|
||||
(prependToBeforeScript [
|
||||
"source setup_nix_ci \"gitlab-ci:pipeline:${pipeline_name}:job-deps:${key}\""
|
||||
]
|
||||
(appendToAfterScript [
|
||||
"finalize_nix_ci"
|
||||
]
|
||||
job))
|
||||
// lib.optionalAttrs job.nix.enable {
|
||||
image = job.image;
|
||||
variables =
|
||||
(filterJobVariables false job)
|
||||
// lib.optionalAttrs job.nix.enable-runner-cache {
|
||||
NIX_CI_CACHE_STRATEGY = "runner";
|
||||
};
|
||||
cache =
|
||||
(
|
||||
let
|
||||
c = job.cache or [];
|
||||
in
|
||||
toList c
|
||||
)
|
||||
++ (lib.optional (job.nix.enable-runner-cache) {
|
||||
key = job.nix.runner-cache-key;
|
||||
paths = [".nix-cache/"];
|
||||
});
|
||||
}
|
||||
) ["nix"];
|
||||
})
|
||||
jobs;
|
||||
in
|
||||
# gitlab-ci:pipeline:<name>
|
||||
# gitlab-ci:pipeline:<name>:job:<name>
|
||||
# gitlab-ci:pipeline:<name>:job-deps:<name>
|
||||
{
|
||||
"gitlab-ci:pipeline:${pipeline_name}" = toYaml "gitlab-ci-${pipeline_name}.yml" (rest // jobsPatched);
|
||||
}
|
||||
// jobsMappedForDeps
|
||||
// jobsMappedForScript
|
||||
) (builtins.attrNames config.pipelines));
|
||||
config.legacyPackages = lib.fold (pipeline: acc: acc // pipeline) {} (
|
||||
map (
|
||||
pipeline_name:
|
||||
(mkPipeline {
|
||||
pipeline = config.pipelines."${pipeline_name}";
|
||||
name = pipeline_name;
|
||||
}).packages
|
||||
) (builtins.attrNames config.pipelines)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
49
lib/helpers.nix
Normal file
49
lib/helpers.nix
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
{lib, ...} @ args: let
|
||||
inherit (lib) isAttrs filterAttrs mapAttrs;
|
||||
in rec {
|
||||
prepend = key: arr: job:
|
||||
job
|
||||
// lib.optionalAttrs (job.nix.enable or false) {
|
||||
${key} =
|
||||
arr
|
||||
++ (job.${key} or []);
|
||||
};
|
||||
append = key: arr: job:
|
||||
job
|
||||
// lib.optionalAttrs (job.nix.enable or false) {
|
||||
${key} = (job.${key} or []) ++ arr;
|
||||
};
|
||||
prependToBeforeScript = prepend "before_script";
|
||||
appendToAfterScript = append "after_script";
|
||||
|
||||
# json is also valid yaml and this removes dependency on jq and/or remarshal
|
||||
# (used in pkgs.formats.json and pkgs.formats.yaml respectively)
|
||||
toYaml = name: value: builtins.toFile name (builtins.toJSON value);
|
||||
|
||||
customMapAttrs = cb: set: builtins.listToAttrs (builtins.map (key: cb key (builtins.getAttr key set)) (builtins.attrNames set));
|
||||
|
||||
filterAttrsRec = pred: v:
|
||||
if isAttrs v
|
||||
then filterAttrs pred (mapAttrs (path: filterAttrsRec pred) v)
|
||||
else v;
|
||||
|
||||
# filter job's variables to either only those containing store paths
|
||||
# or those that do not
|
||||
filterJobVariables = nix: job:
|
||||
lib.concatMapAttrs (
|
||||
name: value:
|
||||
lib.optionalAttrs ((lib.hasInfix "/nix/store/" value) == nix) {
|
||||
${name} = value;
|
||||
}
|
||||
)
|
||||
(job.variables or {});
|
||||
|
||||
# args.pkgs so "pkgs" does not need to be passed all the time
|
||||
stdenvMinimal = args.pkgs.stdenvNoCC.override {
|
||||
cc = null;
|
||||
preHook = "";
|
||||
allowedRequisites = null;
|
||||
initialPath = with args.pkgs; [coreutils findutils];
|
||||
extraNativeBuildInputs = [];
|
||||
};
|
||||
}
|
||||
36
lib/jobDeps.nix
Normal file
36
lib/jobDeps.nix
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cilib = import ./. {inherit lib pkgs;};
|
||||
inherit (cilib.helpers) filterJobVariables stdenvMinimal;
|
||||
in {
|
||||
mkJobDeps = {
|
||||
key,
|
||||
job,
|
||||
}: let
|
||||
variablesWithStorePaths = filterJobVariables true job;
|
||||
variableExports = lib.concatLines (
|
||||
lib.mapAttrsToList (name: value: "export ${name}=\"${value}\"") variablesWithStorePaths
|
||||
);
|
||||
script = ''
|
||||
export PATH="${lib.makeBinPath (job.nix.deps or [])}:$PATH";
|
||||
# variables containing nix derivations:
|
||||
${variableExports}
|
||||
'';
|
||||
in
|
||||
stdenvMinimal.mkDerivation {
|
||||
name = "gitlab-ci-job-deps-${key}";
|
||||
dontUnpack = true;
|
||||
installPhase =
|
||||
# sh
|
||||
''
|
||||
echo '${script}' > $out
|
||||
chmod +x $out
|
||||
'';
|
||||
passthru = {
|
||||
inherit script;
|
||||
};
|
||||
};
|
||||
}
|
||||
49
lib/jobPatch.nix
Normal file
49
lib/jobPatch.nix
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cilib = import ./. {inherit lib pkgs;};
|
||||
inherit (lib) toList;
|
||||
inherit (cilib.helpers) prependToBeforeScript appendToAfterScript filterJobVariables;
|
||||
in {
|
||||
mkJobPatched = {
|
||||
key,
|
||||
job,
|
||||
pipeline_name,
|
||||
}:
|
||||
builtins.removeAttrs (
|
||||
(prependToBeforeScript [
|
||||
"source setup_nix_ci \"gitlab-ci:pipeline:${pipeline_name}:job-deps:${key}\""
|
||||
]
|
||||
(appendToAfterScript [
|
||||
"finalize_nix_ci"
|
||||
]
|
||||
job))
|
||||
// lib.optionalAttrs job.nix.enable (
|
||||
(let
|
||||
variables =
|
||||
(filterJobVariables false job)
|
||||
// lib.optionalAttrs job.nix.enable-runner-cache {
|
||||
NIX_CI_CACHE_STRATEGY = "runner";
|
||||
};
|
||||
in
|
||||
# filter empty variables
|
||||
lib.optionalAttrs (variables != {}) {
|
||||
inherit variables;
|
||||
})
|
||||
// (let
|
||||
cache =
|
||||
(toList (job.cache or []))
|
||||
++ (lib.optional (job.nix.enable-runner-cache) {
|
||||
key = job.nix.runner-cache-key;
|
||||
paths = [".nix-cache/"];
|
||||
});
|
||||
in
|
||||
# filter empty cache
|
||||
lib.optionalAttrs (cache != []) {
|
||||
inherit cache;
|
||||
})
|
||||
)
|
||||
) ["nix"];
|
||||
}
|
||||
48
lib/jobRun.nix
Normal file
48
lib/jobRun.nix
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cilib = import ./. {inherit lib pkgs;};
|
||||
inherit (cilib.helpers) filterJobVariables;
|
||||
in {
|
||||
mkJobRun = {
|
||||
key,
|
||||
job,
|
||||
jobDeps,
|
||||
}: let
|
||||
variablesWithoutStorePaths = filterJobVariables false job;
|
||||
variableExports = lib.concatLines (
|
||||
lib.mapAttrsToList (name: value: "export ${name}=\"${value}\"") variablesWithoutStorePaths
|
||||
);
|
||||
sandboxHelper = pkgs.writeShellScriptBin "gitlab-ci-job-sandbox-helper" (builtins.readFile ./sandbox_helper.sh);
|
||||
actualJobScript = pkgs.writeShellScript "gitlab-ci-job:${key}:raw" ''
|
||||
# set up deps and environment variables containing store paths
|
||||
. ${jobDeps}
|
||||
# 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
|
||||
'';
|
||||
in
|
||||
# this way the sandbox helper just needs to be built once
|
||||
pkgs.writeShellScriptBin "gitlab-ci-job:${key}" ''
|
||||
exec ${lib.getExe sandboxHelper} ${actualJobScript} $@
|
||||
''
|
||||
// {
|
||||
passthru = {
|
||||
inherit jobDeps actualJobScript;
|
||||
};
|
||||
};
|
||||
}
|
||||
61
lib/pipeline.nix
Normal file
61
lib/pipeline.nix
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cilib = import ./. {inherit lib pkgs;};
|
||||
inherit (cilib.helpers) filterAttrsRec customMapAttrs toYaml;
|
||||
inherit (cilib.jobDeps) mkJobDeps;
|
||||
inherit (cilib.jobRun) mkJobRun;
|
||||
inherit (cilib.jobPatch) mkJobPatched;
|
||||
in {
|
||||
mkPipeline = {
|
||||
name,
|
||||
pipeline,
|
||||
}: let
|
||||
jobs = filterAttrsRec (n: v: v != null) pipeline.jobs;
|
||||
rest = filterAttrsRec (n: v: v != null) (builtins.removeAttrs pipeline ["jobs" "config"]);
|
||||
# this allows us to nix build this to get all the mentioned dependencies from the binary cache
|
||||
# pro: we don't have to download everything, just the deps for the current job
|
||||
# before, we just allowed pkgs inside the script string directly, but now with the ability to source this file
|
||||
# we can support different architectures between runners (eg. the arch of the initial runner does not matter)
|
||||
jobsMappedForDeps =
|
||||
customMapAttrs (key: job: {
|
||||
name = "gitlab-ci:pipeline:${name}:job-deps:${key}";
|
||||
value = mkJobDeps {inherit key job;};
|
||||
})
|
||||
jobs;
|
||||
# allows the user to directly run the script
|
||||
jobsMappedForScript =
|
||||
customMapAttrs (key: job: {
|
||||
name = "gitlab-ci:pipeline:${name}:job:${key}";
|
||||
value = mkJobRun {
|
||||
inherit key job;
|
||||
jobDeps = jobsMappedForDeps."gitlab-ci:pipeline:${name}:job-deps:${key}";
|
||||
};
|
||||
})
|
||||
jobs;
|
||||
# build the deps specific for this job before anything, this way the deps should be fetched from the cache
|
||||
jobsPatched =
|
||||
customMapAttrs (key: job: {
|
||||
name = key;
|
||||
value = assert lib.assertMsg (builtins.elem job.stage (rest.stages or [])) "stage '${job.stage}' of job '${key}' does not exist";
|
||||
mkJobPatched {
|
||||
inherit key job;
|
||||
pipeline_name = name;
|
||||
};
|
||||
})
|
||||
jobs;
|
||||
in {
|
||||
packages =
|
||||
# gitlab-ci:pipeline:<name>
|
||||
# gitlab-ci:pipeline:<name>:job:<name>
|
||||
# gitlab-ci:pipeline:<name>:job-deps:<name>
|
||||
{
|
||||
"gitlab-ci:pipeline:${name}" = toYaml "gitlab-ci-${name}.yml" (rest // jobsPatched);
|
||||
}
|
||||
// jobsMappedForDeps
|
||||
// jobsMappedForScript;
|
||||
finalConfig = rest // jobsPatched;
|
||||
};
|
||||
}
|
||||
73
lib/sandbox_helper.sh
Normal file
73
lib/sandbox_helper.sh
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
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
|
||||
|
||||
|
|
@ -1,46 +1,46 @@
|
|||
{
|
||||
mkUtils = {pkgs, ...}: {
|
||||
commitAndPushFiles = {
|
||||
message,
|
||||
files ? [],
|
||||
}: jobArgs:
|
||||
jobArgs
|
||||
// {
|
||||
before_script =
|
||||
(jobArgs.before_script or [])
|
||||
++ [
|
||||
''
|
||||
echo -e "\\e[0Ksection_start:`date +%s`:commit_setup[collapsed=true]\\r\\e[0KSetting up commitAndPushFiles"
|
||||
eval "$(ssh-agent -s)" >/dev/null;
|
||||
mkdir -p ~/.ssh; touch ~/.ssh/known_hosts;
|
||||
ssh-keyscan -t rsa $CI_SERVER_HOST >> ~/.ssh/known_hosts;
|
||||
echo "$GIT_SSH_PRIV_KEY" | tr -d '\r' | ssh-add - >/dev/null;
|
||||
git config --global user.email "$GIT_EMAIL" >/dev/null;
|
||||
git config --global user.name "$GIT_NAME" >/dev/null;
|
||||
export CI_PUSH_REPO=`echo $CI_REPOSITORY_URL | sed -e "s|.*@\(.*\)|git@\1|" -e "s|/|:|"`;
|
||||
git remote rm origin && git remote add origin ''${CI_PUSH_REPO}
|
||||
echo -e "\\e[0Ksection_end:`date +%s`:commit_setup\\r\\e[0K"
|
||||
''
|
||||
];
|
||||
script = let
|
||||
addScript =
|
||||
if builtins.length files == 0
|
||||
then ""
|
||||
else "git add ${builtins.concatStringsSep " " files}";
|
||||
in
|
||||
(jobArgs.script or [])
|
||||
++ [
|
||||
''
|
||||
echo -e "\\e[0Ksection_start:`date +%s`:commit[collapsed=true]\\r\\e[0KCommiting & pushing changes if necessary"
|
||||
${addScript}
|
||||
git diff --cached --exit-code >/dev/null &&
|
||||
echo "Nothing to commit" ||
|
||||
git commit -m "${message}" --no-verify;
|
||||
git push --tags origin ''${GIT_SOURCE_REF:-HEAD}:''${GIT_TARGET_REF:-$CI_COMMIT_REF_NAME} -o ci.skip
|
||||
echo -e "\\e[0Ksection_end:`date +%s`:commit\\r\\e[0K"
|
||||
''
|
||||
];
|
||||
nix.deps = (jobArgs.nix.deps or []) ++ [pkgs.openssh pkgs.gitMinimal pkgs.gnused];
|
||||
};
|
||||
};
|
||||
{pkgs, ...}: {
|
||||
commitAndPushFiles = {
|
||||
message,
|
||||
files ? [],
|
||||
}: jobArgs:
|
||||
jobArgs
|
||||
// {
|
||||
before_script =
|
||||
(jobArgs.before_script or [])
|
||||
++ [
|
||||
# sh
|
||||
''
|
||||
echo -e "\\e[0Ksection_start:`date +%s`:commit_setup[collapsed=true]\\r\\e[0KSetting up commitAndPushFiles"
|
||||
eval "$(ssh-agent -s)" >/dev/null;
|
||||
mkdir -p ~/.ssh; touch ~/.ssh/known_hosts;
|
||||
ssh-keyscan -t rsa $CI_SERVER_HOST >> ~/.ssh/known_hosts;
|
||||
echo "$GIT_SSH_PRIV_KEY" | tr -d '\r' | ssh-add - >/dev/null;
|
||||
git config --global user.email "$GIT_EMAIL" >/dev/null;
|
||||
git config --global user.name "$GIT_NAME" >/dev/null;
|
||||
export CI_PUSH_REPO=`echo $CI_REPOSITORY_URL | sed -e "s|.*@\(.*\)|git@\1|" -e "s|/|:|"`;
|
||||
git remote rm origin && git remote add origin ''${CI_PUSH_REPO}
|
||||
echo -e "\\e[0Ksection_end:`date +%s`:commit_setup\\r\\e[0K"
|
||||
''
|
||||
];
|
||||
script = let
|
||||
addScript =
|
||||
if builtins.length files == 0
|
||||
then ""
|
||||
else "git add ${builtins.concatStringsSep " " files}";
|
||||
in
|
||||
(jobArgs.script or [])
|
||||
++ [
|
||||
# sh
|
||||
''
|
||||
echo -e "\\e[0Ksection_start:`date +%s`:commit[collapsed=true]\\r\\e[0KCommiting & pushing changes if necessary"
|
||||
${addScript}
|
||||
git diff --cached --exit-code >/dev/null &&
|
||||
echo "Nothing to commit" ||
|
||||
git commit -m "${message}" --no-verify;
|
||||
git push --tags origin ''${GIT_SOURCE_REF:-HEAD}:''${GIT_TARGET_REF:-$CI_COMMIT_REF_NAME} -o ci.skip
|
||||
echo -e "\\e[0Ksection_end:`date +%s`:commit\\r\\e[0K"
|
||||
''
|
||||
];
|
||||
nix.deps = (jobArgs.nix.deps or []) ++ [pkgs.openssh pkgs.gitMinimal pkgs.gnused];
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue