Skip to content

auto-configure PATH in shell profile after install#1064

Merged
VaibhavUpreti merged 2 commits intoTracer-Cloud:mainfrom
rrajan94:feature/1063-auto-configure-path
Apr 29, 2026
Merged

auto-configure PATH in shell profile after install#1064
VaibhavUpreti merged 2 commits intoTracer-Cloud:mainfrom
rrajan94:feature/1063-auto-configure-path

Conversation

@rrajan94
Copy link
Copy Markdown
Collaborator

@rrajan94 rrajan94 commented Apr 29, 2026

Fixes #1063

Describe the changes you have made in this PR -

After running the one-liner install, opensre gave command not found because ~/.local/bin wasn't in $PATH. Users had to manually add the export line.

This PR adds a configure_path() function to install.sh that automatically writes the PATH export to the user's shell profile:

  • zsh → ~/.zshrc
  • bash on Linux → ~/.bashrc
  • bash on macOS → ~/.bash_profile
  • fish → ~/.config/fish/config.fish using fish_add_path
  • unknown shell → prints manual instructions, no file touched
  • Windows → unchanged

Re-running the installer never duplicates the line (idempotent via marker comment). The user is told to source <profile> or open a new terminal after install.

Demo/Screenshot for feature changes and bug fixes -

image

Code Understanding and AI Usage

Did you use AI assistance (ChatGPT, Claude, Copilot, etc.) to write any part of this code?

  • No, I wrote all the code myself
  • Yes, I used AI assistance (continue below)

If you used AI assistance:

  • I have reviewed every single line of the AI-generated code
  • I can explain the purpose and logic of each function/component I added
  • I have tested edge cases and understand how the code handles them
  • I have modified the AI output to follow this project's coding standards and conventions

Explain your implementation approach:

The install script was printing a warning asking users to manually add the PATH export. The fix detects the shell via $SHELL, picks the right rc file per shell and OS, then appends an export line guarded by a marker comment so the operation is idempotent. Fish uses fish_add_path instead of export. Two checks prevent duplicate writes: one for the marker comment (installer-managed) and one for the install dir already appearing in the file (user-managed). The function is placed in the function-definition section of the script so it can be extracted and unit-tested in isolation — 11 tests cover all the above cases.


Checklist before requesting a review

  • I have added proper PR title and linked to the issue
  • I have performed a self-review of my code
  • I can explain the purpose of every function, class, and logic block I added
  • I understand why my changes work and have tested them thoroughly
  • I have considered potential edge cases and how my code handles them
  • If it is a core feature, I have added thorough tests
  • My code follows the project's style guidelines and conventions

Note: Please check Allow edits from maintainers if you would like us to assist in the PR.

@rrajan94 rrajan94 requested a review from VaibhavUpreti April 29, 2026 02:35
Comment thread tests/cli/test_install_sh_path.py Fixed
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 29, 2026

Greptile Summary

This PR adds a configure_path() function to install.sh that automatically writes a PATH export to the user's shell rc file (zsh, bash, fish, or a manual fallback) after a successful install, replacing the previous manual-instruction warning. Eleven new pytest tests validate each shell branch and idempotency.

  • P1 – silent failure: When the # Added by opensre installer marker exists in the rc file but the export PATH line was manually deleted, the second guard returns without re-adding the path and without printing any message, so the user has no indication that PATH is unconfigured.

Confidence Score: 4/5

Safe to merge after fixing the marker-only idempotency guard that silently skips re-adding PATH when the export line has been deleted.

One P1 logic bug: when the installer marker is present but the path export line was manually removed, configure_path returns silently without re-adding the path or informing the user. All other findings are P2 style/test gaps. The fix is a one-liner and the test suite otherwise provides solid coverage.

install.sh lines 325-328 (marker-only idempotency check)

Important Files Changed

Filename Overview
install.sh Adds configure_path() that auto-writes the PATH export to the user's shell rc file; contains a logic bug where the marker-only check silently returns without re-adding the path if the export line was manually removed.
tests/cli/test_install_sh_path.py New test module covering 11 cases for configure_path(); unused pytest import and no test for the marker-exists-but-path-removed edge case.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[configure_path called] --> B{INSTALL_DIR already in PATH env?}
    B -- Yes --> Z[return]
    B -- No --> C{platform = windows?}
    C -- Yes --> D[warn: add to Git Bash / Windows PATH]
    D --> Z
    C -- No --> E[detect shell_name via $SHELL]
    E --> F{shell_name?}
    F -- zsh --> G[rc_file = ~/.zshrc]
    F -- bash/linux --> H[rc_file = ~/.bashrc]
    F -- bash/darwin --> I[rc_file = ~/.bash_profile]
    F -- fish --> J[rc_file = ~/.config/fish/config.fish]
    F -- unknown --> K[log manual export instruction]
    K --> Z
    G & H & I & J --> L[mkdir -p rc_dir if missing]
    L --> M{INSTALL_DIR string in rc_file?}
    M -- Yes --> Z
    M -- No --> N{marker comment in rc_file?}
    N -- Yes --> Z
    N -- No --> O[append marker + path_line to rc_file]
    O --> P[log source instruction to user]
    P --> Z
Loading

Reviews (1): Last reviewed commit: "auto-configure PATH in shell profile aft..." | Re-trigger Greptile

Comment thread install.sh
Comment on lines +325 to +328
local marker="# Added by opensre installer"
if [ -f "$rc_file" ] && grep -qF "$marker" "$rc_file"; then
return
fi
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Silent failure when marker exists but path line was removed

If a user manually deletes the export PATH=... line from their rc file but leaves the # Added by opensre installer marker, the second guard fires and configure_path returns silently — no log output, no warning. The user re-runs the installer, it prints "Installed … to …" and exits cleanly, but opensre is still not on PATH. The idempotency check should only skip when the path line itself is present, not merely the marker.

Suggested change
local marker="# Added by opensre installer"
if [ -f "$rc_file" ] && grep -qF "$marker" "$rc_file"; then
return
fi
local marker="# Added by opensre installer"
if [ -f "$rc_file" ] && grep -qF "$marker" "$rc_file" && grep -qF "${INSTALL_DIR}" "$rc_file"; then
return
fi

Comment thread install.sh Outdated

log ""
log "${BIN_NAME:-opensre} has been added to PATH in ${rc_file}."
log "To apply now, run: source ${rc_file}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unquoted path in source instruction

If rc_file contains spaces (e.g. a home directory like /home/john doe/.zshrc), the displayed command source /home/john doe/.zshrc is syntactically invalid. The path should be quoted.

Suggested change
log "To apply now, run: source ${rc_file}"
log "To apply now, run: source \"${rc_file}\""

Comment thread tests/cli/test_install_sh_path.py Outdated
import textwrap
from pathlib import Path

import pytest
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unused import

pytest is imported but never referenced in the test file — no fixtures, marks, or pytest.raises calls. Can be removed.

Comment on lines +78 to +83
def test_idempotent_no_duplicate_on_rerun(tmp_path: Path) -> None:
_run(tmp_path, shell="/bin/zsh")
_run(tmp_path, shell="/bin/zsh")
content = (tmp_path / "home" / ".zshrc").read_text()
export_lines = [ln for ln in content.splitlines() if _LOCAL_BIN in ln and "export PATH" in ln]
assert len(export_lines) == 1
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 No test for the marker-present / path-removed edge case

The idempotency suite covers "second run adds no duplicate," but there is no test that verifies the installer re-adds the export line when the marker comment is already in the file but the export PATH line has been manually deleted. Adding this case would also serve as a regression guard for the logic fix above.

Copy link
Copy Markdown
Member

@VaibhavUpreti VaibhavUpreti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cheers @rrajan94 ! Could you please make a task for someone to check for windows? I'm merging this

@VaibhavUpreti VaibhavUpreti merged commit 2272070 into Tracer-Cloud:main Apr 29, 2026
7 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

🐉 Legend says enough merged PRs and you ascend. @rrajan94 is dangerously close. 🌤️


👋 Join us on Discord - OpenSRE : hang out, contribute, or hunt for features and issues. Everyone's welcome.

muddlebee pushed a commit that referenced this pull request Apr 30, 2026
…1099) (#1101)

The post-merge ``test (windows-latest)`` job on commit 67dc64d (PR #1090
landing) is failing with two distinct symptoms in the install.sh test
suites added by PR #1064:

1. ``tests/cli/test_install_sh_path.py`` — 12 tests fail because the
   subprocess call ``subprocess.run(["bash", "-c", script])`` resolves
   ``bash`` to ``wsl.exe`` on the GitHub Actions ``windows-latest``
   runner, and that runner has no installed WSL distribution. Every
   ``_run`` call exits 1 with a literal "Windows Subsystem for Linux
   has no installed distributions" message, so none of the asserted
   rc files (``.zshrc``/``.bashrc``/``config.fish``) ever get written.

2. ``tests/cli/test_install_sh_resolution.py`` — module fails to import
   on Windows: the existing
   ``@pytest.mark.skipif(os.geteuid() == 0, reason=...)`` decorator
   evaluates ``os.geteuid()`` at decorator-application time, but
   ``os.geteuid`` does not exist on Windows. ``AttributeError`` fires
   *before* pytest can read any markers, blocking collection of every
   test in the module.

Both files exclusively test ``install.sh``, which is a POSIX shell
script (zsh/bash/fish RC files) with no Windows analogue, so the
correct fix for the Windows runner is to skip them.

Changes:

- ``test_install_sh_path.py``: module-level
  ``pytestmark = pytest.mark.skipif(sys.platform == "win32", ...)``
  with a comment that names the failure mode.

- ``test_install_sh_resolution.py``: same module-level skipif, *and*
  defensively replace ``os.geteuid() == 0`` with
  ``_RUNNING_AS_ROOT = hasattr(os, "geteuid") and os.geteuid() == 0``
  evaluated once at module load. ``hasattr`` short-circuits the ``and``
  on Windows so ``os.geteuid()`` is never called there — the module
  imports cleanly even before pytest reads ``pytestmark``.

No source-checkout behaviour change: skipif is a no-op on macOS/Linux,
and the existing root-only test still skips correctly on those
platforms (verified by running ``pytest tests/cli/test_install_sh_path.py
tests/cli/test_install_sh_resolution.py`` locally — 15 / 15 pass).
Full unit suite: 4164 pass / 2 skipped / 1 xfailed.

Closes #1099.
gitsofaryan pushed a commit to gitsofaryan/opensre that referenced this pull request May 3, 2026
…racer-Cloud#1099) (Tracer-Cloud#1101)

The post-merge ``test (windows-latest)`` job on commit 67dc64d (PR Tracer-Cloud#1090
landing) is failing with two distinct symptoms in the install.sh test
suites added by PR Tracer-Cloud#1064:

1. ``tests/cli/test_install_sh_path.py`` — 12 tests fail because the
   subprocess call ``subprocess.run(["bash", "-c", script])`` resolves
   ``bash`` to ``wsl.exe`` on the GitHub Actions ``windows-latest``
   runner, and that runner has no installed WSL distribution. Every
   ``_run`` call exits 1 with a literal "Windows Subsystem for Linux
   has no installed distributions" message, so none of the asserted
   rc files (``.zshrc``/``.bashrc``/``config.fish``) ever get written.

2. ``tests/cli/test_install_sh_resolution.py`` — module fails to import
   on Windows: the existing
   ``@pytest.mark.skipif(os.geteuid() == 0, reason=...)`` decorator
   evaluates ``os.geteuid()`` at decorator-application time, but
   ``os.geteuid`` does not exist on Windows. ``AttributeError`` fires
   *before* pytest can read any markers, blocking collection of every
   test in the module.

Both files exclusively test ``install.sh``, which is a POSIX shell
script (zsh/bash/fish RC files) with no Windows analogue, so the
correct fix for the Windows runner is to skip them.

Changes:

- ``test_install_sh_path.py``: module-level
  ``pytestmark = pytest.mark.skipif(sys.platform == "win32", ...)``
  with a comment that names the failure mode.

- ``test_install_sh_resolution.py``: same module-level skipif, *and*
  defensively replace ``os.geteuid() == 0`` with
  ``_RUNNING_AS_ROOT = hasattr(os, "geteuid") and os.geteuid() == 0``
  evaluated once at module load. ``hasattr`` short-circuits the ``and``
  on Windows so ``os.geteuid()`` is never called there — the module
  imports cleanly even before pytest reads ``pytestmark``.

No source-checkout behaviour change: skipif is a no-op on macOS/Linux,
and the existing root-only test still skips correctly on those
platforms (verified by running ``pytest tests/cli/test_install_sh_path.py
tests/cli/test_install_sh_resolution.py`` locally — 15 / 15 pass).
Full unit suite: 4164 pass / 2 skipped / 1 xfailed.

Closes Tracer-Cloud#1099.
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.

install.sh should automatically configure PATH in user's shell profile

3 participants