nix-gitlab-ci/lib/impl/helpers.nix
technofab 31f0e4ea13
fix(jobPatched): fix variables not being unset if all contain store paths
the goal was to remove "variables" when it's empty, but this resulted in
the original value being used if all of the variables contained store
paths. This is not supposed to happen and thus fixed with this.
2025-09-03 15:17:51 +02:00

115 lines
2.9 KiB
Nix

{
pkgs,
lib,
} @ args: let
inherit
(lib)
types
isAttrs
filterAttrs
mapAttrs
mkOption
mkOptionType
isType
literalExpression
pipe
hasInfix
concatMapAttrs
optionalAttrs
;
in rec {
prepend = key: arr: job: {
${key} = arr ++ (job.${key} or []);
};
append = key: arr: job: {
${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:
pipe value [
builtins.toJSON
builtins.unsafeDiscardOutputDependency
builtins.unsafeDiscardStringContext
(builtins.toFile name)
];
toYamlPretty = (pkgs.formats.yaml {}).generate;
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 = shouldContain: job:
concatMapAttrs (
name: value:
optionalAttrs ((hasInfix "/nix/store/" value) == shouldContain) {
${name} = value;
}
)
(job.variables or {});
deepMerge = lhs: rhs:
lhs
// rhs
// (builtins.mapAttrs (
rName: rValue: let
lValue = lhs.${rName} or null;
in
if builtins.isAttrs lValue && builtins.isAttrs rValue
then deepMerge lValue rValue
else if builtins.isList lValue && builtins.isList rValue
then lValue ++ rValue
else rValue
)
rhs);
unsetType = mkOptionType {
name = "unset";
description = "unset";
descriptionClass = "noun";
check = _value: true;
};
unset = {
_type = "unset";
};
isUnset = isType "unset";
unsetOr = typ:
(types.either unsetType typ)
// {
inherit (typ) description;
};
mkUnsetOption = opts:
mkOption (opts
// {
type = unsetOr opts.type;
default = opts.default or unset;
defaultText = literalExpression "unset";
});
filterUnset = value:
if builtins.isAttrs value && !builtins.hasAttr "_type" value
then let
filteredAttrs = builtins.mapAttrs (_n: filterUnset) value;
in
filterAttrs (_name: value: (!isUnset value)) filteredAttrs
else if builtins.isList value
then builtins.filter (elem: !isUnset elem) (map filterUnset value)
else value;
# 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 = [];
};
}