Skip to content

octo: refuse nested publisher layouts before generating workflows - #194

Open
jscjscjscjscjsc wants to merge 1 commit into
OctoSense-org:mainfrom
jscjscjscjscjsc:codex/publisher-root-guard-20261014
Open

jscjscjscjscjsc wants to merge 1 commit into
OctoSense-org:mainfrom
jscjscjscjscjsc:codex/publisher-root-guard-20261014

Conversation

@jscjscjscjscjsc

@jscjscjscjscjsc jscjscjscjscjsc commented Oct 14, 2026 •

Copy link
Copy Markdown

octo publish-github reports success for an app nested inside a Git repository, but writes .github/workflows/publish-app.yml under that app directory. GitHub only discovers workflows at the repository root, and the generated template assumes the app's bundle/ and components/ are there. This affected morning-brief's my-entry/morning-brief layout; simply moving the generated file does not fix its build paths.

Add a nearest-.git boundary check before generating a publishing workflow or creating an ordinary new app. Fail before writing anything for a nested layout, even with --replace, and explain where a manually reviewed root workflow belongs. A separate nested Git repository and a linked worktree root remain supported. Keep new --system's shell-repository behavior. This is a refusal of an unsupported generated layout, not automatic monorepo publishing.

This upstream submission reuses the team's existing morning-brief ISSUE-06 fix. The archived team patch also addresses UTF-8/LF authoring; those encoding changes have been deliberately excluded from this PR. English and Chinese publishing references document the same boundary.

Validation on Windows / Python 3.12.10 against d0344682:

  • Real local Git repositories and linked worktrees reproduce 4 failing assertions before the fix.
  • Publishing suite: 16 tests, OK (skipped=3) after the fix; the three symlink subcases cannot run with this Windows user's symlink privileges and are not claimed verified.
  • Broader CLI suite in an exported Unicode-path fixture: 39 tests, the same 3 pre-existing failures and 6 skips before and after. The remaining failures concern two release-shell fixtures and the existing SDK-path JSON-escape assertion. No new failures; the complete CLI suite is not claimed green.
  • tools/check-links.py: 0 broken, 0 pending; git diff --check passes.
  • octo doctor passes when pointed at the machine's existing hub/card-host binaries. No Rust/GUI build or hosted-app acceptance is claimed.

Fixtures use a temporary directory outside any Git repository, with Python UTF-8 mode enabled to isolate this layout fix from the separate encoding issue. No actual GitHub Actions workflow was executed, no tag/release or app submission was created, and no developer workflow, source pin or sealed bundle bytes were changed.

Team / 项目归属

Submitted by the 共创队(晨报卡 / Morning Brief;报名 ID:小鞠老师), via GitHub account jscjscjscjscjsc. Project repository: jscjscjscjscjsc/morning-brief. This contribution comes from issues encountered and fixes developed collaboratively while building the Morning Brief hackathon project.

本 PR 为晨报卡共创团队的上游贡献,关联项目仓库及已有修复记录;提交账号是团队贡献的提交入口。团队归属不代表主办方已经确认加分,上游合并状态以本 PR 为准。

@BH3GEI BH3GEI left a comment

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.

Thanks for putting this together — the guard is the right minimal fix and the tests pin exactly the invariants that matter.

Verified on macOS (Python 3.14.5) at 2f0c62c, differentially against base d034468:

  • tools/test_github_publish: 16/16 OK — the three symlink subcases that were skipped on Windows run and pass here. Full python -m unittest discover -s tools -p "test_*.py": 57 tests, OK (skipped=6, platform/environment skips only, same set as base).
  • Pre-fix reproduction: the new tests applied to the base commit fail exactly the 4 claimed assertions (nested publish without and with --replace, nested new, nested-in-linked-worktree); the four "remains supported" tests pass on both sides, so nothing else flipped.
  • Real-CLI end-to-end with unmodified tools/octo on real repositories and linked worktrees: a nested app is refused before any write (pre-existing developer workflow bytes unchanged, no .github created at the repository root, --replace included); an app at the repository root, an app with its own .git nested in an outer repo, a linked-worktree-root app, and a plain non-git directory all still publish; nested new refuses before creating the destination; new --system inside a shell repository still scaffolds. The refusal names the actual repository root and its .github/workflows path.
  • tools/check-links.py: 0 broken, 0 pending. Both doc hunks (EN/ZH) match the implemented behavior.

Two verified non-blocking notes, take or leave:

  1. tools/test_github_publish.py:69/90/112 assert the unresolved fixture path (from tempfile) against the error text, while both call sites resolve() the app path first. Stock CI TMPDIRs pass because the resolved path happens to contain the unresolved one, but a renamed symlinked TMPDIR makes four assertions fail (reproduced: TMPDIR=<symlink> python3 -m unittest test_github_publish → failures=4). Applying .resolve() to the expected path would make these robust.
  2. In cmd_publish_github the nested-layout error now wins over the sealed-bundle error for a nested sealed app (reproduced; tools/octo:609 precedes the sealed check). Both exit 1 with no writes, so cosmetic only — noting it in case you'd rather the sealed message surface first.

Scope is tight, the refusal fires before any filesystem effect in both entry points, and the message text is accurate. Approving.

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.

2 participants