nixpkgs/pkgs/development/tools/build-managers/gradle/update-deps.nix
2024-09-29 12:51:44 -07:00

126 lines
5.1 KiB
Nix

{ lib
, runtimeShell
, srcOnly
, stdenvNoCC
, writeTextFile
, writeShellScript
, path
, bubblewrap
, coreutils
, curl
, jq
, mitm-cache
, nix
, openssl
, procps
, python3
}:
lib.makeOverridable
({ pkg, pname, attrPath, bwrapFlags, data, silent, useBwrap }:
let
keep = [ "MITM_CACHE_HOST" "MITM_CACHE_PORT" "MITM_CACHE_ADDRESS" "MITM_CACHE_CA" "MITM_CACHE_CERT_DIR" ];
gradleScript = writeShellScript "gradle-commands.sh" ''
set -eo pipefail
export http_proxy="$MITM_CACHE_ADDRESS"
export https_proxy="$MITM_CACHE_ADDRESS"
export SSL_CERT_FILE="$MITM_CACHE_CA"
export NIX_SSL_CERT_FILE="$MITM_CACHE_CA"
export GRADLE_USER_HOME="$(${coreutils}/bin/mktemp -d)"
export IN_GRADLE_UPDATE_DEPS=1
trap "${coreutils}/bin/rm -rf '$GRADLE_USER_HOME'" SIGINT SIGTERM ERR EXIT
cd "$(${coreutils}/bin/mktemp -d)"
${coreutils}/bin/mkdir out
export out="$PWD/out"
trap "${coreutils}/bin/rm -rf '$PWD'" SIGINT SIGTERM ERR EXIT
source "$stdenv/setup"
phases="''${prePhases[*]:-} unpackPhase patchPhase ''${preConfigurePhases[*]:-} configurePhase gradleUpdateScript" genericBuild
'';
source = srcOnly (pkg.overrideAttrs (old: {
mitmCache = "";
gradleInitScript = ./init-deps.gradle;
stdenv = old.stdenv or stdenvNoCC;
}));
sourceDrvPath = builtins.unsafeDiscardOutputDependency source.drvPath;
nixShellKeep = lib.concatMapStringsSep " " (x: "--keep ${x}") keep;
in
writeTextFile {
name = "fetch-deps.sh";
executable = true;
# see pkgs/common-updater/combinators.nix
derivationArgs.passthru =
{ supportedFeatures = lib.optional silent "silent"; }
// lib.optionalAttrs (attrPath != null) { inherit attrPath; };
text = ''
#!${runtimeShell}
set -eo pipefail
export PATH="${lib.makeBinPath ([
coreutils curl jq mitm-cache openssl
procps python3.pkgs.ephemeral-port-reserve
] ++ lib.optional useBwrap bubblewrap)}:$PATH"
outPath="${
# if this is an absolute path in nix store, use path relative to the store path
if lib.hasPrefix "${builtins.storeDir}/" (toString data)
then builtins.concatStringsSep "/" (lib.drop 1 (lib.splitString "/" (lib.removePrefix "${builtins.storeDir}/" (toString data))))
# if this is an absolute path anywhere else, just use that path
else if lib.hasPrefix "/" (toString data)
then toString data
# otherwise, use a path relative to the package
else "${dirOf pkg.meta.position}/${data}"
}"
pushd "$(mktemp -d)" >/dev/null
MITM_CACHE_DIR="$PWD"
trap "rm -rf '$MITM_CACHE_DIR'" SIGINT SIGTERM ERR EXIT
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha256 -days 1 -out ca.cer -subj "/C=AL/ST=a/L=a/O=a/OU=a/CN=example.org"
export MITM_CACHE_HOST=127.0.0.1
export MITM_CACHE_PORT="''${mitmCachePort:-$(ephemeral-port-reserve "$MITM_CACHE_HOST")}"
export MITM_CACHE_ADDRESS="$MITM_CACHE_HOST:$MITM_CACHE_PORT"
# forget all redirects - this makes the lockfiles predictable
# not only does this strip CDN URLs, but it also improves security - since the redirects aren't
# stored in the lockfile, a malicious actor can't change the redirect URL stored in the lockfile
mitm-cache \
-l"$MITM_CACHE_ADDRESS" \
record \
--reject '\.(md5|sha(1|256|512:?):?)$' \
--forget-redirects-from '.*' \
--record-text '/maven-metadata\.xml$' >/dev/null 2>/dev/null &
MITM_CACHE_PID="$!"
# wait for mitm-cache to fully start
for i in {0..20}; do
ps -p "$MITM_CACHE_PID" >/dev/null || (echo "Failed to start mitm-cache" && exit 1)
curl -so/dev/null "$MITM_CACHE_ADDRESS" && break
[[ "$i" -eq 20 ]] && (echo "Failed to start mitm-cache" && exit 1)
sleep 0.5
done
trap "kill '$MITM_CACHE_PID'" SIGINT SIGTERM ERR EXIT
export MITM_CACHE_CERT_DIR="$PWD"
export MITM_CACHE_CA="$MITM_CACHE_CERT_DIR/ca.cer"
popd >/dev/null
useBwrap="''${USE_BWRAP:-${toString useBwrap}}"
if [ -n "$useBwrap" ]; then
# bwrap isn't necessary, it's only used to prevent messy build scripts from touching ~
bwrap \
--unshare-all --share-net --clearenv --chdir / --setenv HOME /homeless-shelter \
--tmpfs /home --bind /tmp /tmp --ro-bind /nix /nix --ro-bind /run /run --proc /proc --dev /dev \
--ro-bind ${toString path} ${toString path} --bind "$MITM_CACHE_CERT_DIR" "$MITM_CACHE_CERT_DIR" \
${builtins.concatStringsSep " " (map (x: "--setenv ${x} \"\$${x}\"") keep)} \
--setenv NIX_BUILD_SHELL ${runtimeShell} ${bwrapFlags} ''${BWRAP_FLAGS:-} \
-- ${nix}/bin/nix-shell --pure --run ${gradleScript} ${nixShellKeep} ${sourceDrvPath}
else
NIX_BUILD_SHELL=${runtimeShell} nix-shell --pure --run ${gradleScript} ${nixShellKeep} ${sourceDrvPath}
fi${lib.optionalString silent " >&2"}
kill -s SIGINT "$MITM_CACHE_PID"
for i in {0..20}; do
# check for valid json
if jq -e 1 "$MITM_CACHE_DIR/out.json" >/dev/null 2>/dev/null; then
exec ${python3.interpreter} ${./compress-deps-json.py} "$MITM_CACHE_DIR/out.json" "$outPath"
fi
sleep 1
done
exit 1
'';
})