Repository navigation
CLI: one HTTP path in client.py; checkout.py and forge.py split from main.py - #52
Merged
Merged
Conversation
Bobowski
force-pushed
the
forges-and-journal
branch
from
November 2, 2026 22:56
b8ac787 to
c073522
Compare
…main.py Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bobowski
force-pushed
the
cli-http-split
branch
from
November 2, 2026 22:56
4c77e94 to
588c883
Compare
Bobowski
added a commit
that referenced
this pull request
Nov 2, 2026
## Intent Remove the code that moves a 0.10 host to 0.11. Source: the user, in the Yard audit. The user asked me to check the host with the yard CLI first. This pull request stacks on #52. ## Found The host runs 0.11 and has moved: - `yard --version` prints `0.11.0`. `yard status` shows `yard-app-1` on the commit of #47. - The `host` column of `yard status` comes from the site files, so the site files exist. Thus the 0.10 import does nothing at boot. - `yard forge ls --json` shows the GitHub state with an `installations` list, and each entry has an account. Thus no state has the old top-level `installation_id`. The code that only served the move: - `sites._import_binds`, `_bind`, and `_owner`: with no site file, boot wrote default sites from the 0.10 bind routes that Caddy resumed. Four tests covered it, one of them on a real Caddy with a 0.10 autosave. - `Forge.installations` read a top-level `installation_id` as one installation. `installation_for` let an installation with no account own every repo. Each `save` dropped the old keys. ## Changed - `sites.boot` only loads the Caddyfile, with the same retry when Caddy is not up yet. Three new small tests cover the retry, the give-up, and a refused load. - `Forge.installations` reads the `installations` list only. `installation_for` matches the account, case-insensitively. The saves drop only `installations`. - `CHANGELOG.md`: two breaking lines ("upgrade a 0.10 host through 0.11 first") and the line for the hosts cache from #50. `AGENTS.md` no longer names `_import_binds`. ## Not done - `CADDY_ADMIN` stays in `ops/compose.yml`. `ops/Caddyfile` sets the same admin socket, so the env is now redundant. But a change to the Caddy service recreates the Caddy container on the next yard deploy, and this pull request must not touch the proxy. - `status._image_plan` (a host with no labelled deploy container) stays. It also serves an app that has no deploy container at all. ## Proof ``` $ just check ... 498 passed in 64.96s ``` ## Questions None 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Split the 1,684-line
app/cli/main.pyalong its seams, and send every HTTP call through one function. Source: the user, in the Yard audit. This pull request stacks on #51.Found
_api_try,_stream,_follow_events, and_follow_deployeach repeated theurlopen,HTTPError,TimeoutError, andURLErrorbranches. The copies had drifted apart:_follow_eventshad noTimeoutErrorbranch.--jsonor for a wrong shape, else print the table" was copied in eight commands._checkout_pairand_app_nameran the same three git calls._read_pemand_ask_keyboth read and checked a PEM. The GitHubPUTbody was built in two places.getattr, but_ManifestServerdeclares those fields.render.py:_agowas an alias ofago,_name_whenhad one caller, and the deploy block wrapped one record in a list (from the olddeploysfield).Changed
app/cli/client.pyholds the login (load), the calls (api,api_try,stream,open_stream), the flags (out.json,out.no_color), anddie,fail,ask,color_on, andshow._urlopenis the one place that opens a request and turns a connection failure into the "did not answer" message.app/cli/checkout.pyholdscheckout()(top, repo, branch),remote_repo,app_name, and the name helpers.app/cli/forge.pyholdsyard forge setup, with one_pem_atand one_put_github.main.pykeeps the commands and the argument tree: 958 lines.client.api_trythrough the module. Thus a test patches one name.tests/cli/test_main.pyhas_fake_api(monkeypatch, fake)in place of the patch,_forge_rows, and_envlines it repeated 34 times.AGENTS.mdnames the new modules.Not done
isinstanceguards on the answers from the server. Without them, an older server can make the CLI raise a traceback in place of printing the raw answer.test_main.pyto a table of routes. Many of them assert on the request body or on the order of the calls, and a table hides that._alignand_renderinrender.pystay separate: one has a header and an(none)line, the other has neither.Proof
The CLI tests run unchanged in what they assert. Only their patch targets changed (
client.api_try,client.out.json,forge.SETUP_POLL, and so on).Questions
None
🤖 Generated with Claude Code