Skip to content

Publishing via action while using "ignore" option #241

Description

@augustjk

We have a monorepo of packages and want to use the "ignore" option to skip versioning and publishing a package temporarily.

The initial run of the workflow correctly runs the version, which respects the ignore option and only consumes, bumps version, and updates changelog for packages not ignored.

However, the subsequent run of the workflow still detects the leftover changeset markdown files of the ignored package, i.e. hasChangesets is true and tries to run the version again. If the detected changesets are all for ignored packages, hasChangesets should be set to false and enter the publish flow.

From what I can tell, the "ignore" option is only read and considered in @changesets/assemble-release-plan.

Instead of just reading all changesets below,

let { changesets } = await readChangesetState();

perhaps it would be better to use @changesets/get-release-plan to get releasable changesets?

Activity

  1. s0 commented on Apr 16, 2026

    @s0
    Member

    I just got hit by this too for a package that's completely ignored as it shares releases with another package in the same monorepo:

  2. yohimik commented on Sep 10, 2026

    @yohimik

    I reproduced the underlying state split with @changesets/cli@3.0.2 in a disposable two-package workspace:

    1. releasable@1.0.0 had a patch changeset.
    2. ignored@1.0.0 was listed in config.ignore and had its own patch changeset.
    3. changeset version exited 0, bumped releasable to 1.0.1, consumed only the releasable changeset, and left the ignored changeset file in place.

    The current Action v2.1.2 source still derives hasChangesets from the raw file count and publishes only in the !hasChangesets && hasPublishScript branch:

    action/src/index.ts

    Lines 55 to 136 in ae32849

    let { changesets } = await readChangesetState(cwd);
    let publishScript = core.getInput("publish-script");
    let hasChangesets = changesets.length !== 0;
    const hasNonEmptyChangesets = changesets.some(
    (changeset) => changeset.releases.length > 0,
    );
    let hasPublishScript = !!publishScript;
    core.setOutput("published", "false");
    core.setOutput("published-packages", "[]");
    core.setOutput("has-changesets", String(hasChangesets));
    switch (true) {
    case !hasChangesets && !hasPublishScript:
    core.info(
    "No changesets present or were removed by merging version PR. Not publishing because publish-script is not set.",
    );
    return;
    case !hasChangesets && hasPublishScript: {
    core.info(
    "No changesets found. Attempting to publish any unpublished packages to npm",
    );
    const createGithubReleases = core.getBooleanInput(
    "create-github-releases",
    );
    const pushGitTags = core.getBooleanInput("push-git-tags");
    if (createGithubReleases && !pushGitTags) {
    throw new Error(
    "The input 'create-github-releases' is set to true, but 'push-git-tags' is set to false. " +
    "Creating GitHub releases requires pushing git tags. Please set 'push-git-tags' to true " +
    "or set 'create-github-releases' to false.",
    );
    }
    const result = await runPublish({
    script: publishScript,
    github,
    createGithubReleases,
    pushGitTags,
    cwd,
    });
    if (result.published) {
    core.setOutput("published", "true");
    core.setOutput(
    "published-packages",
    JSON.stringify(result.publishedPackages),
    );
    }
    if (result.exitCode !== 0) {
    throw new Error(
    `Publish command exited with code ${result.exitCode}${
    result.published
    ? `, but some packages were published: ${result.publishedPackages
    .map((p) => `${p.name}@${p.version}`)
    .join(", ")}`
    : ""
    }`,
    );
    }
    return;
    }
    case hasChangesets && !hasNonEmptyChangesets:
    core.info("All changesets are empty. Not creating PR");
    return;
    case hasChangesets: {
    const { pullRequestNumber } = await runVersion({
    script: getOptionalInput("version-script"),
    github,
    cwd,
    prTitle: getOptionalInput("pr-title"),
    commitMessage: getOptionalInput("commit-message"),
    hasPublishScript,
    prDraft,
    branch: getOptionalInput("pr-base-branch"),
    });
    core.setOutput("pr-number", String(pullRequestNumber));
    return;
    . readChangesetState filters prerelease bookkeeping files but does not apply config.ignore:
    export default async function readChangesetState(
    cwd: string = process.cwd(),
    ): Promise<ChangesetState> {
    let preState = await readPreState(cwd);
    let changesets = await readChangesets(cwd);
    if (preState !== undefined && preState.mode === "pre") {
    return {
    preState,
    changesets: changesets.filter(
    (changeset) => !changeset.id.startsWith("pre/"),
    ),
    };
    }
    return {
    preState: undefined,
    changesets,
    };
    .

    I executed the CLI fixture locally; the Action conclusion below comes from inspecting that pinned source, not from running a production GitHub workflow.

    So after a valid package has been versioned, the retained ignored changeset still sends the next run back through runVersion; runPublish is never called. This is the same mutually exclusive gate described in #507, where a newly arrived changeset can also strand versions already merged to the release branch.

    A focused regression test could start from the state above and assert that an unpublished releasable@1.0.1 is published even while only ignored changesets remain. More generally, the Action seems to need separate decisions for “is there a releasable authoring change?” and “does this ref contain package versions not yet published?” rather than using raw changeset presence for both.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions