Enforce proper casing

This commit is contained in:
Luc Perkins 2024-04-15 19:23:29 -03:00
parent c89881253c
commit 8f4ca496eb
No known key found for this signature in database
GPG key ID: 16DB1108FB591835
3 changed files with 742 additions and 814 deletions

422
dist/index.js generated vendored
View file

@ -97680,45 +97680,45 @@ class NixInstallerAction {
fetchStyle: "nix-style", fetchStyle: "nix-style",
legacySourcePrefix: "nix-installer", legacySourcePrefix: "nix-installer",
}); });
this.platform = get_nix_platform(); this.platform = getNixPlatform(getArchOs());
this.nix_package_url = getStringOrNull("nix-package-url"); this.nixPackageUrl = getStringOrNull("nix-package-url");
this.backtrace = getStringOrNull("backtrace"); this.backtrace = getStringOrNull("backtrace");
this.extra_args = getStringOrNull("extra-args"); this.extraArgs = getStringOrNull("extra-args");
this.extra_conf = getMultilineStringOrNull("extra-conf"); this.extraConf = getMultilineStringOrNull("extra-conf");
this.flakehub = getBool("flakehub"); this.flakehub = getBool("flakehub");
this.kvm = getBool("kvm"); this.kvm = getBool("kvm");
this.force_docker_shim = getBool("force-docker-shim"); this.forceDockerShim = getBool("force-docker-shim");
this.github_token = getStringOrNull("github-token"); this.githubToken = getStringOrNull("github-token");
this.github_server_url = getStringOrNull("github-server-url"); this.githubServerUrl = getStringOrNull("github-server-url");
this.init = getStringOrNull("init"); this.init = getStringOrNull("init");
this.local_root = getStringOrNull("local-root"); this.localRoot = getStringOrNull("local-root");
this.log_directives = getStringOrNull("log-directives"); this.logDirectives = getStringOrNull("log-directives");
this.logger = getStringOrNull("logger"); this.logger = getStringOrNull("logger");
this.ssl_cert_file = getStringOrNull("ssl-cert-file"); this.sslCertFile = getStringOrNull("ssl-cert-file");
this.proxy = getStringOrNull("proxy"); this.proxy = getStringOrNull("proxy");
this.mac_case_sensitive = getStringOrNull("mac-case-sensitive"); this.macCaseSensitive = getStringOrNull("mac-case-sensitive");
this.mac_encrypt = getStringOrNull("mac-encrypt"); this.macEncrypt = getStringOrNull("mac-encrypt");
this.mac_root_disk = getStringOrNull("mac-root-disk"); this.macRootDisk = getStringOrNull("mac-root-disk");
this.mac_volume_label = getStringOrNull("mac-volume-label"); this.macVolumeLabel = getStringOrNull("mac-volume-label");
this.modify_profile = getBool("modify-profile"); this.modifyProfile = getBool("modify-profile");
this.nix_build_group_id = getNumberOrNull("nix-build-group-id"); this.nixBuildGroupId = getNumberOrNull("nix-build-group-id");
this.nix_build_group_name = getStringOrNull("nix-build-group-name"); this.nixBuildGroupName = getStringOrNull("nix-build-group-name");
this.nix_build_user_base = getNumberOrNull("nix_build-user-base"); this.nixBuildUserBase = getNumberOrNull("nix-build-user-base");
this.nix_build_user_count = getNumberOrNull("nix-build-user-count"); this.nixBuildUserCount = getNumberOrNull("nix-build-user-count");
this.nix_build_user_prefix = getStringOrNull("nix-build-user-prefix"); this.nixBuildUserPrefix = getStringOrNull("nix-build-user-prefix");
this.planner = getStringOrNull("planner"); this.planner = getStringOrNull("planner");
this.reinstall = getBool("reinstall"); this.reinstall = getBool("reinstall");
this.start_daemon = getBool("start-daemon"); this.startDaemon = getBool("start-daemon");
this.trust_runner_user = getBool("trust-runner-user"); this.trustRunnerUser = getBool("trust-runner-user");
} }
async detectAndForceDockerShim() { async detectAndForceDockerShim() {
// Detect if we're in a GHA runner which is Linux, doesn't have Systemd, and does have Docker. // Detect if we're in a GHA runner which is Linux, doesn't have Systemd, and does have Docker.
// This is a common case in self-hosted runners, providers like [Namespace](https://namespace.so/), // This is a common case in self-hosted runners, providers like [Namespace](https://namespace.so/),
// and especially GitHub Enterprise Server. // and especially GitHub Enterprise Server.
if (process.env.RUNNER_OS !== "Linux") { if (process.env.RUNNER_OS !== "Linux") {
if (this.force_docker_shim) { if (this.forceDockerShim) {
core.warning("Ignoring force-docker-shim which is set to true, as it is only supported on Linux."); core.warning("Ignoring force-docker-shim which is set to true, as it is only supported on Linux.");
this.force_docker_shim = false; this.forceDockerShim = false;
} }
return; return;
} }
@ -97726,7 +97726,7 @@ class NixInstallerAction {
throwIfNoEntry: false, throwIfNoEntry: false,
}); });
if (systemdCheck?.isDirectory()) { if (systemdCheck?.isDirectory()) {
if (this.force_docker_shim) { if (this.forceDockerShim) {
core.warning("Systemd is detected, but ignoring it since force-docker-shim is enabled."); core.warning("Systemd is detected, but ignoring it since force-docker-shim is enabled.");
} }
else { else {
@ -97737,9 +97737,9 @@ class NixInstallerAction {
this.idslib.addFact("has_systemd", false); this.idslib.addFact("has_systemd", false);
core.debug("Linux detected without systemd, testing for Docker with `docker info` as an alternative daemon supervisor."); core.debug("Linux detected without systemd, testing for Docker with `docker info` as an alternative daemon supervisor.");
this.idslib.addFact("has_docker", false); // Set to false here, and only in the success case do we set it to true this.idslib.addFact("has_docker", false); // Set to false here, and only in the success case do we set it to true
let exit_code; let exitCode;
try { try {
exit_code = await exec.exec("docker", ["info"], { exitCode = await exec.exec("docker", ["info"], {
silent: true, silent: true,
listeners: { listeners: {
stdout: (data) => { stdout: (data) => {
@ -97761,8 +97761,8 @@ class NixInstallerAction {
core.debug("Docker not detected, not enabling docker shim."); core.debug("Docker not detected, not enabling docker shim.");
return; return;
} }
if (exit_code !== 0) { if (exitCode !== 0) {
if (this.force_docker_shim) { if (this.forceDockerShim) {
core.warning("docker info check failed, but trying anyway since force-docker-shim is enabled."); core.warning("docker info check failed, but trying anyway since force-docker-shim is enabled.");
} }
else { else {
@ -97770,7 +97770,7 @@ class NixInstallerAction {
} }
} }
this.idslib.addFact("has_docker", true); this.idslib.addFact("has_docker", true);
if (!this.force_docker_shim && if (!this.forceDockerShim &&
(await this.detectDockerWithMountedDockerSocket())) { (await this.detectDockerWithMountedDockerSocket())) {
core.debug("Detected a Docker container with a Docker socket mounted, not enabling docker shim."); core.debug("Detected a Docker container with a Docker socket mounted, not enabling docker shim.");
return; return;
@ -97784,7 +97784,7 @@ class NixInstallerAction {
core.info(`Changing planner from '${this.planner}' to 'linux'`); core.info(`Changing planner from '${this.planner}' to 'linux'`);
this.planner = "linux"; this.planner = "linux";
} }
this.force_docker_shim = true; this.forceDockerShim = true;
core.endGroup(); core.endGroup();
} }
// Detect if we are running under `act` or some other system which is not using docker-in-docker, // Detect if we are running under `act` or some other system which is not using docker-in-docker,
@ -97792,13 +97792,13 @@ class NixInstallerAction {
// In the case of the socket mount solution, the shim will cause issues since the given mount paths will // In the case of the socket mount solution, the shim will cause issues since the given mount paths will
// equate to mount paths on the host, not mount paths to the docker container in question. // equate to mount paths on the host, not mount paths to the docker container in question.
async detectDockerWithMountedDockerSocket() { async detectDockerWithMountedDockerSocket() {
let cgroups_buffer; let cgroupsBuffer;
try { try {
// If we are inside a docker container, the last line of `/proc/self/cgroup` should be // If we are inside a docker container, the last line of `/proc/self/cgroup` should be
// 0::/docker/$SOME_ID // 0::/docker/$SOME_ID
// //
// If we are not, the line will likely be `0::/` // If we are not, the line will likely be `0::/`
cgroups_buffer = await (0,promises_namespaceObject.readFile)("/proc/self/cgroup", { cgroupsBuffer = await (0,promises_namespaceObject.readFile)("/proc/self/cgroup", {
encoding: "utf-8", encoding: "utf-8",
}); });
} }
@ -97806,48 +97806,48 @@ class NixInstallerAction {
core.debug(`Did not detect \`/proc/self/cgroup\` existence, bailing on docker container ID detection:\n${e}`); core.debug(`Did not detect \`/proc/self/cgroup\` existence, bailing on docker container ID detection:\n${e}`);
return false; return false;
} }
const cgroups = cgroups_buffer.trim().split("\n"); const cgroups = cgroupsBuffer.trim().split("\n");
const last_cgroup = cgroups[cgroups.length - 1]; const lastCgroup = cgroups[cgroups.length - 1];
const last_cgroup_parts = last_cgroup.split(":"); const lastCgroupParts = lastCgroup.split(":");
const last_cgroup_path = last_cgroup_parts[last_cgroup_parts.length - 1]; const lastCgroupPath = lastCgroupParts[lastCgroupParts.length - 1];
if (!last_cgroup_path.includes("/docker/")) { if (!lastCgroupPath.includes("/docker/")) {
core.debug("Did not detect a container ID, bailing on docker.sock detection"); core.debug("Did not detect a container ID, bailing on docker.sock detection");
return false; return false;
} }
// We are in a docker container, now to determine if this container is visible from // We are in a docker container, now to determine if this container is visible from
// the `docker` command, and if so, if there is a `docker.socket` mounted. // the `docker` command, and if so, if there is a `docker.socket` mounted.
const last_cgroup_path_parts = last_cgroup_path.split("/"); const lastCgroupPathParts = lastCgroupPath.split("/");
const container_id = last_cgroup_path_parts[last_cgroup_path_parts.length - 1]; const containerId = lastCgroupPathParts[lastCgroupPathParts.length - 1];
// If we cannot `docker inspect` this discovered container ID, we'll fall through to the `catch` below. // If we cannot `docker inspect` this discovered container ID, we'll fall through to the `catch` below.
let stdout_buffer = ""; let stdoutBuffer = "";
let stderr_buffer = ""; let stderrBuffer = "";
let exit_code; let exitCode;
try { try {
exit_code = await exec.exec("docker", ["inspect", container_id], { exitCode = await exec.exec("docker", ["inspect", containerId], {
silent: true, silent: true,
listeners: { listeners: {
stdout: (data) => { stdout: (data) => {
stdout_buffer += data.toString("utf-8"); stdoutBuffer += data.toString("utf-8");
}, },
stderr: (data) => { stderr: (data) => {
stderr_buffer += data.toString("utf-8"); stderrBuffer += data.toString("utf-8");
}, },
}, },
}); });
} }
catch (e) { catch (e) {
core.debug(`Could not execute \`docker inspect ${container_id}\`, bailing on docker container inspection:\n${e}`); core.debug(`Could not execute \`docker inspect ${containerId}\`, bailing on docker container inspection:\n${e}`);
return false; return false;
} }
if (exit_code !== 0) { if (exitCode !== 0) {
core.debug(`Unable to inspect detected docker container with id \`${container_id}\`, bailing on container inspection (exit ${exit_code}):\n${stderr_buffer}`); core.debug(`Unable to inspect detected docker container with id \`${containerId}\`, bailing on container inspection (exit ${exitCode}):\n${stderrBuffer}`);
return false; return false;
} }
const output = JSON.parse(stdout_buffer); const output = JSON.parse(stdoutBuffer);
// `docker inspect $ID` prints an array containing objects. // `docker inspect $ID` prints an array containing objects.
// In our use case, we should only see 1 item in the array. // In our use case, we should only see 1 item in the array.
if (output.length !== 1) { if (output.length !== 1) {
core.debug(`Got \`docker inspect ${container_id}\` output which was not one item (was ${output.length}), bailing on docker.sock detection.`); core.debug(`Got \`docker inspect ${containerId}\` output which was not one item (was ${output.length}), bailing on docker.sock detection.`);
return false; return false;
} }
const item = output[0]; const item = output[0];
@ -97856,197 +97856,196 @@ class NixInstallerAction {
// We are looking for a `Destination` ending with `docker.sock`. // We are looking for a `Destination` ending with `docker.sock`.
const mounts = item["Mounts"]; const mounts = item["Mounts"];
if (typeof mounts !== "object") { if (typeof mounts !== "object") {
core.debug(`Got non-object in \`Mounts\` field of \`docker inspect ${container_id}\` output, bailing on docker.sock detection.`); core.debug(`Got non-object in \`Mounts\` field of \`docker inspect ${containerId}\` output, bailing on docker.sock detection.`);
return false; return false;
} }
let found_docker_sock_mount = false; let foundDockerSockMount = false;
for (const mount of mounts) { for (const mount of mounts) {
const destination = mount["Destination"]; const destination = mount["Destination"];
if (typeof destination === "string") { if (typeof destination === "string") {
if (destination.endsWith("docker.sock")) { if (destination.endsWith("docker.sock")) {
found_docker_sock_mount = true; foundDockerSockMount = true;
break; break;
} }
} }
} }
return found_docker_sock_mount; return foundDockerSockMount;
} }
async executionEnvironment() { async executionEnvironment() {
const execution_env = {}; const executionEnv = {};
execution_env.NIX_INSTALLER_NO_CONFIRM = "true"; executionEnv.NIX_INSTALLER_NO_CONFIRM = "true";
execution_env.NIX_INSTALLER_DIAGNOSTIC_ATTRIBUTION = JSON.stringify(this.idslib.getCorrelationHashes()); executionEnv.NIX_INSTALLER_DIAGNOSTIC_ATTRIBUTION = JSON.stringify(this.idslib.getCorrelationHashes());
if (this.backtrace !== null) { if (this.backtrace !== null) {
execution_env.RUST_BACKTRACE = this.backtrace; executionEnv.RUST_BACKTRACE = this.backtrace;
} }
if (this.modify_profile !== null) { if (this.modifyProfile !== null) {
if (this.modify_profile) { if (this.modifyProfile) {
execution_env.NIX_INSTALLER_MODIFY_PROFILE = "true"; executionEnv.NIX_INSTALLER_MODIFY_PROFILE = "true";
} }
else { else {
execution_env.NIX_INSTALLER_MODIFY_PROFILE = "false"; executionEnv.NIX_INSTALLER_MODIFY_PROFILE = "false";
} }
} }
if (this.nix_build_group_id !== null) { if (this.nixBuildGroupId !== null) {
execution_env.NIX_INSTALLER_NIX_BUILD_GROUP_ID = `${this.nix_build_group_id}`; executionEnv.NIX_INSTALLER_NIX_BUILD_GROUP_ID = `${this.nixBuildGroupId}`;
} }
if (this.nix_build_group_name !== null) { if (this.nixBuildGroupName !== null) {
execution_env.NIX_INSTALLER_NIX_BUILD_GROUP_NAME = executionEnv.NIX_INSTALLER_NIX_BUILD_GROUP_NAME = this.nixBuildGroupName;
this.nix_build_group_name;
} }
if (this.nix_build_user_prefix !== null) { if (this.nixBuildUserPrefix !== null) {
execution_env.NIX_INSTALLER_NIX_BUILD_USER_PREFIX = executionEnv.NIX_INSTALLER_NIX_BUILD_USER_PREFIX =
this.nix_build_user_prefix; this.nixBuildUserPrefix;
} }
if (this.nix_build_user_count !== null) { if (this.nixBuildUserCount !== null) {
execution_env.NIX_INSTALLER_NIX_BUILD_USER_COUNT = `${this.nix_build_user_count}`; executionEnv.NIX_INSTALLER_NIX_BUILD_USER_COUNT = `${this.nixBuildUserCount}`;
} }
if (this.nix_build_user_base !== null) { if (this.nixBuildUserBase !== null) {
execution_env.NIX_INSTALLER_NIX_BUILD_USER_ID_BASE = `${this.nix_build_user_count}`; executionEnv.NIX_INSTALLER_NIX_BUILD_USER_ID_BASE = `${this.nixBuildUserCount}`;
} }
if (this.nix_package_url !== null) { if (this.nixPackageUrl !== null) {
execution_env.NIX_INSTALLER_NIX_PACKAGE_URL = `${this.nix_package_url}`; executionEnv.NIX_INSTALLER_NIX_PACKAGE_URL = `${this.nixPackageUrl}`;
} }
if (this.proxy !== null) { if (this.proxy !== null) {
execution_env.NIX_INSTALLER_PROXY = this.proxy; executionEnv.NIX_INSTALLER_PROXY = this.proxy;
} }
if (this.ssl_cert_file !== null) { if (this.sslCertFile !== null) {
execution_env.NIX_INSTALLER_SSL_CERT_FILE = this.ssl_cert_file; executionEnv.NIX_INSTALLER_SSL_CERT_FILE = this.sslCertFile;
} }
execution_env.NIX_INSTALLER_DIAGNOSTIC_ENDPOINT = executionEnv.NIX_INSTALLER_DIAGNOSTIC_ENDPOINT =
this.idslib.getDiagnosticsUrl()?.toString() || ""; this.idslib.getDiagnosticsUrl()?.toString() || "";
// TODO: Error if the user uses these on not-MacOS // TODO: Error if the user uses these on not-MacOS
if (this.mac_encrypt !== null) { if (this.macEncrypt !== null) {
if (process.env.RUNNER_OS !== "macOS") { if (process.env.RUNNER_OS !== "macOS") {
throw new Error("`mac-encrypt` while `$RUNNER_OS` was not `macOS`"); throw new Error("`mac-encrypt` while `$RUNNER_OS` was not `macOS`");
} }
execution_env.NIX_INSTALLER_ENCRYPT = this.mac_encrypt; executionEnv.NIX_INSTALLER_ENCRYPT = this.macEncrypt;
} }
if (this.mac_case_sensitive !== null) { if (this.macCaseSensitive !== null) {
if (process.env.RUNNER_OS !== "macOS") { if (process.env.RUNNER_OS !== "macOS") {
throw new Error("`mac-case-sensitive` while `$RUNNER_OS` was not `macOS`"); throw new Error("`mac-case-sensitive` while `$RUNNER_OS` was not `macOS`");
} }
execution_env.NIX_INSTALLER_CASE_SENSITIVE = this.mac_case_sensitive; executionEnv.NIX_INSTALLER_CASE_SENSITIVE = this.macCaseSensitive;
} }
if (this.mac_volume_label !== null) { if (this.macVolumeLabel !== null) {
if (process.env.RUNNER_OS !== "macOS") { if (process.env.RUNNER_OS !== "macOS") {
throw new Error("`mac-volume-label` while `$RUNNER_OS` was not `macOS`"); throw new Error("`mac-volume-label` while `$RUNNER_OS` was not `macOS`");
} }
execution_env.NIX_INSTALLER_VOLUME_LABEL = this.mac_volume_label; executionEnv.NIX_INSTALLER_VOLUME_LABEL = this.macVolumeLabel;
} }
if (this.mac_root_disk !== null) { if (this.macRootDisk !== null) {
if (process.env.RUNNER_OS !== "macOS") { if (process.env.RUNNER_OS !== "macOS") {
throw new Error("`mac-root-disk` while `$RUNNER_OS` was not `macOS`"); throw new Error("`mac-root-disk` while `$RUNNER_OS` was not `macOS`");
} }
execution_env.NIX_INSTALLER_ROOT_DISK = this.mac_root_disk; executionEnv.NIX_INSTALLER_ROOT_DISK = this.macRootDisk;
} }
if (this.logger !== null) { if (this.logger !== null) {
execution_env.NIX_INSTALLER_LOGGER = this.logger; executionEnv.NIX_INSTALLER_LOGGER = this.logger;
} }
if (this.log_directives !== null) { if (this.logDirectives !== null) {
execution_env.NIX_INSTALLER_LOG_DIRECTIVES = this.log_directives; executionEnv.NIX_INSTALLER_LOG_DIRECTIVES = this.logDirectives;
} }
// TODO: Error if the user uses these on MacOS // TODO: Error if the user uses these on MacOS
if (this.init !== null) { if (this.init !== null) {
if (process.env.RUNNER_OS === "macOS") { if (process.env.RUNNER_OS === "macOS") {
throw new Error("`init` is not a valid option when `$RUNNER_OS` is `macOS`"); throw new Error("`init` is not a valid option when `$RUNNER_OS` is `macOS`");
} }
execution_env.NIX_INSTALLER_INIT = this.init; executionEnv.NIX_INSTALLER_INIT = this.init;
} }
if (this.start_daemon !== null) { if (this.startDaemon !== null) {
if (this.start_daemon) { if (this.startDaemon) {
execution_env.NIX_INSTALLER_START_DAEMON = "true"; executionEnv.NIX_INSTALLER_START_DAEMON = "true";
} }
else { else {
execution_env.NIX_INSTALLER_START_DAEMON = "false"; executionEnv.NIX_INSTALLER_START_DAEMON = "false";
} }
} }
let extra_conf = ""; let extraConf = "";
if (this.github_server_url !== null && this.github_token !== null) { if (this.githubServerUrl !== null && this.githubToken !== null) {
const server_url = this.github_server_url.replace("https://", ""); const serverUrl = this.githubServerUrl.replace("https://", "");
extra_conf += `access-tokens = ${server_url}=${this.github_token}`; extraConf += `access-tokens = ${serverUrl}=${this.githubToken}`;
extra_conf += "\n"; extraConf += "\n";
} }
if (this.trust_runner_user !== null) { if (this.trustRunnerUser !== null) {
const user = (0,external_node_os_.userInfo)().username; const user = (0,external_node_os_.userInfo)().username;
if (user) { if (user) {
extra_conf += `trusted-users = root ${user}`; extraConf += `trusted-users = root ${user}`;
} }
else { else {
extra_conf += `trusted-users = root`; extraConf += `trusted-users = root`;
} }
extra_conf += "\n"; extraConf += "\n";
} }
if (this.flakehub) { if (this.flakehub) {
extra_conf += `netrc-file = ${await this.flakehub_login()}`; extraConf += `netrc-file = ${await this.flakehubLogin()}`;
extra_conf += "\n"; extraConf += "\n";
} }
if (this.extra_conf !== null && this.extra_conf.length !== 0) { if (this.extraConf !== null && this.extraConf.length !== 0) {
extra_conf += this.extra_conf.join("\n"); extraConf += this.extraConf.join("\n");
extra_conf += "\n"; extraConf += "\n";
} }
execution_env.NIX_INSTALLER_EXTRA_CONF = extra_conf; executionEnv.NIX_INSTALLER_EXTRA_CONF = extraConf;
if (process.env.ACT && !process.env.NOT_ACT) { if (process.env.ACT && !process.env.NOT_ACT) {
this.idslib.addFact("in_act", true); this.idslib.addFact("in_act", true);
core.info("Detected `$ACT` environment, assuming this is a https://github.com/nektos/act created container, set `NOT_ACT=true` to override this. This will change the setting of the `init` to be compatible with `act`"); core.info("Detected `$ACT` environment, assuming this is a https://github.com/nektos/act created container, set `NOT_ACT=true` to override this. This will change the setting of the `init` to be compatible with `act`");
execution_env.NIX_INSTALLER_INIT = "none"; executionEnv.NIX_INSTALLER_INIT = "none";
} }
if (process.env.NSC_VM_ID && !process.env.NOT_NAMESPACE) { if (process.env.NSC_VM_ID && !process.env.NOT_NAMESPACE) {
this.idslib.addFact("in_namespace_so", true); this.idslib.addFact("in_namespace_so", true);
core.info("Detected Namespace runner, assuming this is a https://namespace.so created container, set `NOT_NAMESPACE=true` to override this. This will change the setting of the `init` to be compatible with Namespace"); core.info("Detected Namespace runner, assuming this is a https://namespace.so created container, set `NOT_NAMESPACE=true` to override this. This will change the setting of the `init` to be compatible with Namespace");
execution_env.NIX_INSTALLER_INIT = "none"; executionEnv.NIX_INSTALLER_INIT = "none";
} }
return execution_env; return executionEnv;
} }
async execute_install(binary_path) { async executeInstall(binaryPath) {
const execution_env = await this.executionEnvironment(); const executionEnv = await this.executionEnvironment();
core.debug(`Execution environment: ${JSON.stringify(execution_env, null, 4)}`); core.debug(`Execution environment: ${JSON.stringify(executionEnv, null, 4)}`);
const args = ["install"]; const args = ["install"];
if (this.planner) { if (this.planner) {
this.idslib.addFact("nix_installer_planner", this.planner); this.idslib.addFact("nix_installer_planner", this.planner);
args.push(this.planner); args.push(this.planner);
} }
else { else {
this.idslib.addFact("nix_installer_planner", get_default_planner()); this.idslib.addFact("nix_installer_planner", getDefaultPlanner());
args.push(get_default_planner()); args.push(getDefaultPlanner());
} }
if (this.extra_args) { if (this.extraArgs) {
const extra_args = parseArgsStringToArgv(this.extra_args); const extraArgs = parseArgsStringToArgv(this.extraArgs);
args.concat(extra_args); args.concat(extraArgs);
} }
this.idslib.recordEvent("install_nix_start"); this.idslib.recordEvent("install_nix_start");
const exit_code = await exec.exec(binary_path, args, { const exitCode = await exec.exec(binaryPath, args, {
env: { env: {
...execution_env, ...executionEnv,
...process.env, // To get $PATH, etc ...process.env, // To get $PATH, etc
}, },
}); });
if (exit_code !== 0) { if (exitCode !== 0) {
this.idslib.recordEvent("install_nix_failure", { this.idslib.recordEvent("install_nix_failure", {
exit_code, exitCode,
}); });
throw new Error(`Non-zero exit code of \`${exit_code}\` detected`); throw new Error(`Non-zero exit code of \`${exitCode}\` detected`);
} }
this.idslib.recordEvent("install_nix_success"); this.idslib.recordEvent("install_nix_success");
return exit_code; return exitCode;
} }
async install() { async install() {
const existing_install = await this.detect_existing(); const existingInstall = await this.detectExisting();
if (existing_install) { if (existingInstall) {
if (this.reinstall) { if (this.reinstall) {
// We need to uninstall, then reinstall // We need to uninstall, then reinstall
core.info("Nix was already installed, `reinstall` is set, uninstalling for a reinstall"); core.info("Nix was already installed, `reinstall` is set, uninstalling for a reinstall");
await this.execute_uninstall(); await this.executeUninstall();
} }
else { else {
// We're already installed, and not reinstalling, just set GITHUB_PATH and finish early // We're already installed, and not reinstalling, just set GITHUB_PATH and finish early
await this.set_github_path(); await this.setGithubPath();
core.info("Nix was already installed, using existing install"); core.info("Nix was already installed, using existing install");
return; return;
} }
} }
if (this.kvm) { if (this.kvm) {
core.startGroup("Configuring KVM"); core.startGroup("Configuring KVM");
if (await this.setup_kvm()) { if (await this.setupKvm()) {
core.endGroup(); core.endGroup();
core.info("\u001b[32m Accelerated KVM is enabled \u001b[33m⚡"); core.info("\u001b[32m Accelerated KVM is enabled \u001b[33m⚡");
core.exportVariable("DETERMINATE_NIX_KVM", "1"); core.exportVariable("DETERMINATE_NIX_KVM", "1");
@ -98059,13 +98058,13 @@ class NixInstallerAction {
} }
// Normal just doing of the install // Normal just doing of the install
core.startGroup("Installing Nix"); core.startGroup("Installing Nix");
const binary_path = await this.fetch_binary(); const binaryPath = await this.fetchBinary();
await this.execute_install(binary_path); await this.executeInstall(binaryPath);
core.endGroup(); core.endGroup();
if (this.force_docker_shim) { if (this.forceDockerShim) {
await this.spawnDockerShim(); await this.spawnDockerShim();
} }
await this.set_github_path(); await this.setGithubPath();
} }
async spawnDockerShim() { async spawnDockerShim() {
core.startGroup("Configuring the Docker shim as the Nix Daemon's process supervisor"); core.startGroup("Configuring the Docker shim as the Nix Daemon's process supervisor");
@ -98085,7 +98084,7 @@ class NixInstallerAction {
} }
core.debug("Loading image: determinate-nix-shim:latest..."); core.debug("Loading image: determinate-nix-shim:latest...");
{ {
const exit_code = await exec.exec("docker", ["image", "load", "--input", images[arch]], { const exitCode = await exec.exec("docker", ["image", "load", "--input", images[arch]], {
silent: true, silent: true,
listeners: { listeners: {
stdout: (data) => { stdout: (data) => {
@ -98102,14 +98101,14 @@ class NixInstallerAction {
}, },
}, },
}); });
if (exit_code !== 0) { if (exitCode !== 0) {
throw new Error(`Failed to build the shim image, exit code: \`${exit_code}\``); throw new Error(`Failed to build the shim image, exit code: \`${exitCode}\``);
} }
} }
{ {
core.debug("Starting the Nix daemon through Docker..."); core.debug("Starting the Nix daemon through Docker...");
this.idslib.recordEvent("start_docker_shim"); this.idslib.recordEvent("start_docker_shim");
const exit_code = await exec.exec("docker", [ const exitCode = await exec.exec("docker", [
"--log-level=debug", "--log-level=debug",
"run", "run",
"--detach", "--detach",
@ -98155,20 +98154,20 @@ class NixInstallerAction {
}, },
}, },
}); });
if (exit_code !== 0) { if (exitCode !== 0) {
throw new Error(`Failed to start the Nix daemon through Docker, exit code: \`${exit_code}\``); throw new Error(`Failed to start the Nix daemon through Docker, exit code: \`${exitCode}\``);
} }
} }
core.endGroup(); core.endGroup();
return; return;
} }
async cleanupDockerShim() { async cleanupDockerShim() {
const container_id = core.getState("docker_shim_container_id"); const containerId = core.getState("docker_shim_container_id");
if (container_id !== "") { if (containerId !== "") {
core.startGroup("Cleaning up the Nix daemon's Docker shim"); core.startGroup("Cleaning up the Nix daemon's Docker shim");
let cleaned = false; let cleaned = false;
try { try {
await exec.exec("docker", ["rm", "--force", container_id]); await exec.exec("docker", ["rm", "--force", containerId]);
cleaned = true; cleaned = true;
} }
catch { catch {
@ -98177,7 +98176,7 @@ class NixInstallerAction {
if (!cleaned) { if (!cleaned) {
core.info("trying to pkill the container's shim process"); core.info("trying to pkill the container's shim process");
try { try {
await exec.exec("pkill", [container_id]); await exec.exec("pkill", [containerId]);
cleaned = true; cleaned = true;
} }
catch { catch {
@ -98193,52 +98192,52 @@ class NixInstallerAction {
core.endGroup(); core.endGroup();
} }
} }
async set_github_path() { async setGithubPath() {
// Interim versions of the `nix-installer` crate may have already manipulated `$GITHUB_PATH`, as root even! Accessing that will be an error. // Interim versions of the `nix-installer` crate may have already manipulated `$GITHUB_PATH`, as root even! Accessing that will be an error.
try { try {
const nix_var_nix_profile_path = "/nix/var/nix/profiles/default/bin"; const nixVarNixProfilePath = "/nix/var/nix/profiles/default/bin";
const home_nix_profile_path = `${process.env.HOME}/.nix-profile/bin`; const homeNixProfilePath = `${process.env.HOME}/.nix-profile/bin`;
core.addPath(nix_var_nix_profile_path); core.addPath(nixVarNixProfilePath);
core.addPath(home_nix_profile_path); core.addPath(homeNixProfilePath);
core.info(`Added \`${nix_var_nix_profile_path}\` and \`${home_nix_profile_path}\` to \`$GITHUB_PATH\``); core.info(`Added \`${nixVarNixProfilePath}\` and \`${homeNixProfilePath}\` to \`$GITHUB_PATH\``);
} }
catch (error) { catch (error) {
core.info("Skipping setting $GITHUB_PATH in action, the `nix-installer` crate seems to have done this already. From `nix-installer` version 0.11.0 and up, this step is done in the action. Prior to 0.11.0, this was only done in the `nix-installer` binary."); core.info("Skipping setting $GITHUB_PATH in action, the `nix-installer` crate seems to have done this already. From `nix-installer` version 0.11.0 and up, this step is done in the action. Prior to 0.11.0, this was only done in the `nix-installer` binary.");
} }
} }
async flakehub_login() { async flakehubLogin() {
this.idslib.recordEvent("login_to_flakehub"); this.idslib.recordEvent("login_to_flakehub");
const netrc_path = `${process.env["RUNNER_TEMP"]}/determinate-nix-installer-netrc`; const netrcPath = `${process.env["RUNNER_TEMP"]}/determinate-nix-installer-netrc`;
const jwt = await core.getIDToken("api.flakehub.com"); const jwt = await core.getIDToken("api.flakehub.com");
await (0,promises_namespaceObject.writeFile)(netrc_path, [ await (0,promises_namespaceObject.writeFile)(netrcPath, [
`machine api.flakehub.com login flakehub password ${jwt}`, `machine api.flakehub.com login flakehub password ${jwt}`,
`machine flakehub.com login flakehub password ${jwt}`, `machine flakehub.com login flakehub password ${jwt}`,
].join("\n")); ].join("\n"));
core.info("Logging in to FlakeHub."); core.info("Logging in to FlakeHub.");
// the join followed by a match on ^... looks silly, but extra_config // the join followed by a match on ^... looks silly, but extra_config
// could contain multi-line values // could contain multi-line values
if (this.extra_conf?.join("\n").match(/^netrc-file/m)) { if (this.extraConf?.join("\n").match(/^netrc-file/m)) {
core.warning("Logging in to FlakeHub conflicts with the Nix option `netrc-file`."); core.warning("Logging in to FlakeHub conflicts with the Nix option `netrc-file`.");
} }
return netrc_path; return netrcPath;
} }
async execute_uninstall() { async executeUninstall() {
this.idslib.recordEvent("uninstall"); this.idslib.recordEvent("uninstall");
const exit_code = await exec.exec(`/nix/nix-installer`, ["uninstall"], { const exitCode = await exec.exec(`/nix/nix-installer`, ["uninstall"], {
env: { env: {
NIX_INSTALLER_NO_CONFIRM: "true", NIX_INSTALLER_NO_CONFIRM: "true",
...process.env, // To get $PATH, etc ...process.env, // To get $PATH, etc
}, },
}); });
if (exit_code !== 0) { if (exitCode !== 0) {
throw new Error(`Non-zero exit code of \`${exit_code}\` detected`); throw new Error(`Non-zero exit code of \`${exitCode}\` detected`);
} }
return exit_code; return exitCode;
} }
async detect_existing() { async detectExisting() {
const receipt_path = "/nix/receipt.json"; const receiptPath = "/nix/receipt.json";
try { try {
await (0,promises_namespaceObject.access)(receipt_path); await (0,promises_namespaceObject.access)(receiptPath);
// There is a /nix/receipt.json // There is a /nix/receipt.json
return true; return true;
} }
@ -98247,16 +98246,16 @@ class NixInstallerAction {
return false; return false;
} }
} }
async setup_kvm() { async setupKvm() {
this.idslib.recordEvent("setup_kvm"); this.idslib.recordEvent("setup_kvm");
const current_user = (0,external_node_os_.userInfo)(); const currentUser = (0,external_node_os_.userInfo)();
const is_root = current_user.uid === 0; const isRoot = currentUser.uid === 0;
const maybe_sudo = is_root ? "" : "sudo"; const maybeSudo = isRoot ? "" : "sudo";
const kvm_rules = "/etc/udev/rules.d/99-determinate-nix-installer-kvm.rules"; const kvmRules = "/etc/udev/rules.d/99-determinate-nix-installer-kvm.rules";
try { try {
const write_file_exit_code = await exec.exec("sh", [ const writeFileExitCode = await exec.exec("sh", [
"-c", "-c",
`echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | ${maybe_sudo} tee ${kvm_rules} > /dev/null`, `echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | ${maybeSudo} tee ${kvmRules} > /dev/null`,
], { ], {
silent: true, silent: true,
listeners: { listeners: {
@ -98274,15 +98273,15 @@ class NixInstallerAction {
}, },
}, },
}); });
if (write_file_exit_code !== 0) { if (writeFileExitCode !== 0) {
throw new Error(`Non-zero exit code of \`${write_file_exit_code}\` detected while writing '${kvm_rules}'`); throw new Error(`Non-zero exit code of \`${writeFileExitCode}\` detected while writing '${kvmRules}'`);
} }
const debug_root_run_throw = async (action, command, args) => { const debugRootRunThrow = async (action, command, args) => {
if (!is_root) { if (!isRoot) {
args = [command, ...args]; args = [command, ...args];
command = "sudo"; command = "sudo";
} }
const reload_exit_code = await exec.exec(command, args, { const reloadExitCode = await exec.exec(command, args, {
silent: true, silent: true,
listeners: { listeners: {
stdout: (data) => { stdout: (data) => {
@ -98299,56 +98298,56 @@ class NixInstallerAction {
}, },
}, },
}); });
if (reload_exit_code !== 0) { if (reloadExitCode !== 0) {
throw new Error(`Non-zero exit code of \`${reload_exit_code}\` detected while ${action}.`); throw new Error(`Non-zero exit code of \`${reloadExitCode}\` detected while ${action}.`);
} }
}; };
await debug_root_run_throw("reloading udev rules", "udevadm", [ await debugRootRunThrow("reloading udev rules", "udevadm", [
"control", "control",
"--reload-rules", "--reload-rules",
]); ]);
await debug_root_run_throw("triggering udev against kvm", "udevadm", [ await debugRootRunThrow("triggering udev against kvm", "udevadm", [
"trigger", "trigger",
"--name-match=kvm", "--name-match=kvm",
]); ]);
return true; return true;
} }
catch (error) { catch (error) {
if (is_root) { if (isRoot) {
await exec.exec("rm", ["-f", kvm_rules]); await exec.exec("rm", ["-f", kvmRules]);
} }
else { else {
await exec.exec("sudo", ["rm", "-f", kvm_rules]); await exec.exec("sudo", ["rm", "-f", kvmRules]);
} }
return false; return false;
} }
} }
async fetch_binary() { async fetchBinary() {
if (!this.local_root) { if (!this.localRoot) {
return await this.idslib.fetchExecutable(); return await this.idslib.fetchExecutable();
} }
else { else {
const local_path = (0,external_node_path_namespaceObject.join)(this.local_root, `nix-installer-${this.platform}`); const localPath = (0,external_node_path_namespaceObject.join)(this.localRoot, `nix-installer-${this.platform}`);
core.info(`Using binary ${local_path}`); core.info(`Using binary ${localPath}`);
return local_path; return localPath;
} }
} }
async report_overall() { async reportOverall() {
try { try {
this.idslib.recordEvent("conclude_workflow", { this.idslib.recordEvent("conclude_workflow", {
conclusion: await this.get_workflow_conclusion(), conclusion: await this.getWorkflowConclusion(),
}); });
} }
catch (error) { catch (error) {
core.debug(`Error submitting post-run diagnostics report: ${error}`); core.debug(`Error submitting post-run diagnostics report: ${error}`);
} }
} }
async get_workflow_conclusion() { async getWorkflowConclusion() {
if (this.github_token == null) { if (this.githubToken == null) {
return undefined; return undefined;
} }
try { try {
const octokit = github.getOctokit(this.github_token); const octokit = github.getOctokit(this.githubToken);
const jobs = await octokit.paginate(octokit.rest.actions.listJobsForWorkflowRun, { const jobs = await octokit.paginate(octokit.rest.actions.listJobsForWorkflowRun, {
owner: github.context.repo.owner, owner: github.context.repo.owner,
repo: github.context.repo.repo, repo: github.context.repo.repo,
@ -98381,35 +98380,16 @@ class NixInstallerAction {
} }
} }
} }
function get_nix_platform() { function getDefaultPlanner() {
const env_os = process.env.RUNNER_OS; const envOs = process.env.RUNNER_OS;
const env_arch = process.env.RUNNER_ARCH; if (envOs === "macOS") {
if (env_os === "macOS" && env_arch === "X64") {
return "x86_64-darwin";
}
else if (env_os === "macOS" && env_arch === "ARM64") {
return "aarch64-darwin";
}
else if (env_os === "Linux" && env_arch === "X64") {
return "x86_64-linux";
}
else if (env_os === "Linux" && env_arch === "ARM64") {
return "aarch64-linux";
}
else {
throw new Error(`Unsupported \`RUNNER_OS\` (currently \`${env_os}\`) and \`RUNNER_ARCH\` (currently \`${env_arch}\`) combination`);
}
}
function get_default_planner() {
const env_os = process.env.RUNNER_OS;
if (env_os === "macOS") {
return "macos"; return "macos";
} }
else if (env_os === "Linux") { else if (envOs === "Linux") {
return "linux"; return "linux";
} }
else { else {
throw new Error(`Unsupported \`RUNNER_OS\` (currently \`${env_os}\`)`); throw new Error(`Unsupported \`RUNNER_OS\` (currently \`${envOs}\`)`);
} }
} }
function main() { function main() {
@ -98420,7 +98400,7 @@ function main() {
}); });
installer.idslib.onPost(async () => { installer.idslib.onPost(async () => {
await installer.cleanupDockerShim(); await installer.cleanupDockerShim();
await installer.report_overall(); await installer.reportOverall();
}); });
installer.idslib.execute(); installer.idslib.execute();
} }

534
dist/main.js generated vendored
View file

@ -1,13 +1,13 @@
import * as actions_core from "@actions/core"; import * as actionsCore from "@actions/core";
import * as github from "@actions/github"; import * as github from "@actions/github";
import * as actions_exec from "@actions/exec"; import * as actionsExec from "@actions/exec";
import { access, writeFile, readFile } from "node:fs/promises"; import { access, writeFile, readFile } from "node:fs/promises";
import { join } from "node:path"; import { join } from "node:path";
import fs from "node:fs"; import fs from "node:fs";
import { userInfo } from "node:os"; import { userInfo } from "node:os";
import stringArgv from "string-argv"; import stringArgv from "string-argv";
import * as path from "path"; import * as path from "path";
import { IdsToolbox, inputs } from "detsys-ts"; import { IdsToolbox, inputs, platform } from "detsys-ts";
import { randomUUID } from "node:crypto"; import { randomUUID } from "node:crypto";
class NixInstallerAction { class NixInstallerAction {
constructor() { constructor() {
@ -16,45 +16,45 @@ class NixInstallerAction {
fetchStyle: "nix-style", fetchStyle: "nix-style",
legacySourcePrefix: "nix-installer", legacySourcePrefix: "nix-installer",
}); });
this.platform = get_nix_platform(); this.platform = platform.getNixPlatform(platform.getArchOs());
this.nix_package_url = inputs.getStringOrNull("nix-package-url"); this.nixPackageUrl = inputs.getStringOrNull("nix-package-url");
this.backtrace = inputs.getStringOrNull("backtrace"); this.backtrace = inputs.getStringOrNull("backtrace");
this.extra_args = inputs.getStringOrNull("extra-args"); this.extraArgs = inputs.getStringOrNull("extra-args");
this.extra_conf = inputs.getMultilineStringOrNull("extra-conf"); this.extraConf = inputs.getMultilineStringOrNull("extra-conf");
this.flakehub = inputs.getBool("flakehub"); this.flakehub = inputs.getBool("flakehub");
this.kvm = inputs.getBool("kvm"); this.kvm = inputs.getBool("kvm");
this.force_docker_shim = inputs.getBool("force-docker-shim"); this.forceDockerShim = inputs.getBool("force-docker-shim");
this.github_token = inputs.getStringOrNull("github-token"); this.githubToken = inputs.getStringOrNull("github-token");
this.github_server_url = inputs.getStringOrNull("github-server-url"); this.githubServerUrl = inputs.getStringOrNull("github-server-url");
this.init = inputs.getStringOrNull("init"); this.init = inputs.getStringOrNull("init");
this.local_root = inputs.getStringOrNull("local-root"); this.localRoot = inputs.getStringOrNull("local-root");
this.log_directives = inputs.getStringOrNull("log-directives"); this.logDirectives = inputs.getStringOrNull("log-directives");
this.logger = inputs.getStringOrNull("logger"); this.logger = inputs.getStringOrNull("logger");
this.ssl_cert_file = inputs.getStringOrNull("ssl-cert-file"); this.sslCertFile = inputs.getStringOrNull("ssl-cert-file");
this.proxy = inputs.getStringOrNull("proxy"); this.proxy = inputs.getStringOrNull("proxy");
this.mac_case_sensitive = inputs.getStringOrNull("mac-case-sensitive"); this.macCaseSensitive = inputs.getStringOrNull("mac-case-sensitive");
this.mac_encrypt = inputs.getStringOrNull("mac-encrypt"); this.macEncrypt = inputs.getStringOrNull("mac-encrypt");
this.mac_root_disk = inputs.getStringOrNull("mac-root-disk"); this.macRootDisk = inputs.getStringOrNull("mac-root-disk");
this.mac_volume_label = inputs.getStringOrNull("mac-volume-label"); this.macVolumeLabel = inputs.getStringOrNull("mac-volume-label");
this.modify_profile = inputs.getBool("modify-profile"); this.modifyProfile = inputs.getBool("modify-profile");
this.nix_build_group_id = inputs.getNumberOrNull("nix-build-group-id"); this.nixBuildGroupId = inputs.getNumberOrNull("nix-build-group-id");
this.nix_build_group_name = inputs.getStringOrNull("nix-build-group-name"); this.nixBuildGroupName = inputs.getStringOrNull("nix-build-group-name");
this.nix_build_user_base = inputs.getNumberOrNull("nix_build-user-base"); this.nixBuildUserBase = inputs.getNumberOrNull("nix-build-user-base");
this.nix_build_user_count = inputs.getNumberOrNull("nix-build-user-count"); this.nixBuildUserCount = inputs.getNumberOrNull("nix-build-user-count");
this.nix_build_user_prefix = inputs.getStringOrNull("nix-build-user-prefix"); this.nixBuildUserPrefix = inputs.getStringOrNull("nix-build-user-prefix");
this.planner = inputs.getStringOrNull("planner"); this.planner = inputs.getStringOrNull("planner");
this.reinstall = inputs.getBool("reinstall"); this.reinstall = inputs.getBool("reinstall");
this.start_daemon = inputs.getBool("start-daemon"); this.startDaemon = inputs.getBool("start-daemon");
this.trust_runner_user = inputs.getBool("trust-runner-user"); this.trustRunnerUser = inputs.getBool("trust-runner-user");
} }
async detectAndForceDockerShim() { async detectAndForceDockerShim() {
// Detect if we're in a GHA runner which is Linux, doesn't have Systemd, and does have Docker. // Detect if we're in a GHA runner which is Linux, doesn't have Systemd, and does have Docker.
// This is a common case in self-hosted runners, providers like [Namespace](https://namespace.so/), // This is a common case in self-hosted runners, providers like [Namespace](https://namespace.so/),
// and especially GitHub Enterprise Server. // and especially GitHub Enterprise Server.
if (process.env.RUNNER_OS !== "Linux") { if (process.env.RUNNER_OS !== "Linux") {
if (this.force_docker_shim) { if (this.forceDockerShim) {
actions_core.warning("Ignoring force-docker-shim which is set to true, as it is only supported on Linux."); actionsCore.warning("Ignoring force-docker-shim which is set to true, as it is only supported on Linux.");
this.force_docker_shim = false; this.forceDockerShim = false;
} }
return; return;
} }
@ -62,8 +62,8 @@ class NixInstallerAction {
throwIfNoEntry: false, throwIfNoEntry: false,
}); });
if (systemdCheck?.isDirectory()) { if (systemdCheck?.isDirectory()) {
if (this.force_docker_shim) { if (this.forceDockerShim) {
actions_core.warning("Systemd is detected, but ignoring it since force-docker-shim is enabled."); actionsCore.warning("Systemd is detected, but ignoring it since force-docker-shim is enabled.");
} }
else { else {
this.idslib.addFact("has_systemd", true); this.idslib.addFact("has_systemd", true);
@ -71,119 +71,119 @@ class NixInstallerAction {
} }
} }
this.idslib.addFact("has_systemd", false); this.idslib.addFact("has_systemd", false);
actions_core.debug("Linux detected without systemd, testing for Docker with `docker info` as an alternative daemon supervisor."); actionsCore.debug("Linux detected without systemd, testing for Docker with `docker info` as an alternative daemon supervisor.");
this.idslib.addFact("has_docker", false); // Set to false here, and only in the success case do we set it to true this.idslib.addFact("has_docker", false); // Set to false here, and only in the success case do we set it to true
let exit_code; let exitCode;
try { try {
exit_code = await actions_exec.exec("docker", ["info"], { exitCode = await actionsExec.exec("docker", ["info"], {
silent: true, silent: true,
listeners: { listeners: {
stdout: (data) => { stdout: (data) => {
const trimmed = data.toString("utf-8").trimEnd(); const trimmed = data.toString("utf-8").trimEnd();
if (trimmed.length >= 0) { if (trimmed.length >= 0) {
actions_core.debug(trimmed); actionsCore.debug(trimmed);
} }
}, },
stderr: (data) => { stderr: (data) => {
const trimmed = data.toString("utf-8").trimEnd(); const trimmed = data.toString("utf-8").trimEnd();
if (trimmed.length >= 0) { if (trimmed.length >= 0) {
actions_core.debug(trimmed); actionsCore.debug(trimmed);
} }
}, },
}, },
}); });
} }
catch (e) { catch (e) {
actions_core.debug("Docker not detected, not enabling docker shim."); actionsCore.debug("Docker not detected, not enabling docker shim.");
return; return;
} }
if (exit_code !== 0) { if (exitCode !== 0) {
if (this.force_docker_shim) { if (this.forceDockerShim) {
actions_core.warning("docker info check failed, but trying anyway since force-docker-shim is enabled."); actionsCore.warning("docker info check failed, but trying anyway since force-docker-shim is enabled.");
} }
else { else {
return; return;
} }
} }
this.idslib.addFact("has_docker", true); this.idslib.addFact("has_docker", true);
if (!this.force_docker_shim && if (!this.forceDockerShim &&
(await this.detectDockerWithMountedDockerSocket())) { (await this.detectDockerWithMountedDockerSocket())) {
actions_core.debug("Detected a Docker container with a Docker socket mounted, not enabling docker shim."); actionsCore.debug("Detected a Docker container with a Docker socket mounted, not enabling docker shim.");
return; return;
} }
actions_core.startGroup("Enabling the Docker shim for running Nix on Linux in CI without Systemd."); actionsCore.startGroup("Enabling the Docker shim for running Nix on Linux in CI without Systemd.");
if (this.init !== "none") { if (this.init !== "none") {
actions_core.info(`Changing init from '${this.init}' to 'none'`); actionsCore.info(`Changing init from '${this.init}' to 'none'`);
this.init = "none"; this.init = "none";
} }
if (this.planner !== "linux") { if (this.planner !== "linux") {
actions_core.info(`Changing planner from '${this.planner}' to 'linux'`); actionsCore.info(`Changing planner from '${this.planner}' to 'linux'`);
this.planner = "linux"; this.planner = "linux";
} }
this.force_docker_shim = true; this.forceDockerShim = true;
actions_core.endGroup(); actionsCore.endGroup();
} }
// Detect if we are running under `act` or some other system which is not using docker-in-docker, // Detect if we are running under `act` or some other system which is not using docker-in-docker,
// and instead using a mounted docker socket. // and instead using a mounted docker socket.
// In the case of the socket mount solution, the shim will cause issues since the given mount paths will // In the case of the socket mount solution, the shim will cause issues since the given mount paths will
// equate to mount paths on the host, not mount paths to the docker container in question. // equate to mount paths on the host, not mount paths to the docker container in question.
async detectDockerWithMountedDockerSocket() { async detectDockerWithMountedDockerSocket() {
let cgroups_buffer; let cgroupsBuffer;
try { try {
// If we are inside a docker container, the last line of `/proc/self/cgroup` should be // If we are inside a docker container, the last line of `/proc/self/cgroup` should be
// 0::/docker/$SOME_ID // 0::/docker/$SOME_ID
// //
// If we are not, the line will likely be `0::/` // If we are not, the line will likely be `0::/`
cgroups_buffer = await readFile("/proc/self/cgroup", { cgroupsBuffer = await readFile("/proc/self/cgroup", {
encoding: "utf-8", encoding: "utf-8",
}); });
} }
catch (e) { catch (e) {
actions_core.debug(`Did not detect \`/proc/self/cgroup\` existence, bailing on docker container ID detection:\n${e}`); actionsCore.debug(`Did not detect \`/proc/self/cgroup\` existence, bailing on docker container ID detection:\n${e}`);
return false; return false;
} }
const cgroups = cgroups_buffer.trim().split("\n"); const cgroups = cgroupsBuffer.trim().split("\n");
const last_cgroup = cgroups[cgroups.length - 1]; const lastCgroup = cgroups[cgroups.length - 1];
const last_cgroup_parts = last_cgroup.split(":"); const lastCgroupParts = lastCgroup.split(":");
const last_cgroup_path = last_cgroup_parts[last_cgroup_parts.length - 1]; const lastCgroupPath = lastCgroupParts[lastCgroupParts.length - 1];
if (!last_cgroup_path.includes("/docker/")) { if (!lastCgroupPath.includes("/docker/")) {
actions_core.debug("Did not detect a container ID, bailing on docker.sock detection"); actionsCore.debug("Did not detect a container ID, bailing on docker.sock detection");
return false; return false;
} }
// We are in a docker container, now to determine if this container is visible from // We are in a docker container, now to determine if this container is visible from
// the `docker` command, and if so, if there is a `docker.socket` mounted. // the `docker` command, and if so, if there is a `docker.socket` mounted.
const last_cgroup_path_parts = last_cgroup_path.split("/"); const lastCgroupPathParts = lastCgroupPath.split("/");
const container_id = last_cgroup_path_parts[last_cgroup_path_parts.length - 1]; const containerId = lastCgroupPathParts[lastCgroupPathParts.length - 1];
// If we cannot `docker inspect` this discovered container ID, we'll fall through to the `catch` below. // If we cannot `docker inspect` this discovered container ID, we'll fall through to the `catch` below.
let stdout_buffer = ""; let stdoutBuffer = "";
let stderr_buffer = ""; let stderrBuffer = "";
let exit_code; let exitCode;
try { try {
exit_code = await actions_exec.exec("docker", ["inspect", container_id], { exitCode = await actionsExec.exec("docker", ["inspect", containerId], {
silent: true, silent: true,
listeners: { listeners: {
stdout: (data) => { stdout: (data) => {
stdout_buffer += data.toString("utf-8"); stdoutBuffer += data.toString("utf-8");
}, },
stderr: (data) => { stderr: (data) => {
stderr_buffer += data.toString("utf-8"); stderrBuffer += data.toString("utf-8");
}, },
}, },
}); });
} }
catch (e) { catch (e) {
actions_core.debug(`Could not execute \`docker inspect ${container_id}\`, bailing on docker container inspection:\n${e}`); actionsCore.debug(`Could not execute \`docker inspect ${containerId}\`, bailing on docker container inspection:\n${e}`);
return false; return false;
} }
if (exit_code !== 0) { if (exitCode !== 0) {
actions_core.debug(`Unable to inspect detected docker container with id \`${container_id}\`, bailing on container inspection (exit ${exit_code}):\n${stderr_buffer}`); actionsCore.debug(`Unable to inspect detected docker container with id \`${containerId}\`, bailing on container inspection (exit ${exitCode}):\n${stderrBuffer}`);
return false; return false;
} }
const output = JSON.parse(stdout_buffer); const output = JSON.parse(stdoutBuffer);
// `docker inspect $ID` prints an array containing objects. // `docker inspect $ID` prints an array containing objects.
// In our use case, we should only see 1 item in the array. // In our use case, we should only see 1 item in the array.
if (output.length !== 1) { if (output.length !== 1) {
actions_core.debug(`Got \`docker inspect ${container_id}\` output which was not one item (was ${output.length}), bailing on docker.sock detection.`); actionsCore.debug(`Got \`docker inspect ${containerId}\` output which was not one item (was ${output.length}), bailing on docker.sock detection.`);
return false; return false;
} }
const item = output[0]; const item = output[0];
@ -192,219 +192,218 @@ class NixInstallerAction {
// We are looking for a `Destination` ending with `docker.sock`. // We are looking for a `Destination` ending with `docker.sock`.
const mounts = item["Mounts"]; const mounts = item["Mounts"];
if (typeof mounts !== "object") { if (typeof mounts !== "object") {
actions_core.debug(`Got non-object in \`Mounts\` field of \`docker inspect ${container_id}\` output, bailing on docker.sock detection.`); actionsCore.debug(`Got non-object in \`Mounts\` field of \`docker inspect ${containerId}\` output, bailing on docker.sock detection.`);
return false; return false;
} }
let found_docker_sock_mount = false; let foundDockerSockMount = false;
for (const mount of mounts) { for (const mount of mounts) {
const destination = mount["Destination"]; const destination = mount["Destination"];
if (typeof destination === "string") { if (typeof destination === "string") {
if (destination.endsWith("docker.sock")) { if (destination.endsWith("docker.sock")) {
found_docker_sock_mount = true; foundDockerSockMount = true;
break; break;
} }
} }
} }
return found_docker_sock_mount; return foundDockerSockMount;
} }
async executionEnvironment() { async executionEnvironment() {
const execution_env = {}; const executionEnv = {};
execution_env.NIX_INSTALLER_NO_CONFIRM = "true"; executionEnv.NIX_INSTALLER_NO_CONFIRM = "true";
execution_env.NIX_INSTALLER_DIAGNOSTIC_ATTRIBUTION = JSON.stringify(this.idslib.getCorrelationHashes()); executionEnv.NIX_INSTALLER_DIAGNOSTIC_ATTRIBUTION = JSON.stringify(this.idslib.getCorrelationHashes());
if (this.backtrace !== null) { if (this.backtrace !== null) {
execution_env.RUST_BACKTRACE = this.backtrace; executionEnv.RUST_BACKTRACE = this.backtrace;
} }
if (this.modify_profile !== null) { if (this.modifyProfile !== null) {
if (this.modify_profile) { if (this.modifyProfile) {
execution_env.NIX_INSTALLER_MODIFY_PROFILE = "true"; executionEnv.NIX_INSTALLER_MODIFY_PROFILE = "true";
} }
else { else {
execution_env.NIX_INSTALLER_MODIFY_PROFILE = "false"; executionEnv.NIX_INSTALLER_MODIFY_PROFILE = "false";
} }
} }
if (this.nix_build_group_id !== null) { if (this.nixBuildGroupId !== null) {
execution_env.NIX_INSTALLER_NIX_BUILD_GROUP_ID = `${this.nix_build_group_id}`; executionEnv.NIX_INSTALLER_NIX_BUILD_GROUP_ID = `${this.nixBuildGroupId}`;
} }
if (this.nix_build_group_name !== null) { if (this.nixBuildGroupName !== null) {
execution_env.NIX_INSTALLER_NIX_BUILD_GROUP_NAME = executionEnv.NIX_INSTALLER_NIX_BUILD_GROUP_NAME = this.nixBuildGroupName;
this.nix_build_group_name;
} }
if (this.nix_build_user_prefix !== null) { if (this.nixBuildUserPrefix !== null) {
execution_env.NIX_INSTALLER_NIX_BUILD_USER_PREFIX = executionEnv.NIX_INSTALLER_NIX_BUILD_USER_PREFIX =
this.nix_build_user_prefix; this.nixBuildUserPrefix;
} }
if (this.nix_build_user_count !== null) { if (this.nixBuildUserCount !== null) {
execution_env.NIX_INSTALLER_NIX_BUILD_USER_COUNT = `${this.nix_build_user_count}`; executionEnv.NIX_INSTALLER_NIX_BUILD_USER_COUNT = `${this.nixBuildUserCount}`;
} }
if (this.nix_build_user_base !== null) { if (this.nixBuildUserBase !== null) {
execution_env.NIX_INSTALLER_NIX_BUILD_USER_ID_BASE = `${this.nix_build_user_count}`; executionEnv.NIX_INSTALLER_NIX_BUILD_USER_ID_BASE = `${this.nixBuildUserCount}`;
} }
if (this.nix_package_url !== null) { if (this.nixPackageUrl !== null) {
execution_env.NIX_INSTALLER_NIX_PACKAGE_URL = `${this.nix_package_url}`; executionEnv.NIX_INSTALLER_NIX_PACKAGE_URL = `${this.nixPackageUrl}`;
} }
if (this.proxy !== null) { if (this.proxy !== null) {
execution_env.NIX_INSTALLER_PROXY = this.proxy; executionEnv.NIX_INSTALLER_PROXY = this.proxy;
} }
if (this.ssl_cert_file !== null) { if (this.sslCertFile !== null) {
execution_env.NIX_INSTALLER_SSL_CERT_FILE = this.ssl_cert_file; executionEnv.NIX_INSTALLER_SSL_CERT_FILE = this.sslCertFile;
} }
execution_env.NIX_INSTALLER_DIAGNOSTIC_ENDPOINT = executionEnv.NIX_INSTALLER_DIAGNOSTIC_ENDPOINT =
this.idslib.getDiagnosticsUrl()?.toString() || ""; this.idslib.getDiagnosticsUrl()?.toString() || "";
// TODO: Error if the user uses these on not-MacOS // TODO: Error if the user uses these on not-MacOS
if (this.mac_encrypt !== null) { if (this.macEncrypt !== null) {
if (process.env.RUNNER_OS !== "macOS") { if (process.env.RUNNER_OS !== "macOS") {
throw new Error("`mac-encrypt` while `$RUNNER_OS` was not `macOS`"); throw new Error("`mac-encrypt` while `$RUNNER_OS` was not `macOS`");
} }
execution_env.NIX_INSTALLER_ENCRYPT = this.mac_encrypt; executionEnv.NIX_INSTALLER_ENCRYPT = this.macEncrypt;
} }
if (this.mac_case_sensitive !== null) { if (this.macCaseSensitive !== null) {
if (process.env.RUNNER_OS !== "macOS") { if (process.env.RUNNER_OS !== "macOS") {
throw new Error("`mac-case-sensitive` while `$RUNNER_OS` was not `macOS`"); throw new Error("`mac-case-sensitive` while `$RUNNER_OS` was not `macOS`");
} }
execution_env.NIX_INSTALLER_CASE_SENSITIVE = this.mac_case_sensitive; executionEnv.NIX_INSTALLER_CASE_SENSITIVE = this.macCaseSensitive;
} }
if (this.mac_volume_label !== null) { if (this.macVolumeLabel !== null) {
if (process.env.RUNNER_OS !== "macOS") { if (process.env.RUNNER_OS !== "macOS") {
throw new Error("`mac-volume-label` while `$RUNNER_OS` was not `macOS`"); throw new Error("`mac-volume-label` while `$RUNNER_OS` was not `macOS`");
} }
execution_env.NIX_INSTALLER_VOLUME_LABEL = this.mac_volume_label; executionEnv.NIX_INSTALLER_VOLUME_LABEL = this.macVolumeLabel;
} }
if (this.mac_root_disk !== null) { if (this.macRootDisk !== null) {
if (process.env.RUNNER_OS !== "macOS") { if (process.env.RUNNER_OS !== "macOS") {
throw new Error("`mac-root-disk` while `$RUNNER_OS` was not `macOS`"); throw new Error("`mac-root-disk` while `$RUNNER_OS` was not `macOS`");
} }
execution_env.NIX_INSTALLER_ROOT_DISK = this.mac_root_disk; executionEnv.NIX_INSTALLER_ROOT_DISK = this.macRootDisk;
} }
if (this.logger !== null) { if (this.logger !== null) {
execution_env.NIX_INSTALLER_LOGGER = this.logger; executionEnv.NIX_INSTALLER_LOGGER = this.logger;
} }
if (this.log_directives !== null) { if (this.logDirectives !== null) {
execution_env.NIX_INSTALLER_LOG_DIRECTIVES = this.log_directives; executionEnv.NIX_INSTALLER_LOG_DIRECTIVES = this.logDirectives;
} }
// TODO: Error if the user uses these on MacOS // TODO: Error if the user uses these on MacOS
if (this.init !== null) { if (this.init !== null) {
if (process.env.RUNNER_OS === "macOS") { if (process.env.RUNNER_OS === "macOS") {
throw new Error("`init` is not a valid option when `$RUNNER_OS` is `macOS`"); throw new Error("`init` is not a valid option when `$RUNNER_OS` is `macOS`");
} }
execution_env.NIX_INSTALLER_INIT = this.init; executionEnv.NIX_INSTALLER_INIT = this.init;
} }
if (this.start_daemon !== null) { if (this.startDaemon !== null) {
if (this.start_daemon) { if (this.startDaemon) {
execution_env.NIX_INSTALLER_START_DAEMON = "true"; executionEnv.NIX_INSTALLER_START_DAEMON = "true";
} }
else { else {
execution_env.NIX_INSTALLER_START_DAEMON = "false"; executionEnv.NIX_INSTALLER_START_DAEMON = "false";
} }
} }
let extra_conf = ""; let extraConf = "";
if (this.github_server_url !== null && this.github_token !== null) { if (this.githubServerUrl !== null && this.githubToken !== null) {
const server_url = this.github_server_url.replace("https://", ""); const serverUrl = this.githubServerUrl.replace("https://", "");
extra_conf += `access-tokens = ${server_url}=${this.github_token}`; extraConf += `access-tokens = ${serverUrl}=${this.githubToken}`;
extra_conf += "\n"; extraConf += "\n";
} }
if (this.trust_runner_user !== null) { if (this.trustRunnerUser !== null) {
const user = userInfo().username; const user = userInfo().username;
if (user) { if (user) {
extra_conf += `trusted-users = root ${user}`; extraConf += `trusted-users = root ${user}`;
} }
else { else {
extra_conf += `trusted-users = root`; extraConf += `trusted-users = root`;
} }
extra_conf += "\n"; extraConf += "\n";
} }
if (this.flakehub) { if (this.flakehub) {
extra_conf += `netrc-file = ${await this.flakehub_login()}`; extraConf += `netrc-file = ${await this.flakehubLogin()}`;
extra_conf += "\n"; extraConf += "\n";
} }
if (this.extra_conf !== null && this.extra_conf.length !== 0) { if (this.extraConf !== null && this.extraConf.length !== 0) {
extra_conf += this.extra_conf.join("\n"); extraConf += this.extraConf.join("\n");
extra_conf += "\n"; extraConf += "\n";
} }
execution_env.NIX_INSTALLER_EXTRA_CONF = extra_conf; executionEnv.NIX_INSTALLER_EXTRA_CONF = extraConf;
if (process.env.ACT && !process.env.NOT_ACT) { if (process.env.ACT && !process.env.NOT_ACT) {
this.idslib.addFact("in_act", true); this.idslib.addFact("in_act", true);
actions_core.info("Detected `$ACT` environment, assuming this is a https://github.com/nektos/act created container, set `NOT_ACT=true` to override this. This will change the setting of the `init` to be compatible with `act`"); actionsCore.info("Detected `$ACT` environment, assuming this is a https://github.com/nektos/act created container, set `NOT_ACT=true` to override this. This will change the setting of the `init` to be compatible with `act`");
execution_env.NIX_INSTALLER_INIT = "none"; executionEnv.NIX_INSTALLER_INIT = "none";
} }
if (process.env.NSC_VM_ID && !process.env.NOT_NAMESPACE) { if (process.env.NSC_VM_ID && !process.env.NOT_NAMESPACE) {
this.idslib.addFact("in_namespace_so", true); this.idslib.addFact("in_namespace_so", true);
actions_core.info("Detected Namespace runner, assuming this is a https://namespace.so created container, set `NOT_NAMESPACE=true` to override this. This will change the setting of the `init` to be compatible with Namespace"); actionsCore.info("Detected Namespace runner, assuming this is a https://namespace.so created container, set `NOT_NAMESPACE=true` to override this. This will change the setting of the `init` to be compatible with Namespace");
execution_env.NIX_INSTALLER_INIT = "none"; executionEnv.NIX_INSTALLER_INIT = "none";
} }
return execution_env; return executionEnv;
} }
async execute_install(binary_path) { async executeInstall(binaryPath) {
const execution_env = await this.executionEnvironment(); const executionEnv = await this.executionEnvironment();
actions_core.debug(`Execution environment: ${JSON.stringify(execution_env, null, 4)}`); actionsCore.debug(`Execution environment: ${JSON.stringify(executionEnv, null, 4)}`);
const args = ["install"]; const args = ["install"];
if (this.planner) { if (this.planner) {
this.idslib.addFact("nix_installer_planner", this.planner); this.idslib.addFact("nix_installer_planner", this.planner);
args.push(this.planner); args.push(this.planner);
} }
else { else {
this.idslib.addFact("nix_installer_planner", get_default_planner()); this.idslib.addFact("nix_installer_planner", getDefaultPlanner());
args.push(get_default_planner()); args.push(getDefaultPlanner());
} }
if (this.extra_args) { if (this.extraArgs) {
const extra_args = stringArgv(this.extra_args); const extraArgs = stringArgv(this.extraArgs);
args.concat(extra_args); args.concat(extraArgs);
} }
this.idslib.recordEvent("install_nix_start"); this.idslib.recordEvent("install_nix_start");
const exit_code = await actions_exec.exec(binary_path, args, { const exitCode = await actionsExec.exec(binaryPath, args, {
env: { env: {
...execution_env, ...executionEnv,
...process.env, // To get $PATH, etc ...process.env, // To get $PATH, etc
}, },
}); });
if (exit_code !== 0) { if (exitCode !== 0) {
this.idslib.recordEvent("install_nix_failure", { this.idslib.recordEvent("install_nix_failure", {
exit_code, exitCode,
}); });
throw new Error(`Non-zero exit code of \`${exit_code}\` detected`); throw new Error(`Non-zero exit code of \`${exitCode}\` detected`);
} }
this.idslib.recordEvent("install_nix_success"); this.idslib.recordEvent("install_nix_success");
return exit_code; return exitCode;
} }
async install() { async install() {
const existing_install = await this.detect_existing(); const existingInstall = await this.detectExisting();
if (existing_install) { if (existingInstall) {
if (this.reinstall) { if (this.reinstall) {
// We need to uninstall, then reinstall // We need to uninstall, then reinstall
actions_core.info("Nix was already installed, `reinstall` is set, uninstalling for a reinstall"); actionsCore.info("Nix was already installed, `reinstall` is set, uninstalling for a reinstall");
await this.execute_uninstall(); await this.executeUninstall();
} }
else { else {
// We're already installed, and not reinstalling, just set GITHUB_PATH and finish early // We're already installed, and not reinstalling, just set GITHUB_PATH and finish early
await this.set_github_path(); await this.setGithubPath();
actions_core.info("Nix was already installed, using existing install"); actionsCore.info("Nix was already installed, using existing install");
return; return;
} }
} }
if (this.kvm) { if (this.kvm) {
actions_core.startGroup("Configuring KVM"); actionsCore.startGroup("Configuring KVM");
if (await this.setup_kvm()) { if (await this.setupKvm()) {
actions_core.endGroup(); actionsCore.endGroup();
actions_core.info("\u001b[32m Accelerated KVM is enabled \u001b[33m⚡"); actionsCore.info("\u001b[32m Accelerated KVM is enabled \u001b[33m⚡");
actions_core.exportVariable("DETERMINATE_NIX_KVM", "1"); actionsCore.exportVariable("DETERMINATE_NIX_KVM", "1");
} }
else { else {
actions_core.endGroup(); actionsCore.endGroup();
actions_core.info("KVM is not available."); actionsCore.info("KVM is not available.");
actions_core.exportVariable("DETERMINATE_NIX_KVM", "0"); actionsCore.exportVariable("DETERMINATE_NIX_KVM", "0");
} }
} }
// Normal just doing of the install // Normal just doing of the install
actions_core.startGroup("Installing Nix"); actionsCore.startGroup("Installing Nix");
const binary_path = await this.fetch_binary(); const binaryPath = await this.fetchBinary();
await this.execute_install(binary_path); await this.executeInstall(binaryPath);
actions_core.endGroup(); actionsCore.endGroup();
if (this.force_docker_shim) { if (this.forceDockerShim) {
await this.spawnDockerShim(); await this.spawnDockerShim();
} }
await this.set_github_path(); await this.setGithubPath();
} }
async spawnDockerShim() { async spawnDockerShim() {
actions_core.startGroup("Configuring the Docker shim as the Nix Daemon's process supervisor"); actionsCore.startGroup("Configuring the Docker shim as the Nix Daemon's process supervisor");
const images = { const images = {
X64: path.join(__dirname, "/../docker-shim/amd64.tar.gz"), X64: path.join(__dirname, "/../docker-shim/amd64.tar.gz"),
ARM64: path.join(__dirname, "/../docker-shim/arm64.tar.gz"), ARM64: path.join(__dirname, "/../docker-shim/arm64.tar.gz"),
@ -419,33 +418,33 @@ class NixInstallerAction {
else { else {
throw Error("Architecture not supported in Docker shim mode."); throw Error("Architecture not supported in Docker shim mode.");
} }
actions_core.debug("Loading image: determinate-nix-shim:latest..."); actionsCore.debug("Loading image: determinate-nix-shim:latest...");
{ {
const exit_code = await actions_exec.exec("docker", ["image", "load", "--input", images[arch]], { const exitCode = await actionsExec.exec("docker", ["image", "load", "--input", images[arch]], {
silent: true, silent: true,
listeners: { listeners: {
stdout: (data) => { stdout: (data) => {
const trimmed = data.toString("utf-8").trimEnd(); const trimmed = data.toString("utf-8").trimEnd();
if (trimmed.length >= 0) { if (trimmed.length >= 0) {
actions_core.debug(trimmed); actionsCore.debug(trimmed);
} }
}, },
stderr: (data) => { stderr: (data) => {
const trimmed = data.toString("utf-8").trimEnd(); const trimmed = data.toString("utf-8").trimEnd();
if (trimmed.length >= 0) { if (trimmed.length >= 0) {
actions_core.debug(trimmed); actionsCore.debug(trimmed);
} }
}, },
}, },
}); });
if (exit_code !== 0) { if (exitCode !== 0) {
throw new Error(`Failed to build the shim image, exit code: \`${exit_code}\``); throw new Error(`Failed to build the shim image, exit code: \`${exitCode}\``);
} }
} }
{ {
actions_core.debug("Starting the Nix daemon through Docker..."); actionsCore.debug("Starting the Nix daemon through Docker...");
this.idslib.recordEvent("start_docker_shim"); this.idslib.recordEvent("start_docker_shim");
const exit_code = await actions_exec.exec("docker", [ const exitCode = await actionsExec.exec("docker", [
"--log-level=debug", "--log-level=debug",
"run", "run",
"--detach", "--detach",
@ -475,106 +474,106 @@ class NixInstallerAction {
silent: true, silent: true,
listeners: { listeners: {
stdline: (data) => { stdline: (data) => {
actions_core.saveState("docker_shim_container_id", data.trimEnd()); actionsCore.saveState("docker_shim_container_id", data.trimEnd());
}, },
stdout: (data) => { stdout: (data) => {
const trimmed = data.toString("utf-8").trimEnd(); const trimmed = data.toString("utf-8").trimEnd();
if (trimmed.length >= 0) { if (trimmed.length >= 0) {
actions_core.debug(trimmed); actionsCore.debug(trimmed);
} }
}, },
stderr: (data) => { stderr: (data) => {
const trimmed = data.toString("utf-8").trimEnd(); const trimmed = data.toString("utf-8").trimEnd();
if (trimmed.length >= 0) { if (trimmed.length >= 0) {
actions_core.debug(trimmed); actionsCore.debug(trimmed);
} }
}, },
}, },
}); });
if (exit_code !== 0) { if (exitCode !== 0) {
throw new Error(`Failed to start the Nix daemon through Docker, exit code: \`${exit_code}\``); throw new Error(`Failed to start the Nix daemon through Docker, exit code: \`${exitCode}\``);
} }
} }
actions_core.endGroup(); actionsCore.endGroup();
return; return;
} }
async cleanupDockerShim() { async cleanupDockerShim() {
const container_id = actions_core.getState("docker_shim_container_id"); const containerId = actionsCore.getState("docker_shim_container_id");
if (container_id !== "") { if (containerId !== "") {
actions_core.startGroup("Cleaning up the Nix daemon's Docker shim"); actionsCore.startGroup("Cleaning up the Nix daemon's Docker shim");
let cleaned = false; let cleaned = false;
try { try {
await actions_exec.exec("docker", ["rm", "--force", container_id]); await actionsExec.exec("docker", ["rm", "--force", containerId]);
cleaned = true; cleaned = true;
} }
catch { catch {
actions_core.warning("failed to cleanup nix daemon container"); actionsCore.warning("failed to cleanup nix daemon container");
} }
if (!cleaned) { if (!cleaned) {
actions_core.info("trying to pkill the container's shim process"); actionsCore.info("trying to pkill the container's shim process");
try { try {
await actions_exec.exec("pkill", [container_id]); await actionsExec.exec("pkill", [containerId]);
cleaned = true; cleaned = true;
} }
catch { catch {
actions_core.warning("failed to forcibly kill the container's shim process"); actionsCore.warning("failed to forcibly kill the container's shim process");
} }
} }
if (cleaned) { if (cleaned) {
this.idslib.recordEvent("clean_up_docker_shim"); this.idslib.recordEvent("clean_up_docker_shim");
} }
else { else {
actions_core.warning("Giving up on cleaning up the nix daemon container"); actionsCore.warning("Giving up on cleaning up the nix daemon container");
} }
actions_core.endGroup(); actionsCore.endGroup();
} }
} }
async set_github_path() { async setGithubPath() {
// Interim versions of the `nix-installer` crate may have already manipulated `$GITHUB_PATH`, as root even! Accessing that will be an error. // Interim versions of the `nix-installer` crate may have already manipulated `$GITHUB_PATH`, as root even! Accessing that will be an error.
try { try {
const nix_var_nix_profile_path = "/nix/var/nix/profiles/default/bin"; const nixVarNixProfilePath = "/nix/var/nix/profiles/default/bin";
const home_nix_profile_path = `${process.env.HOME}/.nix-profile/bin`; const homeNixProfilePath = `${process.env.HOME}/.nix-profile/bin`;
actions_core.addPath(nix_var_nix_profile_path); actionsCore.addPath(nixVarNixProfilePath);
actions_core.addPath(home_nix_profile_path); actionsCore.addPath(homeNixProfilePath);
actions_core.info(`Added \`${nix_var_nix_profile_path}\` and \`${home_nix_profile_path}\` to \`$GITHUB_PATH\``); actionsCore.info(`Added \`${nixVarNixProfilePath}\` and \`${homeNixProfilePath}\` to \`$GITHUB_PATH\``);
} }
catch (error) { catch (error) {
actions_core.info("Skipping setting $GITHUB_PATH in action, the `nix-installer` crate seems to have done this already. From `nix-installer` version 0.11.0 and up, this step is done in the action. Prior to 0.11.0, this was only done in the `nix-installer` binary."); actionsCore.info("Skipping setting $GITHUB_PATH in action, the `nix-installer` crate seems to have done this already. From `nix-installer` version 0.11.0 and up, this step is done in the action. Prior to 0.11.0, this was only done in the `nix-installer` binary.");
} }
} }
async flakehub_login() { async flakehubLogin() {
this.idslib.recordEvent("login_to_flakehub"); this.idslib.recordEvent("login_to_flakehub");
const netrc_path = `${process.env["RUNNER_TEMP"]}/determinate-nix-installer-netrc`; const netrcPath = `${process.env["RUNNER_TEMP"]}/determinate-nix-installer-netrc`;
const jwt = await actions_core.getIDToken("api.flakehub.com"); const jwt = await actionsCore.getIDToken("api.flakehub.com");
await writeFile(netrc_path, [ await writeFile(netrcPath, [
`machine api.flakehub.com login flakehub password ${jwt}`, `machine api.flakehub.com login flakehub password ${jwt}`,
`machine flakehub.com login flakehub password ${jwt}`, `machine flakehub.com login flakehub password ${jwt}`,
].join("\n")); ].join("\n"));
actions_core.info("Logging in to FlakeHub."); actionsCore.info("Logging in to FlakeHub.");
// the join followed by a match on ^... looks silly, but extra_config // the join followed by a match on ^... looks silly, but extra_config
// could contain multi-line values // could contain multi-line values
if (this.extra_conf?.join("\n").match(/^netrc-file/m)) { if (this.extraConf?.join("\n").match(/^netrc-file/m)) {
actions_core.warning("Logging in to FlakeHub conflicts with the Nix option `netrc-file`."); actionsCore.warning("Logging in to FlakeHub conflicts with the Nix option `netrc-file`.");
} }
return netrc_path; return netrcPath;
} }
async execute_uninstall() { async executeUninstall() {
this.idslib.recordEvent("uninstall"); this.idslib.recordEvent("uninstall");
const exit_code = await actions_exec.exec(`/nix/nix-installer`, ["uninstall"], { const exitCode = await actionsExec.exec(`/nix/nix-installer`, ["uninstall"], {
env: { env: {
NIX_INSTALLER_NO_CONFIRM: "true", NIX_INSTALLER_NO_CONFIRM: "true",
...process.env, // To get $PATH, etc ...process.env, // To get $PATH, etc
}, },
}); });
if (exit_code !== 0) { if (exitCode !== 0) {
throw new Error(`Non-zero exit code of \`${exit_code}\` detected`); throw new Error(`Non-zero exit code of \`${exitCode}\` detected`);
} }
return exit_code; return exitCode;
} }
async detect_existing() { async detectExisting() {
const receipt_path = "/nix/receipt.json"; const receiptPath = "/nix/receipt.json";
try { try {
await access(receipt_path); await access(receiptPath);
// There is a /nix/receipt.json // There is a /nix/receipt.json
return true; return true;
} }
@ -583,114 +582,114 @@ class NixInstallerAction {
return false; return false;
} }
} }
async setup_kvm() { async setupKvm() {
this.idslib.recordEvent("setup_kvm"); this.idslib.recordEvent("setup_kvm");
const current_user = userInfo(); const currentUser = userInfo();
const is_root = current_user.uid === 0; const isRoot = currentUser.uid === 0;
const maybe_sudo = is_root ? "" : "sudo"; const maybeSudo = isRoot ? "" : "sudo";
const kvm_rules = "/etc/udev/rules.d/99-determinate-nix-installer-kvm.rules"; const kvmRules = "/etc/udev/rules.d/99-determinate-nix-installer-kvm.rules";
try { try {
const write_file_exit_code = await actions_exec.exec("sh", [ const writeFileExitCode = await actionsExec.exec("sh", [
"-c", "-c",
`echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | ${maybe_sudo} tee ${kvm_rules} > /dev/null`, `echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | ${maybeSudo} tee ${kvmRules} > /dev/null`,
], { ], {
silent: true, silent: true,
listeners: { listeners: {
stdout: (data) => { stdout: (data) => {
const trimmed = data.toString("utf-8").trimEnd(); const trimmed = data.toString("utf-8").trimEnd();
if (trimmed.length >= 0) { if (trimmed.length >= 0) {
actions_core.debug(trimmed); actionsCore.debug(trimmed);
} }
}, },
stderr: (data) => { stderr: (data) => {
const trimmed = data.toString("utf-8").trimEnd(); const trimmed = data.toString("utf-8").trimEnd();
if (trimmed.length >= 0) { if (trimmed.length >= 0) {
actions_core.debug(trimmed); actionsCore.debug(trimmed);
} }
}, },
}, },
}); });
if (write_file_exit_code !== 0) { if (writeFileExitCode !== 0) {
throw new Error(`Non-zero exit code of \`${write_file_exit_code}\` detected while writing '${kvm_rules}'`); throw new Error(`Non-zero exit code of \`${writeFileExitCode}\` detected while writing '${kvmRules}'`);
} }
const debug_root_run_throw = async (action, command, args) => { const debugRootRunThrow = async (action, command, args) => {
if (!is_root) { if (!isRoot) {
args = [command, ...args]; args = [command, ...args];
command = "sudo"; command = "sudo";
} }
const reload_exit_code = await actions_exec.exec(command, args, { const reloadExitCode = await actionsExec.exec(command, args, {
silent: true, silent: true,
listeners: { listeners: {
stdout: (data) => { stdout: (data) => {
const trimmed = data.toString("utf-8").trimEnd(); const trimmed = data.toString("utf-8").trimEnd();
if (trimmed.length >= 0) { if (trimmed.length >= 0) {
actions_core.debug(trimmed); actionsCore.debug(trimmed);
} }
}, },
stderr: (data) => { stderr: (data) => {
const trimmed = data.toString("utf-8").trimEnd(); const trimmed = data.toString("utf-8").trimEnd();
if (trimmed.length >= 0) { if (trimmed.length >= 0) {
actions_core.debug(trimmed); actionsCore.debug(trimmed);
} }
}, },
}, },
}); });
if (reload_exit_code !== 0) { if (reloadExitCode !== 0) {
throw new Error(`Non-zero exit code of \`${reload_exit_code}\` detected while ${action}.`); throw new Error(`Non-zero exit code of \`${reloadExitCode}\` detected while ${action}.`);
} }
}; };
await debug_root_run_throw("reloading udev rules", "udevadm", [ await debugRootRunThrow("reloading udev rules", "udevadm", [
"control", "control",
"--reload-rules", "--reload-rules",
]); ]);
await debug_root_run_throw("triggering udev against kvm", "udevadm", [ await debugRootRunThrow("triggering udev against kvm", "udevadm", [
"trigger", "trigger",
"--name-match=kvm", "--name-match=kvm",
]); ]);
return true; return true;
} }
catch (error) { catch (error) {
if (is_root) { if (isRoot) {
await actions_exec.exec("rm", ["-f", kvm_rules]); await actionsExec.exec("rm", ["-f", kvmRules]);
} }
else { else {
await actions_exec.exec("sudo", ["rm", "-f", kvm_rules]); await actionsExec.exec("sudo", ["rm", "-f", kvmRules]);
} }
return false; return false;
} }
} }
async fetch_binary() { async fetchBinary() {
if (!this.local_root) { if (!this.localRoot) {
return await this.idslib.fetchExecutable(); return await this.idslib.fetchExecutable();
} }
else { else {
const local_path = join(this.local_root, `nix-installer-${this.platform}`); const localPath = join(this.localRoot, `nix-installer-${this.platform}`);
actions_core.info(`Using binary ${local_path}`); actionsCore.info(`Using binary ${localPath}`);
return local_path; return localPath;
} }
} }
async report_overall() { async reportOverall() {
try { try {
this.idslib.recordEvent("conclude_workflow", { this.idslib.recordEvent("conclude_workflow", {
conclusion: await this.get_workflow_conclusion(), conclusion: await this.getWorkflowConclusion(),
}); });
} }
catch (error) { catch (error) {
actions_core.debug(`Error submitting post-run diagnostics report: ${error}`); actionsCore.debug(`Error submitting post-run diagnostics report: ${error}`);
} }
} }
async get_workflow_conclusion() { async getWorkflowConclusion() {
if (this.github_token == null) { if (this.githubToken == null) {
return undefined; return undefined;
} }
try { try {
const octokit = github.getOctokit(this.github_token); const octokit = github.getOctokit(this.githubToken);
const jobs = await octokit.paginate(octokit.rest.actions.listJobsForWorkflowRun, { const jobs = await octokit.paginate(octokit.rest.actions.listJobsForWorkflowRun, {
owner: github.context.repo.owner, owner: github.context.repo.owner,
repo: github.context.repo.repo, repo: github.context.repo.repo,
run_id: github.context.runId, run_id: github.context.runId,
}); });
actions_core.debug(`awaited jobs: ${jobs}`); actionsCore.debug(`awaited jobs: ${jobs}`);
const job = jobs const job = jobs
.filter((candidate) => candidate.name === github.context.job) .filter((candidate) => candidate.name === github.context.job)
.at(0); .at(0);
@ -712,40 +711,21 @@ class NixInstallerAction {
return "success"; return "success";
} }
catch (error) { catch (error) {
actions_core.debug(`Error determining final disposition: ${error}`); actionsCore.debug(`Error determining final disposition: ${error}`);
return "unavailable"; return "unavailable";
} }
} }
} }
function get_nix_platform() { function getDefaultPlanner() {
const env_os = process.env.RUNNER_OS; const envOs = process.env.RUNNER_OS;
const env_arch = process.env.RUNNER_ARCH; if (envOs === "macOS") {
if (env_os === "macOS" && env_arch === "X64") {
return "x86_64-darwin";
}
else if (env_os === "macOS" && env_arch === "ARM64") {
return "aarch64-darwin";
}
else if (env_os === "Linux" && env_arch === "X64") {
return "x86_64-linux";
}
else if (env_os === "Linux" && env_arch === "ARM64") {
return "aarch64-linux";
}
else {
throw new Error(`Unsupported \`RUNNER_OS\` (currently \`${env_os}\`) and \`RUNNER_ARCH\` (currently \`${env_arch}\`) combination`);
}
}
function get_default_planner() {
const env_os = process.env.RUNNER_OS;
if (env_os === "macOS") {
return "macos"; return "macos";
} }
else if (env_os === "Linux") { else if (envOs === "Linux") {
return "linux"; return "linux";
} }
else { else {
throw new Error(`Unsupported \`RUNNER_OS\` (currently \`${env_os}\`)`); throw new Error(`Unsupported \`RUNNER_OS\` (currently \`${envOs}\`)`);
} }
} }
function main() { function main() {
@ -756,7 +736,7 @@ function main() {
}); });
installer.idslib.onPost(async () => { installer.idslib.onPost(async () => {
await installer.cleanupDockerShim(); await installer.cleanupDockerShim();
await installer.report_overall(); await installer.reportOverall();
}); });
installer.idslib.execute(); installer.idslib.execute();
} }

File diff suppressed because it is too large Load diff