gh-stack 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -78,12 +78,14 @@ create <branch-name> [--description <desc>]
78
78
  Create a new git branch off the current branch and add it to
79
79
  the stack. The current branch must already be tracked.
80
80
 
81
- submit [-d|--draft] [-n|--no-edit] [--dry-run]
81
+ submit [-d|--draft] [-n|--no-edit] [-t|--title <t>] [-b|--body <b>] [--body-file <f>] [--dry-run]
82
82
  Push all downstack branches to GitHub, create PRs for branches
83
83
  that don't have them, and update all PR descriptions with stack
84
84
  visualization. Idempotent — safe to run repeatedly.
85
85
 
86
- In --yes mode, auto-generates PR titles from branch names.
86
+ --title/-t and --body/-b provide PR details directly (skips prompts).
87
+ --body-file reads body from a file. In --yes mode without --title,
88
+ auto-generates PR titles from branch names.
87
89
  ```
88
90
 
89
91
  ### Stack Navigation
@@ -129,8 +131,9 @@ sync [--dry-run]
129
131
 
130
132
  merge [--dry-run]
131
133
  Squash-merge the stack top-down locally (PR3 → PR2 → PR1),
132
- then optionally rebase onto main. Closes intermediate PRs and
133
- archives the stack on completion.
134
+ then rebases onto main, closes intermediate PRs, pushes the
135
+ base branch, and enables GitHub auto-merge (squash). Archives
136
+ the stack on completion.
134
137
 
135
138
  delete [<branch>]
136
139
  Remove a branch from the stack and re-parent its children.
@@ -251,7 +254,7 @@ gh-stack top # jump to tip
251
254
  gh-stack status
252
255
 
253
256
  # When PRs are approved, merge the stack
254
- gh-stack merge
257
+ gh-stack merge # squash-merges down, pushes, enables auto-merge
255
258
  ```
256
259
 
257
260
  ## Agent/CI Usage
@@ -263,7 +266,8 @@ gh-stack is designed to be used by AI agents and CI pipelines:
263
266
  export GH_STACK_YES=1
264
267
 
265
268
  gh-stack init # No confirmations
266
- gh-stack submit # Auto-generates PR titles
269
+ gh-stack submit -t "Title [WEB-1234]" -b "Description" # Explicit PR details
270
+ gh-stack submit -n # Or auto-generate titles
267
271
  gh-stack sync
268
272
  gh-stack restack
269
273
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gh-stack",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Stacked PR manager for squash-merge workflows",
5
5
  "author": "Kiliman <kiliman@gmail.com>",
6
6
  "license": "MIT",
@@ -6,6 +6,7 @@ import * as git from "../lib/git.ts";
6
6
  import { findStackForBranch, getOrderedBranches, writeMetadata } from "../lib/metadata.ts";
7
7
  import { ensureMetadata, ensureCleanWorkingTree, ensureValidStack } from "../lib/safety.ts";
8
8
  import { takeSnapshot } from "../lib/snapshot.ts";
9
+ import { $ } from "bun";
9
10
  import { closePr } from "../lib/github.ts";
10
11
  import { confirmAction } from "../lib/ui.ts";
11
12
 
@@ -167,10 +168,40 @@ This keeps all commits local (avoiding orphaned squash commits).
167
168
  }
168
169
  await writeMetadata(meta);
169
170
 
170
- p.outro(pc.green("Stack merge complete! Stack archived."));
171
-
171
+ // Push base branch and enable auto-merge
172
172
  console.log();
173
- console.log(" Next steps:");
174
- console.log(` 1. Push ${pc.yellow(baseBranch)} and let CI run`);
175
- console.log(` 2. Squash-merge ${pc.yellow(baseBranch)} into main via GitHub`);
173
+ const pushAndMerge = await confirmAction(
174
+ `Push ${pc.yellow(baseBranch)} and enable auto-merge (squash)?`,
175
+ );
176
+
177
+ if (pushAndMerge) {
178
+ const pushSpinner = p.spinner();
179
+ pushSpinner.start(`Pushing ${pc.blue(baseBranch)}...`);
180
+ const pushOk = await git.forcePushWithLease(baseBranch);
181
+ if (pushOk) {
182
+ pushSpinner.stop(`Pushed ${pc.blue(baseBranch)}`);
183
+ } else {
184
+ pushSpinner.stop(pc.red(`Failed to push ${baseBranch}`));
185
+ p.outro(
186
+ pc.yellow("Stack merged locally but push failed. Push manually and merge via GitHub."),
187
+ );
188
+ return;
189
+ }
190
+
191
+ // Enable auto-merge via gh CLI
192
+ const basePrNum = stack.branches[baseBranch]?.pr;
193
+ if (basePrNum) {
194
+ const mergeSpinner = p.spinner();
195
+ mergeSpinner.start("Enabling auto-merge...");
196
+ try {
197
+ await $`gh pr merge ${basePrNum} --squash --auto`.quiet();
198
+ mergeSpinner.stop(`Auto-merge enabled for PR #${basePrNum} — will merge when CI passes`);
199
+ } catch {
200
+ mergeSpinner.stop(pc.yellow(`Could not enable auto-merge for PR #${basePrNum}`));
201
+ p.log.info(`Enable manually: ${pc.dim(`gh pr merge ${basePrNum} --squash --auto`)}`);
202
+ }
203
+ }
204
+ }
205
+
206
+ p.outro(pc.green("Stack merge complete! Stack archived."));
176
207
  }