Skip to content

fix(setup): make setup.sh work when it is not run interactively - #1374

Open
dholt wants to merge 2 commits into
masterfrom
dholt/fix-setup-sh-noninteractive
Open

fix(setup): make setup.sh work when it is not run interactively#1374
dholt wants to merge 2 commits into
masterfrom
dholt/fix-setup-sh-noninteractive

Conversation

@dholt

@dholt dholt commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

The bug

The usual no-argument ./scripts/setup.sh invocation silently does nothing and
exits 0 when run non-interactively, including from CI outside this repository,
remote commands, pipelines, and agents.

$ ./scripts/setup.sh </dev/null ; echo "exit=$?"
exit=0

$ bash scripts/setup.sh
... works normally

Why

The old shebang was #!/bin/bash --init-file. --init-file FILE consumes the
script path as its option argument, leaving Bash with no script operand.

  • In an interactive terminal, Bash sources the file as an init file and opens
    a shell with the virtual environment activated.
  • Non-interactively, --init-file is ignored. Bash reads EOF from stdin and
    exits successfully without running the setup.

The old workflow invoked bash scripts/setup.sh, which supplied a script
operand and bypassed the shebang, so it did not cover the failing path.

Why removing the trick is safe

The interactive convenience is redundant:

  • The script already adds the activation command to ~/.bashrc, so the
    environment activates automatically in later shells.
  • The script prints the explicit activation command when it finishes.
  • --init-file replaces ~/.bashrc, so the subshell omitted the user's normal
    aliases, functions, and prompt.

Running ./scripts/setup.sh from a terminal will no longer leave an activated
subshell; use the command it prints or open a new shell.

Adjacent fixes

  • The root check previously printed an error and used a bare exit, which
    inherited echo's successful status. It now exits 1 and writes to stderr.
  • The unsupported-OS message referenced the nonexistent ${DEPS_RPM[@]}
    array. It now prints the actual RPM and Debian dependency arrays.

The unsupported-OS branch remains non-fatal because later setup is
distribution-independent and the existing virtualenv check still fails
loudly when a required dependency is genuinely absent.

Regression coverage

The setup workflow now runs:

./scripts/setup.sh </dev/null

That exercises the executable/shebang path on both Ubuntu 22.04 and Ubuntu
24.04 instead of bypassing it with bash scripts/setup.sh.

Validation on this head includes:

  • Bash syntax
  • workflow YAML parsing
  • direct non-interactive executable-path reproduction
  • root-refusal exit status
  • the Ubuntu 22.04 and Ubuntu 24.04 setup workflow jobs

Follow-up

Add Rocky Linux to the dependency-install case so the distribution already
supported elsewhere in DeepOps receives automatic setup dependencies instead
of the manual fallback message. AlmaLinux and Oracle Linux can be evaluated
separately as Red Hat-compatible candidates rather than being implied as
currently supported.

dholt added 2 commits July 28, 2026 09:31
`./scripts/setup.sh` silently does nothing and exits 0 for every
non-interactive caller — CI outside this repo, `ssh host './scripts/setup.sh'`,
pipelines, and AI agents.

The cause is the shebang. `--init-file FILE` consumes the script path as its
option argument, so bash is left with no script operand. An interactive shell
sources it as an init file (the intended trick, which drops you into a shell
with the venv active). A non-interactive shell ignores `--init-file`, has no
operand, reads EOF from stdin, and exits 0 having done nothing.

    $ ./scripts/setup.sh </dev/null ; echo "exit=$?"
    exit=0          # no packages, no venv, no output at all

    $ bash scripts/setup.sh        # works — operand form bypasses the shebang

That contrast is also why CI has never caught this: .github/workflows/setup.yml
runs the operand form.

Removing the trick costs little. The script already appends
`source ${VENV_DIR}/bin/activate` to ~/.bashrc and prints the activate command
on its last line, so the venv is still one command away and automatic in the
next shell. The `--init-file` shell was in any case a degraded one — it
*replaces* ~/.bashrc, so it had none of the user's aliases, functions or prompt.

Two adjacent bugs in the same file:

* The root check did `echo` then a bare `exit`, which inherits echo's status —
  so refusing to run as root also reported success. Now exits 1, on stderr.
* The unsupported-OS branch printed `${DEPS_RPM[@]}`, an array that has never
  been defined anywhere in the tree (`git log -S DEPS_RPM` finds only the commit
  that introduced the reference). It now names the real arrays and prints both
  the RPM and DEB lists, since the previous text offered EL package names to
  everyone including Debian users.

That branch stays non-fatal deliberately. It is an escape hatch: everything
after the `case` is distro-agnostic, and Rocky (`ID=rocky`) and AlmaLinux
(`ID=almalinux`) fall through it today because the case only matches
`rhel*|centos*|ubuntu*` — while README.md claims Rocky 8/9 support. Making it
exit would turn a working path into a hard failure for a supported distro. The
existing `virtualenv` check below still fails loudly when a dependency is
genuinely missing.

Behaviour changes worth calling out for anyone with existing automation:
running as root now fails loudly instead of quietly succeeding, and a
non-interactive `./scripts/setup.sh` now actually does the setup.

Signed-off-by: Doug Holt <dholt@nvidia.com>
@dholt

dholt commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Regression coverage is now part of this PR: the executable path runs on both
Ubuntu 22.04 and Ubuntu 24.04, and all checks pass on ff760eef. The PR body
has been updated to match the tested behavior. Ready for review.

@dholt
dholt requested a review from michael-balint July 28, 2026 23:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant