Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,10 @@ The child working directory is not changed. A resolved wrapper receives:
- `RUNSEAL_WRAPPER_FILE`

Seal wrappers use the `.seal` suffix and are interpreted directly by runseal.
On Unix, shell wrappers use the `.sh` suffix and must be executable. On Windows,
runseal also checks `.exe`, `.cmd`, and `.bat` when the wrapper name has no
extension.
On Unix, shell wrappers use the `.sh` suffix and must be executable.
Extensionless files in `.runseal/wrappers` are not wrapper entrypoints; migrate
legacy wrappers to `<name>.seal` or `<name>.sh`. On Windows, runseal also
checks `.exe`, `.cmd`, and `.bat` when the wrapper name has no extension.

### Seal wrappers

Expand Down
6 changes: 4 additions & 2 deletions app/src/core/internal_help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,10 @@ Lookup order:

Profile-local wrappers shadow home wrappers with the same name. On Unix, wrapper
shell files use the .sh suffix and must be executable. Seal wrappers use the
.seal suffix and are interpreted directly by runseal. On Windows, runseal also
checks .exe, .cmd, and .bat when the wrapper name has no extension.
.seal suffix and are interpreted directly by runseal. Extensionless files in a
wrappers directory are not wrapper entrypoints; migrate legacy wrappers to
<name>.seal or <name>.sh. On Windows, runseal also checks .exe, .cmd, and .bat
when the wrapper name has no extension.

.seal wrappers are bash-runnable wrapper glue. They are intended for
cross-platform repository operations where bash and PowerShell share a clear
Expand Down
7 changes: 7 additions & 0 deletions app/tests/fixtures/estate/ssh.seal
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ if [ -z "$1" ]; then
exit 0
fi

case "$1" in
-h|--help|help)
usage
exit 0
;;
esac

host=$1
shift

Expand Down
16 changes: 16 additions & 0 deletions app/tests/internal_wrappers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,22 @@ fn seal_wrapper_resolves() {
assert!(stdout.contains("seal-tool.seal"));
}

#[test]
#[cfg(unix)]
fn extensionless_is_ignored() {
let fx = fixture();
make_wrapper(&fx.project_wrappers.join("legacy"), "legacy");

let output = run_in(&fx, &[":legacy"]);

assert!(!output.status.success());
let stderr = String::from_utf8(output.stderr).expect("stderr should be UTF-8");
assert!(stderr.contains("wrapper not found: :legacy"));
assert!(stderr.contains("legacy.seal"));
assert!(stderr.contains("legacy.sh"));
assert!(!stderr.contains(".runseal/wrappers/legacy\n"));
}

#[test]
fn seal_wrapper_runs_directly() {
let fx = fixture();
Expand Down
15 changes: 15 additions & 0 deletions app/tests/operator/estate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,21 @@ fn ssh_remote_args() {
assert!(String::from_utf8_lossy(&denied.stderr).contains("host is not declared"));
}

#[test]
fn ssh_help() {
let fx = fixture();

let output = run_wrapper(&fx, "ssh", &["--help"]);

assert!(output.status.success());
assert_eq!(
String::from_utf8(output.stdout).expect("stdout should be UTF-8"),
"Usage: runseal :ssh <host> [--run <script> [-- <args>...] | -- <remote-command>...]\n"
);
assert!(output.stderr.is_empty());
assert!(log(&fx).is_empty());
}

#[test]
fn ssh_run_mode() {
let fx = fixture();
Expand Down
Loading