mirror of
https://github.com/DeterminateSystems/nix-installer-action.git
synced 2024-12-23 05:22:21 +01:00
KVM support out of the box, plus a refreshed README (#56)
* support kvm * Refresh the readme * Update README.md Co-authored-by: Ana Hobden <operator@hoverbear.org> * Update README.md Co-authored-by: Luc Perkins <lucperkins@gmail.com> * Update README.md --------- Co-authored-by: Ana Hobden <operator@hoverbear.org> Co-authored-by: Luc Perkins <lucperkins@gmail.com>
This commit is contained in:
parent
5620eb4af6
commit
07b8bcba1b
5 changed files with 240 additions and 15 deletions
62
README.md
62
README.md
|
@ -1,6 +1,19 @@
|
|||
# Nix Installer Action
|
||||
# The Determinate Nix Installer Action
|
||||
|
||||
You can use [`nix-installer`](https://github.com/DeterminateSystems/nix-installer) as a Github action like so:
|
||||
Based on the [Determinate Nix Installer](https://github.com/DeterminateSystems/nix-installer), responsible for over tens of thousands of Nix installs daily.
|
||||
The fast, friendly, and reliable GitHub Action to install Nix with Flakes.
|
||||
|
||||
## Supports
|
||||
|
||||
* ✅ **Accelerated KVM** on open source projects and larger runners. See [GitHub's announcement](https://github.blog/changelog/2023-02-23-hardware-accelerated-android-virtualization-on-actions-windows-and-linux-larger-hosted-runners/) for more info.
|
||||
* ✅ Linux, x86_64, aarch64, and i686
|
||||
* ✅ macOS, x86_64 and aarch64
|
||||
* ✅ WSL2, x86_64 and aarch64
|
||||
* ✅ Containers
|
||||
* ✅ Valve's SteamOS
|
||||
* ✅ GitHub Hosted, self-hosted, and long running Actions Runners
|
||||
|
||||
## Usage
|
||||
|
||||
```yaml
|
||||
on:
|
||||
|
@ -11,18 +24,16 @@ on:
|
|||
jobs:
|
||||
lints:
|
||||
name: Build
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
- name: Run `nix build`
|
||||
run: nix build .
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
- run: nix build .
|
||||
```
|
||||
|
||||
See [`.github/workflows/ci.yml`](.github/workflows/ci.yml) for a full example.
|
||||
### With FlakeHub
|
||||
|
||||
To use private flakes from FlakeHub, use a configuration like this:
|
||||
To fetch private flakes from FlakeHub, update the `permissions` block and pass `flakehub: true`:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
|
@ -33,20 +44,42 @@ on:
|
|||
jobs:
|
||||
lints:
|
||||
name: Build
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: "write"
|
||||
contents: "read"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
flakehub: true
|
||||
- name: Run `nix build`
|
||||
run: nix build .
|
||||
- run: nix build .
|
||||
```
|
||||
|
||||
See [`.github/workflows/ci.yml`](.github/workflows/ci.yml) for a full example.
|
||||
|
||||
### Advanced Usage
|
||||
|
||||
* If KVM is available, the installer sets up KVM so that Nix can use it ,and exports the `DETERMINATE_NIX_KVM` environment variable set to 1.
|
||||
If KVM is not available, `DETERMINATE_NIX_KVM` is set to 0.
|
||||
This can be used in combination with GitHub Actions' `if` syntax for turning on and off steps.
|
||||
|
||||
## Installation Differences
|
||||
|
||||
Differing from the upstream [Nix](https://github.com/NixOS/nix) installer scripts:
|
||||
|
||||
* In `nix.conf`:
|
||||
+ the `nix-command` and `flakes` features are enabled
|
||||
+ `bash-prompt-prefix` is set
|
||||
+ `auto-optimise-store` is set to `true` (On Linux only)
|
||||
* `extra-nix-path` is set to `nixpkgs=flake:nixpkgs`
|
||||
* `max-jobs` is set to `auto`
|
||||
* KVM is enabled by default.
|
||||
* an installation receipt (for uninstalling) is stored at `/nix/receipt.json` as well as a copy of the install binary at `/nix/nix-installer`
|
||||
* `nix-channel --update` is not run, `~/.nix-channels` is not provisioned
|
||||
* `ssl-cert-file` is set in `/etc/nix/nix.conf` if the `ssl-cert-file` argument is used.
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
| Parameter | Description | Type | Default |
|
||||
|
@ -57,6 +90,7 @@ jobs:
|
|||
| `flakehub` | Log in to FlakeHub to pull private flakes using the GitHub Actions [JSON Web Token](https://jwt.io) (JWT), which is bound to the `api.flakehub.com` audience. | Boolean | `false` |
|
||||
| `github-token` | A [GitHub token] for making authenticated requests (which have a higher rate-limit quota than unauthenticated requests) | string | `${{ github.token }}` |
|
||||
| `init` | The init system to configure (requires `planner: linux-multi`) | enum (`none` or `systemd`) | |
|
||||
| `kvm` | Automatically configure the GitHub Actions Runner for NixOS test support, if the host supports it. | Boolean | `true` |
|
||||
| `local-root` | A local `nix-installer` binary root. Overrides the `nix-installer-url` setting (a `nix-installer.sh` should exist, binaries should be named `nix-installer-$ARCH`, eg. `nix-installer-x86_64-linux`). | Boolean | `false` |
|
||||
| `log-directives` | A list of [tracing directives], comma separated with `-`s replaced with `_` (eg. `nix_installer=trace`) | string | |
|
||||
| `logger` | The logger to use during installation | enum (`pretty`, `json`, `full`, `compact`) | |
|
||||
|
|
|
@ -23,6 +23,10 @@ inputs:
|
|||
init:
|
||||
description: "The init system to configure, requires `planner: linux-multi` (allowing the choice between `none` or `systemd`)"
|
||||
required: false
|
||||
kvm:
|
||||
description: Automatically configure the GitHub Actions Runner for NixOS test supports, if the host supports it.
|
||||
required: false
|
||||
default: true
|
||||
local-root:
|
||||
description: A local `nix-installer` binary root, overrides any settings which change the `nix-installer` used (binaries should be named `nix-installer-$ARCH-$OS`, eg. `nix-installer-x86_64-linux`)
|
||||
required: false
|
||||
|
|
81
dist/index.js
vendored
81
dist/index.js
vendored
|
@ -41,6 +41,7 @@ class NixInstallerAction {
|
|||
this.extra_args = action_input_string_or_null("extra-args");
|
||||
this.extra_conf = action_input_multiline_string_or_null("extra-conf");
|
||||
this.flakehub = action_input_bool("flakehub");
|
||||
this.kvm = action_input_bool("kvm");
|
||||
this.github_token = action_input_string_or_null("github-token");
|
||||
this.init = action_input_string_or_null("init");
|
||||
this.local_root = action_input_string_or_null("local-root");
|
||||
|
@ -236,6 +237,20 @@ class NixInstallerAction {
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (this.kvm) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.startGroup("Configuring KVM");
|
||||
if (await this.setup_kvm()) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.endGroup();
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.info("\u001b[32m Accelerated KVM is enabled \u001b[33m⚡️");
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.exportVariable("DETERMINATE_NIX_KVM", "1");
|
||||
}
|
||||
else {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.endGroup();
|
||||
_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
|
||||
const binary_path = await this.fetch_binary();
|
||||
await this.execute_install(binary_path);
|
||||
|
@ -305,6 +320,72 @@ class NixInstallerAction {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
async setup_kvm() {
|
||||
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`,
|
||||
], {
|
||||
listeners: {
|
||||
stderr: (data) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug(trimmed);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
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 reload_exit_code = await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec(command, args, {
|
||||
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);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
if (reload_exit_code !== 0) {
|
||||
throw new Error(`Non-zero exit code of \`${reload_exit_code}\` detected while ${action}.`);
|
||||
}
|
||||
};
|
||||
await debug_run_throw("reloading udev rules", `sudo`, [
|
||||
"udevadm",
|
||||
"control",
|
||||
"--reload-rules",
|
||||
]);
|
||||
await debug_run_throw("triggering udev against kvm", `sudo`, [
|
||||
"udevadm",
|
||||
"trigger",
|
||||
"--name-match=kvm",
|
||||
]);
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__.exec("sudo", ["rm", "-f", kvm_rules], {
|
||||
listeners: {
|
||||
stderr: (data) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.info(trimmed);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
async fetch_binary() {
|
||||
if (!this.local_root) {
|
||||
_actions_core__WEBPACK_IMPORTED_MODULE_0__.info(`Fetching binary from ${this.nix_installer_url}`);
|
||||
|
|
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
106
src/main.ts
106
src/main.ts
|
@ -15,6 +15,7 @@ class NixInstallerAction {
|
|||
extra_args: string | null;
|
||||
extra_conf: string[] | null;
|
||||
flakehub: boolean;
|
||||
kvm: boolean;
|
||||
github_token: string | null;
|
||||
// TODO: linux_init
|
||||
init: string | null;
|
||||
|
@ -53,6 +54,7 @@ class NixInstallerAction {
|
|||
this.extra_args = action_input_string_or_null("extra-args");
|
||||
this.extra_conf = action_input_multiline_string_or_null("extra-conf");
|
||||
this.flakehub = action_input_bool("flakehub");
|
||||
this.kvm = action_input_bool("kvm");
|
||||
this.github_token = action_input_string_or_null("github-token");
|
||||
this.init = action_input_string_or_null("init");
|
||||
this.local_root = action_input_string_or_null("local-root");
|
||||
|
@ -305,6 +307,24 @@ class NixInstallerAction {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.kvm) {
|
||||
actions_core.startGroup("Configuring KVM");
|
||||
if (await this.setup_kvm()) {
|
||||
actions_core.endGroup();
|
||||
actions_core.info(
|
||||
"\u001b[32m Accelerated KVM is enabled \u001b[33m⚡️",
|
||||
);
|
||||
actions_core.exportVariable("DETERMINATE_NIX_KVM", "1");
|
||||
} else {
|
||||
actions_core.endGroup();
|
||||
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
|
||||
const binary_path = await this.fetch_binary();
|
||||
await this.execute_install(binary_path);
|
||||
|
@ -399,6 +419,92 @@ class NixInstallerAction {
|
|||
}
|
||||
}
|
||||
|
||||
private async setup_kvm(): Promise<boolean> {
|
||||
const kvm_rules =
|
||||
"/etc/udev/rules.d/99-determinate-nix-installer-kvm.rules";
|
||||
try {
|
||||
const write_file_exit_code = await actions_exec.exec(
|
||||
"sh",
|
||||
[
|
||||
"-c",
|
||||
`echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee ${kvm_rules} > /dev/null`,
|
||||
],
|
||||
{
|
||||
listeners: {
|
||||
stderr: (data: Buffer) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
actions_core.debug(trimmed);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
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: string,
|
||||
command: string,
|
||||
args: string[],
|
||||
): Promise<void> => {
|
||||
const reload_exit_code = await actions_exec.exec(command, args, {
|
||||
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);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (reload_exit_code !== 0) {
|
||||
throw new Error(
|
||||
`Non-zero exit code of \`${reload_exit_code}\` detected while ${action}.`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
await debug_run_throw("reloading udev rules", `sudo`, [
|
||||
"udevadm",
|
||||
"control",
|
||||
"--reload-rules",
|
||||
]);
|
||||
|
||||
await debug_run_throw("triggering udev against kvm", `sudo`, [
|
||||
"udevadm",
|
||||
"trigger",
|
||||
"--name-match=kvm",
|
||||
]);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
await actions_exec.exec("sudo", ["rm", "-f", kvm_rules], {
|
||||
listeners: {
|
||||
stderr: (data: Buffer) => {
|
||||
const trimmed = data.toString("utf-8").trimEnd();
|
||||
if (trimmed.length >= 0) {
|
||||
actions_core.info(trimmed);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private async fetch_binary(): Promise<string> {
|
||||
if (!this.local_root) {
|
||||
actions_core.info(`Fetching binary from ${this.nix_installer_url}`);
|
||||
|
|
Loading…
Reference in a new issue