Add action & Tune Tracing (#119)
* Add action * Checkout so we have actions.yml * yaml poking * Handle GITHUB_TOKEN * Don't ask github to do templating, use directives for logging * Missing changes * Fix build error * Fix yaml even more * Add shell command * Add a wait on the socket again * Print some debugging * Use more correct env vars * Correct install url logic * Use different style for inputs * Fix yaml errror * Tweak around local-root * provision nix-install.sh as well * Use nix-install.sh path directory in NIX_INSTALL_URL * Tweak variables to hopefully work * Call it BINARY_ROOT instead * Add exec output * Set no-confirm * no echo * Add token to workflow * Set no-confirm properly * Add no-confirm back for uninstall * Correct some env and vars * CreateDirectory respects existing symlink * Add a few more checks to the CI * pass valid yaml... * Slightly more aggressive cleanup of /nix * Ensure steam-deck cleans /home/nix * Add steam-deck check for persistence * Canonicalize steam-deck persistence * Ensure absolute path * Inverted logic sad * python3 on mac * Add readme info and fix a extra-conf mistype * Add unsaved changes * More fine grained trace logging * Restore spans we lost in refactor * BuiltinPlanner can accept settings * Reflect feedback * Push actually working code hopefully this time * Speeling
This commit is contained in:
parent
cc3521a798
commit
c4274c93fb
202
.github/workflows/ci.yml
vendored
202
.github/workflows/ci.yml
vendored
|
@ -5,14 +5,6 @@ on:
|
|||
push:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
NIX_INSTALL_FORCE_ALLOW_HTTP: "1"
|
||||
NIX_INSTALL_UPDATE_ROOT: "http://0.0.0.0:8000"
|
||||
RUST_BACKTRACE: "full"
|
||||
HARMONIC_VERBOSITY: "2"
|
||||
HARMONIC_NO_CONFIRM: "true"
|
||||
HARMONIC_LOGGER: "pretty"
|
||||
|
||||
jobs:
|
||||
lints:
|
||||
name: Lints
|
||||
|
@ -37,12 +29,6 @@ jobs:
|
|||
run: nix develop --store ~/.ci-store --command check-nixpkgs-fmt
|
||||
- name: Check EditorConfig conformance
|
||||
run: nix develop --store ~/.ci-store --command check-editorconfig
|
||||
- name: Create artifact for `nix-install.sh`
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nix-install
|
||||
path: |
|
||||
nix-install.sh
|
||||
|
||||
build-x86_64-linux:
|
||||
name: Build x86_64 Linux
|
||||
|
@ -102,29 +88,54 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
needs: [build-x86_64-linux, lints]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: sudo apt install fish zsh
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: harmonic-x86_64-linux
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: nix-install
|
||||
- name: Move & set executable
|
||||
run: |
|
||||
chmod +x ./harmonic
|
||||
mv harmonic harmonic-x86_64-linux
|
||||
mkdir install-root
|
||||
cp nix-install.sh install-root/nix-install.sh
|
||||
mv harmonic install-root/harmonic-x86_64-linux
|
||||
- name: Initial install
|
||||
run: |
|
||||
python -m http.server --bind 0.0.0.0 8000 &
|
||||
timeout 20 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/localhost/8000; do echo "Waiting for server..."; sleep 1; done'
|
||||
curl -L http://0.0.0.0:8000/nix-install.sh | sh -s -- install linux-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}"
|
||||
uses: ./
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
log-directives: harmonic=trace
|
||||
backtrace: full
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Initial uninstall (without a `nix run` first)
|
||||
run: sudo -E /nix/harmonic uninstall
|
||||
- name: Repeated install
|
||||
env:
|
||||
HARMONIC_NO_CONFIRM: true
|
||||
HARMONIC_LOGGER: pretty
|
||||
HARMONIC_LOG_DIRECTIVES: harmonic=trace
|
||||
RUST_BACKTRACE: full
|
||||
- name: Ensure `nix` is removed
|
||||
run: |
|
||||
python -m http.server --bind 0.0.0.0 8000 &
|
||||
timeout 20 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/localhost/8000; do echo "Waiting for server..."; sleep 1; done'
|
||||
curl -L http://0.0.0.0:8000/nix-install.sh | sh -s -- install linux-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}"
|
||||
if systemctl is-active nix-daemon.socket; then
|
||||
echo "nix-daemon.socket was still running"
|
||||
exit 1
|
||||
fi
|
||||
if systemctl is-active nix-daemon.service; then
|
||||
echo "nix-daemon.service was still running"
|
||||
exit 1
|
||||
fi
|
||||
if [ -e /nix ]; then
|
||||
echo "/nix exists"
|
||||
exit 1
|
||||
fi
|
||||
- name: Repeated install
|
||||
uses: ./
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
log-directives: harmonic=trace
|
||||
backtrace: full
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: echo $PATH
|
||||
run: echo $PATH
|
||||
- name: Test `nix` with `$GITHUB_PATH`
|
||||
|
@ -148,23 +159,42 @@ jobs:
|
|||
shell: fish --login {0}
|
||||
- name: Repeated uninstall
|
||||
run: sudo -E /nix/harmonic uninstall
|
||||
env:
|
||||
HARMONIC_NO_CONFIRM: true
|
||||
HARMONIC_LOGGER: pretty
|
||||
HARMONIC_LOG_DIRECTIVES: harmonic=trace
|
||||
RUST_BACKTRACE: full
|
||||
- name: Ensure `nix` is removed
|
||||
run: |
|
||||
if systemctl is-active nix-daemon.socket; then
|
||||
echo "nix-daemon.socket was still running"
|
||||
exit 1
|
||||
fi
|
||||
if systemctl is-active nix-daemon.service; then
|
||||
echo "nix-daemon.service was still running"
|
||||
exit 1
|
||||
fi
|
||||
if [ -e /nix ]; then
|
||||
echo "/nix exists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run-steam-deck:
|
||||
name: Run Steam Deck (mock)
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [build-x86_64-linux, lints]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: sudo apt install fish zsh
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: harmonic-x86_64-linux
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: nix-install
|
||||
- name: Move & set executable
|
||||
run: |
|
||||
chmod +x ./harmonic
|
||||
mv harmonic harmonic-x86_64-linux
|
||||
mkdir install-root
|
||||
cp nix-install.sh install-root/nix-install.sh
|
||||
mv harmonic install-root/harmonic-x86_64-linux
|
||||
- name: Make the CI look like a steam deck
|
||||
run: |
|
||||
mkdir -p ~/bin
|
||||
|
@ -172,17 +202,50 @@ jobs:
|
|||
sudo chmod +x /bin/steamos-readonly
|
||||
sudo useradd -m deck
|
||||
- name: Initial install
|
||||
run: |
|
||||
python -m http.server --bind 0.0.0.0 8000 &
|
||||
timeout 20 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/localhost/8000; do echo "Waiting for server..."; sleep 1; done'
|
||||
curl -L http://0.0.0.0:8000/nix-install.sh | sh -s -- install steam-deck --persistence `pwd`/ci-test-nix --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}"
|
||||
uses: ./
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
log-directives: harmonic=trace
|
||||
backtrace: full
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
planner: steam-deck
|
||||
extra-args: --persistence /home/runner/.ci-test-nix-home
|
||||
- name: Initial uninstall (without a `nix run` first)
|
||||
run: sudo -E /nix/harmonic uninstall
|
||||
- name: Repeated install
|
||||
env:
|
||||
HARMONIC_NO_CONFIRM: true
|
||||
HARMONIC_LOGGER: pretty
|
||||
HARMONIC_LOG_DIRECTIVES: harmonic=trace
|
||||
RUST_BACKTRACE: full
|
||||
- name: Ensure `nix` is removed
|
||||
run: |
|
||||
python -m http.server --bind 0.0.0.0 8000 &
|
||||
timeout 20 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/localhost/8000; do echo "Waiting for server..."; sleep 1; done'
|
||||
curl -L http://0.0.0.0:8000/nix-install.sh | sh -s -- install steam-deck --persistence `pwd`/ci-test-nix --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}"
|
||||
if systemctl is-active nix-daemon.socket; then
|
||||
echo "nix-daemon.socket was still running"
|
||||
exit 1
|
||||
fi
|
||||
if systemctl is-active nix-daemon.service; then
|
||||
echo "nix-daemon.service was still running"
|
||||
exit 1
|
||||
fi
|
||||
if [ -e /nix ]; then
|
||||
echo "/nix exists"
|
||||
exit 1
|
||||
fi
|
||||
if [ -e /home/runner/.ci-test-nix-home ]; then
|
||||
echo "/home/runner/.ci-test-nix-home exists"
|
||||
exit 1
|
||||
fi
|
||||
- name: Repeated install
|
||||
uses: ./
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
log-directives: harmonic=trace
|
||||
backtrace: full
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
planner: steam-deck
|
||||
extra-args: --persistence /home/runner/.ci-test-nix-home
|
||||
- name: echo $PATH
|
||||
run: echo $PATH
|
||||
- name: Test `nix` with `$GITHUB_PATH`
|
||||
|
@ -206,6 +269,29 @@ jobs:
|
|||
shell: fish --login {0}
|
||||
- name: Repeated uninstall
|
||||
run: sudo -E /nix/harmonic uninstall
|
||||
env:
|
||||
HARMONIC_NO_CONFIRM: true
|
||||
HARMONIC_LOGGER: pretty
|
||||
HARMONIC_LOG_DIRECTIVES: harmonic=trace
|
||||
RUST_BACKTRACE: full
|
||||
- name: Ensure `nix` is removed
|
||||
run: |
|
||||
if systemctl is-active nix-daemon.socket; then
|
||||
echo "nix-daemon.socket was still running"
|
||||
exit 1
|
||||
fi
|
||||
if systemctl is-active nix-daemon.service; then
|
||||
echo "nix-daemon.service was still running"
|
||||
exit 1
|
||||
fi
|
||||
if [ -e /nix ]; then
|
||||
echo "/nix exists"
|
||||
exit 1
|
||||
fi
|
||||
if [ -e /home/runner/.ci-test-nix-home ]; then
|
||||
echo "/home/runner/.ci-test-nix-home exists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
build-x86_64-darwin:
|
||||
name: Build x86_64 Darwin
|
||||
|
@ -231,29 +317,40 @@ jobs:
|
|||
runs-on: macos-12
|
||||
needs: [build-x86_64-darwin, lints]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: brew install fish coreutils
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: harmonic-x86_64-darwin
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: nix-install
|
||||
- name: Move & set executable
|
||||
run: |
|
||||
chmod +x ./harmonic
|
||||
mv harmonic harmonic-x86_64-darwin
|
||||
mkdir install-root
|
||||
cp nix-install.sh install-root/nix-install.sh
|
||||
mv harmonic install-root/harmonic-x86_64-darwin
|
||||
- name: Initial install
|
||||
run: |
|
||||
python3 -m http.server --bind 0.0.0.0 8000 &
|
||||
gtimeout 20 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/localhost/8000; do echo "Waiting for server..."; sleep 1; done'
|
||||
curl -L http://0.0.0.0:8000/nix-install.sh | sh -s -- install darwin-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}"
|
||||
uses: ./
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
log-directives: harmonic=trace
|
||||
backtrace: full
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Initial uninstall (without a `nix run` first)
|
||||
run: sudo -E /nix/harmonic uninstall
|
||||
env:
|
||||
HARMONIC_NO_CONFIRM: true
|
||||
HARMONIC_LOGGER: pretty
|
||||
HARMONIC_LOG_DIRECTIVES: harmonic=trace
|
||||
RUST_BACKTRACE: full
|
||||
- name: Repeated install
|
||||
run: |
|
||||
python -m http.server --bind 0.0.0.0 8000 &
|
||||
timeout 20 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/localhost/8000; do echo "Waiting for server..."; sleep 1; done'
|
||||
curl -L http://0.0.0.0:8000/nix-install.sh | sh -s -- install darwin-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}"
|
||||
uses: ./
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
log-directives: harmonic=trace
|
||||
backtrace: full
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: echo $PATH
|
||||
run: echo $PATH
|
||||
- name: Test `nix` with `$GITHUB_PATH`
|
||||
|
@ -277,4 +374,9 @@ jobs:
|
|||
shell: fish --login {0}
|
||||
- name: Repeated uninstall
|
||||
run: sudo -E /nix/harmonic uninstall
|
||||
env:
|
||||
HARMONIC_NO_CONFIRM: true
|
||||
HARMONIC_LOGGER: pretty
|
||||
HARMONIC_LOG_DIRECTIVES: harmonic=trace
|
||||
RUST_BACKTRACE: full
|
||||
|
24
README.md
24
README.md
|
@ -173,4 +173,28 @@ Documentation is also available via `nix` build:
|
|||
```bash
|
||||
nix build github:DeterminateSystems/harmonic#harmonic.doc
|
||||
firefox result-doc/harmonic/index.html
|
||||
```
|
||||
|
||||
## As a Github Action
|
||||
|
||||
You can use Harmonic as a Github action like so:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
lints:
|
||||
name: Build
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/harmonic@main
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Run `nix build`
|
||||
run: nix build .
|
||||
```
|
199
action.yml
Normal file
199
action.yml
Normal file
|
@ -0,0 +1,199 @@
|
|||
name: Harmonic
|
||||
description: Install Nix
|
||||
inputs:
|
||||
planner:
|
||||
description: A planner to use
|
||||
required: false
|
||||
extra-args:
|
||||
description: Extra args to pass to the planner (prefer using structured `with:` arguments unless using a custom planner!)
|
||||
required: false
|
||||
github-token:
|
||||
description: A Github Token so that authenticated requests can be made (set this to `secrets.GITHUB_TOKEN`)
|
||||
channels:
|
||||
description: Channel(s) to add (eg `nixpkgs=https://nixos.org/channels/nixpkgs-unstable`)
|
||||
required: false
|
||||
modify-profile:
|
||||
description: Modify the user profile to automatically load nix
|
||||
required: false
|
||||
daemon-user-count:
|
||||
description: Number of build users to create
|
||||
required: false
|
||||
nix-build-group-name:
|
||||
description: The Nix build group name
|
||||
required: false
|
||||
nix-build-group-id:
|
||||
description: The Nix build group GID
|
||||
required: false
|
||||
nix-build-user-prefix:
|
||||
description: The Nix build user prefix (user numbers will be postfixed)
|
||||
required: false
|
||||
nix-build-user-base:
|
||||
description: The Nix build user base UID (ascending)
|
||||
required: false
|
||||
nix-package-url:
|
||||
description: The Nix package URL
|
||||
required: false
|
||||
extra-conf:
|
||||
description: Extra configuration lines for `/etc/nix.conf` (includes `access-tokens` with `secrets.GITHUB_TOKEN` automatically if `github-token` is set)
|
||||
required: false
|
||||
mac-encrypt:
|
||||
description: Force encryption on the volume (Mac only)
|
||||
required: false
|
||||
mac-case-sensitive:
|
||||
description: Use a case sensitive volume (Mac only)
|
||||
required: false
|
||||
mac-volume-label:
|
||||
description: The label for the created APFS volume (Mac only)
|
||||
required: false
|
||||
mac-root-disk:
|
||||
description: The root disk of the target (Mac only)
|
||||
required: false
|
||||
nix-install-url:
|
||||
description: A URL pointing to a harmonic `nix-install.sh` script
|
||||
required: true
|
||||
default: https://install.determinate.systems/nix
|
||||
local-root:
|
||||
description: A local `harmonic` binary root, overrides the `nix-install` setting (binaries should be named `harmonic-$ARCH`, eg. `harmonic-x86_64-linux`)
|
||||
required: false
|
||||
logger:
|
||||
description: The logger to use for install (eg. `pretty`, `json`, `full`, `compact`)
|
||||
required: false
|
||||
log-directives:
|
||||
description: A list of Tracing directives, comma separated (eg. `harmonic=trace`, see https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives)
|
||||
required: false
|
||||
backtrace:
|
||||
description: The setting for `RUST_BACKTRACE` (see https://doc.rust-lang.org/std/backtrace/index.html#environment-variables)
|
||||
required: false
|
||||
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Install Nix
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -n "${{ inputs.channels }}" ]; then
|
||||
export HARMONIC_CHANNELS=${{ inputs.channels }}
|
||||
echo "Set HARMONIC_CHANNELS=$HARMONIC_CHANNELS"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.modify-profile }}" ]; then
|
||||
export HARMONIC_MODIFY_PROFILE=${{ inputs.modify-profile }}
|
||||
echo "Set HARMONIC_MODIFY_PROFILE=$HARMONIC_MODIFY_PROFILE"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.daemon-user-count }}" ]; then
|
||||
export HARMONIC_DAEMON_USER_COUNT=${{ inputs.daemon-user-count }}
|
||||
echo "Set HARMONIC_DAEMON_USER_COUNT=$HARMONIC_DAEMON_USER_COUNT"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.nix-build-group-name }}" ]; then
|
||||
export HARMONIC_NIX_BUILD_GROUP_NAME=${{ inputs.nix-build-group-name }}
|
||||
echo "Set HARMONIC_NIX_BUILD_GROUP_NAME=$HARMONIC_NIX_BUILD_GROUP_NAME"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.nix-build-group-id }}" ]; then
|
||||
export HARMONIC_NIX_BUILD_GROUP_ID=${{ inputs.nix-build-group-id }}
|
||||
echo "Set HARMONIC_NIX_BUILD_GROUP_ID=$HARMONIC_NIX_BUILD_GROUP_ID"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.nix-build-user-prefix }}" ]; then
|
||||
export HARMONIC_NIX_BUILD_USER_ID_BASE=${{ inputs.nix-build-user-prefix }}
|
||||
echo "Set HARMONIC_NIX_BUILD_USER_ID_BASE=$HARMONIC_NIX_BUILD_USER_ID_BASE"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.nix-build-user-base }}" ]; then
|
||||
export HARMONIC_NIX_BUILD_USER_PREFIX=${{ inputs.nix-build-user-base }}
|
||||
echo "Set HARMONIC_NIX_BUILD_USER_PREFIX=$HARMONIC_NIX_BUILD_USER_PREFIX"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.nix-package-url }}" ]; then
|
||||
export HARMONIC_NIX_PACKAGE_URL=${{ inputs.nix-package-url }}
|
||||
echo "Set HARMONIC_NIX_PACKAGE_URL=$HARMONIC_NIX_PACKAGE_URL"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.extra-conf }}" ]; then
|
||||
if [ -n "${{ inputs.github-token }}" ]; then
|
||||
export HARMONIC_EXTRA_CONF="${{ inputs.extra-conf }}\naccess-tokens = github.com=${{ inputs.github-token }}"
|
||||
else
|
||||
export HARMONIC_EXTRA_CONF="${{ inputs.extra-conf }}"
|
||||
fi
|
||||
echo "Set HARMONIC_EXTRA_CONF=$HARMONIC_EXTRA_CONF"
|
||||
else
|
||||
if [ -n "${{ inputs.github-token }}" ]; then
|
||||
export HARMONIC_EXTRA_CONF="access-tokens = github.com=${{ inputs.github-token }}"
|
||||
echo "Set HARMONIC_EXTRA_CONF=$HARMONIC_EXTRA_CONF"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.mac-encrypt }}" ]; then
|
||||
export HARMONIC_ENCRYPT=${{ inputs.mac-encrypt }}
|
||||
echo "Set HARMONIC_ENCRYPT=$HARMONIC_ENCRYPT"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.mac-case-sensitive }}" ]; then
|
||||
export HARMONIC_CASE_SENSITIVE=${{ inputs.mac-case-sensitive }}
|
||||
echo "Set HARMONIC_CASE_SENSITIVE=$HARMONIC_CASE_SENSITIVE"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.mac-volume-label }}" ]; then
|
||||
export HARMONIC_VOLUME_LABEL=${{ inputs.mac-volume-label }}
|
||||
echo "Set HARMONIC_VOLUME_LABEL=$HARMONIC_VOLUME_LABEL"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.mac-root-disk }}" ]; then
|
||||
export HARMONIC_ROOT_DISK=${{ inputs.mac-root-disk }}
|
||||
echo "Set HARMONIC_ROOT_DISK=$HARMONIC_ROOT_DISK"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.local-root }}" ]; then
|
||||
if [ "$RUNNER_OS" == "macOS" ]; then
|
||||
export PYTHON="python3"
|
||||
else
|
||||
export PYTHON="python"
|
||||
fi
|
||||
$PYTHON -m http.server --directory ${{ inputs.local-root }} --bind 0.0.0.0 8000 &
|
||||
export HTTP_PID=$!
|
||||
echo "Started simple http server for ${{ inputs.local-root }} on 0.0.0.0:8000"
|
||||
while (! (: </dev/tcp/localhost/8000) &> /dev/null); do
|
||||
sleep 1
|
||||
done
|
||||
export NIX_INSTALL_FORCE_ALLOW_HTTP="1"
|
||||
echo "Set NIX_INSTALL_FORCE_ALLOW_HTTP=$NIX_INSTALL_FORCE_ALLOW_HTTP"
|
||||
export NIX_INSTALL_URL=0.0.0.0:8000/nix-install.sh
|
||||
echo "Set NIX_INSTALL_URL=$NIX_INSTALL_URL"
|
||||
export NIX_INSTALL_BINARY_ROOT=http://0.0.0.0:8000/
|
||||
echo "Set NIX_INSTALL_BINARY_ROOT=$NIX_INSTALL_BINARY_ROOT"
|
||||
export NIX_INSTALL_FORCE_ALLOW_HTTP=1
|
||||
echo "Set NIX_INSTALL_FORCE_ALLOW_HTTP=$NIX_INSTALL_FORCE_ALLOW_HTTP"
|
||||
else
|
||||
export NIX_INSTALL_URL=${{ inputs.nix-install-url }}
|
||||
echo "Set NIX_INSTALL_URL=$NIX_INSTALL_URL"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.logger }}" ]; then
|
||||
export HARMONIC_LOGGER=${{ inputs.logger }}
|
||||
echo "Set HARMONIC_LOGGER=$HARMONIC_LOGGER"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.log-directives }}" ]; then
|
||||
export HARMONIC_LOG_DIRECTIVES=${{ inputs.log-directives }}
|
||||
echo "Set HARMONIC_LOG_DIRECTIVES=$HARMONIC_LOG_DIRECTIVES"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.backtrace }}" ]; then
|
||||
export RUST_BACKTRACE=${{ inputs.backtrace }}
|
||||
echo "Set RUST_BACKTRACE=$RUST_BACKTRACE"
|
||||
fi
|
||||
|
||||
export HARMONIC_NO_CONFIRM=true
|
||||
echo "Set HARMONIC_NO_CONFIRM=$HARMONIC_NO_CONFIRM"
|
||||
|
||||
curl --retry 20 -L $NIX_INSTALL_URL | sh -s -- install ${{ inputs.planner }} ${{ inputs.extra-args }}
|
||||
|
||||
if [ -n "$HTTP_PID" ]; then
|
||||
kill $HTTP_PID
|
||||
fi
|
||||
|
||||
|
||||
|
|
@ -21,8 +21,8 @@ fi
|
|||
|
||||
set -u
|
||||
|
||||
# If NIX_INSTALL_UPDATE_ROOT is unset or empty, default it.
|
||||
NIX_INSTALL_UPDATE_ROOT="${NIX_INSTALL_UPDATE_ROOT:-https://install.determinate.systems/nix}"
|
||||
# If NIX_INSTALL_BINARY_ROOT is unset or empty, default it.
|
||||
NIX_INSTALL_BINARY_ROOT="${NIX_INSTALL_BINARY_ROOT:-https://install.determinate.systems/nix}"
|
||||
|
||||
main() {
|
||||
downloader --check
|
||||
|
@ -44,7 +44,7 @@ main() {
|
|||
;;
|
||||
esac
|
||||
|
||||
local _url="${NIX_INSTALL_OVERRIDE_URL-${NIX_INSTALL_UPDATE_ROOT}/harmonic-${_arch}${_ext}}"
|
||||
local _url="${NIX_INSTALL_OVERRIDE_URL-${NIX_INSTALL_BINARY_ROOT}/harmonic-${_arch}${_ext}}"
|
||||
|
||||
local _dir
|
||||
if ! _dir="$(ensure mktemp -d)"; then
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::path::{Path, PathBuf};
|
|||
use nix::unistd::{chown, Group, User};
|
||||
|
||||
use tokio::fs::{create_dir, remove_dir_all};
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionState};
|
||||
use crate::action::{ActionError, StatefulAction};
|
||||
|
@ -74,16 +75,24 @@ impl Action for CreateDirectory {
|
|||
format!("Create directory `{}`", self.path.display())
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"create_directory",
|
||||
path = tracing::field::display(self.path.display()),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = self
|
||||
.mode
|
||||
.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
path,
|
||||
|
@ -150,12 +159,7 @@ impl Action for CreateDirectory {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
path,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use nix::unistd::{chown, Group, User};
|
||||
use tracing::{span, Span};
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use tokio::{
|
||||
|
@ -58,16 +59,31 @@ impl Action for CreateFile {
|
|||
fn tracing_synopsis(&self) -> String {
|
||||
format!("Create or overwrite file `{}`", self.path.display())
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
let span = span!(
|
||||
tracing::Level::DEBUG,
|
||||
"create_file",
|
||||
path = tracing::field::display(self.path.display()),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = self
|
||||
.mode
|
||||
.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
buf = tracing::field::Empty,
|
||||
);
|
||||
|
||||
if tracing::enabled!(tracing::Level::TRACE) {
|
||||
span.record("buf", &self.buf);
|
||||
}
|
||||
span
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
path,
|
||||
|
@ -78,6 +94,11 @@ impl Action for CreateFile {
|
|||
force: _,
|
||||
} = self;
|
||||
|
||||
if tracing::enabled!(tracing::Level::TRACE) {
|
||||
let span = tracing::Span::current();
|
||||
span.record("buf", &buf);
|
||||
}
|
||||
|
||||
let mut options = OpenOptions::new();
|
||||
options.create_new(true).write(true).read(true);
|
||||
|
||||
|
@ -135,12 +156,7 @@ impl Action for CreateFile {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
path,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::ActionError;
|
||||
use crate::execute_command;
|
||||
|
@ -37,10 +38,16 @@ impl Action for CreateGroup {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
user = self.name,
|
||||
gid = self.gid,
|
||||
))]
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"create_group",
|
||||
user = self.name,
|
||||
gid = self.gid,
|
||||
)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self { name, gid } = self;
|
||||
|
||||
|
@ -108,10 +115,7 @@ impl Action for CreateGroup {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
user = self.name,
|
||||
gid = self.gid,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self { name, gid: _ } = self;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use nix::unistd::{chown, Group, User};
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, StatefulAction};
|
||||
use std::{
|
||||
io::SeekFrom,
|
||||
os::unix::prelude::PermissionsExt,
|
||||
|
@ -9,8 +10,7 @@ use tokio::{
|
|||
fs::{remove_file, OpenOptions},
|
||||
io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt},
|
||||
};
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, StatefulAction};
|
||||
use tracing::{span, Span};
|
||||
|
||||
/** Create a file at the given location with the provided `buf`,
|
||||
optionally with an owning user, group, and mode.
|
||||
|
@ -58,16 +58,30 @@ impl Action for CreateOrAppendFile {
|
|||
format!("Create or append file `{}`", self.path.display())
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
let span = span!(
|
||||
tracing::Level::DEBUG,
|
||||
"create_or_append_file",
|
||||
path = tracing::field::display(self.path.display()),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = self
|
||||
.mode
|
||||
.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
buf = tracing::field::Empty,
|
||||
);
|
||||
|
||||
if tracing::enabled!(tracing::Level::TRACE) {
|
||||
span.record("buf", &self.buf);
|
||||
}
|
||||
span
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
path,
|
||||
|
@ -142,12 +156,7 @@ impl Action for CreateOrAppendFile {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
path,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::ActionError;
|
||||
use crate::execute_command;
|
||||
|
@ -38,6 +39,18 @@ impl Action for CreateUser {
|
|||
self.name, self.uid, self.groupname, self.gid
|
||||
)
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"create_user",
|
||||
user = self.name,
|
||||
uid = self.uid,
|
||||
groupname = self.groupname,
|
||||
gid = self.gid,
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
self.tracing_synopsis(),
|
||||
|
@ -47,12 +60,7 @@ impl Action for CreateUser {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
user = self.name,
|
||||
uid = self.uid,
|
||||
groupname = self.groupname,
|
||||
gid = self.gid,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
name,
|
||||
|
@ -231,11 +239,7 @@ impl Action for CreateUser {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
user = self.name,
|
||||
uid = self.uid,
|
||||
gid = self.gid,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
name,
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::path::PathBuf;
|
|||
|
||||
use bytes::Buf;
|
||||
use reqwest::Url;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, StatefulAction};
|
||||
|
||||
|
@ -31,14 +32,20 @@ impl Action for FetchAndUnpackNix {
|
|||
format!("Fetch `{}` to `{}`", self.url, self.dest.display())
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"fetch_and_unpack_nix",
|
||||
url = tracing::field::display(&self.url),
|
||||
dest = tracing::field::display(self.dest.display()),
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
url = %self.url,
|
||||
dest = %self.dest.display(),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self { url, dest } = self;
|
||||
|
||||
|
@ -66,10 +73,7 @@ impl Action for FetchAndUnpackNix {
|
|||
vec![/* Deliberately empty -- this is a noop */]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
url = %self.url,
|
||||
dest = %self.dest.display(),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self { url: _, dest: _ } = self;
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, StatefulAction};
|
||||
|
||||
const DEST: &str = "/nix/store";
|
||||
|
@ -27,6 +29,15 @@ impl Action for MoveUnpackedNix {
|
|||
"Move the downloaded Nix into `/nix`".to_string()
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"mount_unpacked_nix",
|
||||
src = tracing::field::display(self.src.display()),
|
||||
dest = DEST,
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
format!("Move the downloaded Nix into `/nix`"),
|
||||
|
@ -37,10 +48,7 @@ impl Action for MoveUnpackedNix {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
src = %self.src.display(),
|
||||
dest = DEST,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self { src } = self;
|
||||
|
||||
|
@ -73,10 +81,7 @@ impl Action for MoveUnpackedNix {
|
|||
vec![/* Deliberately empty -- this is a noop */]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
src = %self.src.display(),
|
||||
dest = DEST,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
// Noop
|
||||
Ok(())
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
|||
use glob::glob;
|
||||
|
||||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{Action, ActionDescription};
|
||||
|
||||
|
@ -31,13 +32,19 @@ impl Action for SetupDefaultProfile {
|
|||
"Setup the default Nix profile".to_string()
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"setup_default_profile",
|
||||
channels = self.channels.join(","),
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
channels = %self.channels.join(","),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self { channels } = self;
|
||||
|
||||
|
@ -156,9 +163,7 @@ impl Action for SetupDefaultProfile {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
channels = %self.channels.join(","),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
std::env::remove_var("NIX_SSL_CERT_FILE");
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ use crate::{
|
|||
};
|
||||
|
||||
use reqwest::Url;
|
||||
use tracing::{span, Instrument, Span};
|
||||
|
||||
/**
|
||||
Configure Nix and start it
|
||||
|
@ -68,6 +69,10 @@ impl Action for ConfigureNix {
|
|||
"Configure Nix".to_string()
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(tracing::Level::DEBUG, "configure_nix",)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
let Self {
|
||||
setup_default_profile,
|
||||
|
@ -98,17 +103,67 @@ impl Action for ConfigureNix {
|
|||
} = self;
|
||||
|
||||
if let Some(configure_shell_profile) = configure_shell_profile {
|
||||
let setup_default_profile_span = tracing::Span::current().clone();
|
||||
let (
|
||||
place_nix_configuration_span,
|
||||
place_channel_configuration_span,
|
||||
configure_shell_profile_span,
|
||||
) = (
|
||||
setup_default_profile_span.clone(),
|
||||
setup_default_profile_span.clone(),
|
||||
setup_default_profile_span.clone(),
|
||||
);
|
||||
tokio::try_join!(
|
||||
async move { setup_default_profile.try_execute().await },
|
||||
async move { place_nix_configuration.try_execute().await },
|
||||
async move { place_channel_configuration.try_execute().await },
|
||||
async move { configure_shell_profile.try_execute().await },
|
||||
async move {
|
||||
setup_default_profile
|
||||
.try_execute()
|
||||
.instrument(setup_default_profile_span)
|
||||
.await
|
||||
},
|
||||
async move {
|
||||
place_nix_configuration
|
||||
.try_execute()
|
||||
.instrument(place_nix_configuration_span)
|
||||
.await
|
||||
},
|
||||
async move {
|
||||
place_channel_configuration
|
||||
.try_execute()
|
||||
.instrument(place_channel_configuration_span)
|
||||
.await
|
||||
},
|
||||
async move {
|
||||
configure_shell_profile
|
||||
.try_execute()
|
||||
.instrument(configure_shell_profile_span)
|
||||
.await
|
||||
},
|
||||
)?;
|
||||
} else {
|
||||
let place_channel_configuration_span = tracing::Span::current().clone();
|
||||
let (setup_default_profile_span, place_nix_configuration_span) = (
|
||||
place_channel_configuration_span.clone(),
|
||||
place_channel_configuration_span.clone(),
|
||||
);
|
||||
tokio::try_join!(
|
||||
async move { setup_default_profile.try_execute().await },
|
||||
async move { place_nix_configuration.try_execute().await },
|
||||
async move { place_channel_configuration.try_execute().await },
|
||||
async move {
|
||||
setup_default_profile
|
||||
.try_execute()
|
||||
.instrument(setup_default_profile_span)
|
||||
.await
|
||||
},
|
||||
async move {
|
||||
place_nix_configuration
|
||||
.try_execute()
|
||||
.instrument(place_nix_configuration_span)
|
||||
.await
|
||||
},
|
||||
async move {
|
||||
place_channel_configuration
|
||||
.try_execute()
|
||||
.instrument(place_channel_configuration_span)
|
||||
.await
|
||||
},
|
||||
)?;
|
||||
};
|
||||
configure_nix_daemon_service.try_execute().await?;
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::action::{Action, ActionDescription, ActionError, StatefulAction};
|
|||
use nix::unistd::User;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tokio::task::JoinSet;
|
||||
use tracing::{span, Instrument, Span};
|
||||
|
||||
// Fish has different syntax than zsh/bash, treat it separate
|
||||
const PROFILE_FISH_SUFFIX: &str = "conf.d/nix.fish";
|
||||
|
@ -141,6 +142,10 @@ impl Action for ConfigureShellProfile {
|
|||
"Configure the shell profiles".to_string()
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(tracing::Level::DEBUG, "configure_shell_profile",)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
self.tracing_synopsis(),
|
||||
|
@ -166,8 +171,10 @@ impl Action for ConfigureShellProfile {
|
|||
let span = tracing::Span::current().clone();
|
||||
let mut create_or_append_file_clone = create_or_append_file.clone();
|
||||
let _abort_handle = set.spawn(async move {
|
||||
let _ = span.enter();
|
||||
create_or_append_file_clone.try_execute().await?;
|
||||
create_or_append_file_clone
|
||||
.try_execute()
|
||||
.instrument(span)
|
||||
.await?;
|
||||
Result::<_, ActionError>::Ok((idx, create_or_append_file_clone))
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::base::CreateDirectory;
|
||||
use crate::action::{Action, ActionDescription, ActionError, StatefulAction};
|
||||
|
||||
|
@ -45,6 +47,10 @@ impl Action for CreateNixTree {
|
|||
"Create a directory tree in `/nix`".to_string()
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(tracing::Level::DEBUG, "create_nix_tree",)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
self.tracing_synopsis(),
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
|||
settings::CommonSettings,
|
||||
};
|
||||
use tokio::task::JoinSet;
|
||||
use tracing::{span, Instrument, Span};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateUsersAndGroups {
|
||||
|
@ -62,6 +63,18 @@ impl Action for CreateUsersAndGroups {
|
|||
)
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"create_users_and_group",
|
||||
daemon_user_count = self.daemon_user_count,
|
||||
nix_build_group_name = self.nix_build_group_name,
|
||||
nix_build_group_id = self.nix_build_group_id,
|
||||
nix_build_user_prefix = self.nix_build_user_prefix,
|
||||
nix_build_user_id_base = self.nix_build_user_id_base,
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
let Self {
|
||||
daemon_user_count: _,
|
||||
|
@ -91,13 +104,7 @@ impl Action for CreateUsersAndGroups {
|
|||
vec![ActionDescription::new(self.tracing_synopsis(), explanation)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
daemon_user_count = self.daemon_user_count,
|
||||
nix_build_group_name = self.nix_build_group_name,
|
||||
nix_build_group_id = self.nix_build_group_id,
|
||||
nix_build_user_prefix = self.nix_build_user_prefix,
|
||||
nix_build_user_id_base = self.nix_build_user_id_base,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
create_users,
|
||||
|
@ -129,9 +136,10 @@ impl Action for CreateUsersAndGroups {
|
|||
let mut set = JoinSet::new();
|
||||
let mut errors: Vec<Box<ActionError>> = Vec::new();
|
||||
for (idx, create_user) in create_users.iter_mut().enumerate() {
|
||||
let span = tracing::Span::current().clone();
|
||||
let mut create_user_clone = create_user.clone();
|
||||
let _abort_handle = set.spawn(async move {
|
||||
create_user_clone.try_execute().await?;
|
||||
create_user_clone.try_execute().instrument(span).await?;
|
||||
Result::<_, _>::Ok((idx, create_user_clone))
|
||||
});
|
||||
}
|
||||
|
@ -188,13 +196,7 @@ impl Action for CreateUsersAndGroups {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
daemon_user_count = self.daemon_user_count,
|
||||
nix_build_group_name = self.nix_build_group_name,
|
||||
nix_build_group_id = self.nix_build_group_id,
|
||||
nix_build_user_prefix = self.nix_build_user_prefix,
|
||||
nix_build_user_id_base = self.nix_build_user_id_base,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
create_users,
|
||||
|
@ -210,9 +212,10 @@ impl Action for CreateUsersAndGroups {
|
|||
let mut errors = Vec::default();
|
||||
|
||||
for (idx, create_user) in create_users.iter().enumerate() {
|
||||
let span = tracing::Span::current().clone();
|
||||
let mut create_user_clone = create_user.clone();
|
||||
let _abort_handle = set.spawn(async move {
|
||||
create_user_clone.try_revert().await?;
|
||||
create_user_clone.try_revert().instrument(span).await?;
|
||||
Result::<_, ActionError>::Ok((idx, create_user_clone))
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::action::base::CreateFile;
|
|||
use crate::action::ActionError;
|
||||
use crate::action::{Action, ActionDescription, StatefulAction};
|
||||
use reqwest::Url;
|
||||
use tracing::{span, Span};
|
||||
|
||||
/**
|
||||
Place a channel configuration containing `channels` to the `$ROOT_HOME/.nix-channels` file
|
||||
|
@ -54,13 +55,24 @@ impl Action for PlaceChannelConfiguration {
|
|||
)
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"place_channel_configuration",
|
||||
channels = self
|
||||
.channels
|
||||
.iter()
|
||||
.map(|(c, u)| format!("{c}={u}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
channels = self.channels.iter().map(|(c, u)| format!("{c}={u}")).collect::<Vec<_>>().join(", "),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
create_file,
|
||||
|
@ -82,9 +94,7 @@ impl Action for PlaceChannelConfiguration {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
channels = self.channels.iter().map(|(c, u)| format!("{c}={u}")).collect::<Vec<_>>().join(", "),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
create_file,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::base::{CreateDirectory, CreateFile};
|
||||
use crate::action::{Action, ActionDescription, ActionError, StatefulAction};
|
||||
|
||||
|
@ -50,6 +52,10 @@ impl Action for PlaceNixConfiguration {
|
|||
format!("Place the Nix configuration in `{NIX_CONF}`")
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(tracing::Level::DEBUG, "place_nix_configuration",)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
self.tracing_synopsis(),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use tracing::{span, Span};
|
||||
|
||||
use super::{CreateNixTree, CreateUsersAndGroups};
|
||||
use crate::{
|
||||
action::{
|
||||
|
@ -48,6 +50,10 @@ impl Action for ProvisionNix {
|
|||
"Provision Nix".to_string()
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(tracing::Level::DEBUG, "provision_nix",)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
let Self {
|
||||
fetch_nix,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{ActionError, StatefulAction};
|
||||
use crate::execute_command;
|
||||
|
@ -32,13 +33,19 @@ impl Action for BootstrapApfsVolume {
|
|||
format!("Bootstrap and kickstart `{}`", self.path.display())
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"bootstrap_volume",
|
||||
path = %self.path.display(),
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
path = %self.path.display(),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self { path } = self;
|
||||
|
||||
|
@ -70,9 +77,7 @@ impl Action for BootstrapApfsVolume {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
path = %self.path.display(),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self { path } = self;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{ActionError, StatefulAction};
|
||||
use crate::execute_command;
|
||||
|
@ -41,15 +42,21 @@ impl Action for CreateApfsVolume {
|
|||
)
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"create_volume",
|
||||
disk = %self.disk.display(),
|
||||
name = %self.name,
|
||||
case_sensitive = %self.case_sensitive,
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
disk = %self.disk.display(),
|
||||
name = %self.name,
|
||||
case_sensitive = %self.case_sensitive,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
disk,
|
||||
|
@ -91,11 +98,7 @@ impl Action for CreateApfsVolume {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
disk = %self.disk.display(),
|
||||
name = %self.name,
|
||||
case_sensitive = %self.case_sensitive,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
disk: _,
|
||||
|
|
|
@ -11,6 +11,7 @@ use std::{
|
|||
time::Duration,
|
||||
};
|
||||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
pub const NIX_VOLUME_MOUNTD_DEST: &str = "/Library/LaunchDaemons/org.nixos.darwin-store.plist";
|
||||
|
||||
|
@ -143,6 +144,15 @@ impl Action for CreateNixVolume {
|
|||
)
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"create_apfs_volume",
|
||||
disk = tracing::field::display(self.disk.display()),
|
||||
name = self.name
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
let Self {
|
||||
disk: _, name: _, ..
|
||||
|
@ -150,7 +160,7 @@ impl Action for CreateNixVolume {
|
|||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(destination,))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
disk: _,
|
||||
|
@ -213,7 +223,7 @@ impl Action for CreateNixVolume {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(disk, name))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
disk: _,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::execute_command;
|
||||
|
||||
|
@ -22,6 +23,10 @@ impl Action for CreateSyntheticObjects {
|
|||
"Create objects defined in `/etc/synthetic.conf`".to_string()
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(tracing::Level::DEBUG, "create_synthetic_objects",)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
self.tracing_synopsis(),
|
||||
|
@ -29,7 +34,7 @@ impl Action for CreateSyntheticObjects {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields())]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
// Yup we literally call both and ignore the error! Reasoning: https://github.com/NixOS/nix/blob/95331cb9c99151cbd790ceb6ddaf49fc1c0da4b3/scripts/create-darwin-volume.sh#L261
|
||||
execute_command(
|
||||
|
@ -59,7 +64,7 @@ impl Action for CreateSyntheticObjects {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields())]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
// Yup we literally call both and ignore the error! Reasoning: https://github.com/NixOS/nix/blob/95331cb9c99151cbd790ceb6ddaf49fc1c0da4b3/scripts/create-darwin-volume.sh#L261
|
||||
execute_command(
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::io::Cursor;
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{ActionError, StatefulAction};
|
||||
use crate::execute_command;
|
||||
|
@ -34,13 +35,19 @@ impl Action for EnableOwnership {
|
|||
format!("Enable ownership on {}", self.path.display())
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"enable_ownership",
|
||||
path = %self.path.display(),
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
path = %self.path.display(),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self { path } = self;
|
||||
|
||||
|
@ -79,9 +86,7 @@ impl Action for EnableOwnership {
|
|||
vec![]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
path = %self.path.display(),
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
// noop
|
||||
Ok(())
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
|||
use rand::Rng;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
/**
|
||||
Encrypt an APFS volume
|
||||
|
@ -43,6 +44,14 @@ impl Action for EncryptApfsVolume {
|
|||
)
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"encrypt_volume",
|
||||
disk = tracing::field::display(self.disk.display()),
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{ActionError, StatefulAction};
|
||||
use crate::execute_command;
|
||||
|
@ -28,13 +29,19 @@ impl Action for KickstartLaunchctlService {
|
|||
format!("Kickstart the launchctl unit `{unit}`")
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"kickstart_launchctl_service",
|
||||
unit = %self.unit,
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
unit = %self.unit,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self { unit } = self;
|
||||
|
||||
|
@ -56,9 +63,7 @@ impl Action for KickstartLaunchctlService {
|
|||
vec![]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
unit = %self.unit,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
// noop
|
||||
Ok(())
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{ActionError, StatefulAction};
|
||||
use crate::execute_command;
|
||||
|
@ -34,14 +35,20 @@ impl Action for UnmountApfsVolume {
|
|||
format!("Unmount the `{}` APFS volume", self.name)
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"unmount_volume",
|
||||
disk = tracing::field::display(self.disk.display()),
|
||||
name = self.name,
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
disk = %self.disk.display(),
|
||||
name = %self.name,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self { disk: _, name } = self;
|
||||
|
||||
|
@ -62,10 +69,7 @@ impl Action for UnmountApfsVolume {
|
|||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
disk = %self.disk.display(),
|
||||
name = %self.name,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self { disk: _, name } = self;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::path::{Path, PathBuf};
|
|||
use target_lexicon::OperatingSystem;
|
||||
use tokio::fs::remove_file;
|
||||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{ActionError, StatefulAction};
|
||||
use crate::execute_command;
|
||||
|
@ -50,6 +51,11 @@ impl Action for ConfigureNixDaemonService {
|
|||
fn tracing_synopsis(&self) -> String {
|
||||
"Configure Nix daemon related settings with systemd".to_string()
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(tracing::Level::DEBUG, "configure_nix_daemon",)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
self.tracing_synopsis(),
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{ActionError, ActionState, StatefulAction};
|
||||
use crate::execute_command;
|
||||
|
@ -32,13 +33,19 @@ impl Action for StartSystemdUnit {
|
|||
format!("Enable (and start) the systemd unit {}", self.unit)
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"start_systemd_unit",
|
||||
unit = %self.unit,
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
unit = %self.unit,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self { unit, .. } = self;
|
||||
|
||||
|
@ -64,9 +71,7 @@ impl Action for StartSystemdUnit {
|
|||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
unit = %self.unit,
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self { unit, .. } = self;
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ A custom [`Action`] can be created then used in a custom [`Planner`](crate::plan
|
|||
|
||||
```rust,no_run
|
||||
use std::{error::Error, collections::HashMap};
|
||||
use tracing::{Span, span};
|
||||
use harmonic::{
|
||||
InstallPlan,
|
||||
settings::{CommonSettings, InstallSettingsError},
|
||||
|
@ -71,13 +72,19 @@ impl Action for MyAction {
|
|||
"My action".to_string()
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"my_action",
|
||||
// Tracing fields here ...
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
// Tracing fields...
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
// Execute steps ...
|
||||
Ok(())
|
||||
|
@ -87,9 +94,7 @@ impl Action for MyAction {
|
|||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, fields(
|
||||
// Tracing fields...
|
||||
))]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
// Revert steps...
|
||||
Ok(())
|
||||
|
@ -159,6 +164,7 @@ mod stateful;
|
|||
pub use stateful::{ActionState, StatefulAction};
|
||||
use std::error::Error;
|
||||
use tokio::task::JoinError;
|
||||
use tracing::Span;
|
||||
|
||||
use crate::error::HasExpectedErrors;
|
||||
|
||||
|
@ -172,6 +178,14 @@ use crate::error::HasExpectedErrors;
|
|||
pub trait Action: Send + Sync + std::fmt::Debug + dyn_clone::DynClone {
|
||||
/// A synopsis of the action for tracing purposes
|
||||
fn tracing_synopsis(&self) -> String;
|
||||
/// A tracing span suitable for the action
|
||||
///
|
||||
/// It should be [`tracing::Level::DEBUG`] and contain the same name as the [`typetag::serde`] entry.
|
||||
///
|
||||
/// It may contain any fields, and will be attached in the [`StatefulAction::try_execute`] and [`StatefulAction::try_revert`] functions.
|
||||
///
|
||||
/// See [`tracing::Span`] for more details.
|
||||
fn tracing_span(&self) -> Span;
|
||||
/// A description of what this action would do during execution
|
||||
///
|
||||
/// If this action calls sub-[`Action`]s, care should be taken to use [`StatefulAction::describe_execute`] on those actions, not [`execute_description`][Action::execute_description].
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{Instrument, Span};
|
||||
|
||||
use super::{Action, ActionDescription, ActionError};
|
||||
|
||||
|
@ -26,6 +27,10 @@ impl StatefulAction<Box<dyn Action>> {
|
|||
pub fn tracing_synopsis(&self) -> String {
|
||||
self.action.tracing_synopsis()
|
||||
}
|
||||
/// A tracing span suitable for the action
|
||||
pub fn tracing_span(&self) -> Span {
|
||||
self.action.tracing_span()
|
||||
}
|
||||
/// A description of what this action would do during execution
|
||||
pub fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
match self.state {
|
||||
|
@ -47,6 +52,7 @@ impl StatefulAction<Box<dyn Action>> {
|
|||
/// Perform any execution steps
|
||||
///
|
||||
/// You should prefer this ([`try_execute`][StatefulAction::try_execute]) over [`execute`][Action::execute] as it handles [`ActionState`] and does tracing
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn try_execute(&mut self) -> Result<(), ActionError> {
|
||||
match self.state {
|
||||
ActionState::Completed => {
|
||||
|
@ -73,6 +79,7 @@ impl StatefulAction<Box<dyn Action>> {
|
|||
/// Perform any revert steps
|
||||
///
|
||||
/// You should prefer this ([`try_revert`][StatefulAction::try_revert]) over [`revert`][Action::revert] as it handles [`ActionState`] and does tracing
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn try_revert(&mut self) -> Result<(), ActionError> {
|
||||
match self.state {
|
||||
ActionState::Uncompleted => {
|
||||
|
@ -106,6 +113,11 @@ where
|
|||
self.action.tracing_synopsis()
|
||||
}
|
||||
|
||||
/// A tracing span suitable for the action
|
||||
pub fn tracing_span(&self) -> Span {
|
||||
self.action.tracing_span()
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> &A {
|
||||
&self.action
|
||||
}
|
||||
|
@ -137,24 +149,34 @@ where
|
|||
///
|
||||
/// You should prefer this ([`try_execute`][StatefulAction::try_execute]) over [`execute`][Action::execute] as it handles [`ActionState`] and does tracing
|
||||
pub async fn try_execute(&mut self) -> Result<(), ActionError> {
|
||||
let span = self.action.tracing_span();
|
||||
match self.state {
|
||||
ActionState::Completed => {
|
||||
tracing::trace!(
|
||||
parent: &span,
|
||||
"Completed: (Already done) {}",
|
||||
self.action.tracing_synopsis()
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
ActionState::Skipped => {
|
||||
tracing::trace!("Skipped: {}", self.action.tracing_synopsis());
|
||||
tracing::trace!(parent: &span, "Skipped: {}", self.action.tracing_synopsis());
|
||||
Ok(())
|
||||
},
|
||||
_ => {
|
||||
self.state = ActionState::Progress;
|
||||
tracing::debug!("Executing: {}", self.action.tracing_synopsis());
|
||||
self.action.execute().await?;
|
||||
tracing::debug!(
|
||||
parent: &span,
|
||||
"Executing: {}",
|
||||
self.action.tracing_synopsis()
|
||||
);
|
||||
self.action.execute().instrument(span.clone()).await?;
|
||||
self.state = ActionState::Completed;
|
||||
tracing::debug!("Completed: {}", self.action.tracing_synopsis());
|
||||
tracing::debug!(
|
||||
parent: &span,
|
||||
"Completed: {}",
|
||||
self.action.tracing_synopsis()
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
|
@ -163,23 +185,33 @@ where
|
|||
///
|
||||
/// You should prefer this ([`try_revert`][StatefulAction::try_revert]) over [`revert`][Action::revert] as it handles [`ActionState`] and does tracing
|
||||
pub async fn try_revert(&mut self) -> Result<(), ActionError> {
|
||||
let span = self.action.tracing_span();
|
||||
match self.state {
|
||||
ActionState::Uncompleted => {
|
||||
tracing::trace!(
|
||||
parent: &span,
|
||||
"Reverted: (Already done) {}",
|
||||
self.action.tracing_synopsis()
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
ActionState::Skipped => {
|
||||
tracing::trace!("Skipped: {}", self.action.tracing_synopsis());
|
||||
tracing::trace!(parent: &span, "Skipped: {}", self.action.tracing_synopsis());
|
||||
Ok(())
|
||||
},
|
||||
_ => {
|
||||
self.state = ActionState::Progress;
|
||||
tracing::debug!("Reverting: {}", self.action.tracing_synopsis());
|
||||
self.action.revert().await?;
|
||||
tracing::debug!("Reverted: {}", self.action.tracing_synopsis());
|
||||
tracing::debug!(
|
||||
parent: &span,
|
||||
"Reverting: {}",
|
||||
self.action.tracing_synopsis()
|
||||
);
|
||||
self.action.revert().instrument(span.clone()).await?;
|
||||
tracing::debug!(
|
||||
parent: &span,
|
||||
"Reverted: {}",
|
||||
self.action.tracing_synopsis()
|
||||
);
|
||||
self.state = ActionState::Uncompleted;
|
||||
Ok(())
|
||||
},
|
||||
|
|
|
@ -2,7 +2,9 @@ use atty::Stream;
|
|||
use eyre::WrapErr;
|
||||
use std::error::Error;
|
||||
use tracing_error::ErrorLayer;
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
|
||||
use tracing_subscriber::{
|
||||
filter::Directive, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter,
|
||||
};
|
||||
|
||||
#[derive(Clone, Default, Debug, clap::ValueEnum)]
|
||||
pub enum Logger {
|
||||
|
@ -33,6 +35,11 @@ pub struct Instrumentation {
|
|||
/// Which logger to use
|
||||
#[clap(long, env = "HARMONIC_LOGGER", default_value_t = Default::default(), global = true)]
|
||||
pub logger: Logger,
|
||||
/// Tracing directives
|
||||
///
|
||||
/// See https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives
|
||||
#[clap(long = "log-directive", global = true, env = "HARMONIC_LOG_DIRECTIVES", value_delimiter = ',', num_args = 0..)]
|
||||
pub log_directives: Vec<Directive>,
|
||||
}
|
||||
|
||||
impl<'a> Instrumentation {
|
||||
|
@ -120,7 +127,7 @@ impl<'a> Instrumentation {
|
|||
}
|
||||
|
||||
pub fn filter_layer(&self) -> eyre::Result<EnvFilter> {
|
||||
let filter_layer = match EnvFilter::try_from_default_env() {
|
||||
let mut filter_layer = match EnvFilter::try_from_default_env() {
|
||||
Ok(layer) => layer,
|
||||
Err(e) => {
|
||||
// Catch a parse error and report it, ignore a missing env.
|
||||
|
@ -134,6 +141,11 @@ impl<'a> Instrumentation {
|
|||
},
|
||||
};
|
||||
|
||||
for directive in &self.log_directives {
|
||||
let directive_clone = directive.clone();
|
||||
filter_layer = filter_layer.add_directive(directive_clone);
|
||||
}
|
||||
|
||||
Ok(filter_layer)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::{
|
|||
error::HasExpectedErrors,
|
||||
plan::RECEIPT_LOCATION,
|
||||
planner::Planner,
|
||||
settings::CommonSettings,
|
||||
BuiltinPlanner, InstallPlan,
|
||||
};
|
||||
use clap::{ArgAction, Parser};
|
||||
|
@ -30,6 +31,9 @@ pub struct Install {
|
|||
)]
|
||||
pub no_confirm: bool,
|
||||
|
||||
#[clap(flatten)]
|
||||
pub settings: CommonSettings,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
env = "HARMONIC_EXPLAIN",
|
||||
|
@ -47,12 +51,13 @@ pub struct Install {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl CommandExecute for Install {
|
||||
#[tracing::instrument(level = "debug", skip_all, fields())]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(self) -> eyre::Result<ExitCode> {
|
||||
let Self {
|
||||
no_confirm,
|
||||
plan,
|
||||
planner,
|
||||
settings,
|
||||
explain,
|
||||
} = self;
|
||||
|
||||
|
@ -97,7 +102,7 @@ impl CommandExecute for Install {
|
|||
serde_json::from_str(&install_plan_string)?
|
||||
},
|
||||
(None, None) => {
|
||||
let builtin_planner = BuiltinPlanner::default()
|
||||
let builtin_planner = BuiltinPlanner::from_common_settings(settings)
|
||||
.await
|
||||
.map_err(|e| eyre::eyre!(e))?;
|
||||
let res = builtin_planner.plan().await;
|
||||
|
|
|
@ -42,7 +42,7 @@ pub struct Uninstall {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl CommandExecute for Uninstall {
|
||||
#[tracing::instrument(level = "debug", skip_all, fields())]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(self) -> eyre::Result<ExitCode> {
|
||||
let Self {
|
||||
no_confirm,
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::{
|
|||
Action, BuiltinPlanner,
|
||||
};
|
||||
use std::{collections::HashMap, path::Path};
|
||||
use tokio::process::Command;
|
||||
|
||||
/// A planner for Linux multi-user installs
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
|
@ -37,7 +38,7 @@ impl Planner for LinuxMulti {
|
|||
}
|
||||
|
||||
// For now, we don't try to repair the user's Nix install or anything special.
|
||||
if let Ok(_) = tokio::process::Command::new("nix-env")
|
||||
if let Ok(_) = Command::new("nix-env")
|
||||
.arg("--version")
|
||||
.stdin(std::process::Stdio::null())
|
||||
.status()
|
||||
|
|
|
@ -101,6 +101,11 @@ impl Planner for SteamDeck {
|
|||
|
||||
async fn plan(&self) -> Result<Vec<StatefulAction<Box<dyn Action>>>, PlannerError> {
|
||||
let persistence = &self.persistence;
|
||||
if !persistence.is_absolute() {
|
||||
return Err(PlannerError::Custom(Box::new(
|
||||
SteamDeckError::AbsolutePathRequired(self.persistence.clone()),
|
||||
)));
|
||||
};
|
||||
|
||||
let nix_directory_buf = format!(
|
||||
"\
|
||||
|
@ -247,3 +252,9 @@ impl Into<BuiltinPlanner> for SteamDeck {
|
|||
BuiltinPlanner::SteamDeck(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
enum SteamDeckError {
|
||||
#[error("`{0}` is not a path that can be canonicalized into an absolute path, bind mounts require an absolute path")]
|
||||
AbsolutePathRequired(PathBuf),
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ use std::collections::HashMap;
|
|||
use crate::{
|
||||
action::{ActionError, StatefulAction},
|
||||
error::HasExpectedErrors,
|
||||
settings::InstallSettingsError,
|
||||
settings::{CommonSettings, InstallSettingsError},
|
||||
Action, HarmonicError, InstallPlan,
|
||||
};
|
||||
|
||||
|
@ -144,6 +144,16 @@ impl BuiltinPlanner {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn from_common_settings(settings: CommonSettings) -> Result<Self, PlannerError> {
|
||||
let mut built = Self::default().await?;
|
||||
match &mut built {
|
||||
BuiltinPlanner::LinuxMulti(inner) => inner.settings = settings,
|
||||
BuiltinPlanner::DarwinMulti(inner) => inner.settings = settings,
|
||||
BuiltinPlanner::SteamDeck(inner) => inner.settings = settings,
|
||||
}
|
||||
Ok(built)
|
||||
}
|
||||
|
||||
pub async fn plan(self) -> Result<InstallPlan, HarmonicError> {
|
||||
match self {
|
||||
BuiltinPlanner::LinuxMulti(planner) => InstallPlan::plan(planner).await,
|
||||
|
|
|
@ -32,14 +32,16 @@ Settings which only apply to certain [`Planner`](crate::planner::Planner)s shoul
|
|||
pub struct CommonSettings {
|
||||
/// Channel(s) to add
|
||||
#[cfg_attr(
|
||||
feature = "cli",clap(
|
||||
long,
|
||||
value_parser,
|
||||
name = "channel",
|
||||
action = clap::ArgAction::Append,
|
||||
env = "HARMONIC_CHANNEL",
|
||||
default_value = "nixpkgs=https://nixos.org/channels/nixpkgs-unstable",
|
||||
))]
|
||||
feature = "cli",
|
||||
clap(
|
||||
long,
|
||||
value_parser,
|
||||
name = "channel",
|
||||
action = clap::ArgAction::Append,
|
||||
env = "HARMONIC_CHANNELS",
|
||||
default_value = "nixpkgs=https://nixos.org/channels/nixpkgs-unstable",
|
||||
)
|
||||
)]
|
||||
pub(crate) channels: Vec<ChannelValue>,
|
||||
|
||||
/// Modify the user profile to automatically load nix
|
||||
|
@ -59,26 +61,44 @@ pub struct CommonSettings {
|
|||
/// Number of build users to create
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(long, default_value = "32", env = "HARMONIC_DAEMON_USER_COUNT")
|
||||
clap(
|
||||
long,
|
||||
default_value = "32",
|
||||
env = "HARMONIC_DAEMON_USER_COUNT",
|
||||
global = true
|
||||
)
|
||||
)]
|
||||
pub(crate) daemon_user_count: usize,
|
||||
|
||||
/// The Nix build group name
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(long, default_value = "nixbld", env = "HARMONIC_NIX_BUILD_GROUP_NAME")
|
||||
clap(
|
||||
long,
|
||||
default_value = "nixbld",
|
||||
env = "HARMONIC_NIX_BUILD_GROUP_NAME",
|
||||
global = true
|
||||
)
|
||||
)]
|
||||
pub(crate) nix_build_group_name: String,
|
||||
|
||||
/// The Nix build group GID
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(long, default_value_t = 3000, env = "HARMONIC_NIX_BUILD_GROUP_ID")
|
||||
clap(
|
||||
long,
|
||||
default_value_t = 3000,
|
||||
env = "HARMONIC_NIX_BUILD_GROUP_ID",
|
||||
global = true
|
||||
)
|
||||
)]
|
||||
pub(crate) nix_build_group_id: usize,
|
||||
|
||||
/// The Nix build user prefix (user numbers will be postfixed)
|
||||
#[cfg_attr(feature = "cli", clap(long, env = "HARMONIC_NIX_BUILD_USER_PREFIX"))]
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(long, env = "HARMONIC_NIX_BUILD_USER_PREFIX", global = true)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", feature = "cli"),
|
||||
clap(default_value = "_nixbld")
|
||||
|
@ -90,7 +110,10 @@ pub struct CommonSettings {
|
|||
pub(crate) nix_build_user_prefix: String,
|
||||
|
||||
/// The Nix build user base UID (ascending)
|
||||
#[cfg_attr(feature = "cli", clap(long, env = "HARMONIC_NIX_BUILD_USER_ID_BASE"))]
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(long, env = "HARMONIC_NIX_BUILD_USER_ID_BASE", global = true)
|
||||
)]
|
||||
#[cfg_attr(all(target_os = "macos", feature = "cli"), clap(default_value_t = 300))]
|
||||
#[cfg_attr(
|
||||
all(target_os = "linux", feature = "cli"),
|
||||
|
@ -99,7 +122,10 @@ pub struct CommonSettings {
|
|||
pub(crate) nix_build_user_id_base: usize,
|
||||
|
||||
/// The Nix package URL
|
||||
#[cfg_attr(feature = "cli", clap(long, env = "HARMONIC_NIX_PACKAGE_URL"))]
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(long, env = "HARMONIC_NIX_PACKAGE_URL", global = true)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", feature = "cli"),
|
||||
clap(
|
||||
|
@ -127,7 +153,7 @@ pub struct CommonSettings {
|
|||
pub(crate) nix_package_url: Url,
|
||||
|
||||
/// Extra configuration lines for `/etc/nix.conf`
|
||||
#[cfg_attr(feature = "cli", clap(long, env = "HARMONIC_EXTRA_CONF"))]
|
||||
#[cfg_attr(feature = "cli", clap(long, action = ArgAction::Set, num_args = 0.., value_delimiter = ',', env = "HARMONIC_EXTRA_CONF", global = true))]
|
||||
pub extra_conf: Vec<String>,
|
||||
|
||||
/// If Harmonic should forcibly recreate files it finds existing
|
||||
|
|
Loading…
Reference in a new issue