Skip to content

ci: self-contained stacked-PR breadcrumb workflow - #48

Merged
thecodedrift merged 7 commits into
mainfrom
jakob/stack-breadcrumb-gha
Jul 3, 2026
Merged

ci: self-contained stacked-PR breadcrumb workflow#48
thecodedrift merged 7 commits into
mainfrom
jakob/stack-breadcrumb-gha

Conversation

@thecodedrift

Copy link
Copy Markdown
Member

Bring taskless/taskless's stacked-PR breadcrumb over as a portable GitHub Actions workflow. It keeps each PR in a stack pointing at its siblings (a rendered <!-- stack … --> region in the PR body), reconciled serially per stack root with concurrency control.

Portable by design — no package

The source lives in taskless/taskless as a @taskless/stack-breadcrumb workspace package (pnpm + tsx + turbo). Here it's reduced to:

  • .github/scripts/stack-breadcrumb.cjs — the entire logic (tree derivation from base/head, marker-region splicing, breadcrumb render, reconcile planning) as a single zero-dependency CommonJS module. The gh I/O boundary is removed.
  • .github/workflows/stack-breadcrumb.yml — two jobs using actions/github-script, which supplies an authenticated octokit and loads the module with require. No pnpm install, no tsx, no build step.

Same two-stage design as the original:

  • dispatch (stage 1) — on PR shape events (opened/reopened/edited/closed), resolve the affected stack root(s) and fire a repository_dispatch.
  • reconcile (stage 2) — on that dispatch (or a manual workflow_dispatch), render and propagate the breadcrumb across the tree, serialized per root via a concurrency group.

Least-privilege permissions per job (stage 1 POSTs a dispatch; only stage 2 writes PR bodies) and the fork/bot guards are preserved.

Tests

The pure logic is covered by .github/scripts/stack-breadcrumb.test.cjs (36 cases) using Node's built-in node:test — zero dependencies — ported from the source vitest suite. Wired into CI as node --test .github/scripts/*.test.cjs. Breadcrumb output is asserted byte-for-byte, so this port matches the original exactly.

eslint.config.js ignores .github/scripts/ (CJS infra validated by its own test suite), matching how openspec//plugins//tmp/ are already handled.

Note

The reconcile stage only activates once this is on main — GitHub runs repository_dispatch/workflow_dispatch from the default branch's copy of the workflow only. Expected, and documented in the workflow header.

🤖 Generated with Claude Code

Ports taskless/taskless's stack-breadcrumb as a portable GitHub Actions
workflow: a zero-dependency CJS module loaded via actions/github-script,
no pnpm/tsx/package. Two-stage dispatch/reconcile serialized per stack
root; logic covered by a node:test suite wired into CI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 3, 2026 04:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Ports Taskless’s stacked-PR breadcrumb automation into this repo as a self-contained, zero-dependency GitHub Actions workflow plus a pure CommonJS implementation and Node-native unit tests, so stacks can be reconciled without any build/install step.

Changes:

  • Added a two-stage GitHub Actions workflow (dispatchreconcile) that serializes reconciliation per stack root and updates PR bodies via actions/github-script.
  • Introduced a zero-dependency .cjs module implementing stack discovery, breadcrumb rendering, and minimal PR-body region splicing, plus a Node node:test suite.
  • Wired the new Node test suite into CI and excluded the workflow scripts directory from ESLint.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
eslint.config.js Ignores .github/scripts/ since the new scripts are validated by their own Node test suite.
.github/workflows/stack-breadcrumb.yml Adds dispatch + reconcile jobs to keep PR stack breadcrumbs updated, with per-root concurrency.
.github/workflows/ci.yml Runs node --test against .github/scripts/*.test.cjs in CI.
.github/scripts/stack-breadcrumb.test.cjs Adds Node-native unit tests covering stack parsing, rendering, and reconcile behavior.
.github/scripts/stack-breadcrumb.cjs Adds the portable, pure logic module for deriving stacks and editing the PR body marker region.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/stack-breadcrumb.yml Outdated
Comment thread .github/workflows/stack-breadcrumb.yml Outdated
Comment thread .github/scripts/stack-breadcrumb.cjs
Coerce and validate the root from repository_dispatch client_payload and
workflow_dispatch input to a positive integer; an invalid value now fails
the run instead of silently building an empty tree and no-op'ing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Comment thread .github/workflows/stack-breadcrumb.yml
Comment thread .github/workflows/stack-breadcrumb.yml
Comment thread .github/workflows/stack-breadcrumb.yml
- Filter the open-PR corpus to same-repo PRs in both jobs so a fork PR
  sharing a branch name cannot corrupt branch-name-keyed tree derivation.
- Run the dispatch job from the default branch's copy of the script (not
  the PR head) so the privileged (contents: write) job never executes
  PR-supplied code; a resilient require keeps bootstrapping safe.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Comment thread .github/workflows/stack-breadcrumb.yml Outdated
Comment thread .github/workflows/stack-breadcrumb.yml Outdated
Comment thread .github/workflows/stack-breadcrumb.yml
- workflow_dispatch: fail loudly if the input PR is not open or is not a
  stack root (pointing at the actual root), instead of reconciling the
  wrong subtree or silently no-op'ing.
- repository_dispatch: treat a since-closed root as an explicit logged
  no-op (the documented race) and normalize to the current true root so
  a shifted stack still reconciles correctly.
- Fix header comment: workflow_dispatch runs from the selected branch,
  only repository_dispatch is default-branch-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment thread .github/scripts/stack-breadcrumb.cjs Outdated
Comment thread .github/scripts/stack-breadcrumb.cjs
parseStackComment now requires a full <!-- stack … --> … <!-- /stack -->
region, so a stray/pasted opening marker without a closing tag is no
longer mistaken for a managed region (which could wrongly pull a PR into
the resolveAffectedRoots marker route). Also correct the marker-surgery
comment to describe spliceRegion's actual whitespace normalization.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment thread eslint.config.js Outdated
Comment thread .github/workflows/stack-breadcrumb.yml
reconcile() still continues past an individual failed write (safe
failure), but the job now collects the failed PRs and calls setFailed so
an inconsistent breadcrumb surfaces in CI instead of passing silently.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment thread .github/scripts/stack-breadcrumb.cjs Outdated
Comment thread eslint.config.js Outdated
Removing a stack region no longer globally collapses 3+ newline runs
across the whole PR body (which could alter unrelated spacing); it now
trims only the blank lines hugging the removed region and rejoins the
surrounding text with a single blank line. Also reword the eslint-ignore
comment (scripts are covered by node:test, not linted by it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

@thecodedrift
thecodedrift merged commit 64e4c8b into main Jul 3, 2026
4 checks passed
@thecodedrift
thecodedrift deleted the jakob/stack-breadcrumb-gha branch July 3, 2026 06:43
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