Skip to content

Releases: rijverse/phpvm

phpvm v2.6.1

02 Jun 08:57

Choose a tag to compare

Changed

  • Per-shell switching now self-heals. The shell hooks (bash/zsh/fish) previously forced the shim dir to the front
    of PATH only at source time, so anything that re-prepended /usr/bin or /bin after the rc hook ran (login
    profiles, /etc/environment, snap profile.d scripts, IDE-injected PATH) silently demoted the shim and the pin
    stopped taking effect until a new terminal. The PATH-front logic is now a function, _phpvm_path_fix, re-asserted
    from the cd-hook on every directory change. The case-guard makes the already-front case a no-op, so the per-cd
    cost is negligible. When it does reorder PATH, it also drops the shell command-location cache (hash -r in bash,
    rehash in zsh) so the next php runs from the restored order.
  • phpvm shell <ver> now repairs the current terminal in place. When the shim is on PATH but shadowed by
    another php, the eval'd snippet calls _phpvm_path_fix, so the pin takes effect immediately, with no "open a new
    terminal" step. The hint is reserved for the genuine case where the hook isn't loaded at all.

Fixed

  • Misleading and false "shim not on PATH" warning. The check in phpvm shell and phpvm --current said the shim was
    not on PATH when it actually was, just shadowed by an earlier php, and used a brittle exact-string compare that
    also misfired on symlinked $HOME / user installs (~/.phpvm). On those, detect_hook_dir returned an unresolved
    path while the hooks put the symlink-resolved dir on PATH, so they never matched and the warning fired even when
    switching worked. Replaced with a single shim_status helper (active / shadowed / absent / noshim) that
    compares resolved paths and is shared by phpvm shell, phpvm --current, and phpvm --doctor so the three stay
    consistent. detect_hook_dir now canonicalizes its result (pwd -P).
  • tests/test_cli.sh: the sh-shell shim-hint test now covers all three states. Absent gives the hook-not-loaded
    hint, shadowed does an in-place repair with no stale wording, and active stays silent. tests/test_install.sh: new
    runtime check that the cd-hook restores the shim to PATH front after a simulated late demotion, for both bash and
    zsh.

Docs

  • Rewrote the "Per-shell switching" section of the README so the everyday flow is the automatic, project-driven
    cd-switch (zero commands), and phpvm shell is presented as the manual per-terminal override that sits above it.
    Documents the three layers phpvm --current reports and explains that shell: not pinned is normal when the
    project layer is the one in charge.

phpvm v2.6.0

28 May 17:55

Choose a tag to compare

Added

  • phpvm which <version> prints the absolute binary path (e.g. /usr/bin/php8.2) for one installed PHP version.
    Mirrors nvm which / pyenv which / rbenv which so scripts and IDE config tools can pipe the result straight
    into wherever an interpreter path is needed (PhpStorm CLI Interpreter, VS Code php.validate.executablePath,
    LSP-Intelephense phpExecutablePath, NetBeans interpreters, CI configs). Returns the bare path on stdout, nothing
    else, so it composes. Accepts both 8.2 and php8.2.
  • phpvm --list --paths adds an absolute-path column next to each version, with the active marker preserved.
    Designed for visual IDE setup: one command lists every interpreter you can register and where it lives. Includes
    a dim footer pointing at the README's "Using with your IDE" section so the recipe is one prompt away.
  • phpvm --list --json emits [{"version":"8.2","path":"/usr/bin/php8.2","active":true}, ...] on a single pass:
    dependency-free (no jq needed to produce), stable schema (version / path / active), one entry per
    installed PHP, valid JSON ready for tooling and shell-scripted pipelines
    (jq -r '.[] | select(.active).path').
  • phpvm shell <ver> and phpvm shell --unset now emit a confirmation line via stderr ("pinned this terminal to
    PHP 8.2." / "shell pin removed for this terminal."). Previously silent on success, which left users wondering
    whether anything happened. The line is emitted inside the eval'd snippet so it preserves "after the eval"
    ordering.
  • Inactive-shim hint: when phpvm shell <ver> succeeds but the shim isn't on PATH in the caller's terminal
    (common scenario: terminal was opened before the hook landed), the eval'd snippet prints "shim not on PATH in
    this terminal, so php still resolves to <bin>." plus the exact source command to activate it. The same
    warning block shows up at the bottom of phpvm --current when a shell or project pin is set but php resolves
    to a non-shim binary, so the layer view explains the mismatch users were hitting.
  • tests/test_install.sh: new behavioral suite (18 checks) for install.sh and uninstall.sh. Static guards
    against the sudo-$HOME regression class, behavioral install in a fake HOME (writes to the right rc, no
    leakage, idempotent on re-run, --upgrade restores a missing hook), uninstall round-trip (hook removed, backup
    left, hook dir cleared), and a static + runtime check on the zsh hook (no BASH_SOURCE / PROMPT_COMMAND,
    zsh-native chpwd handler, shim prepended, phpvm() defined). The runtime block auto-skips when zsh isn't
    installed. Wired into tests/local-compat.sh so the docker matrix (Ubuntu 20.04 / 22.04 / 24.04) runs it, zsh
    added to the apt install step.

Fixed

  • install.sh wrote the per-user rc + autostart files using $HOME, which under sudo points at /root. The
    shell hook line landed in root's bashrc (or got silently dropped when that file didn't exist), so users who
    ran sudo ./install.sh never got source /etc/phpvm/php-auto.bash in their own rc. phpvm shell <ver> then
    printed the "needs the shell wrapper" guidance every time. Resolved by resolving USER_HOME and USER_SHELL
    from getent passwd "$CURRENT_USER" when EUID=0, and writing the rc file via sudo -u "$CURRENT_USER" tee -a
    so ownership stays with the invoking user. Same treatment for fish's ~/.config/fish/ directory creation.
    Consolidated the duplicate USER_HOME resolution that the autostart block had been doing inline.
  • install.sh --upgrade silently skipped the shell-hook block entirely. Users hit by the prior $HOME bug
    couldn't recover via --upgrade / --self-update and the hook stayed missing forever. Upgrade mode now writes
    the hook line when it's missing (no prompt, since upgrade implies "I want this installed").
  • shell/php-auto.zsh was a copy of the bash hook and broken in zsh on two counts: ${BASH_SOURCE[0]} is empty
    outside bash so _PHPVM_HOOK_DIR resolved to the current working directory instead of the hook's own location,
    and PROMPT_COMMAND doesn't exist in zsh so the cd auto-switch never fired. Rewrote using ${(%):-%x} for the
    script-self path (zsh prompt-expansion %x) and add-zsh-hook chpwd _php_switcher_auto (with an array-append
    fallback for older zsh without the add-zsh-hook autoload). Idempotent on re-source: add-zsh-hook -d chpwd
    first strips the prior registration, and the fallback path uses an ${array[(r)pattern]} check to skip
    duplicates.
  • uninstall.sh aborted at the first sudo rm when sudo couldn't prompt (running under set -e without a
    controlling terminal, or with cached creds expired), leaving rc files unswept and ~/.phpvm half-removed.
    Wrapped removals in a new _rm_path helper that tries sudo -n (non-interactive), falls back to a regular
    sudo rm with stderr suppressed, and warns + continues instead of failing the script. Result: a user without
    active sudo creds still gets a usable partial uninstall (their own files cleaned, system files left alone with
    a clear warning).

Changed

  • Internal cleanup: install.sh autostart block no longer duplicates the USER_HOME lookup, as both that block and
    the new shell-hook writer read from the single resolution near the top. No user-visible change.

Docs

  • README: new "Using with your IDE" section explaining why a GUI IDE doesn't pick up shell env vars, the three
    primitives phpvm exposes (which, --list --paths, --list --json), and copy-pasteable recipes for PhpStorm,
    VS Code (Intelephense / PHP Tools workspace settings), Sublime / Zed / Helix (LSP), NetBeans, and CI/jq.
    States the reasoning (forward-compat: paths instead of IDE config files) so contributors don't try to add a
    per-IDE config writer later. CLI table gains rows for --list --paths, --list --json, and phpvm which.
  • --doctor sample output in README bumped to v2.6.0.

phpvm v2.5.1

28 May 14:10

Choose a tag to compare

Added

  • install.sh now launches phpvm-gui immediately after installation when the user selected GUI (options 2 or 3).
    Runs in the background with nohup + disown so the tray icon appears without the installer blocking. When run
    under sudo, the session env is mostly stripped; the installer harvests the full set it needs (DISPLAY,
    WAYLAND_DISPLAY, XDG_RUNTIME_DIR, XDG_SESSION_TYPE, XDG_CURRENT_DESKTOP, XDG_DATA_DIRS,
    XDG_CONFIG_DIRS, XAUTHORITY, DBUS_SESSION_BUS_ADDRESS) from a user-owned graphical process via
    /proc/<pid>/environ and re-launches as the real user with sudo -u env .... Without XDG_RUNTIME_DIR the
    AppIndicator backend can't render the label next to the tray icon, and a gnome-terminal later spawned from the
    tray menu (Open Terminal UI) can't reach its session bus, so all of those vars matter for the tray to be usable.
    Skipped silently in non-interactive mode (CI/scripts) or when python3-gi is absent.

Fixed

  • Shell hook only ensured the shim dir was somewhere in PATH, not first. On boxes where something prepends /bin:
    or /usr/bin: to PATH after the hook runs (login shells re-reading /etc/environment, snap profile.d scripts,
    IDE-injected environments), the shim got demoted and php resolved to /usr/bin/php (the global symlink), so
    phpvm shell <ver> set PHPVM_SHELL_VERSION correctly but had no effect on subsequent php calls. The hook now
    forces the shim to position 0 every time it is sourced, stripping any stale copies first so PATH does not grow on
    re-source. Applied to all three hooks (php-auto.bash, php-auto.zsh, php-auto.fish).
  • Uninstaller failed to stop a running phpvm-gui because pgrep/pkill -x phpvm-gui matched on comm, which is
    python3 (from the shebang), not phpvm-gui. The kill step was silently skipped, the binary got removed, and the
    Python process kept its tray indicator registered on D-Bus, so the icon stuck around after uninstall. Switched to
    pgrep/pkill -f with a tight cmdline pattern ((^|[/ ])phpvm-gui( |$) so it won't match unrelated processes that
    happen to mention the name), plus a short post-TERM wait and a SIGKILL fallback if the GTK loop ignores SIGTERM.

Changed

  • install.sh now prints a prominent warning at the end when it has just added the shell hook, telling the user that
    already-open terminals won't pick it up until they source their rc. New terminals work automatically. Replaces the
    easy-to-miss dim one-liner that fired regardless. The same gotcha is now documented in README's "Installing" section.
  • Repo-wide typography sweep: removed all em dashes and Unicode ellipses from code, comments, prose, and CLI output
    (62 occurrences). Replaced with commas, semicolons, colons, periods, or parens; ellipses became ASCII .... Unicode
    arrows () kept as house style for status glyphs.

Docs

  • README: new Installing blockquote calling out the post-install source ~/.bashrc step for the terminal that ran
    the installer, plus a new collapsed <details> block with sample phpvm --doctor output showing what each
    subsystem check looks like on a healthy install. Documented sudo bash install.sh --upgrade / -U for local-clone
    upgrades (same path --self-update runs after it pulls).
  • CONTRIBUTING: added the typography rule to ground rules, a Tests section listing tests/test_cli.sh,
    tests/test_gui.sh, and tests/local-compat.sh, a CI pointer at .github/workflows/compat.yml, and a Changelog
    section pointing PR authors at the [Unreleased] block.

phpvm v2.5.0

27 May 21:53
d712b95

Choose a tag to compare

Added

  • Per-shell switching, now the default. phpvm shell <ver> switches PHP for the current terminal only, with no sudo,
    so two terminals can run two versions at once. It follows the rbenv / pyenv / asdf model: a php shim on PATH
    (installed to <hook dir>/shims/php) reads PHPVM_SHELL_VERSION and execs the matching /usr/bin/phpX.Y, falling
    back to the global symlink. phpvm shell --unset drops the pin.
  • phpvm local <ver> and phpvm global <ver> as the project and system-wide verbs. local writes .php-version
    (no sudo); global moves the update-alternatives symlink (sudo). The old --set and --set-project flags stay as
    aliases, so existing usage and scripts keep working.
  • A php shim template (shell/shim-php) plus a phpvm() shell wrapper in each hook. The wrapper routes shell and
    the bare TUI through eval (fish uses | source) so they can change the current shell; everything else calls the
    binary directly.
  • Resolution is now three layers: shell pin (PHPVM_SHELL_VERSION), then project (PHPVM_AUTO_VERSION, set by the
    cd-hook from .php-version / composer.json), then the global symlink. An explicit shell pin always wins, so it is
    never overridden by a later cd.

Changed

  • The cd-hook no longer runs a sudo global switch. It now resolves the project version with phpvm --auto --print and
    exports PHPVM_AUTO_VERSION (or unsets it on leaving), which the shim reads. The everyday path is sudo-free.
  • The TUI now pins the current shell on Enter when launched through the wrapper (drawing to the terminal while emitting
    the assignment on stdout, the way fzf does), with g for a global switch and p for the project. Run without the
    wrapper, Enter falls back to a global switch and notes how to enable per-shell pinning.
  • phpvm --current reports the shell pin, project, and global layers separately, plus the effective version. --doctor
    gains a "Per-shell switching" section that checks the shim and whether the shim dir is on PATH.
  • install.sh installs the shim, enables the shell hook by default (the everyday behavior depends on it), and reframes
    the sudoers prompt as needed only for phpvm global.
  • The GUI is documented as global by nature: the tray reflects and sets the system default, and a shell pinned with
    phpvm shell can legitimately sit above it.

Fixed

  • phpvm install no longer risks hanging on an unattended --yes run. apt is now invoked as
    sudo env DEBIAN_FRONTEND=noninteractive apt-get ..., so a package postinst (e.g. tzdata) can't block on an
    interactive debconf prompt. sudo resets the environment, which is why the frontend is set through env rather than
    an inline assignment; apt stays password-gated exactly as before.

phpvm v2.4.0

27 May 17:25

Choose a tag to compare

Added

  • phpvm install <ver> installs a PHP minor version from the upstream repo so you no longer hand-run apt install.
    Detects the distro from /etc/os-release: Ubuntu (and derivatives carrying ubuntu in ID_LIKE, e.g. Mint, Pop!_OS)
    use Ondřej Surý's ppa:ondrej/php; Debian uses the deb.sury.org repo with a keyring under /etc/apt/keyrings/sury-php.gpg
    and a [signed-by=...] source list pinned to $VERSION_CODENAME. Other distros get a clean error. Default package set is
    phpX.Y-cli phpX.Y-common phpX.Y-fpm; --minimal drops fpm and --with curl,mbstring appends phpX.Y-<ext>. Accepts
    explicit X.Y or latest (resolved via apt-cache once the repo is configured); patch levels like 8.2.13 are rejected.
    Idempotent: reports and exits if the version is already present. After installing it defensively registers the php
    alternative if the package didn't, then offers to switch (--use auto-switches). --print is a dependency-free, CI-safe
    dry-run that prints the repo and package list without touching the system.
  • phpvm --help documents the new install verb and its flags.

Security

  • phpvm install keeps apt/add-apt-repository under a normal password-gated sudo. The passwordless sudoers rule stays
    scoped to update-alternatives --set only; install never widens it.

phpvm v2.3.3

26 May 21:58

Choose a tag to compare

Changed

  • Repository moved to github.com/rijverse/phpvm (previously rijoanul-shanto/phpvm). The PHPVM_REMOTE default in
    install.sh — used by the remote bootstrap clone and by the --self-update fallback when no URL was recorded at
    install time — now points at the new location, along with every repo link in README.md, CONTRIBUTING.md,
    index.html, and social-preview.html.

Added

  • Project landing page (index.html) — a feature showcase of the taskbar indicator, tray menu, GUI window, and TUI
    picker, each with an annotated screenshot.
  • Social preview — social-preview.html rendered to assets/social-preview.png (1280×640) for the GitHub repo
    preview, plus Open Graph / Twitter Card meta tags on the landing page and a rijverse workspace badge linking to the
    organization.

phpvm v2.3.2

20 May 09:25

Choose a tag to compare

Fixed

  • install.sh prompts were silently skipped under curl … | sudo bash because piping replaces stdin with the pipe,
    making [[ -t 0 ]] return false even when a real terminal is attached. All interactivity checks now use
    { true < /dev/tty; } 2>/dev/null to detect a controlling terminal instead of testing stdin, and all read calls
    redirect from /dev/tty directly. The one-line installer is now fully interactive — same prompts as running
    bash install.sh locally. Truly headless environments (CI, nohup, no controlling tty) still fall back to defaults.

Changed

  • README: corrected the installer interactivity note to reflect /dev/tty-based detection.
  • README: added ## Uninstalling section — remote one-liner (curl … | sudo bash), local clone form, itemized list of
    what gets removed (binaries, hook dir, sudoers rule, desktop/autostart entries, icons, shell RC lines), RC backup
    behaviour, and the sudo-user note.

phpvm v2.3.1

20 May 07:50

Choose a tag to compare

Added

  • One-line remote installer — install.sh now self-bootstraps. When invoked without sibling repo files (e.g.
    curl -fsSL …/install.sh | sudo bash), it git-clones the repo into a mktemp -d, retargets SCRIPT_DIR at the
    clone, and continues in the same process so the EXIT trap removes the tmp dir on exit (no exec, no orphaned clone).
    PHPVM_REMOTE and PHPVM_REF env vars override the default repo URL and ref (main); falls back to a default-branch
    clone + git fetch origin <ref> && checkout FETCH_HEAD when --branch <ref> doesn't match a branch (so tags/SHAs
    work). Hard-fails with a clear message when git is missing.
  • phpvm --doctor — full diagnostic that checks CLI install, PHP runtimes, composer, PHP-FPM units, sudoers rule, shell
    hook wiring, GUI/tray deps (python3-gi / GTK 3 / Ayatana or legacy AppIndicator3 / icon / .desktop entry /
    autostart / running process), and project detection. Counts pass / warn / fail and exits non-zero on any fail.
  • install.sh now offers to enable autostart on login. Writes ~/.config/autostart/phpvm-gui.desktop and, under sudo,
    drops it into the invoking user's $HOME (resolved via getent passwd) with correct ownership. Upgrade mode
    refreshes the file in place if it already exists.
  • CI compatibility matrix (.github/workflows/compat.yml) — CLI and GUI jobs build on ubuntu:20.04 / 22.04 / 24.04
    containers. Runs shellcheck (-S warning), CLI smoke tests, and a GUI import + xvfb --help smoke test on every push
    and PR touching phpvm.sh, phpvm-gui.py, install.sh, uninstall.sh, shell/**, or tests/**.
  • tests/test_cli.sh, tests/test_gui.sh, tests/local-compat.sh — smoke tests for CLI flags, GUI imports, and a
    Docker-driven local matrix runner.

Changed

  • README overhaul: centered logo + GUI screenshots (assets/gui-window.png, assets/gui-tray-menu.png,
    assets/tui.png), expanded --doctor row in the CLI table, new --auto --print [dir] row, "Things it won't do"
    limitations section, and explicit Bash 4.3+ requirement (badge + "What you need").
  • Installer + GUI visual presentation polished — new box-drawing styles, clearer status labels in the GTK window,
    refactored icon-install feedback. Restart FPM button now sits to the left of Switch in the row so the
    destructive-looking action isn't the primary target.
  • install.sh autostart heredoc deduplicated into a single AUTOSTART_CONTENT template; the root and non-root branches
    differ only by the write wrapper (tee under sudo -u vs plain redirect).
  • shell/php-auto.zsh and shell/php-auto.fish headers now document both /etc/phpvm/ (system) and ~/.phpvm/ (user)
    install paths, matching the bash hook.
  • phpvm-gui.py docstring clarifies that Ayatana AppIndicator3 is preferred and legacy AppIndicator3 is accepted as
    a fallback.
  • tests/local-compat.sh aligned with CI — Ubuntu 18.04 dropped from the local matrix (CI never tested it; README only
    claims 20/22/24).
  • CONTRIBUTING.md — real repo URL, Bash target tightened to 4.3+ (local -n is required), matching phpvm.sh's
    guard.
  • .github/workflows/release.yml — every step now earns its keep. Added a repo-integrity pre-check that fails the tag
    if any shipped file is missing (including assets/phpvm.svg, which the installer needs but the previous workflow
    never verified). Added a bash -n syntax gate across phpvm.sh, install.sh, uninstall.sh, and
    shell/php-auto.bash. Every run: block now uses set -euo pipefail so the changelog awk pipeline (and friends)
    can't silently produce empty output. actions/checkout and softprops/action-gh-release are pinned to commit SHAs
    with version comments for supply-chain hardening. Dropped the shellcheck … || true step (lint that always passes is
    theater — lint lives in compat.yml now). Dropped the files: upload list and fetch-depth: 0 — the installer and
    phpvm --self-update both bootstrap via git clone, never via release artifacts, so the per-file uploads were
    decorative; GitHub's auto-attached source tarball still covers the "I want a versioned download" case.
  • .github/workflows/compat.ymlshellcheck is now a real gate. Removed the || true that silently swallowed every
    warning, hoisted lint into a dedicated lint job so it runs once instead of three times per matrix OS, and expanded
    the lint scope to include tests/test_cli.sh and tests/test_gui.sh. Split the GUI dependency install into a
    required step (python3, python3-gi, GTK 3, xvfb, libglib2.0-0 — fails fast) and an optional AppIndicator step (
    Ayatana → legacy → ::warning::), removing the blanket || true that was masking missing-python3 failures. Pinned
    actions/checkout to a commit SHA and added set -euo pipefail to every script block.

Fixed

  • phpvm.sh header comment said v2.1.0 while VERSION="2.2.0" — header bumped to v2.2.0.
  • tests/test_cli.sh was exercising non-existent subcommands (list, current, use) that the CLI never accepted;
    tests only passed because unknown commands return non-zero. Rewritten against the real flags (--list, --current,
    --set), with a regression test that asserts unknown positional use is rejected with Unknown option.
  • uninstall.sh under sudo only cleaned the invoking user's autostart, desktop, and icon files — it left
    ~/.local/bin/phpvm{,-gui}, the ~/.phpvm hook directory, and the user's shell rc lines untouched. SUDO_HOME now
    propagates to BIN_DIRS, HOOK_DIRS, and the rc-cleanup loop.
  • set_project_tui wrote .php-version without normalizing the version string or warning when an existing file held a
    different value — diverged from cmd_set_project. TUI now normalizes via normalize_version and prints an overwrite
    warning before the confirm prompt.
  • README CLI table missed phpvm --auto --print [dir] and undersold --doctor ("install location, sudoers rule, and
    shell-hook setup") versus its actual scope.

phpvm v2.3.0

20 May 07:18

Choose a tag to compare

🎉 phpvm v2.3.0 Release Notes

Added

  • One-line remote installer — install.sh now self-bootstraps. When invoked without sibling repo files (e.g. curl -fsSL …/install.sh | sudo bash), it git-clones the repo into a mktemp -d, retargets SCRIPT_DIR at the clone, and continues in the same process so the EXIT trap removes the tmp dir on exit (no exec, no orphaned clone). PHPVM_REMOTE and PHPVM_REF env vars override the default repo URL and ref (main); falls back to a default-branch clone + git fetch origin <ref> && checkout FETCH_HEAD when --branch <ref> doesn't match a branch (so tags/SHAs work). Hard-fails with a clear message when git is missing.
  • phpvm --doctor — full diagnostic that checks CLI install, PHP runtimes, composer, PHP-FPM units, sudoers rule, shell hook wiring, GUI/tray deps (python3-gi / GTK 3 / Ayatana or legacy AppIndicator3 / icon / .desktop entry / autostart / running process), and project detection. Counts pass / warn / fail and exits non-zero on any fail.
  • install.sh now offers to enable autostart on login. Writes ~/.config/autostart/phpvm-gui.desktop and, under sudo, drops it into the invoking user's $HOME (resolved via getent passwd) with correct ownership. Upgrade mode refreshes the file in place if it already exists.
  • CI compatibility matrix (.github/workflows/compat.yml) — CLI and GUI jobs build on ubuntu:20.04 / 22.04 / 24.04 containers. Runs shellcheck (-S warning), CLI smoke tests, and a GUI import + xvfb --help smoke test on every push and PR touching phpvm.sh, phpvm-gui.py, install.sh, uninstall.sh, shell/**, or tests/**.
  • tests/test_cli.sh, tests/test_gui.sh, tests/local-compat.sh — smoke tests for CLI flags, GUI imports, and a Docker-driven local matrix runner.

Changed

  • README overhaul: centered logo + GUI screenshots (assets/gui-window.png, assets/gui-tray-menu.png, assets/tui.png), expanded --doctor row in the CLI table, new --auto --print [dir] row, "Things it won't do" limitations section, and explicit Bash 4.3+ requirement (badge + "What you need").
  • Installer + GUI visual presentation polished — new box-drawing styles, clearer status labels in the GTK window, refactored icon-install feedback. Restart FPM button now sits to the left of Switch in the row so the destructive-looking action isn't the primary target.
  • install.sh autostart heredoc deduplicated into a single AUTOSTART_CONTENT template; the root and non-root branches differ only by the write wrapper (tee under sudo -u vs plain redirect).
  • shell/php-auto.zsh and shell/php-auto.fish headers now document both /etc/phpvm/ (system) and ~/.phpvm/ (user) install paths, matching the bash hook.
  • phpvm-gui.py docstring clarifies that Ayatana AppIndicator3 is preferred and legacy AppIndicator3 is accepted as a fallback.
  • tests/local-compat.sh aligned with CI — Ubuntu 18.04 dropped from the local matrix (CI never tested it; README only claims 20/22/24).
  • CONTRIBUTING.md — real repo URL, Bash target tightened to 4.3+ (local -n is required), matching phpvm.sh's guard.

Fixed

  • phpvm.sh header comment said v2.1.0 while VERSION="2.2.0" — header bumped to v2.2.0.
  • tests/test_cli.sh was exercising non-existent subcommands (list, current, use) that the CLI never accepted; tests only passed because unknown commands return non-zero. Rewritten against the real flags (--list, --current, --set), with a regression test that asserts unknown positional use is rejected with Unknown option.
  • uninstall.sh under sudo only cleaned the invoking user's autostart, desktop, and icon files — it left ~/.local/bin/phpvm{,-gui}, the ~/.phpvm hook directory, and the user's shell rc lines untouched. SUDO_HOME now propagates to BIN_DIRS, HOOK_DIRS, and the rc-cleanup loop.
  • set_project_tui wrote .php-version without normalizing the version string or warning when an existing file held a different value — diverged from cmd_set_project. TUI now normalizes via normalize_version and prints an overwrite warning before the confirm prompt.
  • README CLI table missed phpvm --auto --print [dir] and undersold --doctor ("install location, sudoers rule, and shell-hook setup") versus its actual scope.

phpvm v2.2.0

11 May 15:53

Choose a tag to compare

🎉 phpvm v2.2.0 Release Notes

Overview

This release brings significant improvements to the GUI components, authentication workflow, and system integration. The focus is on better user experience, improved reliability, and reduced friction in password handling.

✨ New Features

GUI Enhancements

  • In-window status messages: Real-time feedback for switch and FPM restart operations displayed directly in the window instead of system notifications
  • Polkit support: Added fallback to graphical authentication (pkexec) when passwordless sudo isn't configured
  • File monitoring: Automatic detection of PHP version changes from external sources via /etc/alternatives/php monitoring
  • Instance locking: Single instance enforcement to prevent multiple GUI windows running simultaneously

🔧 Major Changes

Authentication Improvements

  • Simplified sudo workflow: Removed the dependency on passwordless sudo configuration
    • Primary method: Fast path with sudo -n (passwordless)
    • Fallback: Graphical polkit dialog (pkexec) with user-friendly password prompts
  • Better error messages: Removed confusing error codes like "needs_sudo" and replaced with actionable status messages
  • Shell script improvements: Updated phpvm.sh to use interactive password prompts (-p flag) instead of silent mode

System Integration

  • Service restart enhancements: FPM restart now supports both passwordless sudo and graphical auth fallback
  • Tray integration: Window state is now properly synchronized with system tray mode
  • Uninstall improvements: uninstall.sh now gracefully stops running phpvm-gui instances

Developer Experience

  • Removed notification dependency: Window status messages replace desktop notifications for better UX
  • Improved callback system: Added on_switch callback mechanism for GUI-tray synchronization
  • Better module imports: Added fcntl support for instance locking

🐛 Bug Fixes

  • Fixed window mode vs tray mode logic (was reversed in previous version)
  • Improved error handling for missing commands
  • Better cache clearing on system state changes
  • Fixed modal dialog handling in folder selection

📋 Technical Details

Files Modified:

  • phpvm-gui.py - Major refactoring of GUI logic and authentication flow
  • phpvm.sh - Updated version number and sudo handling
  • uninstall.sh - Added graceful shutdown of running processes

Version String Updated:

  • v2.1.0v2.2.0

🚀 Migration Notes

  • No breaking changes for existing installations
  • The install.sh passwordless sudo setup is now optional (polkit provides fallback)
  • Users can continue using existing configurations without changes