Skip to content

[Refactor]: split release job to avoid gating every PR-merge approval #383

Description

@martyy-code

Problem It Solves

The current publish.yml workflow references environment: release at the job level. GitHub's environment protection rules (with required reviewers) gate the entire job, not the inner step if: clauses. This means:

  • Every PR merged into main triggers a Release workflow run.
  • The run creates a pending deployment to the release environment.
  • GitHub displays an approval request to the engineering team.
  • This happens regardless of whether the merge commit introduced a changeset.

For an active repository with daily merges (CI fixes, docs, refactors), the engineering team faces approval fatigue for "no-op releases" that intentionally exit 0 with no publish. The release pipeline becomes a tax on every merge.

Proposed Solution

Split into two jobs in the same workflow file:

  1. detect (no environment): runs first, uses git diff or pnpm changeset status to determine whether the merge introduced a changeset. Sets an output has_changesets: bool. No environment, runs on every merge, no approval required.
  2. release (with release environment): only created/skipped based on the detect output. The approval gate only kicks in when there is a real release to publish.

This is the standard two-job pattern in monorepo release pipelines. It keeps the security gate on the publish step without making every merge on main an approval request.

Current state

The publish.yml workflow file on main defines a single release job that:

  • Triggers on pull_request: types: [closed], push: tags, workflow_dispatch.
  • Uses environment: release with required reviewers configured in the GitHub UI (per docs/engineering/plans/release-pipeline-github-ui-setup.md §1.1).
  • Has step-level if: clauses that skip individual publish steps when steps.detect.outputs.has_changeset == 'false'.

The GitHub Actions docs (deployments-and-environments.md) state: "When a workflow job references an environment, the job won't start until all of the environment's protection rules pass." The job-level if: clause is not evaluated before environment gating.

Reproduction steps

  1. Open a PR with only a documentation change (no .changeset/*.md file added or modified).
  2. Merge into main.
  3. Observe: the Release workflow run is created, the environment approval is requested, and the reviewer must approve even though the run will skip every publish step.

Acceptance criteria

  • Merging a PR without changesets does not trigger the release environment approval.
  • Merging a PR with a changeset does trigger the release environment approval.
  • The detect job logs which signal it used (changeset files added, manual dispatch, tag push).
  • The release environment still gates the actual pnpm changeset publish, git tag, and GitHub Release steps.
  • All third-party actions remain SHA-pinned.

Related

  • Plan: docs/engineering/plans/release-pipeline.md §6.4 (Version Packages PR pattern).
  • Runbook: docs/engineering/plans/release-pipeline-github-ui-setup.md §1.1.
  • Validation: observed on the e2e release runs of @deessejs/fp@1.1.0.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    refactorCode cleanuptriageNeeds evaluation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions