Skip to content

feat(n): support standalone repos via bin/repos.local.sh#154

Draft
jason10lee wants to merge 21 commits into
mainfrom
feat/repos-local-sh-hook
Draft

feat(n): support standalone repos via bin/repos.local.sh#154
jason10lee wants to merge 21 commits into
mainfrom
feat/repos-local-sh-hook

Conversation

@jason10lee
Copy link
Copy Markdown
Contributor

@jason10lee jason10lee commented May 29, 2026

All Submissions:

Changes proposed in this Pull Request:

This PR adds a method to better support custom plugins that live within their own standalone repos within the workspace environment.

Add your standalone repos as subdirectories of repos/ (just like before the monorepo) and then register them in bin/repos.local.sh. Examples are available at bin/repos.local.sh.sample.

How to test the changes in this Pull Request:

  1. No-op when absent. With no bin/repos.local.sh file, run n env list, n build, or any n <command> — behaviour should match main.
  2. Tier 1: monorepo plugin extension. Copy bin/repos.local.sh.sample to bin/repos.local.sh, uncomment a tier-1 example line (e.g. newspack_plugins+=("acme-internal-plugin")), create plugins/acme-internal-plugin/. From inside that dir, run n — it should target the right project (no "must be inside one of the repos" error). Confirm bin/repos.local.sh is gitignored: git status shouldn't show it.
  3. Tier 2: standalone repo declaration. Clone any Newspack-adjacent repo to repos/<name>/ (e.g. git clone … repos/newspack-community/). Add newspack_standalone_repos+=("newspack-community") to bin/repos.local.sh. Run bash -c 'source bin/repos.sh; get_repo_host_path newspack-community' — should print repos/newspack-community. From inside repos/newspack-community/, run n — should target the right project.
  4. Tier 2: env create + activate. n env create demo --worktree newspack-community:test-branch — should succeed and create a worktree at worktrees/standalone/newspack-community/test-branch/. Inspect the generated docker-compose.env-demo.yml — it should contain both the worktree mount and a # newspack-wt: repo=… branch=… host=… comment with the original (unsanitized) branch name.
  5. Tier 2: in-env behaviour. n env up demo; visit https://demo.test/wp-admin/plugins.php. The standalone repo should be symlinked into wp-content/plugins/ and listed as an available plugin.
  6. Tier 2: destroy correctness. n env destroy demo --yes. Both the compose file and the tier-2 worktree at worktrees/standalone/newspack-community/test-branch/ should be removed. Run git -C repos/newspack-community branch — the test-branch should be gone too (i.e., the original branch name round-tripped; not the sanitized form).
  7. Slashed branch round-trip. Repeat step 4 with a slashed branch like feat/foo. After destroy, the original feat/foo branch should be deleted from the standalone repo (not feat-foo).
  8. Failure scoping (no leaked worktrees). Try n env create bogus --worktree unknown-repo:any-branch. It should error with "unknown project 'unknown-repo'" and leave no worktree behind at the workspace root (this was the leak that motivated the work).
  9. Collision warning. Add a name to two arrays in bin/repos.local.sh, e.g. newspack_standalone_repos+=("newspack-ads"). bash -c 'source bin/repos.sh' should emit a stderr warning about the duplicate.
  10. Undeclared dirs in repos/ aren't auto-detected. Create repos/random-thing/ (NOT in newspack_standalone_repos). Run n build random-thing — it should error cleanly ("Project random-thing not found").
  11. List output. n env list should show standalone-repo worktrees with their original branch names (not the safe-branch directory form), and should not emit the "lacks newspack-wt metadata" note for envs created on this branch (only for ones from before the metadata was introduced).
  12. Container-side build. Inside the newspack_dev container, n build newspack-community should run composer install then the standalone repo's own pnpm install and pnpm run build from inside repos/newspack-community/ (not via pnpm --filter).

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable? (n/a — shell config + tooling)
  • Have you successfully run tests with your changes locally?

Known follow-ups (deferred to a follow-up PR):

  • bin/test-js.sh needs the same tier-2 dispatch as bin/build-repos.sh.
  • clone-repos.sh still clones canonical plugins into repos/.
  • Pre-v4 compose files (those generated before the # newspack-wt: metadata existed) fall back to safe_branch on destroy; for slashed branches this orphans the branch ref. Affects only legacy envs.
  • cleanup_partial_env_state trap coverage stops at worktree.sh add failures; failures later in env create may leave partial state.

@jason10lee jason10lee self-assigned this May 29, 2026
@jason10lee jason10lee changed the title feat(n): support bin/repos.local.sh for custom plugin lists feat(n): support standalone repos via bin/repos.local.sh May 29, 2026
@adekbadek
Copy link
Copy Markdown
Member

Heads-up: #177 just merged to main (commit dafcf70) — it's the minimal slice of this PR: mount ./repos at /newspack-repos, auto-symlink standalone repos via bin/link-repos.sh, plus .gitignore/AGENTS.md docs.

I test-merged the new main into this branch to scope what's left. Good news: almost everything reconciles automatically — the only real blocker is a pre-existing env.sh conflict that has nothing to do with #177.

Auto-merges cleanly: docker-compose.yml, docker-compose-82.yml, .gitignore, AGENTS.md, n. The duplicate - ./repos:/newspack-repos lines collapse onto the copies now in main.

One manual fix in bin/link-repos.sh: the auto-merge leaves a now-false comment next to main's new loop —

# `/newspack-repos/` is mount-only (available but not auto-linked).   <- delete this
...
# Symlink standalone repos from /newspack-repos/ into wp-content/plugins/.   <- main now auto-links

The decision is to keep auto-link-everything (it matches the pre-monorepo run.sh UX: drop a checkout into repos/ and it appears, no registration needed). So drop the "mount-only" line. The repos.local.sh registry then governs only the n-tooling surface (cwd-detection, n build/test, worktree/env targeting) — orthogonal to WP activation, and it can keep its declaration-gating in resolve-project-path.sh for build/test without affecting linking.

The actual blocker — env.sh (6 conflict hunks), unrelated to #177: main has since gained each_worktree_in_env + anchored-regex volume matching (a false-match robustness fix), while this branch introduces parse_env_worktrees + # newspack-wt: metadata. Those are two implementations of the same enumeration and need a real merge — ideally this branch's richer standalone-repo/metadata parsing layered on top of main's anchored-regex fix, not a take-one-side resolution. Left for you since it's the env feature's core.

Net: with the basic mount+link now in main, this PR shrinks to its real value — the repos.local.sh registry and the standalone-repo env/worktree integration.

Reconcile #154's standalone-repos tooling with the typed repos/{plugins,themes}
layout shipped in #177: existence-based activation (link-repos), registry-gated
n-tooling (build/test/cwd), single tier-2-aware env enumerator.
@jason10lee
Copy link
Copy Markdown
Contributor Author

Thanks for the write-up! That made resolving this a lot easier than otherwise.

With 5aae514cb, the PR's mergeable again. We adopted the typed layout from your commit and refactored on that.

On env.sh: You suggested layering this branch's metadata parsing on top of main's each_worktree_in_env + anchored-regex fix. We found each_worktree_in_env/parse_worktree_mount are used only inside env.sh and only handle tier-1 mounts — they can't parse the tier-2 worktrees/standalone/<repo>/<branch> shape this branch adds, which every call site can hit. Keeping them would've left a second, tier-1-only parser as dead-ish code. So we consolidated onto the single tier-2-capable parse_env_worktrees, folding your robustness fixes into it: the anchored grep (commented-out volume lines can't false-match) and resolve_unsanitized_branch as the branch-name fallback when # newspack-wt: metadata is absent. Easy to split back into two parsers if that winds up being unmaintainable.

Other than that, we verified the parsing/resolution behavior across both tiers (typed host, metadata + live-branch recovery, the false-match guard): all green.

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