Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| de22e16c47 | |||
| e279ba56d8 | |||
| f4a0ffe230 | |||
| ffea801f30 | |||
| 4126bb83b3 | |||
| 81ee88fd4a | |||
| 0f8fa3d242 | |||
| f576e90e2d | |||
| 161c1f6904 | |||
| 0e5b724979 | |||
| 21affdd5d3 |
@@ -16,15 +16,18 @@ jobs:
|
||||
- run: npm run all
|
||||
- run: git status --porcelain=v1
|
||||
- run: test $(git status --porcelain=v1 2>/dev/null | wc -l) -eq 0
|
||||
run-x86_64-linux:
|
||||
name: Run x86_64 Linux
|
||||
run-test-suite:
|
||||
name: Run test suite
|
||||
strategy:
|
||||
matrix:
|
||||
runner:
|
||||
- ubuntu-latest
|
||||
- nscloud-ubuntu-22.04-amd64-4x16
|
||||
- namespace-profile-default-arm64
|
||||
- ubuntu-latest
|
||||
- nscloud-ubuntu-22.04-amd64-4x16
|
||||
- namespace-profile-default-arm64
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Nix
|
||||
@@ -33,8 +36,15 @@ jobs:
|
||||
logger: pretty
|
||||
log-directives: nix_installer=trace
|
||||
backtrace: full
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
- name: echo $PATH
|
||||
run: echo $PATH
|
||||
|
||||
- name: Render the devshell
|
||||
if: success() || failure()
|
||||
run: |
|
||||
nix develop --command date
|
||||
|
||||
- name: Test `nix` with `$GITHUB_PATH`
|
||||
if: success() || failure()
|
||||
run: |
|
||||
@@ -43,6 +53,7 @@ jobs:
|
||||
hello
|
||||
nix store gc
|
||||
nix run nixpkgs#hello
|
||||
|
||||
- name: Test bash
|
||||
run: nix-instantiate -E 'builtins.currentTime' --eval
|
||||
if: success() || failure()
|
||||
@@ -91,6 +102,9 @@ jobs:
|
||||
run-x86_64-darwin:
|
||||
name: Run x86_64 Darwin
|
||||
runs-on: macos-12
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Nix
|
||||
@@ -99,6 +113,7 @@ jobs:
|
||||
logger: pretty
|
||||
log-directives: nix_installer=trace
|
||||
backtrace: full
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
- name: echo $PATH
|
||||
run: echo $PATH
|
||||
- name: Test `nix` with `$GITHUB_PATH`
|
||||
@@ -135,6 +150,10 @@ jobs:
|
||||
hello
|
||||
nix store gc
|
||||
nix run nixpkgs#hello
|
||||
- name: Terminate the magic nix cache pre-reinstall
|
||||
if: success() || failure()
|
||||
run: |
|
||||
pkill magic-nix-cache
|
||||
- name: Reinstall Nix
|
||||
uses: ./
|
||||
with:
|
||||
|
||||
+157
-25
@@ -98,23 +98,30 @@ class NixInstallerAction {
|
||||
}
|
||||
}
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Linux detected without systemd, testing for Docker with `docker info` as an alternative daemon supervisor.");
|
||||
const exit_code = await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec("docker", ["info"], {
|
||||
silent: true,
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug(trimmed);
|
||||
}
|
||||
let exit_code;
|
||||
try {
|
||||
exit_code = await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec("docker", ["info"], {
|
||||
silent: true,
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug(trimmed);
|
||||
}
|
||||
},
|
||||
stderr: (data) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug(trimmed);
|
||||
}
|
||||
},
|
||||
},
|
||||
stderr: (data) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug(trimmed);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Docker not detected, not enabling docker shim.");
|
||||
return;
|
||||
}
|
||||
if (exit_code !== 0) {
|
||||
if (this.force_docker_shim) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.warning("docker info check failed, but trying anyway since force-docker-shim is enabled.");
|
||||
@@ -123,6 +130,11 @@ class NixInstallerAction {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!this.force_docker_shim &&
|
||||
(await this.detectDockerWithMountedDockerSocket())) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Detected a Docker container with a Docker socket mounted, not enabling docker shim.");
|
||||
return;
|
||||
}
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.startGroup("Enabling the Docker shim for running Nix on Linux in CI without Systemd.");
|
||||
if (this.init !== "none") {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.info(`Changing init from '${this.init}' to 'none'`);
|
||||
@@ -135,6 +147,90 @@ class NixInstallerAction {
|
||||
this.force_docker_shim = true;
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.endGroup();
|
||||
}
|
||||
// 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.
|
||||
// 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.
|
||||
async detectDockerWithMountedDockerSocket() {
|
||||
let cgroups_buffer;
|
||||
try {
|
||||
// If we are inside a docker container, the last line of `/proc/self/cgroup` should be
|
||||
// 0::/docker/$SOME_ID
|
||||
//
|
||||
// If we are not, the line will likely be `0::/`
|
||||
cgroups_buffer = await (0,node_fs_promises__WEBPACK_IMPORTED_MODULE_4__.readFile)("/proc/self/cgroup", {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug(`Did not detect \`/proc/self/cgroup\` existence, bailing on docker container ID detection:\n${e}`);
|
||||
return false;
|
||||
}
|
||||
const cgroups = cgroups_buffer.trim().split("\n");
|
||||
const last_cgroup = cgroups[cgroups.length - 1];
|
||||
const last_cgroup_parts = last_cgroup.split(":");
|
||||
const last_cgroup_path = last_cgroup_parts[last_cgroup_parts.length - 1];
|
||||
if (!last_cgroup_path.includes("/docker/")) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Did not detect a container ID, bailing on docker.sock detection");
|
||||
return false;
|
||||
}
|
||||
// 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.
|
||||
const last_cgroup_path_parts = last_cgroup_path.split("/");
|
||||
const container_id = last_cgroup_path_parts[last_cgroup_path_parts.length - 1];
|
||||
// If we cannot `docker inspect` this discovered container ID, we'll fall through to the `catch` below.
|
||||
let stdout_buffer = "";
|
||||
let stderr_buffer = "";
|
||||
let exit_code;
|
||||
try {
|
||||
exit_code = await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec("docker", ["inspect", container_id], {
|
||||
silent: true,
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
stdout_buffer += data.toString("utf-8");
|
||||
},
|
||||
stderr: (data) => {
|
||||
stderr_buffer += data.toString("utf-8");
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug(`Could not execute \`docker inspect ${container_id}\`, bailing on docker container inspection:\n${e}`);
|
||||
return false;
|
||||
}
|
||||
if (exit_code !== 0) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug(`Unable to inspect detected docker container with id \`${container_id}\`, bailing on container inspection (exit ${exit_code}):\n${stderr_buffer}`);
|
||||
return false;
|
||||
}
|
||||
const output = JSON.parse(stdout_buffer);
|
||||
// `docker inspect $ID` prints an array containing objects.
|
||||
// In our use case, we should only see 1 item in the array.
|
||||
if (output.length !== 1) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug(`Got \`docker inspect ${container_id}\` output which was not one item (was ${output.length}), bailing on docker.sock detection.`);
|
||||
return false;
|
||||
}
|
||||
const item = output[0];
|
||||
// On this array item we want the `Mounts` field, which is an array
|
||||
// containing `{ Type, Source, Destination, Mode}`.
|
||||
// We are looking for a `Destination` ending with `docker.sock`.
|
||||
const mounts = item["Mounts"];
|
||||
if (typeof mounts !== "object") {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug(`Got non-object in \`Mounts\` field of \`docker inspect ${container_id}\` output, bailing on docker.sock detection.`);
|
||||
return false;
|
||||
}
|
||||
let found_docker_sock_mount = false;
|
||||
for (const mount of mounts) {
|
||||
const destination = mount["Destination"];
|
||||
if (typeof destination === "string") {
|
||||
if (destination.endsWith("docker.sock")) {
|
||||
found_docker_sock_mount = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found_docker_sock_mount;
|
||||
}
|
||||
async executionEnvironment() {
|
||||
const execution_env = {};
|
||||
execution_env.NIX_INSTALLER_NO_CONFIRM = "true";
|
||||
@@ -310,7 +406,6 @@ class NixInstallerAction {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.info("KVM is not available.");
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.exportVariable("DETERMINATE_NIX_KVM", "0");
|
||||
}
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.exportVariable("DETERMINATE_NIX_KVM", "0");
|
||||
}
|
||||
// Normal just doing of the install
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.startGroup("Installing Nix");
|
||||
@@ -368,9 +463,16 @@ class NixInstallerAction {
|
||||
"run",
|
||||
"--detach",
|
||||
"--privileged",
|
||||
"--network=host",
|
||||
"--userns=host",
|
||||
"--pid=host",
|
||||
"--mount",
|
||||
"type=bind,src=/bin,dst=/bin,readonly",
|
||||
"--mount",
|
||||
"type=bind,src=/lib,dst=/lib,readonly",
|
||||
"--mount",
|
||||
"type=bind,src=/home,dst=/home,readonly",
|
||||
"--mount",
|
||||
"type=bind,src=/tmp,dst=/tmp",
|
||||
"--mount",
|
||||
"type=bind,src=/nix,dst=/nix",
|
||||
@@ -413,7 +515,27 @@ class NixInstallerAction {
|
||||
const container_id = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getState("docker_shim_container_id");
|
||||
if (container_id !== "") {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.startGroup("Cleaning up the Nix daemon's Docker shim");
|
||||
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec("docker", ["rm", "--force", container_id]);
|
||||
let cleaned = false;
|
||||
try {
|
||||
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec("docker", ["rm", "--force", container_id]);
|
||||
cleaned = true;
|
||||
}
|
||||
catch (_a) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.warning("failed to cleanup nix daemon container");
|
||||
}
|
||||
if (!cleaned) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.info("trying to pkill the container's shim process");
|
||||
try {
|
||||
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec("pkill", [container_id]);
|
||||
cleaned = true;
|
||||
}
|
||||
catch (_b) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.warning("failed to forcibly kill the container's shim process");
|
||||
}
|
||||
}
|
||||
if (!cleaned) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.warning("Giving up on cleaning up the nix daemon container");
|
||||
}
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.endGroup();
|
||||
}
|
||||
}
|
||||
@@ -468,11 +590,14 @@ class NixInstallerAction {
|
||||
}
|
||||
}
|
||||
async setup_kvm() {
|
||||
const current_user = (0,node_os__WEBPACK_IMPORTED_MODULE_8__.userInfo)();
|
||||
const is_root = current_user.uid === 0;
|
||||
const maybe_sudo = is_root ? "" : "sudo";
|
||||
const kvm_rules = "/etc/udev/rules.d/99-determinate-nix-installer-kvm.rules";
|
||||
try {
|
||||
const write_file_exit_code = await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec("sh", [
|
||||
"-c",
|
||||
`echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee ${kvm_rules} > /dev/null`,
|
||||
`echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | ${maybe_sudo} tee ${kvm_rules} > /dev/null`,
|
||||
], {
|
||||
silent: true,
|
||||
listeners: {
|
||||
@@ -493,7 +618,11 @@ class NixInstallerAction {
|
||||
if (write_file_exit_code !== 0) {
|
||||
throw new Error(`Non-zero exit code of \`${write_file_exit_code}\` detected while writing '${kvm_rules}'`);
|
||||
}
|
||||
const debug_run_throw = async (action, command, args) => {
|
||||
const debug_root_run_throw = async (action, command, args) => {
|
||||
if (!is_root) {
|
||||
args = [command, ...args];
|
||||
command = "sudo";
|
||||
}
|
||||
const reload_exit_code = await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec(command, args, {
|
||||
silent: true,
|
||||
listeners: {
|
||||
@@ -515,20 +644,23 @@ class NixInstallerAction {
|
||||
throw new Error(`Non-zero exit code of \`${reload_exit_code}\` detected while ${action}.`);
|
||||
}
|
||||
};
|
||||
await debug_run_throw("reloading udev rules", `sudo`, [
|
||||
"udevadm",
|
||||
await debug_root_run_throw("reloading udev rules", "udevadm", [
|
||||
"control",
|
||||
"--reload-rules",
|
||||
]);
|
||||
await debug_run_throw("triggering udev against kvm", `sudo`, [
|
||||
"udevadm",
|
||||
await debug_root_run_throw("triggering udev against kvm", "udevadm", [
|
||||
"trigger",
|
||||
"--name-match=kvm",
|
||||
]);
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec("sudo", ["rm", "-f", kvm_rules]);
|
||||
if (is_root) {
|
||||
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec("rm", ["-f", kvm_rules]);
|
||||
}
|
||||
else {
|
||||
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec("sudo", ["rm", "-f", kvm_rules]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -9,7 +9,7 @@
|
||||
|
||||
outputs = { self, flake-schemas, nixpkgs }:
|
||||
let
|
||||
supportedSystems = [ "x86_64-linux" "aarch64-darwin" ];
|
||||
supportedSystems = [ "x86_64-linux" "aarch64-darwin" "aarch64-linux" "x86_64-darwin" ];
|
||||
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
});
|
||||
@@ -22,6 +22,7 @@
|
||||
packages = with pkgs; [
|
||||
nodejs_latest
|
||||
nixpkgs-fmt
|
||||
nodePackages_latest.typescript-language-server
|
||||
];
|
||||
};
|
||||
});
|
||||
|
||||
+186
-27
@@ -2,7 +2,7 @@ import * as actions_core from "@actions/core";
|
||||
import * as github from "@actions/github";
|
||||
import * as actions_tool_cache from "@actions/tool-cache";
|
||||
import * as actions_exec from "@actions/exec";
|
||||
import { chmod, access, writeFile } from "node:fs/promises";
|
||||
import { chmod, access, writeFile, readFile } from "node:fs/promises";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { join } from "node:path";
|
||||
import fs from "node:fs";
|
||||
@@ -129,23 +129,30 @@ class NixInstallerAction {
|
||||
actions_core.debug(
|
||||
"Linux detected without systemd, testing for Docker with `docker info` as an alternative daemon supervisor.",
|
||||
);
|
||||
const exit_code = await actions_exec.exec("docker", ["info"], {
|
||||
silent: true,
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
actions_core.debug(trimmed);
|
||||
}
|
||||
|
||||
let exit_code;
|
||||
try {
|
||||
exit_code = await actions_exec.exec("docker", ["info"], {
|
||||
silent: true,
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
actions_core.debug(trimmed);
|
||||
}
|
||||
},
|
||||
stderr: (data: Buffer) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
actions_core.debug(trimmed);
|
||||
}
|
||||
},
|
||||
},
|
||||
stderr: (data: Buffer) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
actions_core.debug(trimmed);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
actions_core.debug("Docker not detected, not enabling docker shim.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (exit_code !== 0) {
|
||||
if (this.force_docker_shim) {
|
||||
@@ -157,6 +164,16 @@ class NixInstallerAction {
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!this.force_docker_shim &&
|
||||
(await this.detectDockerWithMountedDockerSocket())
|
||||
) {
|
||||
actions_core.debug(
|
||||
"Detected a Docker container with a Docker socket mounted, not enabling docker shim.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
actions_core.startGroup(
|
||||
"Enabling the Docker shim for running Nix on Linux in CI without Systemd.",
|
||||
);
|
||||
@@ -175,6 +192,108 @@ class NixInstallerAction {
|
||||
actions_core.endGroup();
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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.
|
||||
async detectDockerWithMountedDockerSocket(): Promise<boolean> {
|
||||
let cgroups_buffer;
|
||||
try {
|
||||
// If we are inside a docker container, the last line of `/proc/self/cgroup` should be
|
||||
// 0::/docker/$SOME_ID
|
||||
//
|
||||
// If we are not, the line will likely be `0::/`
|
||||
cgroups_buffer = await readFile("/proc/self/cgroup", {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
} catch (e) {
|
||||
actions_core.debug(
|
||||
`Did not detect \`/proc/self/cgroup\` existence, bailing on docker container ID detection:\n${e}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
const cgroups = cgroups_buffer.trim().split("\n");
|
||||
const last_cgroup = cgroups[cgroups.length - 1];
|
||||
const last_cgroup_parts = last_cgroup.split(":");
|
||||
const last_cgroup_path = last_cgroup_parts[last_cgroup_parts.length - 1];
|
||||
if (!last_cgroup_path.includes("/docker/")) {
|
||||
actions_core.debug(
|
||||
"Did not detect a container ID, bailing on docker.sock detection",
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// 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.
|
||||
const last_cgroup_path_parts = last_cgroup_path.split("/");
|
||||
const container_id =
|
||||
last_cgroup_path_parts[last_cgroup_path_parts.length - 1];
|
||||
|
||||
// If we cannot `docker inspect` this discovered container ID, we'll fall through to the `catch` below.
|
||||
let stdout_buffer = "";
|
||||
let stderr_buffer = "";
|
||||
let exit_code;
|
||||
try {
|
||||
exit_code = await actions_exec.exec("docker", ["inspect", container_id], {
|
||||
silent: true,
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
stdout_buffer += data.toString("utf-8");
|
||||
},
|
||||
stderr: (data: Buffer) => {
|
||||
stderr_buffer += data.toString("utf-8");
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
actions_core.debug(
|
||||
`Could not execute \`docker inspect ${container_id}\`, bailing on docker container inspection:\n${e}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exit_code !== 0) {
|
||||
actions_core.debug(
|
||||
`Unable to inspect detected docker container with id \`${container_id}\`, bailing on container inspection (exit ${exit_code}):\n${stderr_buffer}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
const output = JSON.parse(stdout_buffer);
|
||||
// `docker inspect $ID` prints an array containing objects.
|
||||
// In our use case, we should only see 1 item in the array.
|
||||
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.`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
const item = output[0];
|
||||
// On this array item we want the `Mounts` field, which is an array
|
||||
// containing `{ Type, Source, Destination, Mode}`.
|
||||
// We are looking for a `Destination` ending with `docker.sock`.
|
||||
const mounts = item["Mounts"];
|
||||
if (typeof mounts !== "object") {
|
||||
actions_core.debug(
|
||||
`Got non-object in \`Mounts\` field of \`docker inspect ${container_id}\` output, bailing on docker.sock detection.`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
let found_docker_sock_mount = false;
|
||||
for (const mount of mounts) {
|
||||
const destination = mount["Destination"];
|
||||
if (typeof destination === "string") {
|
||||
if (destination.endsWith("docker.sock")) {
|
||||
found_docker_sock_mount = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found_docker_sock_mount;
|
||||
}
|
||||
|
||||
private async executionEnvironment(): Promise<ExecuteEnvironment> {
|
||||
const execution_env: ExecuteEnvironment = {};
|
||||
|
||||
@@ -394,8 +513,6 @@ class NixInstallerAction {
|
||||
actions_core.info("KVM is not available.");
|
||||
actions_core.exportVariable("DETERMINATE_NIX_KVM", "0");
|
||||
}
|
||||
|
||||
actions_core.exportVariable("DETERMINATE_NIX_KVM", "0");
|
||||
}
|
||||
|
||||
// Normal just doing of the install
|
||||
@@ -468,9 +585,16 @@ class NixInstallerAction {
|
||||
"run",
|
||||
"--detach",
|
||||
"--privileged",
|
||||
"--network=host",
|
||||
"--userns=host",
|
||||
"--pid=host",
|
||||
"--mount",
|
||||
"type=bind,src=/bin,dst=/bin,readonly",
|
||||
"--mount",
|
||||
"type=bind,src=/lib,dst=/lib,readonly",
|
||||
"--mount",
|
||||
"type=bind,src=/home,dst=/home,readonly",
|
||||
"--mount",
|
||||
"type=bind,src=/tmp,dst=/tmp",
|
||||
"--mount",
|
||||
"type=bind,src=/nix,dst=/nix",
|
||||
@@ -521,10 +645,35 @@ class NixInstallerAction {
|
||||
}
|
||||
async cleanupDockerShim(): Promise<void> {
|
||||
const container_id = actions_core.getState("docker_shim_container_id");
|
||||
|
||||
if (container_id !== "") {
|
||||
actions_core.startGroup("Cleaning up the Nix daemon's Docker shim");
|
||||
|
||||
await actions_exec.exec("docker", ["rm", "--force", container_id]);
|
||||
let cleaned = false;
|
||||
try {
|
||||
await actions_exec.exec("docker", ["rm", "--force", container_id]);
|
||||
cleaned = true;
|
||||
} catch {
|
||||
actions_core.warning("failed to cleanup nix daemon container");
|
||||
}
|
||||
|
||||
if (!cleaned) {
|
||||
actions_core.info("trying to pkill the container's shim process");
|
||||
try {
|
||||
await actions_exec.exec("pkill", [container_id]);
|
||||
cleaned = true;
|
||||
} catch {
|
||||
actions_core.warning(
|
||||
"failed to forcibly kill the container's shim process",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!cleaned) {
|
||||
actions_core.warning(
|
||||
"Giving up on cleaning up the nix daemon container",
|
||||
);
|
||||
}
|
||||
|
||||
actions_core.endGroup();
|
||||
}
|
||||
@@ -605,6 +754,10 @@ class NixInstallerAction {
|
||||
}
|
||||
|
||||
private async setup_kvm(): Promise<boolean> {
|
||||
const current_user = userInfo();
|
||||
const is_root = current_user.uid === 0;
|
||||
const maybe_sudo = is_root ? "" : "sudo";
|
||||
|
||||
const kvm_rules =
|
||||
"/etc/udev/rules.d/99-determinate-nix-installer-kvm.rules";
|
||||
try {
|
||||
@@ -612,7 +765,7 @@ class NixInstallerAction {
|
||||
"sh",
|
||||
[
|
||||
"-c",
|
||||
`echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee ${kvm_rules} > /dev/null`,
|
||||
`echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | ${maybe_sudo} tee ${kvm_rules} > /dev/null`,
|
||||
],
|
||||
{
|
||||
silent: true,
|
||||
@@ -639,11 +792,15 @@ class NixInstallerAction {
|
||||
);
|
||||
}
|
||||
|
||||
const debug_run_throw = async (
|
||||
const debug_root_run_throw = async (
|
||||
action: string,
|
||||
command: string,
|
||||
args: string[],
|
||||
): Promise<void> => {
|
||||
if (!is_root) {
|
||||
args = [command, ...args];
|
||||
command = "sudo";
|
||||
}
|
||||
const reload_exit_code = await actions_exec.exec(command, args, {
|
||||
silent: true,
|
||||
listeners: {
|
||||
@@ -669,21 +826,23 @@ class NixInstallerAction {
|
||||
}
|
||||
};
|
||||
|
||||
await debug_run_throw("reloading udev rules", `sudo`, [
|
||||
"udevadm",
|
||||
await debug_root_run_throw("reloading udev rules", "udevadm", [
|
||||
"control",
|
||||
"--reload-rules",
|
||||
]);
|
||||
|
||||
await debug_run_throw("triggering udev against kvm", `sudo`, [
|
||||
"udevadm",
|
||||
await debug_root_run_throw("triggering udev against kvm", "udevadm", [
|
||||
"trigger",
|
||||
"--name-match=kvm",
|
||||
]);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
await actions_exec.exec("sudo", ["rm", "-f", kvm_rules]);
|
||||
if (is_root) {
|
||||
await actions_exec.exec("rm", ["-f", kvm_rules]);
|
||||
} else {
|
||||
await actions_exec.exec("sudo", ["rm", "-f", kvm_rules]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user