git-stack-cli 1.6.2 → 1.8.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.
- package/dist/cjs/index.cjs +106 -18
- package/package.json +1 -1
- package/src/app/DirtyCheck.tsx +18 -8
- package/src/app/Main.tsx +4 -0
- package/src/app/ManualRebase.tsx +8 -2
- package/src/app/PreManualRebase.tsx +100 -0
- package/src/app/SelectCommitRanges.tsx +1 -1
- package/src/app/Store.tsx +5 -0
- package/src/app/YesNoPrompt.tsx +1 -1
- package/src/command.ts +14 -0
- package/src/core/github.tsx +7 -3
package/dist/cjs/index.cjs
CHANGED
|
@@ -17694,7 +17694,7 @@ function YesNoPrompt(props) {
|
|
|
17694
17694
|
n));
|
|
17695
17695
|
}
|
|
17696
17696
|
return (reactExports.createElement(Box, { flexDirection: "column" },
|
|
17697
|
-
reactExports.createElement(Box,
|
|
17697
|
+
reactExports.createElement(Box, { alignItems: "flex-end" },
|
|
17698
17698
|
typeof props.message === "object" ? (props.message) : (reactExports.createElement(Text, { color: colors.yellow }, props.message)),
|
|
17699
17699
|
reactExports.createElement(Text, null, " "),
|
|
17700
17700
|
reactExports.createElement(Parens, null,
|
|
@@ -26209,6 +26209,8 @@ const BaseStore = createStore()(immer((set, get) => ({
|
|
|
26209
26209
|
branch_name: null,
|
|
26210
26210
|
commit_range: null,
|
|
26211
26211
|
commit_map: null,
|
|
26212
|
+
pr_templates: [],
|
|
26213
|
+
pr_template_body: null,
|
|
26212
26214
|
step: "loading",
|
|
26213
26215
|
output: [],
|
|
26214
26216
|
pending_output: {},
|
|
@@ -27040,10 +27042,15 @@ function DirtyCheck(props) {
|
|
|
27040
27042
|
case "done":
|
|
27041
27043
|
return props.children;
|
|
27042
27044
|
case "prompt":
|
|
27043
|
-
return (reactExports.createElement(YesNoPrompt, { message: reactExports.createElement(
|
|
27044
|
-
|
|
27045
|
-
|
|
27046
|
-
|
|
27045
|
+
return (reactExports.createElement(YesNoPrompt, { message: reactExports.createElement(Box, { flexDirection: "column" },
|
|
27046
|
+
reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "{git} repo has uncommitted changes.", values: {
|
|
27047
|
+
git: reactExports.createElement(Command, null, "git"),
|
|
27048
|
+
git_stack: reactExports.createElement(Command, null, "git stack"),
|
|
27049
|
+
} }),
|
|
27050
|
+
reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "Changes may be lost during {git_stack}, are you sure you want to proceed?", values: {
|
|
27051
|
+
git: reactExports.createElement(Command, null, "git"),
|
|
27052
|
+
git_stack: reactExports.createElement(Command, null, "git stack"),
|
|
27053
|
+
} })), onYes: async () => {
|
|
27047
27054
|
patch({ status: "done" });
|
|
27048
27055
|
}, onNo: async () => {
|
|
27049
27056
|
actions.exit(0);
|
|
@@ -27171,9 +27178,9 @@ function format_time(date) {
|
|
|
27171
27178
|
}
|
|
27172
27179
|
|
|
27173
27180
|
function GithubApiError() {
|
|
27174
|
-
return reactExports.createElement(Await, { fallback: null, function: run$
|
|
27181
|
+
return reactExports.createElement(Await, { fallback: null, function: run$5 });
|
|
27175
27182
|
}
|
|
27176
|
-
async function run$
|
|
27183
|
+
async function run$5() {
|
|
27177
27184
|
const actions = Store.getState().actions;
|
|
27178
27185
|
const res = await cli(`gh api https://api.github.com/rate_limit`);
|
|
27179
27186
|
const res_json = JSON.parse(res.stdout);
|
|
@@ -27340,7 +27347,11 @@ async function pr_status(branch) {
|
|
|
27340
27347
|
}
|
|
27341
27348
|
async function pr_create(args) {
|
|
27342
27349
|
const title = safe_quote(args.title);
|
|
27343
|
-
|
|
27350
|
+
let command = `gh pr create --fill --head ${args.branch} --base ${args.base} --title="${title}" --body="${args.body}"`;
|
|
27351
|
+
if (args.draft) {
|
|
27352
|
+
command += " --draft";
|
|
27353
|
+
}
|
|
27354
|
+
const cli_result = await cli(command);
|
|
27344
27355
|
if (cli_result.code !== 0) {
|
|
27345
27356
|
handle_error(cli_result.output);
|
|
27346
27357
|
return null;
|
|
@@ -27630,9 +27641,9 @@ function encode(value) {
|
|
|
27630
27641
|
}
|
|
27631
27642
|
|
|
27632
27643
|
function LocalMergeRebase() {
|
|
27633
|
-
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: run$
|
|
27644
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: run$4 }));
|
|
27634
27645
|
}
|
|
27635
|
-
async function run$
|
|
27646
|
+
async function run$4() {
|
|
27636
27647
|
const state = Store.getState();
|
|
27637
27648
|
const actions = state.actions;
|
|
27638
27649
|
const branch_name = state.branch_name;
|
|
@@ -27922,9 +27933,9 @@ const RE = {
|
|
|
27922
27933
|
};
|
|
27923
27934
|
|
|
27924
27935
|
function ManualRebase() {
|
|
27925
|
-
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: run$
|
|
27936
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: run$3 }));
|
|
27926
27937
|
}
|
|
27927
|
-
async function run$
|
|
27938
|
+
async function run$3() {
|
|
27928
27939
|
const state = Store.getState();
|
|
27929
27940
|
const actions = state.actions;
|
|
27930
27941
|
const argv = state.argv;
|
|
@@ -27938,6 +27949,10 @@ async function run$2() {
|
|
|
27938
27949
|
invariant(repo_root, "repo_root must exist");
|
|
27939
27950
|
// always listen for SIGINT event and restore git state
|
|
27940
27951
|
process.once("SIGINT", handle_exit);
|
|
27952
|
+
let DEFAULT_PR_BODY = "";
|
|
27953
|
+
if (state.pr_template_body) {
|
|
27954
|
+
DEFAULT_PR_BODY = state.pr_template_body;
|
|
27955
|
+
}
|
|
27941
27956
|
const temp_branch_name = `${branch_name}_${short_id()}`;
|
|
27942
27957
|
const commit_range = await range(commit_map);
|
|
27943
27958
|
// reverse commit list so that we can cherry-pick in order
|
|
@@ -28163,7 +28178,8 @@ echo "$GIT_REVISE_TODO" > "$git_revise_todo_path"
|
|
|
28163
28178
|
branch: group.id,
|
|
28164
28179
|
base: group.base,
|
|
28165
28180
|
title: group.title,
|
|
28166
|
-
body:
|
|
28181
|
+
body: DEFAULT_PR_BODY,
|
|
28182
|
+
draft: argv.draft,
|
|
28167
28183
|
});
|
|
28168
28184
|
if (!pr_url) {
|
|
28169
28185
|
throw new Error("unable to create pr");
|
|
@@ -28190,7 +28206,7 @@ echo "$GIT_REVISE_TODO" > "$git_revise_todo_path"
|
|
|
28190
28206
|
// use the updated pr_url_list to get the actual selected_url
|
|
28191
28207
|
const selected_url = pr_url_list[i];
|
|
28192
28208
|
invariant(group.base, "group.base must exist");
|
|
28193
|
-
const body = group.pr?.body ||
|
|
28209
|
+
const body = group.pr?.body || DEFAULT_PR_BODY;
|
|
28194
28210
|
const update_body = write({
|
|
28195
28211
|
body,
|
|
28196
28212
|
pr_url_list,
|
|
@@ -28430,9 +28446,9 @@ function get_status_bold(row) {
|
|
|
28430
28446
|
}
|
|
28431
28447
|
|
|
28432
28448
|
function PostRebaseStatus() {
|
|
28433
|
-
return reactExports.createElement(Await, { fallback: null, function: run$
|
|
28449
|
+
return reactExports.createElement(Await, { fallback: null, function: run$2 });
|
|
28434
28450
|
}
|
|
28435
|
-
async function run$
|
|
28451
|
+
async function run$2() {
|
|
28436
28452
|
const actions = Store.getState().actions;
|
|
28437
28453
|
// reset github pr cache before refreshing via commit range below
|
|
28438
28454
|
actions.reset_pr();
|
|
@@ -28461,6 +28477,65 @@ function PreLocalMergeRebase() {
|
|
|
28461
28477
|
}, onNo: () => actions.exit(0) }));
|
|
28462
28478
|
}
|
|
28463
28479
|
|
|
28480
|
+
function PreManualRebase() {
|
|
28481
|
+
return reactExports.createElement(Await, { fallback: null, function: run$1 });
|
|
28482
|
+
}
|
|
28483
|
+
async function run$1() {
|
|
28484
|
+
const state = Store.getState();
|
|
28485
|
+
const actions = state.actions;
|
|
28486
|
+
const repo_root = state.repo_root;
|
|
28487
|
+
const argv = state.argv;
|
|
28488
|
+
invariant(repo_root, "repo_root must exist");
|
|
28489
|
+
invariant(argv, "argv must exist");
|
|
28490
|
+
if (!argv.template) {
|
|
28491
|
+
return actions.set((state) => {
|
|
28492
|
+
state.step = "manual-rebase";
|
|
28493
|
+
});
|
|
28494
|
+
}
|
|
28495
|
+
let pr_template_body = null;
|
|
28496
|
+
// look for pull request template
|
|
28497
|
+
// https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository
|
|
28498
|
+
// ./.github/pull_request_template.md
|
|
28499
|
+
// ./pull_request_template.md
|
|
28500
|
+
// ./docs/pull_request_template.md
|
|
28501
|
+
for (const key of PR_TEMPLATE_KEY_LIST) {
|
|
28502
|
+
const pr_template_fn = PR_TEMPLATE[key];
|
|
28503
|
+
if (fs.existsSync(pr_template_fn(repo_root))) {
|
|
28504
|
+
pr_template_body = fs.readFileSync(pr_template_fn(repo_root), "utf-8");
|
|
28505
|
+
actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "Using PR template {pr_filepath}", values: {
|
|
28506
|
+
pr_filepath: reactExports.createElement(Brackets, null, pr_template_fn("")),
|
|
28507
|
+
} }));
|
|
28508
|
+
break;
|
|
28509
|
+
}
|
|
28510
|
+
}
|
|
28511
|
+
// ./.github/PULL_REQUEST_TEMPLATE/*.md
|
|
28512
|
+
let pr_templates = [];
|
|
28513
|
+
if (fs.existsSync(PR_TEMPLATE.TemplateDir(repo_root))) {
|
|
28514
|
+
pr_templates = fs.readdirSync(PR_TEMPLATE.TemplateDir(repo_root));
|
|
28515
|
+
}
|
|
28516
|
+
// check if repo has multiple pr templates
|
|
28517
|
+
actions.set((state) => {
|
|
28518
|
+
state.pr_template_body = pr_template_body;
|
|
28519
|
+
state.pr_templates = pr_templates;
|
|
28520
|
+
if (pr_templates.length > 0) {
|
|
28521
|
+
actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "{count} queryable templates found under {dir}, but not supported.", values: {
|
|
28522
|
+
count: (reactExports.createElement(Text, { color: colors.blue }, pr_templates.length)),
|
|
28523
|
+
dir: reactExports.createElement(Brackets, null, PR_TEMPLATE.TemplateDir("")),
|
|
28524
|
+
} }));
|
|
28525
|
+
}
|
|
28526
|
+
state.step = "manual-rebase";
|
|
28527
|
+
});
|
|
28528
|
+
}
|
|
28529
|
+
// prettier-ignore
|
|
28530
|
+
const PR_TEMPLATE = Object.freeze({
|
|
28531
|
+
Github: (root) => path.join(root, ".github", "pull_request_template.md"),
|
|
28532
|
+
Root: (root) => path.join(root, "pull_request_template.md"),
|
|
28533
|
+
Docs: (root) => path.join(root, "docs", "pull_request_template.md"),
|
|
28534
|
+
TemplateDir: (root) => path.join(root, ".github", "PULL_REQUEST_TEMPLATE"),
|
|
28535
|
+
});
|
|
28536
|
+
// prettier-ignore
|
|
28537
|
+
const PR_TEMPLATE_KEY_LIST = Object.keys(PR_TEMPLATE);
|
|
28538
|
+
|
|
28464
28539
|
function PreSelectCommitRanges() {
|
|
28465
28540
|
const actions = Store.useActions();
|
|
28466
28541
|
const argv = Store.useState((state) => state.argv);
|
|
@@ -28776,7 +28851,7 @@ function SelectCommitRangesInternal(props) {
|
|
|
28776
28851
|
}
|
|
28777
28852
|
switch (inputLower) {
|
|
28778
28853
|
case "s":
|
|
28779
|
-
state.step = "manual-rebase";
|
|
28854
|
+
state.step = "pre-manual-rebase";
|
|
28780
28855
|
break;
|
|
28781
28856
|
}
|
|
28782
28857
|
});
|
|
@@ -28975,6 +29050,8 @@ function Main() {
|
|
|
28975
29050
|
return reactExports.createElement(PreSelectCommitRanges, null);
|
|
28976
29051
|
case "select-commit-ranges":
|
|
28977
29052
|
return reactExports.createElement(SelectCommitRanges, null);
|
|
29053
|
+
case "pre-manual-rebase":
|
|
29054
|
+
return reactExports.createElement(PreManualRebase, null);
|
|
28978
29055
|
case "manual-rebase":
|
|
28979
29056
|
return reactExports.createElement(ManualRebase, null);
|
|
28980
29057
|
case "post-rebase-status":
|
|
@@ -34443,12 +34520,23 @@ async function command() {
|
|
|
34443
34520
|
type: "string",
|
|
34444
34521
|
alias: ["b"],
|
|
34445
34522
|
description: 'Set the master branch name, defaults to "master" (or "main" if "master" is not found)',
|
|
34523
|
+
})
|
|
34524
|
+
.option("draft", {
|
|
34525
|
+
type: "boolean",
|
|
34526
|
+
alias: ["d"],
|
|
34527
|
+
default: false,
|
|
34528
|
+
description: "Open all PRs as drafts",
|
|
34446
34529
|
})
|
|
34447
34530
|
.option("write-state-json", {
|
|
34448
34531
|
hidden: true,
|
|
34449
34532
|
type: "boolean",
|
|
34450
34533
|
default: false,
|
|
34451
34534
|
description: "Write state to local json file for debugging",
|
|
34535
|
+
})
|
|
34536
|
+
.option("template", {
|
|
34537
|
+
type: "boolean",
|
|
34538
|
+
default: true,
|
|
34539
|
+
description: "Use automatic Github PR template, e.g. .github/pull_request_template.md, disable with --no-template",
|
|
34452
34540
|
})
|
|
34453
34541
|
.option("mock-metadata", {
|
|
34454
34542
|
hidden: true,
|
|
@@ -34462,7 +34550,7 @@ async function command() {
|
|
|
34462
34550
|
.wrap(123)
|
|
34463
34551
|
// disallow unknown options
|
|
34464
34552
|
.strict()
|
|
34465
|
-
.version("1.
|
|
34553
|
+
.version("1.8.0" )
|
|
34466
34554
|
.showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`")
|
|
34467
34555
|
.help("help", "Show usage via `git stack help`").argv);
|
|
34468
34556
|
}
|
package/package.json
CHANGED
package/src/app/DirtyCheck.tsx
CHANGED
|
@@ -37,14 +37,24 @@ export function DirtyCheck(props: Props) {
|
|
|
37
37
|
return (
|
|
38
38
|
<YesNoPrompt
|
|
39
39
|
message={
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
<Ink.Box flexDirection="column">
|
|
41
|
+
<FormatText
|
|
42
|
+
wrapper={<Ink.Text color={colors.yellow} />}
|
|
43
|
+
message="{git} repo has uncommitted changes."
|
|
44
|
+
values={{
|
|
45
|
+
git: <Command>git</Command>,
|
|
46
|
+
git_stack: <Command>git stack</Command>,
|
|
47
|
+
}}
|
|
48
|
+
/>
|
|
49
|
+
<FormatText
|
|
50
|
+
wrapper={<Ink.Text color={colors.yellow} />}
|
|
51
|
+
message="Changes may be lost during {git_stack}, are you sure you want to proceed?"
|
|
52
|
+
values={{
|
|
53
|
+
git: <Command>git</Command>,
|
|
54
|
+
git_stack: <Command>git stack</Command>,
|
|
55
|
+
}}
|
|
56
|
+
/>
|
|
57
|
+
</Ink.Box>
|
|
48
58
|
}
|
|
49
59
|
onYes={async () => {
|
|
50
60
|
patch({ status: "done" });
|
package/src/app/Main.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import { LocalMergeRebase } from "~/app/LocalMergeRebase";
|
|
|
5
5
|
import { ManualRebase } from "~/app/ManualRebase";
|
|
6
6
|
import { PostRebaseStatus } from "~/app/PostRebaseStatus";
|
|
7
7
|
import { PreLocalMergeRebase } from "~/app/PreLocalMergeRebase";
|
|
8
|
+
import { PreManualRebase } from "~/app/PreManualRebase";
|
|
8
9
|
import { PreSelectCommitRanges } from "~/app/PreSelectCommitRanges";
|
|
9
10
|
import { SelectCommitRanges } from "~/app/SelectCommitRanges";
|
|
10
11
|
import { Status } from "~/app/Status";
|
|
@@ -36,6 +37,9 @@ export function Main() {
|
|
|
36
37
|
case "select-commit-ranges":
|
|
37
38
|
return <SelectCommitRanges />;
|
|
38
39
|
|
|
40
|
+
case "pre-manual-rebase":
|
|
41
|
+
return <PreManualRebase />;
|
|
42
|
+
|
|
39
43
|
case "manual-rebase":
|
|
40
44
|
return <ManualRebase />;
|
|
41
45
|
|
package/src/app/ManualRebase.tsx
CHANGED
|
@@ -46,6 +46,11 @@ async function run() {
|
|
|
46
46
|
// always listen for SIGINT event and restore git state
|
|
47
47
|
process.once("SIGINT", handle_exit);
|
|
48
48
|
|
|
49
|
+
let DEFAULT_PR_BODY = "";
|
|
50
|
+
if (state.pr_template_body) {
|
|
51
|
+
DEFAULT_PR_BODY = state.pr_template_body;
|
|
52
|
+
}
|
|
53
|
+
|
|
49
54
|
const temp_branch_name = `${branch_name}_${short_id()}`;
|
|
50
55
|
|
|
51
56
|
const commit_range = await CommitMetadata.range(commit_map);
|
|
@@ -328,7 +333,8 @@ async function run() {
|
|
|
328
333
|
branch: group.id,
|
|
329
334
|
base: group.base,
|
|
330
335
|
title: group.title,
|
|
331
|
-
body:
|
|
336
|
+
body: DEFAULT_PR_BODY,
|
|
337
|
+
draft: argv.draft,
|
|
332
338
|
});
|
|
333
339
|
|
|
334
340
|
if (!pr_url) {
|
|
@@ -363,7 +369,7 @@ async function run() {
|
|
|
363
369
|
|
|
364
370
|
invariant(group.base, "group.base must exist");
|
|
365
371
|
|
|
366
|
-
const body = group.pr?.body ||
|
|
372
|
+
const body = group.pr?.body || DEFAULT_PR_BODY;
|
|
367
373
|
|
|
368
374
|
const update_body = StackSummaryTable.write({
|
|
369
375
|
body,
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
import * as Ink from "ink-cjs";
|
|
7
|
+
|
|
8
|
+
import { Await } from "~/app/Await";
|
|
9
|
+
import { Brackets } from "~/app/Brackets";
|
|
10
|
+
import { FormatText } from "~/app/FormatText";
|
|
11
|
+
import { Store } from "~/app/Store";
|
|
12
|
+
import { colors } from "~/core/colors";
|
|
13
|
+
import { invariant } from "~/core/invariant";
|
|
14
|
+
|
|
15
|
+
export function PreManualRebase() {
|
|
16
|
+
return <Await fallback={null} function={run} />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function run() {
|
|
20
|
+
const state = Store.getState();
|
|
21
|
+
const actions = state.actions;
|
|
22
|
+
const repo_root = state.repo_root;
|
|
23
|
+
const argv = state.argv;
|
|
24
|
+
|
|
25
|
+
invariant(repo_root, "repo_root must exist");
|
|
26
|
+
invariant(argv, "argv must exist");
|
|
27
|
+
|
|
28
|
+
if (!argv.template) {
|
|
29
|
+
return actions.set((state) => {
|
|
30
|
+
state.step = "manual-rebase";
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let pr_template_body: null | string = null;
|
|
35
|
+
|
|
36
|
+
// look for pull request template
|
|
37
|
+
// https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository
|
|
38
|
+
// ./.github/pull_request_template.md
|
|
39
|
+
// ./pull_request_template.md
|
|
40
|
+
// ./docs/pull_request_template.md
|
|
41
|
+
for (const key of PR_TEMPLATE_KEY_LIST) {
|
|
42
|
+
const pr_template_fn = PR_TEMPLATE[key as keyof typeof PR_TEMPLATE];
|
|
43
|
+
|
|
44
|
+
if (fs.existsSync(pr_template_fn(repo_root))) {
|
|
45
|
+
pr_template_body = fs.readFileSync(pr_template_fn(repo_root), "utf-8");
|
|
46
|
+
|
|
47
|
+
actions.output(
|
|
48
|
+
<FormatText
|
|
49
|
+
wrapper={<Ink.Text color={colors.yellow} />}
|
|
50
|
+
message="Using PR template {pr_filepath}"
|
|
51
|
+
values={{
|
|
52
|
+
pr_filepath: <Brackets>{pr_template_fn("")}</Brackets>,
|
|
53
|
+
}}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ./.github/PULL_REQUEST_TEMPLATE/*.md
|
|
62
|
+
let pr_templates: Array<string> = [];
|
|
63
|
+
if (fs.existsSync(PR_TEMPLATE.TemplateDir(repo_root))) {
|
|
64
|
+
pr_templates = fs.readdirSync(PR_TEMPLATE.TemplateDir(repo_root));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// check if repo has multiple pr templates
|
|
68
|
+
actions.set((state) => {
|
|
69
|
+
state.pr_template_body = pr_template_body;
|
|
70
|
+
state.pr_templates = pr_templates;
|
|
71
|
+
|
|
72
|
+
if (pr_templates.length > 0) {
|
|
73
|
+
actions.output(
|
|
74
|
+
<FormatText
|
|
75
|
+
wrapper={<Ink.Text color={colors.yellow} />}
|
|
76
|
+
message="{count} queryable templates found under {dir}, but not supported."
|
|
77
|
+
values={{
|
|
78
|
+
count: (
|
|
79
|
+
<Ink.Text color={colors.blue}>{pr_templates.length}</Ink.Text>
|
|
80
|
+
),
|
|
81
|
+
dir: <Brackets>{PR_TEMPLATE.TemplateDir("")}</Brackets>,
|
|
82
|
+
}}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
state.step = "manual-rebase";
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// prettier-ignore
|
|
92
|
+
const PR_TEMPLATE = Object.freeze({
|
|
93
|
+
Github: (root: string) => path.join(root, ".github", "pull_request_template.md"),
|
|
94
|
+
Root: (root: string) => path.join(root, "pull_request_template.md"),
|
|
95
|
+
Docs: (root: string) => path.join(root, "docs", "pull_request_template.md"),
|
|
96
|
+
TemplateDir: (root: string) => path.join(root, ".github", "PULL_REQUEST_TEMPLATE"),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// prettier-ignore
|
|
100
|
+
const PR_TEMPLATE_KEY_LIST = Object.keys(PR_TEMPLATE) as Array<keyof typeof PR_TEMPLATE>;
|
package/src/app/Store.tsx
CHANGED
|
@@ -38,6 +38,8 @@ export type State = {
|
|
|
38
38
|
branch_name: null | string;
|
|
39
39
|
commit_range: null | CommitMetadata.CommitRange;
|
|
40
40
|
commit_map: null | CommitMap;
|
|
41
|
+
pr_templates: Array<string>;
|
|
42
|
+
pr_template_body: null | string;
|
|
41
43
|
|
|
42
44
|
step:
|
|
43
45
|
| "github-api-error"
|
|
@@ -47,6 +49,7 @@ export type State = {
|
|
|
47
49
|
| "local-merge-rebase"
|
|
48
50
|
| "pre-select-commit-ranges"
|
|
49
51
|
| "select-commit-ranges"
|
|
52
|
+
| "pre-manual-rebase"
|
|
50
53
|
| "manual-rebase"
|
|
51
54
|
| "post-rebase-status";
|
|
52
55
|
|
|
@@ -98,6 +101,8 @@ const BaseStore = createStore<State>()(
|
|
|
98
101
|
branch_name: null,
|
|
99
102
|
commit_range: null,
|
|
100
103
|
commit_map: null,
|
|
104
|
+
pr_templates: [],
|
|
105
|
+
pr_template_body: null,
|
|
101
106
|
|
|
102
107
|
step: "loading",
|
|
103
108
|
|
package/src/app/YesNoPrompt.tsx
CHANGED
package/src/command.ts
CHANGED
|
@@ -71,6 +71,13 @@ export async function command() {
|
|
|
71
71
|
'Set the master branch name, defaults to "master" (or "main" if "master" is not found)',
|
|
72
72
|
})
|
|
73
73
|
|
|
74
|
+
.option("draft", {
|
|
75
|
+
type: "boolean",
|
|
76
|
+
alias: ["d"],
|
|
77
|
+
default: false,
|
|
78
|
+
description: "Open all PRs as drafts",
|
|
79
|
+
})
|
|
80
|
+
|
|
74
81
|
.option("write-state-json", {
|
|
75
82
|
hidden: true,
|
|
76
83
|
type: "boolean",
|
|
@@ -78,6 +85,13 @@ export async function command() {
|
|
|
78
85
|
description: "Write state to local json file for debugging",
|
|
79
86
|
})
|
|
80
87
|
|
|
88
|
+
.option("template", {
|
|
89
|
+
type: "boolean",
|
|
90
|
+
default: true,
|
|
91
|
+
description:
|
|
92
|
+
"Use automatic Github PR template, e.g. .github/pull_request_template.md, disable with --no-template",
|
|
93
|
+
})
|
|
94
|
+
|
|
81
95
|
.option("mock-metadata", {
|
|
82
96
|
hidden: true,
|
|
83
97
|
type: "boolean",
|
package/src/core/github.tsx
CHANGED
|
@@ -131,14 +131,18 @@ type CreatePullRequestArgs = {
|
|
|
131
131
|
base: string;
|
|
132
132
|
title: string;
|
|
133
133
|
body: string;
|
|
134
|
+
draft: boolean;
|
|
134
135
|
};
|
|
135
136
|
|
|
136
137
|
export async function pr_create(args: CreatePullRequestArgs) {
|
|
137
138
|
const title = safe_quote(args.title);
|
|
139
|
+
let command = `gh pr create --fill --head ${args.branch} --base ${args.base} --title="${title}" --body="${args.body}"`;
|
|
138
140
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
141
|
+
if (args.draft) {
|
|
142
|
+
command += " --draft";
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const cli_result = await cli(command);
|
|
142
146
|
|
|
143
147
|
if (cli_result.code !== 0) {
|
|
144
148
|
handle_error(cli_result.output);
|