Repository navigation
Each forge reads its own deliveries and connect fields; one journal follow for logs and events - #51
Merged
Merged
Conversation
Bobowski
force-pushed
the
status-and-podman
branch
from
November 2, 2026 22:55
d5d3016 to
a24bed3
Compare
…ollow for logs and events Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bobowski
force-pushed
the
forges-and-journal
branch
from
November 2, 2026 22:56
b8ac787 to
c073522
Compare
Bobowski
added a commit
that referenced
this pull request
Nov 2, 2026
…main.py (#52) ## Intent Split the 1,684-line `app/cli/main.py` along 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_deploy` each repeated the `urlopen`, `HTTPError`, `TimeoutError`, and `URLError` branches. The copies had drifted apart: `_follow_events` had no `TimeoutError` branch. - The pattern "print the raw answer for `--json` or for a wrong shape, else print the table" was copied in eight commands. - `_checkout_pair` and `_app_name` ran the same three git calls. `_read_pem` and `_ask_key` both read and checked a PEM. The GitHub `PUT` body was built in two places. - The manifest handler read its server state with `getattr`, but `_ManifestServer` declares those fields. - Small leftovers in `render.py`: `_ago` was an alias of `ago`, `_name_when` had one caller, and the deploy block wrapped one record in a list (from the old `deploys` field). ## Changed - `app/cli/client.py` holds the login (`load`), the calls (`api`, `api_try`, `stream`, `open_stream`), the flags (`out.json`, `out.no_color`), and `die`, `fail`, `ask`, `color_on`, and `show`. `_urlopen` is the one place that opens a request and turns a connection failure into the "did not answer" message. - `app/cli/checkout.py` holds `checkout()` (top, repo, branch), `remote_repo`, `app_name`, and the name helpers. - `app/cli/forge.py` holds `yard forge setup`, with one `_pem_at` and one `_put_github`. - `main.py` keeps the commands and the argument tree: 958 lines. - The other modules call `client.api_try` through the module. Thus a test patches one name. `tests/cli/test_main.py` has `_fake_api(monkeypatch, fake)` in place of the patch, `_forge_rows`, and `_env` lines it repeated 34 times. - `AGENTS.md` names the new modules. ## Not done - I kept most `isinstance` guards 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. - I did not convert the remaining hand-written fakes in `test_main.py` to a table of routes. Many of them assert on the request body or on the order of the calls, and a table hides that. - `_align` and `_render` in `render.py` stay separate: one has a header and an `(none)` line, the other has neither. ## Proof ``` $ just check ... 501 passed in 63.19s ``` 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](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
Let each forge own its own differences, and let the journal adapter own the follow process. Source: the user, in the Yard audit. This pull request stacks on #50.
Found
origin_hookandgithub_hookinapi.pyeach read the body, parsed the JSON, found the repo, loggedhook.received, and scheduled a check. Only the signature and the body shape differ.forge_puthad one branch for each forge, withisinstancechecks. Each branch validated its fields, calledconnect, sent the same journal event, and built the app answer.apps.pyand two times inrepos.py._stream_journal(with and without a filter) and_stream_eventseach ran the journalctl follow process, read lines, and killed the process in afinally.logs_gethad three read paths: JSON, text without a filter, and text with a filter._deploy_rowin the events had its own copy of the exit-code rule from One plan builds the compose project and its image; the deploy record is a dataclass #49.Changed
Forgegetssigned,delivery,connect_with,app_info,require_connected, and the attributesevent_header,signature_header, andconnect_fields. Origin and GitHub fill them in.HooksPage._hookis the one handler for both routes.forge_putvalidatesconnect_fieldsand has noisinstancechecks.journal.follow_entries(proc, tick)yields the entries of a follow process, andNoneat each tick with no new line. It kills the process when it closes. Both streams use it incontextlib.aclosing.journal.followstill starts the process before the headers go out, so a missing journal is still a 502.logs_getreads the entries once, applies the filter once, then writes JSON or text._logs_pageis gone._deploy_rowusesstatus.deploy_statusandstatus.deploy_error.The webhook body shapes moved from
api.pyintoforges.py.forges.pyalready reads the other forge-specific answers (installations, tokens, field names), so a delivery body fits there.Not done
Forge.installationsstays. A later pull request removes it with the 0.10 migration.Proof
The hook tests in
tests/server/test_api.py(status codes, a bad signature, a push, an installation event) and the log and event tests intests/server/test_journal.pypass without a change.Questions
last_deliverybefore the 400. Before, only a delivery that parsed set it. GitHub already set it before the parse.🤖 Generated with Claude Code