Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
552a95c
feat: publish workspace dependency closures
privatenumber Sep 4, 2026
621a6f7
fix: preserve workspace publication errors
privatenumber Sep 5, 2026
ce1a7b7
fix: scope workspace discovery to Git root
privatenumber Sep 5, 2026
9440e1f
refactor: separate workspace package publication
privatenumber Sep 5, 2026
cd23e75
feat: add publish branch templates
privatenumber Sep 5, 2026
9a75c03
fix: use square bracket branch templates
privatenumber Sep 5, 2026
1ef842e
fix: restore curly branch templates
privatenumber Sep 5, 2026
a3162a9
refactor: simplify workspace publication flow
privatenumber Sep 5, 2026
f1d9ff8
refactor: streamline publication selection
privatenumber Sep 5, 2026
10713f5
fix: isolate workspace package preparation
privatenumber Sep 5, 2026
4823ff7
fix: expose dependency binaries to Bun pack hooks
privatenumber Sep 5, 2026
3d98fc2
fix: restore GitHub install shorthand
privatenumber Sep 5, 2026
56130e0
feat: show workspace package publication progress
privatenumber Sep 5, 2026
618753a
fix: retain workspace publication diagnostics
privatenumber Sep 5, 2026
6a7d8db
fix: preserve workspace publication success
privatenumber Sep 5, 2026
cc4f21d
fix: report workspace package timing
privatenumber Sep 5, 2026
83f7770
refactor: reuse package publication preparation
privatenumber Sep 5, 2026
063065b
fix: retain standalone publication success
privatenumber Sep 5, 2026
2434bfc
refactor: share install command formatting
privatenumber Sep 5, 2026
bdf7bdf
fix: preserve standalone publication metadata
privatenumber Sep 5, 2026
1c99a46
refactor: decouple package preparation tasks
privatenumber Sep 5, 2026
3392497
fix: use inline task output
privatenumber Sep 5, 2026
0b007c6
refactor: separate standalone publication flow
privatenumber Sep 5, 2026
efa2cd7
test: cover publication output outcomes
privatenumber Sep 5, 2026
f160edf
refactor: share subprocess diagnostics
privatenumber Sep 5, 2026
4342e73
ci: install Bun for package manager tests
privatenumber Sep 5, 2026
0ae8a3e
fix: protect private workspace dependencies
privatenumber Sep 6, 2026
434fd6d
fix: preserve nested cleanup diagnostics
privatenumber Sep 6, 2026
3f5422e
test: make output diagnostics deterministic
privatenumber Sep 6, 2026
fbc84c8
refactor: migrate terminal colors to ansis
privatenumber Sep 6, 2026
dd471f5
chore: upgrade tasuku to beta.6
privatenumber Sep 6, 2026
7b0bcaf
feat: simplify standalone publication summary
privatenumber Sep 6, 2026
220fabc
chore: test inline clear prerelease
privatenumber Sep 6, 2026
29b97c7
style: unify package size column color
privatenumber Sep 6, 2026
a540cba
style: sort published file summary
privatenumber Sep 6, 2026
26cce4d
upgrade
privatenumber Sep 6, 2026
b2216aa
upgrade
privatenumber Sep 6, 2026
0618cc7
chore: install tasuku from public GitHub branch
privatenumber Sep 6, 2026
3c219cb
Revert "chore: install tasuku from public GitHub branch"
privatenumber Sep 6, 2026
d4d9649
upgrade
privatenumber Sep 6, 2026
10a4b6d
upgrade
privatenumber Sep 6, 2026
d389657
feat: warn when listed package files are missing from publish (#77)
privatenumber Sep 8, 2026
e34b997
docs: explain monorepo builds and fork preparation hooks
privatenumber Sep 8, 2026
b414e24
docs: link pnpm workspace and dependency policy references
privatenumber Sep 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ jobs:
with:
run_install: true

- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0

- name: Lint
run: pnpm lint

Expand Down
66 changes: 63 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ git-publish

| Flag | Description |
| ----------------------- | ------------------------------------------------------------- |
| `-b, --branch <name>` | Target branch name. Defaults to `npm/<current branch or tag>` |
| `-b, --branch <template>` | Target branch template. Supports `{gitRef}`, `{gitSha}`, and `{package}` |
| `-r, --remote <remote>` | Git remote name or URL to push to (default: `origin`) |
| `-o, --fresh` | Create a fresh single-commit branch. Force-pushes to remote |
| `-d, --dry` | Simulate the process. Does not commit or push |
Expand Down Expand Up @@ -95,6 +95,10 @@ Add your build command to the [`prepack`](https://docs.npmjs.com/cli/v8/using-np

This mirrors the same behavior as `npm publish`.

`git-publish` checks each positive `package.json` `"files"` entry from the packed package after lifecycle hooks run. If an entry matches no packed file or directory, it warns and still publishes. That usually means the build did not run, or the entry is wrong.

You can also run the build before `git-publish`. Existing build output, including gitignored files such as `dist/`, is included when it matches the package's `files` field. See [Preparing monorepo packages](#preparing-monorepo-packages) for workspace builds and custom hooks in a fork.

### What does `git-publish` do?

1. Checks out or creates the publish branch
Expand Down Expand Up @@ -126,10 +130,66 @@ Manual commits often:

Yes. Run `git-publish` from inside the specific package directory (e.g., `packages/my-lib`).

It will detect and publish only that package's contents to the root of the Git branch.
`git-publish` publishes the selected package and its internal `workspace:` dependencies from `dependencies` and `optionalDependencies`. It creates each package commit before one atomic push, so a failed branch update does not expose a partial dependency closure.

`--branch` accepts a small branch template with these placeholders:

- `{gitRef}`: The current branch, exact tag, or short commit fallback.
- `{gitSha}`: The full source commit object ID.
- `{package}`: The package name from `package.json`.

Quote branch templates in the shell, for example `'preview/{package}'`.

When `--branch` is omitted, workspace packages use the default template `npm/{gitRef}-{package}`. For a `core <- broker <- adapter` closure published from `feature/auth`, it creates:

```text
npm/feature/auth-@acme/core
npm/feature/auth-@acme/broker
npm/feature/auth-@acme/adapter
```

Pass a template to choose each workspace branch independently:

```sh
git-publish --branch 'preview/{package}'
```

For one package, a literal branch remains exact. For example, `git-publish --branch preview` publishes to `preview`. A multi-package workspace closure must render a unique branch for every package. Include `{package}` when a literal template would collide.

Standalone packages keep the default `npm/<gitRef>` branch. An explicit `--branch` can use the same placeholders or remain a literal branch name.

Internal workspace peer dependencies are not published. `git-publish` prints a warning for each peer so consumers can provide it.

> [!IMPORTANT]
> Currently does not support resolving `workspace:` protocol dependencies. Avoid using those or pre-bundle them before publishing.
> A recursive publication requires one push URL. Git cannot atomically push one dependency closure to multiple destinations.

#### Preparing monorepo packages

Install the repository's dependencies before publishing so the package manager can resolve [`workspace:` references](https://pnpm.io/workspaces#workspace-protocol-workspace) and run package hooks. `git-publish` does not automatically run a script named `build`.

If the repository has a workspace build command, run it before publishing. For example, in a pnpm monorepo with a root `build` script and a remote named `fork` pointing to your fork:

```sh
# From the repository root
pnpm install
pnpm build
cd packages/my-lib
git-publish --remote fork
```

Use the repository's documented build command to generate output for the selected package and all its required workspace dependencies. Each package's `files` field must include its build output.

If packages need custom preparation, add or adjust their `prepack` scripts in your fork's `package.json` files. Each package can use its own command. Commit the manifest and source changes before running `git-publish`: it requires a clean tracked working tree and packs from the committed source. Gitignored build output does not need to be committed.

Package hooks run in an isolated checkout that is cleaned between packages. If one package's build needs another package's generated files, build those dependencies in your source checkout first; do not rely on output from an earlier package's pack hook being retained for the next package.

#### Installing with pnpm

pnpm can block a Git dependency declared by another Git dependency with [`blockExoticSubdeps`](https://pnpm.io/settings/dependency-resolution#blockexoticsubdeps). A consumer that installs a published workspace closure must opt in:

```sh
pnpm install --config.block-exotic-subdeps=false '<install-specifier>'
```

### Can I publish to and install from a private repository?

Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,30 @@
"@manypkg/tools": "^2.1.2",
"fast-glob": "^3.3.3",
"gunzip-maybe": "^1.4.2",
"micromatch": "^4.0.8",
"tar-fs": "^3.1.2",
"tasuku": "^2.3.0"
"tasuku": "3.0.0-beta.7"
},
"devDependencies": {
"@types/gunzip-maybe": "^1.4.3",
"@types/js-yaml": "^4.0.9",
"@types/micromatch": "^4.0.10",
"@types/node": "^25.9.2",
"@types/npmcli__package-json": "^4.0.4",
"@types/tar-fs": "^2.0.4",
"ansis": "^4.3.1",
"byte-size": "^9.0.1",
"clean-pkg-json": "^2.0.0",
"cleye": "^2.6.0",
"find-up-simple": "^1.0.1",
"fs-fixture": "^2.16.0",
"js-yaml": "^4.2.0",
"kolorist": "^1.8.0",
"lintroll": "^1.30.2",
"manten": "^2.0.0",
"nano-spawn": "^2.1.0",
"pkgroll": "^2.27.1",
"skills-npm": "^1.2.0",
"terminal-columns": "^2.0.0",
"terminal-link": "^5.0.0",
"typescript": "^6.0.3"
}
Expand Down
49 changes: 36 additions & 13 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading