git-stack-cli 1.11.6 → 1.12.0

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.
@@ -29784,8 +29784,39 @@ async function pr_edit(args) {
29784
29784
  handle_error(cli_result.output);
29785
29785
  }
29786
29786
  }
29787
+ async function pr_draft(args) {
29788
+ const mutation_name = args.draft
29789
+ ? "convertPullRequestToDraft"
29790
+ : "markPullRequestReadyForReview";
29791
+ let query = `
29792
+ mutation($id: ID!) {
29793
+ ${mutation_name}(input: { pullRequestId: $id }) {
29794
+ pullRequest {
29795
+ id
29796
+ number
29797
+ isDraft
29798
+ }
29799
+ }
29800
+ }
29801
+ `;
29802
+ query = query.replace(/\n/g, " ");
29803
+ query = query.replace(/\s+/g, " ");
29804
+ query = query.trim();
29805
+ // lookup id from pr cache using args.branch
29806
+ const state = Store.getState();
29807
+ const cache_pr = state.pr[args.branch];
29808
+ invariant(cache_pr, "cache_pr must exist");
29809
+ const command_parts = [
29810
+ `gh api graphql -F id="${cache_pr.id}" -f query='${query}'`,
29811
+ ];
29812
+ const command = command_parts.join(" ");
29813
+ const cli_result = await cli(command);
29814
+ if (cli_result.code !== 0) {
29815
+ handle_error(cli_result.output);
29816
+ }
29817
+ }
29787
29818
  // prettier-ignore
29788
- const JSON_FIELDS = "--json number,state,baseRefName,headRefName,commits,title,body,url";
29819
+ const JSON_FIELDS = "--json id,number,state,baseRefName,headRefName,commits,title,body,url,isDraft";
29789
29820
  // consistent handle gh cli commands returning json
29790
29821
  // redirect to tmp file to avoid scrollback overflow causing scrollback to be cleared
29791
29822
  async function gh_json(command) {
@@ -30914,10 +30945,22 @@ async function run$6() {
30914
30945
  actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow, wrap: "truncate-end" }), message: "Syncing {group}\u2026", values: {
30915
30946
  group: (reactExports.createElement(Brackets, null, group.pr?.title || group.title || group.id)),
30916
30947
  } }));
30948
+ // we may temporarily mark PR as a draft before editing it
30949
+ // if it is not already a draft PR, to avoid notification spam
30950
+ let is_temp_draft = false;
30917
30951
  // before pushing reset base to master temporarily
30918
30952
  // avoid accidentally pointing to orphaned parent commit
30919
30953
  // should hopefully fix issues where a PR includes a bunch of commits after pushing
30920
30954
  if (group.pr) {
30955
+ if (!group.pr.isDraft) {
30956
+ is_temp_draft = true;
30957
+ }
30958
+ if (is_temp_draft) {
30959
+ await pr_draft({
30960
+ branch: group.id,
30961
+ draft: true,
30962
+ });
30963
+ }
30921
30964
  await pr_edit({
30922
30965
  branch: group.id,
30923
30966
  base: master_branch,
@@ -30941,6 +30984,13 @@ async function run$6() {
30941
30984
  selected_url,
30942
30985
  }),
30943
30986
  });
30987
+ if (is_temp_draft) {
30988
+ // mark pr as ready for review again
30989
+ await pr_draft({
30990
+ branch: group.id,
30991
+ draft: false,
30992
+ });
30993
+ }
30944
30994
  }
30945
30995
  else {
30946
30996
  if (!args.skip_checkout) {
@@ -31917,11 +31967,11 @@ function VerboseDebugInfo(props) {
31917
31967
  async function run$2() {
31918
31968
  const actions = Store.getState().actions;
31919
31969
  try {
31920
- await cli(`git config --list --show-origin`);
31921
31970
  await cli(`echo HOME=$HOME`);
31922
31971
  await cli(`echo USER=$USER`);
31923
31972
  await cli(`echo GIT_AUTHOR_NAME=$GIT_AUTHOR_NAME`);
31924
31973
  await cli(`echo GIT_AUTHOR_EMAIL=$GIT_AUTHOR_EMAIL`);
31974
+ await cli(`git config --list --show-origin`);
31925
31975
  }
31926
31976
  catch (err) {
31927
31977
  actions.error("Unable to log verbose debug information.");
@@ -31976,6 +32026,10 @@ async function run$1() {
31976
32026
  // get the commit SHA of the target commit
31977
32027
  const commit_sha = (await cli(`git rev-parse HEAD~${adjusted_number}`))
31978
32028
  .stdout;
32029
+ actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "\uD83D\uDEE0\uFE0F fixup {relative_number} {commit_sha}", values: {
32030
+ commit_sha: reactExports.createElement(Parens, null, commit_sha),
32031
+ relative_number: relative_number,
32032
+ } }));
31979
32033
  await cli(`git commit --fixup ${commit_sha}`);
31980
32034
  // check if stash required
31981
32035
  let save_stash = false;
@@ -31987,21 +32041,26 @@ async function run$1() {
31987
32041
  await cli("git stash -q");
31988
32042
  actions.output(reactExports.createElement(Text, null, "\uD83D\uDCE6 Changes saved to stash"));
31989
32043
  }
31990
- // rebase target needs to account for new commit created above
31991
- const rebase_target = Number(relative_number) + 1;
31992
- await cli(`git rebase -i --autosquash HEAD~${rebase_target}`, {
31993
- env: {
31994
- PATH: process.env.PATH,
31995
- GIT_EDITOR: "true",
31996
- },
31997
- });
31998
- actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "\uD83D\uDEE0\uFE0F fixup {relative_number} {commit_sha}", values: {
31999
- commit_sha: reactExports.createElement(Parens, null, commit_sha),
32000
- relative_number: relative_number,
32001
- } }));
32002
- if (save_stash) {
32003
- await cli("git stash pop -q");
32004
- actions.output(reactExports.createElement(Text, { color: colors.green }, "\u2705 Changes restored from stash"));
32044
+ try {
32045
+ // rebase target needs to account for new commit created above
32046
+ const rebase_target = Number(relative_number) + 1;
32047
+ await cli(`git rebase -i --autosquash HEAD~${rebase_target}`, {
32048
+ env: {
32049
+ ...process.env,
32050
+ GIT_EDITOR: "true",
32051
+ },
32052
+ });
32053
+ }
32054
+ catch (error) {
32055
+ actions.error("🚨 Fixup failed");
32056
+ await cli("git rebase --abort");
32057
+ await cli("git reset --soft HEAD~1");
32058
+ }
32059
+ finally {
32060
+ if (save_stash) {
32061
+ await cli("git stash pop -q");
32062
+ actions.output(reactExports.createElement(Text, { color: colors.green }, "\u2705 Changes restored from stash"));
32063
+ }
32005
32064
  }
32006
32065
  }
32007
32066
 
@@ -37420,7 +37479,7 @@ async function command() {
37420
37479
  .wrap(123)
37421
37480
  // disallow unknown options
37422
37481
  .strict()
37423
- .version("1.11.6" )
37482
+ .version("1.12.0" )
37424
37483
  .showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`")
37425
37484
  .help("help", "Show usage via `git stack help`")
37426
37485
  .argv;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-stack-cli",
3
- "version": "1.11.6",
3
+ "version": "1.12.0",
4
4
  "description": "",
5
5
  "author": "magus",
6
6
  "license": "MIT",
@@ -290,10 +290,25 @@ async function run() {
290
290
  />
291
291
  );
292
292
 
293
+ // we may temporarily mark PR as a draft before editing it
294
+ // if it is not already a draft PR, to avoid notification spam
295
+ let is_temp_draft = false;
296
+
293
297
  // before pushing reset base to master temporarily
294
298
  // avoid accidentally pointing to orphaned parent commit
295
299
  // should hopefully fix issues where a PR includes a bunch of commits after pushing
296
300
  if (group.pr) {
301
+ if (!group.pr.isDraft) {
302
+ is_temp_draft = true;
303
+ }
304
+
305
+ if (is_temp_draft) {
306
+ await github.pr_draft({
307
+ branch: group.id,
308
+ draft: true,
309
+ });
310
+ }
311
+
297
312
  await github.pr_edit({
298
313
  branch: group.id,
299
314
  base: master_branch,
@@ -322,6 +337,14 @@ async function run() {
322
337
  selected_url,
323
338
  }),
324
339
  });
340
+
341
+ if (is_temp_draft) {
342
+ // mark pr as ready for review again
343
+ await github.pr_draft({
344
+ branch: group.id,
345
+ draft: false,
346
+ });
347
+ }
325
348
  } else {
326
349
  if (!args.skip_checkout) {
327
350
  // delete local group branch if leftover
@@ -29,11 +29,11 @@ async function run() {
29
29
  const actions = Store.getState().actions;
30
30
 
31
31
  try {
32
- await cli(`git config --list --show-origin`);
33
32
  await cli(`echo HOME=$HOME`);
34
33
  await cli(`echo USER=$USER`);
35
34
  await cli(`echo GIT_AUTHOR_NAME=$GIT_AUTHOR_NAME`);
36
35
  await cli(`echo GIT_AUTHOR_EMAIL=$GIT_AUTHOR_EMAIL`);
36
+ await cli(`git config --list --show-origin`);
37
37
  } catch (err) {
38
38
  actions.error("Unable to log verbose debug information.");
39
39
 
@@ -74,6 +74,17 @@ async function run() {
74
74
  const commit_sha = (await cli(`git rev-parse HEAD~${adjusted_number}`))
75
75
  .stdout;
76
76
 
77
+ actions.output(
78
+ <FormatText
79
+ wrapper={<Ink.Text color={colors.yellow} />}
80
+ message="🛠️ fixup {relative_number} {commit_sha}"
81
+ values={{
82
+ commit_sha: <Parens>{commit_sha}</Parens>,
83
+ relative_number: relative_number,
84
+ }}
85
+ />
86
+ );
87
+
77
88
  await cli(`git commit --fixup ${commit_sha}`);
78
89
 
79
90
  // check if stash required
@@ -91,31 +102,27 @@ async function run() {
91
102
  actions.output(<Ink.Text>📦 Changes saved to stash</Ink.Text>);
92
103
  }
93
104
 
94
- // rebase target needs to account for new commit created above
95
- const rebase_target = Number(relative_number) + 1;
96
- await cli(`git rebase -i --autosquash HEAD~${rebase_target}`, {
97
- env: {
98
- PATH: process.env.PATH,
99
- GIT_EDITOR: "true",
100
- },
101
- });
102
-
103
- actions.output(
104
- <FormatText
105
- wrapper={<Ink.Text color={colors.yellow} />}
106
- message="🛠️ fixup {relative_number} {commit_sha}"
107
- values={{
108
- commit_sha: <Parens>{commit_sha}</Parens>,
109
- relative_number: relative_number,
110
- }}
111
- />
112
- );
113
-
114
- if (save_stash) {
115
- await cli("git stash pop -q");
116
-
117
- actions.output(
118
- <Ink.Text color={colors.green}>✅ Changes restored from stash</Ink.Text>
119
- );
105
+ try {
106
+ // rebase target needs to account for new commit created above
107
+ const rebase_target = Number(relative_number) + 1;
108
+
109
+ await cli(`git rebase -i --autosquash HEAD~${rebase_target}`, {
110
+ env: {
111
+ ...process.env,
112
+ GIT_EDITOR: "true",
113
+ },
114
+ });
115
+ } catch (error) {
116
+ actions.error("🚨 Fixup failed");
117
+ await cli("git rebase --abort");
118
+ await cli("git reset --soft HEAD~1");
119
+ } finally {
120
+ if (save_stash) {
121
+ await cli("git stash pop -q");
122
+
123
+ actions.output(
124
+ <Ink.Text color={colors.green}>✅ Changes restored from stash</Ink.Text>
125
+ );
126
+ }
120
127
  }
121
128
  }
@@ -82,6 +82,8 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
82
82
  id: "AAWsYx1UU",
83
83
  title: "banana",
84
84
  pr: {
85
+ id: "PR_kwDOKjvFM85ghvAH",
86
+ isDraft: false,
85
87
  baseRefName: "master",
86
88
  body: "adsf\r\n\r\n#### git stack\n- ⏳ `2` https://github.com/magus/git-multi-diff-playground/pull/47\n- 👉 `1` https://github.com/magus/git-multi-diff-playground/pull/43",
87
89
  commits: [
@@ -123,6 +125,8 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
123
125
  id: "E63ytp5dj",
124
126
  title: "lemon color",
125
127
  pr: {
128
+ id: "PR_kwDOKjvFM85gwTkx",
129
+ isDraft: false,
126
130
  baseRefName: "AAWsYx1UU",
127
131
  body: "\r\n\r\n#### git stack\n- 👉 `3` https://github.com/magus/git-multi-diff-playground/pull/47\n- ⏳ `2` https://github.com/magus/git-multi-diff-playground/pull/43\n- ✅ `1`\n https://github.com/magus/git-multi-diff-playground/pull/42",
128
132
  commits: [
@@ -251,6 +255,8 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
251
255
  ],
252
256
  pr_lookup: {
253
257
  AAWsYx1UU: {
258
+ id: "PR_kwDOKjvFM85ghvAH",
259
+ isDraft: false,
254
260
  baseRefName: "master",
255
261
  body: "adsf\r\n\r\n#### git stack\n- ⏳ `2` https://github.com/magus/git-multi-diff-playground/pull/47\n- 👉 `1` https://github.com/magus/git-multi-diff-playground/pull/43",
256
262
  commits: [
@@ -277,6 +283,8 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
277
283
  url: "https://github.com/magus/git-multi-diff-playground/pull/43",
278
284
  },
279
285
  E63ytp5dj: {
286
+ id: "PR_kwDOKjvFM85gwTkx",
287
+ isDraft: false,
280
288
  baseRefName: "AAWsYx1UU",
281
289
  body: "\r\n\r\n#### git stack\n- 👉 `3` https://github.com/magus/git-multi-diff-playground/pull/47\n- ⏳ `2` https://github.com/magus/git-multi-diff-playground/pull/43\n- ✅ `1`\n https://github.com/magus/git-multi-diff-playground/pull/42",
282
290
  commits: [
@@ -343,6 +351,8 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
343
351
  id: "AAWsYx1UU",
344
352
  title: "banana",
345
353
  pr: {
354
+ id: "PR_kwDOKjvFM85ghvAH",
355
+ isDraft: false,
346
356
  baseRefName: "master",
347
357
  body: "adsf\r\n\r\n#### git stack\n- ⏳ `2` https://github.com/magus/git-multi-diff-playground/pull/47\n- 👉 `1` https://github.com/magus/git-multi-diff-playground/pull/43",
348
358
  commits: [
@@ -384,6 +394,8 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
384
394
  id: "E63ytp5dj",
385
395
  title: "lemon color",
386
396
  pr: {
397
+ id: "PR_kwDOKjvFM85gwTkx",
398
+ isDraft: false,
387
399
  baseRefName: "AAWsYx1UU",
388
400
  body: "\r\n\r\n#### git stack\n- 👉 `3` https://github.com/magus/git-multi-diff-playground/pull/47\n- ⏳ `2` https://github.com/magus/git-multi-diff-playground/pull/43\n- ✅ `1`\n https://github.com/magus/git-multi-diff-playground/pull/42",
389
401
  commits: [
@@ -521,6 +533,8 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
521
533
  ],
522
534
  pr_lookup: {
523
535
  AAWsYx1UU: {
536
+ id: "PR_kwDOKjvFM85ghvAH",
537
+ isDraft: false,
524
538
  baseRefName: "master",
525
539
  body: "adsf\r\n\r\n#### git stack\n- ⏳ `2` https://github.com/magus/git-multi-diff-playground/pull/47\n- 👉 `1` https://github.com/magus/git-multi-diff-playground/pull/43",
526
540
  commits: [
@@ -547,6 +561,8 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
547
561
  url: "https://github.com/magus/git-multi-diff-playground/pull/43",
548
562
  },
549
563
  E63ytp5dj: {
564
+ id: "PR_kwDOKjvFM85gwTkx",
565
+ isDraft: false,
550
566
  baseRefName: "AAWsYx1UU",
551
567
  body: "\r\n\r\n#### git stack\n- 👉 `3` https://github.com/magus/git-multi-diff-playground/pull/47\n- ⏳ `2` https://github.com/magus/git-multi-diff-playground/pull/43\n- ✅ `1`\n https://github.com/magus/git-multi-diff-playground/pull/42",
552
568
  commits: [
@@ -160,8 +160,52 @@ export async function pr_edit(args: EditPullRequestArgs) {
160
160
  }
161
161
  }
162
162
 
163
+ type DraftPullRequestArgs = {
164
+ branch: string;
165
+ draft: boolean;
166
+ };
167
+
168
+ export async function pr_draft(args: DraftPullRequestArgs) {
169
+ const mutation_name = args.draft
170
+ ? "convertPullRequestToDraft"
171
+ : "markPullRequestReadyForReview";
172
+
173
+ let query = `
174
+ mutation($id: ID!) {
175
+ ${mutation_name}(input: { pullRequestId: $id }) {
176
+ pullRequest {
177
+ id
178
+ number
179
+ isDraft
180
+ }
181
+ }
182
+ }
183
+ `;
184
+
185
+ query = query.replace(/\n/g, " ");
186
+ query = query.replace(/\s+/g, " ");
187
+ query = query.trim();
188
+
189
+ // lookup id from pr cache using args.branch
190
+ const state = Store.getState();
191
+ const cache_pr = state.pr[args.branch];
192
+ invariant(cache_pr, "cache_pr must exist");
193
+
194
+ const command_parts = [
195
+ `gh api graphql -F id="${cache_pr.id}" -f query='${query}'`,
196
+ ];
197
+
198
+ const command = command_parts.join(" ");
199
+
200
+ const cli_result = await cli(command);
201
+
202
+ if (cli_result.code !== 0) {
203
+ handle_error(cli_result.output);
204
+ }
205
+ }
206
+
163
207
  // prettier-ignore
164
- const JSON_FIELDS = "--json number,state,baseRefName,headRefName,commits,title,body,url";
208
+ const JSON_FIELDS = "--json id,number,state,baseRefName,headRefName,commits,title,body,url,isDraft";
165
209
 
166
210
  // consistent handle gh cli commands returning json
167
211
  // redirect to tmp file to avoid scrollback overflow causing scrollback to be cleared
@@ -220,6 +264,7 @@ type Commit = {
220
264
  };
221
265
 
222
266
  export type PullRequest = {
267
+ id: string;
223
268
  number: number;
224
269
  state: "OPEN" | "MERGED" | "CLOSED";
225
270
  baseRefName: string;
@@ -228,4 +273,5 @@ export type PullRequest = {
228
273
  title: string;
229
274
  body: string;
230
275
  url: string;
276
+ isDraft: boolean;
231
277
  };