ALPHA: wire is a tool to deploy nixos systems wire.althaea.zone/

misc changes

+278 -111
+9 -4
doc/.vitepress/config.ts
··· 85 85 ], 86 86 }, 87 87 { 88 - text: "How-to Guides", 88 + text: "How-To Guides", 89 89 collapsed: false, 90 90 items: [ 91 91 { text: "Install wire", link: "/guides/installation" }, 92 - { text: "Migrate to wire", link: "/guides/migrate" }, 92 + { 93 + text: "Write a Hive", 94 + link: "/guides/writing-a-hive", 95 + }, 93 96 { 94 - text: "Flakes", 97 + text: "With Flakes", 98 + link: "/guides/flakes/overview", 95 99 items: [ 96 - { text: "Use Flakes", link: "/guides/flakes/overview" }, 97 100 { 98 101 text: "Keep Using nixos-rebuild", 99 102 link: "/guides/flakes/nixos-rebuild", 100 103 }, 101 104 ], 102 105 }, 106 + { text: "Migrate to wire", link: "/guides/migrate" }, 103 107 { text: "Apply your Config", link: "/guides/apply" }, 108 + { text: "Use a non-root user", link: "/guides/non-root-user" }, 104 109 { text: "Target Nodes", link: "/guides/targeting" }, 105 110 { 106 111 text: "Features",
+11 -23
doc/guides/flakes/nixos-rebuild.md
··· 15 15 the same name together. 16 16 17 17 ::: tip 18 - It should be noted that there are a few downsides. For example, you cannot access `config.deployment` from `nixosConfigurations`. For this reason it would be best practice to limit configuration in `colmena` to simply defining keys and deployment options. 18 + You should include the wire module, which will provide the `deployment` options, even if nixos-rebuild can't directly use them. 19 19 ::: 20 20 21 21 ::: code-group ··· 24 24 25 25 Now, if we run `wire show`, you will see that wire only finds 26 26 the `nixosConfigurations`-es that also match a node in the hive. 27 + `some-other-host` is not included in the hive unless specified in `makeHive`. 27 28 28 29 ``` 29 30 $ wire show 30 - Hive { 31 - nodes: { 32 - Name( 33 - "node-a", 34 - ): Node { 35 - target: Target { 36 - hosts: [ 37 - "node-a", 38 - ], 39 - user: "root", 40 - port: 22, 41 - current_host: 0, 42 - }, 43 - build_remotely: false, 44 - allow_local_deployment: true, 45 - tags: {}, 46 - keys: [], 47 - host_platform: "x86_64-linux", 48 - }, 49 - }, 50 - schema: 0, 51 - } 31 + Node node-a (x86_64-linux): 32 + 33 + > Connection: {root@node-a:22} 34 + > Build remotely `deployment.buildOnTarget`: false 35 + > Local apply allowed `deployment.allowLocalDeployment`: true 36 + 37 + Summary: 1 total node(s), totalling 0 keys (0 distinct). 38 + Note: Listed connections are tried from Left to Right 39 + 52 40 ``` 53 41 54 42 This way, you can continue using `nixos-rebuild` and wire at the same time.
+10
doc/guides/flakes/overview.md
··· 27 27 $ nix flake show 28 28 git+file:///some/path 29 29 └───wire: unknown 30 + 31 + $ wire show 32 + Node node-a (x86_64-linux): 33 + 34 + > Connection: {root@node-a:22} 35 + > Build remotely `deployment.buildOnTarget`: false 36 + > Local apply allowed `deployment.allowLocalDeployment`: true 37 + 38 + Summary: 1 total node(s), totalling 0 keys (0 distinct). 39 + Note: Listed connections are tried from Left to Right 30 40 ```
+15 -11
doc/guides/installation.md
··· 15 15 16 16 ::: 17 17 18 + It is recommended you stick to either using a tagged version of wire, or the `stable` branch which tracks the latest stable tag. 19 + 18 20 ## Binary Cache 19 21 20 - You should trust the substituter `https://wires.cachix.org` by 21 - either editing `/etc/nix/nix.conf` or updating your NixOS configuration: 22 - 23 - ::: code-group 24 - 25 - <<< @/snippets/getting-started/nix.conf 26 - <<< @/snippets/getting-started/cache.nix [configuration.nix] 27 - 28 - ::: 22 + You must enable the [garnix binary cache](https://garnix.io/docs/caching) on all 23 + nodes in your wire hive, otherwise they will not accept the wire key agent and 24 + you will be compiling everything from source. 29 25 30 26 ## Installation through flakes 31 27 ··· 45 41 you'd like, really. 46 42 47 43 ```sh 48 - $ npins add github mrshmllow wire 44 + $ npins add github mrshmllow wire --branch stable 49 45 ``` 50 46 47 + Alternatively, you can use a tag instead: 48 + 49 + ```sh 50 + $ npins add github mrshmllow wire --at v1.0.0-alpha.0 51 + ``` 52 + 53 + Then, use this pinned version of wire for both your `hive.nix` and `shell.nix`: 54 + 51 55 ::: code-group 52 56 <<< @/snippets/guides/installation/shell.nix{8} [shell.nix] 53 - <<< @/snippets/guides/installation/hive.nix{8} [hive.nix] 57 + <<< @/snippets/guides/installation/hive.nix [hive.nix] 54 58 :::
+3
doc/guides/non-root-user.md
··· 22 22 - "Non-interactive SSH Auth" here most likely meaning an SSH key, anything that 23 23 does not require keyboard input in the terminal. 24 24 25 + To put it simply, you cannot have a password on _ssh_, but you can have a 26 + password on _sudo_. 27 + 25 28 ## Changing the user 26 29 27 30 By default, the target is set to root:
+112
doc/guides/writing-a-hive.md
··· 1 + --- 2 + comment: true 3 + title: Write a Hive 4 + --- 5 + 6 + # {{ $frontmatter.title }} 7 + 8 + ## Anatomy of a Hive 9 + 10 + A "Hive" is the attribute set that you pass to `wire.makeHive`. It has the 11 + following layout: 12 + 13 + ```nix 14 + # `meta` 15 + # type: attrset 16 + meta = { 17 + # `meta.nixpkgs` tells wire how to get nixpkgs. 18 + # type: "A path or an instance of nixpkgs." 19 + nixpkgs = <nixpkgs>; 20 + 21 + # `meta.specialArgs` are specialArgs to pass to each node & default 22 + # type: attrset 23 + specialArgs = { }; 24 + }; 25 + 26 + # `defaults` is a module applied to every node 27 + # type: NixOS Module 28 + defaults = { ... }: { }; 29 + 30 + # Any other attributes are nodes. 31 + ``` 32 + 33 + ### `<node-name>` 34 + 35 + Other attributes are NixOs modules that describe a system. They automatically 36 + have `defaults` and the wire NixOS module imported. 37 + 38 + They also have the `name` and `nodes` attributes passed to them, `name` being a string of the nodes name, and `nodes` being an attribute set of every node in the hive. 39 + 40 + ### `meta` 41 + 42 + There is more detailed information about `meta` in [the 43 + reference](/reference/meta.html). 44 + 45 + ### `defaults` 46 + 47 + De-duplicate options with default node configuration. 48 + 49 + At the top level of a hive wire reserves the `defaults` attribute. It's applied 50 + to every node. 51 + 52 + ::: warning 53 + 54 + `defaults` must not rely on modules that a node imports, but a 55 + node may rely on modules that default imports. 56 + 57 + ::: 58 + 59 + ## Example 60 + 61 + There is more detailed information the special options for nodes [the 62 + reference](/reference/module.html). 63 + 64 + ```nix:line-numbers [hive.nix] 65 + { 66 + meta.nixpkgs = import some-sources-or-inputs.nixpkgs { }; 67 + 68 + defaults = { 69 + # name of the node that defaults is being applied to 70 + name, 71 + # attribute set of all nodes 72 + nodes, 73 + pkgs, 74 + ... 75 + }: { 76 + import = [ 77 + ./default-module.nix 78 + 79 + # module that is imported for all nodes 80 + some-flake.nixosModules.default 81 + ]; 82 + 83 + # all nodes should include vim! 84 + environment.systemPackages [ pkgs.vim ]; 85 + }; 86 + 87 + node-a = { 88 + # name of the node that defaults is being applied to 89 + name, 90 + # attribute set of all nodes 91 + nodes, 92 + pkgs, 93 + ... 94 + }: { 95 + imports = [ 96 + # import the hardware-config and all your extra stuff 97 + ./node-a 98 + ]; 99 + 100 + deployment = { 101 + target.host = "192.0.2.1"; 102 + tags = [ "x86" ]; 103 + }; 104 + }; 105 + 106 + # as many nodes as you'd like... 107 + 108 + node-g = { 109 + # some more config 110 + }; 111 + } 112 + ```
-13
doc/snippets/getting-started/cache.nix
··· 1 - { 2 - nix.settings = { 3 - substituters = [ 4 - "https://cache.nixos.org" 5 - "https://cache.althaea.zone" 6 - # ... 7 - ]; 8 - trusted-public-keys = [ 9 - "cache.althaea.zone:BelRpa863X9q3Y+AOnl5SM7QFzre3qb+5I7g2s/mqHI=" 10 - # ... 11 - ]; 12 - }; 13 - }
+11 -3
doc/snippets/getting-started/flake-merged.nix
··· 9 9 ... 10 10 } @ inputs: { 11 11 wire = wire.makeHive { 12 - # Give wire our ninixosConfigurations 12 + # Give wire our nixosConfigurations 13 13 inherit (self) nixosConfigurations; 14 14 15 15 meta = { 16 - # ... from above 16 + nixpkgs = import nixpkgs {localSystem = "x86_64-linux";}; 17 17 }; 18 18 19 19 node-a.deployment = { 20 + tags = [ 21 + # some tags 22 + ]; 23 + 20 24 # ... 21 25 }; 22 26 }; ··· 26 30 system = "x86_64-linux"; 27 31 specialArgs = {inherit inputs;}; 28 32 modules = [ 33 + wire.nixosModules.default 29 34 { 30 35 nixpkgs.hostPlatform = "x86_64-linux"; 36 + 37 + # you can put deployment options here too! 38 + deployment.target = "some-hostname"; 31 39 } 32 40 ]; 33 41 }; 34 42 35 - node-b = nixpkgs.lib.nixosSystem { 43 + some-other-host = nixpkgs.lib.nixosSystem { 36 44 system = "x86_64-linux"; 37 45 specialArgs = {inherit inputs;}; 38 46 modules = [
+2
doc/snippets/getting-started/flake.nix
··· 22 22 }; 23 23 24 24 node-a = { 25 + nixpkgs.hostPlatform = "x86_64-linux"; 26 + 25 27 # ... 26 28 }; 27 29 };
-3
doc/snippets/getting-started/nix.conf
··· 1 - # /etc/nix/nix.conf 2 - trusted-substituters = https://cache.nixos.org https://cache.althaea.zone 3 - trusted-public-keys = ... cache.althaea.zone:BelRpa863X9q3Y+AOnl5SM7QFzre3qb+5I7g2s/mqHI=
+7 -1
doc/snippets/guides/installation/flake.nix
··· 2 2 inputs = { 3 3 nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 4 4 wire.url = "github:mrshmllow/wire/stable"; 5 + 6 + # alternatively, you can use a tag instead: 7 + # wire.url = "github:mrshmllow/wire/v1.0.0-alpha.0"; 8 + 5 9 systems.url = "github:nix-systems/default"; 6 10 }; 7 11 ··· 14 18 forAllSystems = nixpkgs.lib.genAttrs (import systems); 15 19 in { 16 20 wire = wire.makeHive { 17 - # ... 21 + nixpkgs = import nixpkgs {localSystem = "x86_64-linux";}; 22 + 23 + # Continue to next How-To guide to fill this section 18 24 }; 19 25 20 26 devShells = forAllSystems (
+1 -1
doc/snippets/guides/installation/hive.nix
··· 6 6 # give wire nixpkgs from npins 7 7 meta.nixpkgs = import sources.nixpkgs {}; 8 8 9 - # ... 9 + # Continue to next How-To guide to fill this section 10 10 }
+3 -1
doc/tutorial/overview.md
··· 18 18 19 19 In this tutorial we will create and deploy a wire Hive. Along the way we will 20 20 encounter [npins](https://github.com/andir/npins), simple NixOS 21 - configurations, virutal machines, and deployment keys. 21 + configurations, virtual machines, and deployment keys. 22 + 23 + You'll need at least 10~ GB of free disk space to complete this tutorial. 22 24 23 25 <div class="tip custom-block" style="padding-top: 8px"> 24 26
+1 -1
doc/tutorial/part-one/basic-hive.md
··· 40 40 41 41 ``` 42 42 43 - The line `nodes: {}` means theres no "nodes" in our hive. 43 + The line `nodes: {}` means there is no "nodes" in our hive. 44 44 45 45 ## Adding The First Node 46 46
+4 -13
doc/tutorial/part-one/nix-setup.md
··· 26 26 nix (Nix) 2.11.0 27 27 ``` 28 28 29 - ## Using `cache.althaea.zone` 29 + ## Binary Cache 30 30 31 31 Because wire can be heavy to compile, it is distributed with a [binary 32 - cache](https://wiki.nixos.org/wiki/Binary_Cache). It's URL is 33 - `https://cache.althaea.zone` and it's public key is 34 - `cache.althaea.zone:BelRpa863X9q3Y+AOnl5SM7QFzre3qb+5I7g2s/mqHI=`. 32 + cache](https://wiki.nixos.org/wiki/Binary_Cache). 35 33 36 - You should trust the substituter `https://wires.cachix.org` by 37 - either editing `/etc/nix/nix.conf` or updating your NixOS configuration: 38 - 39 - ::: code-group 40 - 41 - <<< @/snippets/getting-started/nix.conf 42 - <<< @/snippets/getting-started/cache.nix [configuration.nix] 43 - 44 - ::: 34 + You must enable the [garnix binary cache](https://garnix.io/docs/caching) or you 35 + will be compiling everything from source.
+6 -11
doc/tutorial/part-one/repo-setup.md
··· 27 27 [nix-shell]$ git init wire-tutorial 28 28 Initialized empty Git repository in /home/.../wire-tutorial/.git/ 29 29 [nix-shell]$ cd wire-tutorial/ 30 - [nix-shell]$ npins init --bare 30 + [nix-shell]$ npins init 31 31 [INFO ] Welcome to npins! 32 32 [INFO ] Creating `npins` directory 33 33 [INFO ] Writing default.nix 34 34 [INFO ] Writing initial lock file (empty) 35 35 [INFO ] Successfully written initial files to 'npins/sources.json'. 36 - [nix-shell]$ npins add github pkpbynum nixpkgs --branch pb/disk-size-bootloader 37 36 ``` 38 37 39 - ::: details 40 - 41 - This tutorial is using a [PR](https://github.com/NixOS/nixpkgs/pull/449945) that 42 - fixes virutal machine bootloader disk sizes. 43 - 44 - ::: 45 - 46 38 This has created a pinned version of `nixpkgs` for us to use in our wire hive. 47 39 48 40 ## Adding wire as a dependency ··· 50 42 We can now need to tell `npins` to use `mrshmllow/wire` as a dependency. 51 43 52 44 ```sh 53 - [nix-shell]$ npins add github mrshmllow wire 45 + [nix-shell]$ npins add github mrshmllow wire --branch stable 54 46 [INFO ] Adding 'wire' … 55 47 repository: https://github.com/mrshmllow/wire.git 56 48 pre_releases: false ··· 102 94 pkgs.git 103 95 ]; 104 96 105 - NIX_PATH = "nixpkgs=${sources.nixpkgs.outPath}"; 97 + shellHook = '' 98 + export NIX_PATH="nixpkgs=${sources.nixpkgs.outPath}" 99 + ''; 106 100 } 107 101 ``` 108 102 ··· 113 107 ```sh 114 108 [nix-shell]$ exit 115 109 exit 110 + $ cd wire-tutorial/ 116 111 $ nix-shell 117 112 [nix-shell]$ wire --version 118 113 wire 0.5.0
+30 -5
doc/tutorial/part-one/vm-setup.md
··· 10 10 11 11 ## Creating a `vm.nix` 12 12 13 + For this step, you'll need your ssh public key, which you can obtain from 14 + `ssh-add -L`. 15 + 13 16 Open a text editor and edit `vm.nix`. Place in it this basic NixOS 14 17 virtual machine configuration, which enables openssh and forwards it's 22 port: 15 18 ··· 22 25 23 26 networking.hostName = "wire-tutorial"; 24 27 28 + users.users.root = { 29 + initialPassword = "root"; 30 + openssh.authorizedKeys.keys = [ 31 + # I made this a nix syntax error so you're forced to deal with it! 32 + <your ssh public-key as a string> 33 + ]; 34 + }; 35 + 25 36 boot = { 26 37 loader = { 27 38 systemd-boot.enable = true; ··· 29 40 }; 30 41 31 42 kernelParams = [ "console=ttyS0" ]; 43 + 44 + boot.growPartition = true; 32 45 }; 33 46 34 47 # enable openssh ··· 41 54 getty.autologinUser = "root"; 42 55 }; 43 56 44 - boot.growPartition = true; 45 - 46 57 virtualisation = { 47 58 graphics = false; 48 59 useBootLoader = true; 49 60 61 + # use a 5gb disk 50 62 diskSize = 5 * 1024; 51 63 64 + # grow the filesystem to fit the 5 gb we reserved 65 + fileSystems."/".autoResize = true; 66 + 52 67 # forward `openssh` port 22 to localhost:2222. 53 68 forwardPorts = [ 54 69 { ··· 58 73 } 59 74 ]; 60 75 }; 61 - 62 - users.users.root.initialPassword = "root"; 63 76 64 77 system.stateVersion = "23.11"; 65 78 } ··· 70 83 71 84 ## Building & Running the virtual machine 72 85 73 - Open a seperate Terminal tab/window/instance, ensuring you enter the development 86 + Open a separate Terminal tab/window/instance, ensuring you enter the development 74 87 shell with `nix-shell`. 75 88 Then, build the virtual machine with a bootloader, 76 89 taking our `vm.nix` as the nixos configuration. ··· 79 92 $ nix-shell 80 93 [nix-shell]$ nix-build '<nixpkgs/nixos>' -A vmWithBootLoader -I nixos-config=./vm.nix 81 94 ``` 95 + 96 + ::: tip HELP 97 + 98 + If you got an error such as 99 + 100 + ``` 101 + error: The option `...' in `...' is already declared in `...'. 102 + ``` 103 + 104 + make sure you ran the above command in the `nix-shell`! 105 + 106 + ::: 82 107 83 108 Building the virtual machine can take some time, but once it completes, start it 84 109 by running:
+10 -8
doc/tutorial/part-two/encryption.md
··· 10 10 11 11 ::: tip 12 12 For this tutorial we will be using [`age`](https://github.com/FiloSottile/age), 13 - but other encryption cli tools work just as well such as GnuPG. 13 + but other encryption CLI tools work just as well such as GnuPG. 14 14 ::: 15 15 16 16 ## Installing age ··· 31 31 pkgs.age # [!code ++] 32 32 ]; 33 33 34 - NIX_PATH = "nixpkgs=${sources.nixpkgs.outPath}"; 34 + shellHook = '' 35 + export NIX_PATH="nixpkgs=${sources.nixpkgs.outPath}" 36 + ''; 35 37 } 36 38 ``` 37 39 ··· 69 71 use the redirection operator to save the encrypted data to `top-secret.age`. 70 72 71 73 ```sh 72 - [nix-shell]$ echo "!! encrypted string !!" | age --encrypt --recipient $(age-keygen -y key.txt) > top-secret.age 74 + [nix-shell]$ echo "encrypted string!" | age --encrypt --recipient $(age-keygen -y key.txt) > top-secret.age 73 75 ``` 74 76 75 77 ## Adding an age-encrypted key 76 78 77 79 Now, lets combine our previous command-sourced key with `age`. Pass the 78 - arguments `age --decrypt --identity key.txt ./age-secret.age` to wire: 80 + arguments `age --decrypt --identity key.txt ./top-secret.age` to wire: 79 81 80 82 ```nix:line-numbers [secrets.nix] 81 83 { 82 84 deployment.keys = { 83 85 # ... 84 86 85 - "age-secret" = { # [!code ++] 87 + "top-secret" = { # [!code ++] 86 88 source = [ # [!code ++] 87 89 "age" # [!code ++] 88 90 "--decrypt" # [!code ++] 89 91 "--identity" # [!code ++] 90 92 "key.txt" # [!code ++] 91 - "${./age-secret.age}" # [!code ++] 93 + "${./top-secret.age}" # [!code ++] 92 94 ]; # [!code ++] 93 95 }; # [!code ++] 94 96 }; ··· 99 101 key: 100 102 101 103 ```sh [Virtual Machine] 102 - [root@wire-tutorial:~]# cat /run/keys/age-secret 103 - !! encrypted string !! 104 + [root@wire-tutorial:~]# cat /run/keys/top-secret 105 + encrypted string! 104 106 105 107 ```
-4
wire/cli/src/cli.rs
··· 134 134 /// Inspect hive 135 135 #[clap(visible_alias = "show")] 136 136 Inspect { 137 - /// Include liveliness 138 - #[arg(short, long, default_value_t = false)] 139 - online: bool, 140 - 141 137 /// Return in JSON format 142 138 #[arg(short, long, default_value_t = false)] 143 139 json: bool,
+1 -1
wire/cli/src/main.rs
··· 54 54 let mut hive = Hive::new_from_path(&location, modifiers).await?; 55 55 apply::apply(&mut hive, location, apply_args, modifiers).await?; 56 56 } 57 - cli::Commands::Inspect { online: _, json } => println!("{}", { 57 + cli::Commands::Inspect { json } => println!("{}", { 58 58 let hive = Hive::new_from_path(&location, modifiers).await?; 59 59 if json { 60 60 serde_json::to_string(&hive).into_diagnostic()?
+30 -5
wire/lib/src/commands/common.rs
··· 8 8 use crate::{ 9 9 EvalGoal, SubCommandModifiers, 10 10 commands::{CommandArguments, Either, WireCommandChip, run_command, run_command_with_env}, 11 - errors::HiveLibError, 11 + errors::{CommandError, HiveLibError}, 12 12 hive::{ 13 13 HiveLocation, 14 14 node::{Context, Push}, ··· 52 52 Ok(()) 53 53 } 54 54 55 + fn get_common_command_help(error: &CommandError) -> Option<String> { 56 + if let CommandError::CommandFailed { logs, .. } = error 57 + // marshmallow: your using this repo as a hive you idiot 58 + && (logs.contains("attribute 'inspect' missing") 59 + // using a flake that does not provide `wire` 60 + || logs.contains("does not provide attribute 'packages.x86_64-linux.wire'") 61 + // using a file called `hive.nix` that is not actually a hive 62 + || logs.contains("attribute 'inspect' in selection path")) 63 + { 64 + Some("Double check this `--path` or `--flake` is a wire hive. You may be pointing to the wrong directory.".to_string()) 65 + } else { 66 + None 67 + } 68 + } 69 + 55 70 /// Evaluates the hive in flakeref with regards to the given goal, 56 71 /// and returns stdout. 57 72 #[instrument(ret(level = tracing::Level::TRACE), skip_all)] ··· 99 114 ) 100 115 .await?; 101 116 102 - child 103 - .wait_till_success() 104 - .await 105 - .map_err(|source| HiveLibError::NixEvalError { attribute, source }) 117 + let status = child.wait_till_success().await; 118 + 119 + let help = if let Err(ref error) = status { 120 + get_common_command_help(error).map(Box::new) 121 + } else { 122 + None 123 + }; 124 + 125 + status 126 + .map_err(|source| HiveLibError::NixEvalError { 127 + attribute, 128 + source, 129 + help, 130 + }) 106 131 .map(|x| match x { 107 132 Either::Left((_, stdout)) | Either::Right((_, stdout)) => stdout, 108 133 })
+4 -1
wire/lib/src/commands/mod.rs
··· 109 109 envs: HashMap<String, String>, 110 110 ) -> Result<Either<InteractiveChildChip, NonInteractiveChildChip>, HiveLibError> { 111 111 // use the non interactive command runner when forced 112 - if arguments.modifiers.non_interactive { 112 + // ... or when there is no reason for interactivity, local and unprivileged 113 + if arguments.modifiers.non_interactive 114 + || (arguments.target.is_none() && !arguments.is_elevated()) 115 + { 113 116 return Ok(Either::Right(non_interactive_command_with_env( 114 117 arguments, envs, 115 118 )?));
+1 -1
wire/lib/src/commands/pty/mod.rs
··· 121 121 } 122 122 } 123 123 124 - #[instrument(skip_all, name = "run-int", fields(elevated = %arguments.is_elevated()))] 124 + #[instrument(skip_all, name = "run-int", fields(elevated = %arguments.is_elevated(), mode = ?arguments.output_mode))] 125 125 pub(crate) async fn interactive_command_with_env<S: AsRef<str>>( 126 126 arguments: &CommandArguments<'_, S>, 127 127 envs: std::collections::HashMap<String, String>,
+4 -1
wire/lib/src/commands/pty/output.rs
··· 165 165 166 166 let findings = search_string(aho_corasick, raw_mode_buffer, status_sender, began_tx); 167 167 168 - if !matches!(findings, SearchFindings::None) { 168 + if matches!( 169 + findings, 170 + SearchFindings::Started | SearchFindings::Terminate 171 + ) { 169 172 return Ok(findings); 170 173 } 171 174
+3
wire/lib/src/errors.rs
··· 345 345 346 346 #[source] 347 347 source: CommandError, 348 + 349 + #[help] 350 + help: Option<Box<String>>, 348 351 }, 349 352 350 353 #[diagnostic(