Skip to content

fix(homebrew): post_install cannot migrate legacy gateway.toml because Pathname#write refuses to overwrite #3746

Description

@sandeepstele

User Story

As a macOS user upgrading a Homebrew install of OpenShell, I want post_install to migrate my generated gateway.toml, so the upgrade completes and the gateway uses the current config.

Problem Statement

The formula's post_install migrates a legacy, formula-generated var/openshell/gateway.toml with gateway_config.write gateway_config_contents. Homebrew's Pathname#write refuses to replace an existing file. Library/Homebrew/extend/pathname/write_mkpath_extension.rb does this:

raise "Will not overwrite #{self}" if exist? && !offset && !mode&.match?(/^a\+?$/)

The migration branch only runs when the file already exists, so it always raises. post_install then aborts, and the old config stays in place. The steps after it also never run: the VM-driver entitlements write and codesign.

The call is in tasks/scripts/release.py on main, in the else branch that matches legacy_empty_gateway_config_contents / legacy_ipv6_gateway_config_contents. It also ships in the v0.1.1 openshell.rb release asset at line 132. The same formula already uses atomic_write for the entitlements plist, which overwrites safely.

Impact / Why This Matters

  • Any Homebrew user whose gateway.toml exactly matches one of the two legacy v1 configs hits this on upgrade. Those configs are exactly what earlier formulas generated, so this is the normal upgrade path, not an edge case.
  • brew upgrade or brew reinstall reports "The post-install step did not complete successfully".
  • The gateway keeps the legacy config. For the IPv6 variant that means bind_address = "[::1]:17670", which the migration exists to remove.
  • The driver-vm signing step is skipped.
  • Downstream installers that check brew's exit status fail. NVIDIA/NemoClaw's scripts/install-openshell.sh stops with status 69 ([macOS/WSL2][Onboard][Regression] OpenShell dashboard forward times out and blocks sandbox onboarding NemoClaw#11963 has the report).

Acceptance Criteria

  • Upgrading over either legacy v1 config rewrites var/openshell/gateway.toml to the current contents, and post_install completes.
  • A user-edited config (one that matches neither legacy config) is still left untouched.
  • python/openshell/release_formula_test.py asserts the overwrite-safe call. It currently asserts gateway_config.write gateway_config_contents (line 103), which locks the bug in.

Suggested fix: use gateway_config.atomic_write gateway_config_contents in the migration branch. The first-install branch can stay as write, because the file does not exist there.

Reproduction Steps

  1. On Apple Silicon macOS, install an OpenShell Homebrew formula that generated the legacy config. For example 0.0.106, which wrote:
    [openshell]
    version = 1
    
    [openshell.gateway]
    bind_address = "[::1]:17670"
  2. Upgrade to a formula that contains the migration. 0.0.116 reproduces it, and the v0.1.1 formula has the same code.
  3. Run brew postinstall --debug --verbose nvidia/openshell/openshell.

Expected: gateway.toml is migrated and post_install completes.
Actual: RuntimeError: Will not overwrite /opt/homebrew/var/openshell/gateway.toml, and post_install aborts.

Confirming the diagnosis: after I replaced the file by hand, brew postinstall completed and signed openshell-driver-vm with the hypervisor entitlement.

Environment

  • macOS 26.6, Apple M5 (arm64)
  • Homebrew 6.0.22
  • OpenShell upgraded from 0.0.106 to 0.0.116 through the nvidia/openshell tap (the pinned formula NemoClaw installs)
  • Code checked on NVIDIA/OpenShell main at a3ed8c7 and in the v0.1.1 openshell.rb release asset

Logs

==> Postinstalling openshell
==> /opt/homebrew/Cellar/openshell/0.0.116/bin/openshell-gateway generate-certs
Warning: The post-install step did not complete successfully
...
RuntimeError: Will not overwrite /opt/homebrew/var/openshell/gateway.toml

I'm not vouched yet, so I haven't opened a PR. The change is the one-line write → atomic_write swap above, plus the matching test assertion.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:triage-neededOpened without agent diagnostics and needs triage

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions