Skip to content

feat(host-tools): shell variables above the bashrc guard, and home-relative ones - #187

Merged
Mearman merged 3 commits into
mainfrom
fix/host-tools-env-before-guard
Nov 3, 2026
Merged

Mearman merged 3 commits into
mainfrom
fix/host-tools-env-before-guard

Conversation

@Mearman

@Mearman Mearman commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

github_runner_host_tools_shell_env blocks were appended to the end of ~/.bashrc. On Ubuntu that is below the default interactive guard (case $- in *i*) ;; *) return;; esac), and a non-interactive bash, which is what sshd starts for ssh host cmd, stops reading the file there.

Seen live on the fleet's two Ubuntu 26.04 hosts: the block is at line 131 of ~/.bashrc on one (guard at line 9) and line 124 on the other (guard at line 6), and ssh <host> 'echo ${UV_PYTHON_DOWNLOADS-unset}' prints unset on both. On the Macs zsh reads ~/.zshenv for every shell, so it works there.

The managed env blocks are now inserted before the first line of the file. A block an earlier run appended lower down is removed and written again at the top (so existing hosts converge on the next run, no duplicate). Whether a block already leads the file is decided from the file's order (only blanks, comments and the role's own blocks above it), so any style of guard is stepped over. The Homebrew and mise blocks stay at the end. zsh follows the same rule, and a .zshenv laid out by the previous version (env block after the Homebrew and mise blocks) is already in order and is not touched.

Debian's bash reads ~/.bashrc for a shell whose stdin is a network connection (bash(1), archived); upstream bash does so only if built with SSH_SOURCE_BASHRC.

Tests run the role against a byte-for-byte copy of Ubuntu's /etc/skel/.bashrc and read the result with a real non-interactive bash. Run against the previous tasks, the new bash cases fail (unset != never).

The second commit adds github_runner_host_tools_shell_env_home_relative, a mapping of variable names to paths relative to the user's home, written as export NAME="$HOME/<path>". The play runs with gather_facts: false, so a fleet cannot name the home directory, and github_runner_host_tools_shell_env quotes $HOME so it stays literal. The path is escaped for double quotes (backslash, $, backtick, ") and read back through real sh, bash and zsh in the tests. Absolute, empty and .. paths, and a name set in both mappings, fail before any file is changed. Placement, the never-override rule and --check are the same as for the other mapping.

…uard

A non-interactive bash, which is what sshd starts for an SSH command,
reads ~/.bashrc only as far as the interactive guard that Debian and
Ubuntu put near the top of the default file. The managed blocks for
github_runner_host_tools_shell_env were appended at the end, below the
guard, so the variables were never set for an SSH command on those hosts.

A variable is now inserted before the file's first line, and a block an
earlier run appended lower down is taken out and written again at the
top, so existing hosts converge without anyone touching them. Whether a
block leads the file is decided from the file's own order (only blanks,
comments and the role's other blocks above it), not from a pattern for
the guard, so any way of writing the guard is stepped over. The Homebrew
and mise blocks stay at the end, where the interactive setup is.

The tests drive the role against a copy of Ubuntu's /etc/skel/.bashrc and
read the result with a real bash.
… home directory

The play runs with gather_facts false, so a fleet cannot say "the user's
home plus .cache/turbo", and github_runner_host_tools_shell_env quotes a
literal $HOME so that it never expands.

github_runner_host_tools_shell_env_home_relative maps a variable name to a
path relative to the user's home directory and writes it as
export NAME="$HOME/<path>", so the shell works the home directory out when
it reads the startup file. The characters special inside double quotes (a
backslash, a dollar sign, a backtick and a double quote) are escaped, so
the path reaches the variable as given in sh, bash and zsh. An absolute or
empty path, a path with a .. component and a name set in both mappings
fail the run before any file is changed.

The block is placed, skipped when a startup file already assigns the
variable, and checked exactly as for github_runner_host_tools_shell_env.
@Mearman Mearman changed the title fix(host-tools): write shell variables above the bashrc interactive guard feat(host-tools): shell variables above the bashrc guard, and home-relative ones Nov 3, 2026
…es back

The host tools tests run the lines the role writes through a real sh, bash and zsh,
and the runner image has no zsh.
@Mearman
Mearman marked this pull request as ready for review November 3, 2026 10:00
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review ⚠️ Failed 2026-11-03T10:01:02.652053Z
We couldn’t complete this review. Comment @codex security review to try again.
cf0c5a9 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

This security review couldn’t start because the paying account has exhausted its Codex allowance and has insufficient available credits. The payer can check their balance and add credits in the Codex usage dashboard, then try again. If you do not manage the paying account, contact this repository's admins.

@Mearman
Mearman merged commit c12ccbe into main Nov 3, 2026
25 checks passed
@Mearman
Mearman deleted the fix/host-tools-env-before-guard branch November 3, 2026 10:01
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 2.23.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant