From f5f43654eba008d9eebd438d71826a2d78cf0cce Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 2 Aug 2026 19:10:42 +0000 Subject: [PATCH] docs: fix cwd wording and add consumer troubleshooting Align README/action.yml cwd descriptions with post-#486 wiring (no process.chdir). Document pushTag/createGithubReleases pitfalls and add a scan-friendly troubleshooting index for common consumer failures. Co-authored-by: Mohamed --- README.md | 4 +- action.yml | 5 +- docs/action-runtime.md | 9 ++-- docs/auth-and-publishing.md | 20 ++++++-- docs/push-changes-internals.md | 28 +++++++++-- docs/troubleshooting.md | 88 ++++++++++++++++++++++++++++++++++ 6 files changed, 140 insertions(+), 14 deletions(-) create mode 100644 docs/troubleshooting.md diff --git a/README.md b/README.md index 1f4ee472..26ca80e6 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ This action for [Changesets](https://github.com/changesets/changesets) creates a - commit - The commit message to use. Default to `Version Packages` - title - The pull request title. Default to `Version Packages` - setupGitUser - Sets up the git user for commits as `"github-actions[bot]"`. Default to `true` -- createGithubReleases - A boolean value to indicate whether to create Github releases after `publish` or not. Default to `true` +- createGithubReleases - When `true` (default), after a successful publish the action pushes git tags and creates GitHub Releases from changelog entries. When `false`, the action skips **both** tag pushes and GitHub Release creation (your publish script must handle tags if you still need them). - commitMode - Specifies the commit mode. Use `"git-cli"` to push changes using the Git CLI, or `"github-api"` to push changes via the GitHub API. When using `"github-api"`, all commits and tags are GPG-signed and attributed to the user or app who owns the `GITHUB_TOKEN`. Default to `git-cli`. -- cwd - Changes node's `process.cwd()` if the project is not located on the root. Default to `process.cwd()` +- cwd - Working directory passed to git operations and the `publish` script (resolved with `path.resolve`). Does **not** call `process.chdir`. The initial changeset read and the version path from the entrypoint still use the job’s `process.cwd()`, so keep `.changeset/` at the job working directory unless you only need `cwd` for publish/git scoping. Default: `process.cwd()`. - branch - Branch the action treats as the release base (version PR targets this branch; version branch is `changeset-release/`). Defaults to the current branch from `github.context.ref` with the `refs/heads/` prefix removed. ### Outputs diff --git a/action.yml b/action.yml index 89fe87a7..09921b7b 100644 --- a/action.yml +++ b/action.yml @@ -15,7 +15,10 @@ inputs: description: "The command to update version, edit CHANGELOG, read and delete changesets. Default to `changeset version` if not provided" required: false cwd: - description: Sets the cwd for the node process. Default to `process.cwd()` + description: > + Working directory for git operations and the publish script (path.resolve). + Does not change process.cwd(); the entrypoint's initial changeset read and + version path still use the job working directory. Default: process.cwd(). required: false commit: description: | diff --git a/docs/action-runtime.md b/docs/action-runtime.md index da9ed702..ef09f8db 100644 --- a/docs/action-runtime.md +++ b/docs/action-runtime.md @@ -2,9 +2,7 @@ Engineering notes for the Changesets Release Action control flow in `src/index.ts` and `src/run.ts`. -User-facing usage: [`README.md`](../README.md). -Auth / npm: [`auth-and-publishing.md`](./auth-and-publishing.md). -How version commits are pushed: [`push-changes-internals.md`](./push-changes-internals.md). +Related docs: [`README.md`](../README.md) (usage) · [`auth-and-publishing.md`](./auth-and-publishing.md) · [`push-changes-internals.md`](./push-changes-internals.md) · [`troubleshooting.md`](./troubleshooting.md). --- @@ -140,11 +138,12 @@ Runs only from the dispatch publish case (no remaining changesets + `publish` in - **Monorepo / non-root tool:** lines matching `New tag:\s+(@[^/]+\/[^@]+|[^/]+)@([^\s]+)`. - **Root package:** first line matching `New tag:` → treat the single root package as released; GitHub tag name `v{version}`. 3. If `createGithubReleases` is true (default) and packages were detected: - - Push each tag via `git.pushTag`. + - Push each tag via `git.pushTag` (see [`push-changes-internals.md`](./push-changes-internals.md) §5 — github-api tags `github.context.sha`; failures only warn). - `repos.createRelease` with body from that version’s changelog entry; `prerelease` when the version contains `-`. - Missing changelog file → skip that release silently (`ENOENT`); missing entry for the version → throw. +4. If `createGithubReleases` is false → **no** `pushTag` and **no** GitHub Release, even when `New tag:` lines were parsed. `published` / `publishedPackages` still reflect stdout detection. -If stdout has no `New tag:` lines, result is `{ published: false }` and outputs stay at the startup defaults. +If stdout has no `New tag:` lines, result is `{ published: false }` and outputs stay at the startup defaults. Your publish script must print `New tag: …` (changeset publish does) or the action will not treat the run as published. --- diff --git a/docs/auth-and-publishing.md b/docs/auth-and-publishing.md index de62c42e..d293ae1a 100644 --- a/docs/auth-and-publishing.md +++ b/docs/auth-and-publishing.md @@ -2,8 +2,7 @@ Engineering notes for token resolution and npm auth in `src/index.ts` / `src/run.ts` (behavior shipped for `@changesets/action@1.7.0`). -User-facing examples live in the root [`README.md`](../README.md). -Dispatch / version-PR / publish detection: [`action-runtime.md`](./action-runtime.md). +Related docs: [`README.md`](../README.md) (examples) · [`action-runtime.md`](./action-runtime.md) · [`troubleshooting.md`](./troubleshooting.md). --- @@ -79,12 +78,27 @@ Auth-line detection matches npm CLI style: `/^\s*\/\/registry\.npmjs\.org\/:[_-] --- -## 4. Related codepaths +## 4. Octokit throttling (`src/octokit.ts`) + +Every Octokit instance is created with `@octokit/plugin-throttling`: + +| Event | Behavior | +|-------|----------| +| Primary rate limit | Warning; retry if `retryCount <= 2` after `retryAfter` seconds | +| Secondary rate limit | Same retry policy | + +After three attempts the request fails. See [`troubleshooting.md`](./troubleshooting.md) §6. + +--- + +## 5. Related codepaths | Path | Role | |------|------| | `action.yml` → `github-token` | Default `${{ github.token }}` | | `src/index.ts` | Token resolve, `.netrc`, `.npmrc` / OIDC branch, dispatch publish vs version | +| `src/octokit.ts` | Throttled Octokit factory | | `src/run.ts` → `runPublish` / `runVersion` | Inject `GITHUB_TOKEN` into script env | | `docs/action-runtime.md` | When the action publishes, opens a PR, or exits | | `docs/push-changes-internals.md` | How commits are pushed after versioning | +| `docs/troubleshooting.md` | Consumer pitfall index | diff --git a/docs/push-changes-internals.md b/docs/push-changes-internals.md index db750cf4..3c7948da 100644 --- a/docs/push-changes-internals.md +++ b/docs/push-changes-internals.md @@ -123,6 +123,28 @@ This is GitHub's official [Commits API](https://docs.github.com/en/graphql/refer - **`pushChanges`** is called during `runVersion` to push the version-bump commit to the PR branch (`changeset-release/`). - **Existing PR fetch before push** — `runVersion` lists open PRs for `head: owner:changeset-release/` **before** `pushChanges`. With `commitMode: github-api`, `@changesets/ghcommit` may reset the remote branch to the base SHA (which would otherwise close the PR); keeping the PR number and calling `pulls.update` with `state: "open"` reopens/updates it (#488). Full version-PR lifecycle: [`action-runtime.md`](./action-runtime.md) §5. -- **`pushTag`** is called during `runPublish` to tag releases after stdout `New tag:` detection: - - git-cli: `git push origin ` - - github-api: `octokit.rest.git.createRef({ ref: "refs/tags/", sha: github.context.sha })` + +--- + +## 5. `pushTag` — publish-time tags (`src/git.ts`) + +Called from `runPublish` **only when** `createGithubReleases` is `true` (default). Setting `createGithubReleases: false` skips **both** tag creation/push by the action **and** `repos.createRelease`. + +| Mode | Behavior | +|------|----------| +| **git-cli** | `git push origin ` in `cwd`. Expects the publish script (e.g. `changeset publish` / `changeset tag`) to have created the local tag already. | +| **github-api** | `octokit.rest.git.createRef({ ref: "refs/tags/", sha: github.context.sha })`. The tag always points at the **workflow triggering commit** (`github.context.sha`), not at a commit the publish script may have created afterward. | + +### Tag name conventions (chosen in `runPublish`, not in `pushTag`) + +| Package layout (`@manypkg/get-packages` `tool`) | Tag name | +|------------------------------------------------|----------| +| Non-root (monorepo) | `{packageName}@{version}` | +| Root | `v{version}` | + +### Pitfalls + +1. **`createGithubReleases: false` disables action tag pushes** — if you rely on the action (not your script) to publish tags, leave it `true` or push tags in `publish`. +2. **github-api tags `github.context.sha`** — correct when publish does not create a new git commit; wrong if your publish script commits first and you expected the tag on that new commit. +3. **createRef failures are warnings** — `.catch` logs `Failed to create tag …` and continues (assumes a custom publish script already pushed the tag). `createRelease` still runs afterward. +4. **git-cli missing local tag** — `git push origin ` fails the step if the tag was never created locally. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 00000000..05e46a7a --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,88 @@ +# Troubleshooting — consumer pitfalls + +Scan-friendly fixes for common `@changesets/action` surprises. Behavior verified against `src/index.ts`, `src/run.ts`, `src/git.ts`, and `src/readChangesetState.ts`. + +Deeper notes: [`action-runtime.md`](./action-runtime.md) · [`auth-and-publishing.md`](./auth-and-publishing.md) · [`push-changes-internals.md`](./push-changes-internals.md) · user examples in [`README.md`](../README.md). + +--- + +## 1. Version Packages PR never opens + +| Symptom | Likely cause | What to check | +|---------|--------------|---------------| +| Log: `All changesets are empty; not creating PR` | Every remaining changeset has `releases: []` | Remove or fill empty changesets. `hasChangesets` stays `"true"`. | +| Log: no changesets / no publish script | Merge cleared changesets and workflow omits `publish` | Expected no-op. Add `publish` if you want the publish path. | +| Changeset files exist but action says none | Pre mode already consumed those ids | `readChangesetState` filters ids listed in `preState.changesets` while `mode === "pre"`. | + +--- + +## 2. Publish did not run / `published` is false + +| Symptom | Likely cause | What to check | +|---------|--------------|---------------| +| Custom step `if: hasChangesets == 'false'` never runs | Empty-changeset skip left `hasChangesets=true` | See §1; empty changesets block both the Version PR and this pattern. | +| Action ran publish script but `published` is `false` | Stdout had no `New tag:` lines | Detection parses **stdout only**. Monorepo lines must match `New tag: name@version`; root needs any `New tag:` line. | +| npm 401 / auth errors | Token or OIDC misconfigured | [`auth-and-publishing.md`](./auth-and-publishing.md): `NPM_TOKEN` vs trusted publishing (`id-token: write`), custom registries need your own `.npmrc`. | + +--- + +## 3. `cwd` input surprises + +After #486 the action does **not** call `process.chdir`. + +| Works with `cwd` | Still uses job `process.cwd()` | +|------------------|--------------------------------| +| `Git` (commit/push/tag via git-cli) | Initial `readChangesetState()` in `src/index.ts` | +| `runPublish({ cwd })` (publish script + package discovery) | `runVersion(...)` call from the entrypoint (omits `cwd`) | + +**Practical rule:** keep the package root (and `.changeset/`) as the job working directory. Treat non-root `cwd` as best-effort for publish/git scoping only. + +--- + +## 4. Tags and GitHub Releases + +| Symptom | Likely cause | What to check | +|---------|--------------|---------------| +| No tags and no Releases after publish | `createGithubReleases: false` | That flag skips **both** `pushTag` and `repos.createRelease`. | +| Tag points at unexpected commit (`commitMode: github-api`) | `pushTag` uses `github.context.sha` | Tag is the workflow triggering SHA, not a commit your publish script created later. | +| Warning `Failed to create tag …` then Release still appears | Tag already existed remotely | createRef errors are swallowed as warnings; `createRelease` still runs. | +| git-cli: push tag failed | Local tag missing | Publish script must create the tag before the action pushes it. | +| Release creation throws | Changelog has no heading equal to the version | Missing `CHANGELOG.md` skips that release (`ENOENT`); missing **entry** throws. | + +Tag names: monorepo `{name}@{version}`; root package `v{version}`. Details: [`push-changes-internals.md`](./push-changes-internals.md) §5. + +--- + +## 5. `commitMode: github-api` issues + +| Symptom | Likely cause | What to check | +|---------|--------------|---------------| +| Version PR closed then reopened / flicker | Branch reset to base SHA before new commit | Action lists open PRs **before** push and force-opens on update (#488). | +| Error about symlink or executable | Changed symlink/executable in the version commit | API cannot add/update those; use `git-cli` (default) or avoid changing them. | +| `setupGitUser: true` had no effect | github-api path | `Git.setupUser` is a no-op when Octokit is set; attribution follows the token owner. | + +--- + +## 6. GitHub API rate limits + +`setupOctokit` (`src/octokit.ts`) uses `@octokit/plugin-throttling`: + +- On primary or secondary rate limit → warning log. +- Retries while `retryCount <= 2` (up to three attempts), waiting `retryAfter` seconds. +- Further limits fail the request. + +Large monorepos with many Releases or frequent version-PR updates are the usual trigger. + +--- + +## 7. Permissions quick checklist + +Minimum for opening/updating the Version Packages PR with `github.token`: + +```yaml +permissions: + contents: write + pull-requests: write +``` + +Add `id-token: write` when using npm trusted publishing (no `NPM_TOKEN`). Use a PAT / GitHub App token via `github-token` when the default token cannot trigger downstream workflows.