git-stack-cli 1.15.1 → 2.0.1-beta
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 +15 -12
- package/dist/js/index.js +45723 -0
- package/package.json +17 -24
- package/scripts/bun-build.ts +111 -0
- package/scripts/bun-compile.ts +79 -0
- package/scripts/npm-prepublishOnly.ts +1 -1
- package/scripts/release-brew.ts +27 -49
- package/scripts/release-github.ts +21 -9
- package/scripts/release-npm.ts +8 -11
- package/src/app/Store.tsx +16 -5
- package/src/commands/Fixup.tsx +2 -0
- package/src/commands/Log.tsx +2 -0
- package/src/components/ExitingGate.tsx +19 -9
- package/src/core/GitReviseTodo.ts +6 -4
- package/src/index.tsx +4 -0
- package/src/types/global.d.ts +0 -1
- package/tsconfig.json +1 -1
- package/dist/cjs/index.cjs +0 -38528
- package/rollup.config.js +0 -54
- package/scripts/build-standalone.ts +0 -73
- package/scripts/link.ts +0 -14
package/package.json
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-stack-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1-beta",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "magus",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0",
|
|
7
8
|
"repository": {
|
|
8
9
|
"type": "git",
|
|
9
10
|
"url": "git+https://github.com/magus/git-stack-cli.git"
|
|
10
11
|
},
|
|
11
12
|
"type": "module",
|
|
12
13
|
"bin": {
|
|
13
|
-
"git-stack": "dist/
|
|
14
|
+
"git-stack": "dist/js/index.js"
|
|
14
15
|
},
|
|
15
16
|
"files": [
|
|
16
|
-
"dist/
|
|
17
|
+
"dist/js",
|
|
18
|
+
"package.json",
|
|
19
|
+
"pnpm-lock.yaml",
|
|
17
20
|
"scripts",
|
|
18
21
|
"src",
|
|
19
|
-
"package-lock.json",
|
|
20
|
-
"rollup.config.js",
|
|
21
22
|
"tsconfig.json"
|
|
22
23
|
],
|
|
23
24
|
"scripts": {
|
|
24
|
-
"dev": "
|
|
25
|
-
"build": "
|
|
26
|
-
"
|
|
27
|
-
"link": "bun run scripts/link.ts",
|
|
25
|
+
"dev": "pnpm run build --watch",
|
|
26
|
+
"build": "bun run scripts/bun-build.ts",
|
|
27
|
+
"compile": "bun run scripts/bun-compile.ts",
|
|
28
28
|
"release:npm": "bun run scripts/release-npm.ts",
|
|
29
29
|
"release:github": "bun run scripts/release-github.ts",
|
|
30
30
|
"release:brew": "bun run scripts/release-brew.ts",
|
|
31
|
-
"release": "
|
|
31
|
+
"release": "pnpm run release:npm && pnpm run release:github && pnpm run release:brew",
|
|
32
32
|
"lint:check": "eslint . --cache",
|
|
33
|
-
"lint": "
|
|
34
|
-
"prettier:check": "prettier
|
|
35
|
-
"prettier": "
|
|
33
|
+
"lint": "pnpm run lint:check --fix",
|
|
34
|
+
"prettier:check": "prettier src scripts config .eslintrc.cjs --check --cache",
|
|
35
|
+
"prettier": "pnpm run prettier:check --write",
|
|
36
36
|
"test": "bun test",
|
|
37
|
-
"test:watch": "
|
|
37
|
+
"test:watch": "pnpm run test --watch",
|
|
38
38
|
"test:types": "tsc",
|
|
39
|
-
"test:all": "
|
|
39
|
+
"test:all": "pnpm run prettier:check && pnpm run lint:check && pnpm run test:types",
|
|
40
40
|
"prepublishOnly": "bun run scripts/npm-prepublishOnly.ts"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
@@ -52,12 +52,6 @@
|
|
|
52
52
|
"zustand": "^4.4.4"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@rollup/plugin-alias": "^5.1.0",
|
|
56
|
-
"@rollup/plugin-commonjs": "^25.0.7",
|
|
57
|
-
"@rollup/plugin-json": "^6.1.0",
|
|
58
|
-
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
59
|
-
"@rollup/plugin-replace": "^5.0.5",
|
|
60
|
-
"@rollup/plugin-typescript": "^11.1.6",
|
|
61
55
|
"@types/chalk": "^2.2.0",
|
|
62
56
|
"@types/lodash": "^4.17.7",
|
|
63
57
|
"@types/luxon": "^3.4.2",
|
|
@@ -66,14 +60,13 @@
|
|
|
66
60
|
"@types/yargs": "^17.0.29",
|
|
67
61
|
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
|
68
62
|
"@typescript-eslint/parser": "^6.9.0",
|
|
69
|
-
"bun
|
|
63
|
+
"bun": "1.1.44",
|
|
64
|
+
"bun-types": "1.1.44",
|
|
70
65
|
"eslint": "^8.52.0",
|
|
71
66
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
72
67
|
"eslint-plugin-import": "^2.29.0",
|
|
73
68
|
"eslint-plugin-react": "^7.33.2",
|
|
74
|
-
"pkg": "^5.8.1",
|
|
75
69
|
"prettier": "^3.0.3",
|
|
76
|
-
"rollup": "^4.10.0",
|
|
77
70
|
"typescript": "^5.2.2"
|
|
78
71
|
}
|
|
79
72
|
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import * as util from "util";
|
|
4
|
+
|
|
5
|
+
import * as file from "~/core/file";
|
|
6
|
+
import { spawn } from "~/core/spawn";
|
|
7
|
+
|
|
8
|
+
const parsed_args = util.parseArgs({
|
|
9
|
+
args: Bun.argv,
|
|
10
|
+
options: {
|
|
11
|
+
watch: {
|
|
12
|
+
type: "boolean",
|
|
13
|
+
default: false,
|
|
14
|
+
},
|
|
15
|
+
verbose: {
|
|
16
|
+
type: "boolean",
|
|
17
|
+
default: false,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
strict: true,
|
|
21
|
+
allowPositionals: true,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const WATCH = parsed_args.values.watch;
|
|
25
|
+
const VERBOSE = parsed_args.values.verbose;
|
|
26
|
+
|
|
27
|
+
console.debug("📦 bundle", WATCH ? "watch" : "build");
|
|
28
|
+
|
|
29
|
+
if (VERBOSE) {
|
|
30
|
+
console.debug(parsed_args);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const REPO_ROOT = (await spawn.sync("git rev-parse --show-toplevel")).stdout;
|
|
34
|
+
|
|
35
|
+
const PACKAGE_JSON = await file.read_json(path.join(REPO_ROOT, "package.json"));
|
|
36
|
+
const GIT_SEQUENCE_EDITOR_SCRIPT_PATH = path.join(REPO_ROOT, "scripts", "git-sequence-editor.sh");
|
|
37
|
+
const UNSAFE_GIT_SEQUENCE_EDITOR_SCRIPT = await file.read_text(GIT_SEQUENCE_EDITOR_SCRIPT_PATH);
|
|
38
|
+
const GIT_SEQUENCE_EDITOR_SCRIPT = UNSAFE_GIT_SEQUENCE_EDITOR_SCRIPT.replace(/`/g, "\\`");
|
|
39
|
+
|
|
40
|
+
let GITIGNORE = (await file.read_text(path.join(REPO_ROOT, ".gitignore"))).split("\n");
|
|
41
|
+
GITIGNORE = GITIGNORE.filter((line) => line.trim() && !line.startsWith("#"));
|
|
42
|
+
GITIGNORE.push(".git");
|
|
43
|
+
|
|
44
|
+
const define = {
|
|
45
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
46
|
+
"process.env.CLI_VERSION": JSON.stringify(String(PACKAGE_JSON.version)),
|
|
47
|
+
"process.env.GIT_SEQUENCE_EDITOR_SCRIPT": JSON.stringify(GIT_SEQUENCE_EDITOR_SCRIPT),
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
if (VERBOSE) {
|
|
51
|
+
console.debug({ define });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function run_build() {
|
|
55
|
+
const start = Date.now();
|
|
56
|
+
|
|
57
|
+
const result = await Bun.build({
|
|
58
|
+
entrypoints: ["./src/index.tsx"],
|
|
59
|
+
outdir: "./dist/js",
|
|
60
|
+
target: "node",
|
|
61
|
+
env: "inline",
|
|
62
|
+
format: "esm",
|
|
63
|
+
define,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const duration_ms = Date.now() - start;
|
|
67
|
+
|
|
68
|
+
console.debug(`✅ Build (${duration_ms}ms)`);
|
|
69
|
+
|
|
70
|
+
if (VERBOSE) {
|
|
71
|
+
console.debug({ result });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!WATCH) {
|
|
76
|
+
await run_build();
|
|
77
|
+
} else {
|
|
78
|
+
await run_build();
|
|
79
|
+
|
|
80
|
+
console.debug("👀 Watching for changes…");
|
|
81
|
+
|
|
82
|
+
const { signal } = new AbortController();
|
|
83
|
+
|
|
84
|
+
const watcher = fs.watch(REPO_ROOT, { recursive: true, signal });
|
|
85
|
+
for await (const event of watcher) {
|
|
86
|
+
const filename = event.filename;
|
|
87
|
+
|
|
88
|
+
if (!filename) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ignore this file
|
|
93
|
+
if (import.meta.filename == path.join(REPO_ROOT, filename)) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ignore files in gitignore
|
|
98
|
+
const ignored = GITIGNORE.some((pattern) => filename.startsWith(pattern));
|
|
99
|
+
if (ignored) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.debug(`⚠️ Change ${filename}`);
|
|
104
|
+
|
|
105
|
+
if (VERBOSE) {
|
|
106
|
+
console.debug({ ignored, filename, event });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
await run_build();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import * as util from "util";
|
|
3
|
+
|
|
4
|
+
import * as file from "~/core/file";
|
|
5
|
+
import { spawn } from "~/core/spawn";
|
|
6
|
+
|
|
7
|
+
const parsed_args = util.parseArgs({
|
|
8
|
+
args: Bun.argv,
|
|
9
|
+
options: {
|
|
10
|
+
target: {
|
|
11
|
+
type: "string",
|
|
12
|
+
},
|
|
13
|
+
verbose: {
|
|
14
|
+
type: "boolean",
|
|
15
|
+
default: false,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
strict: true,
|
|
19
|
+
allowPositionals: true,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const TARGET = parsed_args.values.target;
|
|
23
|
+
const VERBOSE = parsed_args.values.verbose;
|
|
24
|
+
|
|
25
|
+
console.debug("📦 compile");
|
|
26
|
+
|
|
27
|
+
if (VERBOSE) {
|
|
28
|
+
console.debug(parsed_args);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const REPO_ROOT = (await spawn.sync("git rev-parse --show-toplevel")).stdout;
|
|
32
|
+
const DIST_DIR = path.join(REPO_ROOT, "dist");
|
|
33
|
+
const INPUT_JS = path.join(DIST_DIR, "js", "index.js");
|
|
34
|
+
|
|
35
|
+
if (!(await file.exists(INPUT_JS))) {
|
|
36
|
+
console.error(`❌ Missing ${path.relative(REPO_ROOT, INPUT_JS)}`);
|
|
37
|
+
console.debug("Run `pnpm run build` first to generate the input file.");
|
|
38
|
+
process.exit(12);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (TARGET) {
|
|
42
|
+
const target = TARGET;
|
|
43
|
+
await compile_target({ target });
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const TARGET_LIST = ["bun-linux-x64", "bun-windows-x64", "bun-darwin-arm64", "bun-darwin-x64"];
|
|
48
|
+
|
|
49
|
+
for (const target of TARGET_LIST) {
|
|
50
|
+
await compile_target({ target });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type CompileTargetArgs = {
|
|
54
|
+
target: string;
|
|
55
|
+
};
|
|
56
|
+
async function compile_target(args: CompileTargetArgs) {
|
|
57
|
+
const outfile = path.join(DIST_DIR, "bin", `git-stack-${args.target}`);
|
|
58
|
+
|
|
59
|
+
const start = Date.now();
|
|
60
|
+
|
|
61
|
+
// bun build --compile --target=bun-darwin-x64 ./path/to/my/app.ts --outfile myapp
|
|
62
|
+
const bun_compile = await spawn.sync([
|
|
63
|
+
"bun",
|
|
64
|
+
"build",
|
|
65
|
+
"--compile",
|
|
66
|
+
`--target=${args.target}`,
|
|
67
|
+
INPUT_JS,
|
|
68
|
+
`--outfile=${outfile}`,
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
if (bun_compile.proc.exitCode) {
|
|
72
|
+
console.error(bun_compile.stderr);
|
|
73
|
+
process.exit(bun_compile.proc.exitCode);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const duration_ms = Date.now() - start;
|
|
77
|
+
|
|
78
|
+
console.debug(`✅ ${path.relative(REPO_ROOT, outfile)} (${duration_ms}ms)`);
|
|
79
|
+
}
|
package/scripts/release-brew.ts
CHANGED
|
@@ -5,26 +5,19 @@ import * as file from "~/core/file";
|
|
|
5
5
|
import { spawn } from "~/core/spawn";
|
|
6
6
|
|
|
7
7
|
// get paths relative to this script
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const package_json = await file.read_json(
|
|
15
|
-
path.join(PROJECT_DIR, "package.json")
|
|
16
|
-
);
|
|
8
|
+
const REPO_ROOT = (await spawn.sync("git rev-parse --show-toplevel")).stdout;
|
|
9
|
+
const DIST_DIR = path.join(REPO_ROOT, "dist");
|
|
10
|
+
const BIN_DIR = path.join(DIST_DIR, "bin");
|
|
11
|
+
const HOMEBREW_DIR = path.join(REPO_ROOT, "homebrew");
|
|
12
|
+
|
|
13
|
+
const package_json = await file.read_json(path.join(REPO_ROOT, "package.json"));
|
|
17
14
|
|
|
18
15
|
const version = package_json.version;
|
|
19
16
|
|
|
20
17
|
process.chdir(HOMEBREW_DIR);
|
|
21
18
|
|
|
22
19
|
// before creating new formula, mv the previous into a versioned formula name
|
|
23
|
-
const previous_formula_path = path.join(
|
|
24
|
-
HOMEBREW_DIR,
|
|
25
|
-
"Formula",
|
|
26
|
-
"git-stack.rb"
|
|
27
|
-
);
|
|
20
|
+
const previous_formula_path = path.join(HOMEBREW_DIR, "Formula", "git-stack.rb");
|
|
28
21
|
|
|
29
22
|
// match either version format from core or tap formula
|
|
30
23
|
//
|
|
@@ -42,36 +35,29 @@ if (!previous_version_match?.groups) {
|
|
|
42
35
|
|
|
43
36
|
const previous_version = previous_version_match.groups.version;
|
|
44
37
|
// convert `1.0.4` to `104`
|
|
45
|
-
const not_dot_version = previous_version.replace(
|
|
38
|
+
const not_dot_version = previous_version.replace(/[^a-z0-9]/gi, "");
|
|
46
39
|
const previous_class = `GitStackAT${not_dot_version}`;
|
|
47
|
-
previous_formula = previous_formula.replace(
|
|
48
|
-
"class GitStack",
|
|
49
|
-
`class ${previous_class}`
|
|
50
|
-
);
|
|
40
|
+
previous_formula = previous_formula.replace("class GitStack", `class ${previous_class}`);
|
|
51
41
|
|
|
52
42
|
await file.write_text(
|
|
53
43
|
path.join(HOMEBREW_DIR, "Formula", `git-stack@${previous_version}.rb`),
|
|
54
|
-
previous_formula
|
|
44
|
+
previous_formula,
|
|
55
45
|
);
|
|
56
46
|
|
|
57
|
-
process.chdir(
|
|
47
|
+
process.chdir(REPO_ROOT);
|
|
58
48
|
|
|
59
|
-
// download github asset and calculate sha256
|
|
60
|
-
// prettier-ignore
|
|
61
|
-
await spawn.sync(["gh", "release", "download", version, "-p", `git-stack-cli-${version}.tgz`]);
|
|
62
|
-
// prettier-ignore
|
|
63
49
|
const tarball_asset = await create_asset(`git-stack-cli-${version}.tgz`, { version });
|
|
64
|
-
await file.rm(tarball_asset.filepath);
|
|
65
50
|
|
|
66
|
-
await spawn(`
|
|
51
|
+
await spawn(`pnpm run compile`);
|
|
67
52
|
|
|
68
|
-
process.chdir(
|
|
53
|
+
process.chdir(BIN_DIR);
|
|
69
54
|
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
const
|
|
55
|
+
const linux_x64_asset = await create_asset("git-stack-bun-linux-x64.zip", { version });
|
|
56
|
+
const macos_x64_asset = await create_asset("git-stack-bun-darwin-x64.zip", { version });
|
|
57
|
+
const macos_arm64_asset = await create_asset("git-stack-bun-darwin-arm64.zip", { version });
|
|
58
|
+
const win_x64_asset = await create_asset("git-stack-bun-windows-x64.exe.zip", { version });
|
|
73
59
|
|
|
74
|
-
console.debug({
|
|
60
|
+
console.debug({ linux_x64_asset, macos_x64_asset, macos_arm64_asset, win_x64_asset });
|
|
75
61
|
|
|
76
62
|
const re_token = (name: string) => new RegExp(`{{ ${name} }}`, "g");
|
|
77
63
|
|
|
@@ -79,35 +65,27 @@ process.chdir(HOMEBREW_DIR);
|
|
|
79
65
|
|
|
80
66
|
// homebrew tap formula (binaries)
|
|
81
67
|
|
|
82
|
-
let tap = await file.read_text(
|
|
83
|
-
path.join("templates", "git-stack.tap.rb.template")
|
|
84
|
-
);
|
|
68
|
+
let tap = await file.read_text(path.join("templates", "git-stack.tap.rb.template"));
|
|
85
69
|
|
|
86
70
|
tap = tap.replace(re_token("version"), version);
|
|
87
|
-
tap = tap.replace(re_token("
|
|
88
|
-
tap = tap.replace(re_token("
|
|
89
|
-
tap = tap.replace(re_token("
|
|
90
|
-
tap = tap.replace(re_token("
|
|
71
|
+
tap = tap.replace(re_token("mac_x64_bin"), macos_x64_asset.filepath);
|
|
72
|
+
tap = tap.replace(re_token("mac_x64_sha256"), macos_x64_asset.sha256);
|
|
73
|
+
tap = tap.replace(re_token("mac_arm64_bin"), macos_arm64_asset.filepath);
|
|
74
|
+
tap = tap.replace(re_token("mac_arm64_sha256"), macos_arm64_asset.sha256);
|
|
75
|
+
tap = tap.replace(re_token("linux_x64_bin"), linux_x64_asset.filepath);
|
|
76
|
+
tap = tap.replace(re_token("linux_x64_sha256"), linux_x64_asset.sha256);
|
|
91
77
|
|
|
92
78
|
await file.write_text(path.join("Formula", "git-stack.rb"), tap);
|
|
93
79
|
|
|
94
80
|
// homebrew/core formula (build from source)
|
|
95
81
|
|
|
96
|
-
let core = await file.read_text(
|
|
97
|
-
path.join("templates", "git-stack.core.rb.template")
|
|
98
|
-
);
|
|
82
|
+
let core = await file.read_text(path.join("templates", "git-stack.core.rb.template"));
|
|
99
83
|
|
|
100
84
|
core = core.replace(re_token("version"), version);
|
|
101
85
|
core = core.replace(re_token("tarball_sha256"), tarball_asset.sha256);
|
|
102
86
|
|
|
103
87
|
await file.write_text(path.join("Formula", "git-stack.core.rb"), core);
|
|
104
88
|
|
|
105
|
-
// finally upload the assets to the github release
|
|
106
|
-
process.chdir(STANDALONE_DIR);
|
|
107
|
-
await spawn.sync(`gh release upload ${version} ${linux_asset.filepath}`);
|
|
108
|
-
await spawn.sync(`gh release upload ${version} ${macos_asset.filepath}`);
|
|
109
|
-
await spawn.sync(`gh release upload ${version} ${win_asset.filepath}`);
|
|
110
|
-
|
|
111
89
|
// commit homebrew repo changes
|
|
112
90
|
process.chdir(HOMEBREW_DIR);
|
|
113
91
|
await spawn.sync(`git add .`);
|
|
@@ -115,7 +93,7 @@ await spawn.sync(`git commit -m ${version}`);
|
|
|
115
93
|
await spawn.sync(`git push`);
|
|
116
94
|
|
|
117
95
|
// commmit changes to main repo
|
|
118
|
-
process.chdir(
|
|
96
|
+
process.chdir(REPO_ROOT);
|
|
119
97
|
// prettier-ignore
|
|
120
98
|
await spawn.sync(["git", "commit", "-a", "-m", `homebrew-git-stack ${version}`]);
|
|
121
99
|
await spawn.sync(`git push`);
|
|
@@ -5,29 +5,41 @@ import * as file from "~/core/file";
|
|
|
5
5
|
import { spawn } from "~/core/spawn";
|
|
6
6
|
|
|
7
7
|
// get paths relative to this script
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const REPO_ROOT = (await spawn.sync("git rev-parse --show-toplevel")).stdout;
|
|
9
|
+
const DIST_DIR = path.join(REPO_ROOT, "dist");
|
|
10
|
+
const BIN_DIR = path.join(DIST_DIR, "bin");
|
|
10
11
|
|
|
11
|
-
const package_json = await file.read_json(
|
|
12
|
-
path.join(PROJECT_DIR, "package.json")
|
|
13
|
-
);
|
|
12
|
+
const package_json = await file.read_json(path.join(REPO_ROOT, "package.json"));
|
|
14
13
|
|
|
15
14
|
const version = package_json.version;
|
|
16
15
|
|
|
17
16
|
// generates local tarball e.g. git-stack-cli-1.2.0.tgz
|
|
18
|
-
await spawn("
|
|
17
|
+
await spawn("pnpm pack");
|
|
19
18
|
|
|
20
|
-
//
|
|
21
|
-
|
|
19
|
+
// generate single file executables for all targets
|
|
20
|
+
await spawn(`pnpm run compile`);
|
|
22
21
|
|
|
23
22
|
await spawn.sync(`gh release create ${version} -t ${version} --generate-notes`);
|
|
24
23
|
|
|
24
|
+
const tarball_asset = await create_asset(`git-stack-cli-${version}.tgz`, { version });
|
|
25
25
|
await spawn.sync(`gh release upload ${version} ${tarball_asset.filepath}`);
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
process.chdir(BIN_DIR);
|
|
28
|
+
|
|
29
|
+
await zip_upload("git-stack-bun-darwin-arm64");
|
|
30
|
+
await zip_upload("git-stack-bun-darwin-x64");
|
|
31
|
+
await zip_upload("git-stack-bun-linux-x64");
|
|
32
|
+
await zip_upload("git-stack-bun-windows-x64.exe");
|
|
28
33
|
|
|
29
34
|
console.debug();
|
|
30
35
|
console.debug("✅", "published", version);
|
|
31
36
|
console.debug();
|
|
32
37
|
console.debug("https://github.com/magus/git-stack-cli/releases");
|
|
33
38
|
console.debug();
|
|
39
|
+
|
|
40
|
+
async function zip_upload(filepath: string) {
|
|
41
|
+
const zip_filepath = `${filepath}.zip`;
|
|
42
|
+
await spawn.sync(`zip -r ${zip_filepath} ${filepath}`);
|
|
43
|
+
const asset = await create_asset(zip_filepath, { version });
|
|
44
|
+
await spawn.sync(`gh release upload ${version} ${asset.filepath}`);
|
|
45
|
+
}
|
package/scripts/release-npm.ts
CHANGED
|
@@ -7,15 +7,14 @@ import { spawn } from "~/core/spawn";
|
|
|
7
7
|
process.env.NODE_ENV = "production";
|
|
8
8
|
|
|
9
9
|
// get paths relative to this script
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const DIST_DIR = path.join(PROJECT_DIR, "dist");
|
|
10
|
+
const REPO_ROOT = (await spawn.sync("git rev-parse --show-toplevel")).stdout;
|
|
11
|
+
const DIST_DIR = path.join(REPO_ROOT, "dist");
|
|
13
12
|
|
|
14
13
|
// clear entire dist output directory
|
|
15
14
|
await fs.rmdir(DIST_DIR, { recursive: true });
|
|
16
15
|
await fs.mkdir(DIST_DIR, { recursive: true });
|
|
17
16
|
|
|
18
|
-
process.chdir(
|
|
17
|
+
process.chdir(REPO_ROOT);
|
|
19
18
|
|
|
20
19
|
// require clean git status besides changes to package.json version
|
|
21
20
|
const git_status = await spawn.sync("git status --porcelain");
|
|
@@ -24,9 +23,7 @@ if (!/^M\s+package.json/.test(git_status.stdout)) {
|
|
|
24
23
|
process.exit(4);
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
const package_json = await file.read_json(
|
|
28
|
-
path.join(PROJECT_DIR, "package.json")
|
|
29
|
-
);
|
|
26
|
+
const package_json = await file.read_json(path.join(REPO_ROOT, "package.json"));
|
|
30
27
|
|
|
31
28
|
const version = package_json.version;
|
|
32
29
|
|
|
@@ -40,11 +37,11 @@ if (git_tag.stdout) {
|
|
|
40
37
|
}
|
|
41
38
|
|
|
42
39
|
// install all dependencies even though we are NODE_ENV=production
|
|
43
|
-
await spawn(`
|
|
40
|
+
await spawn(`pnpm install --frozen-lockfile --production=false`);
|
|
44
41
|
|
|
45
|
-
await spawn(`
|
|
42
|
+
await spawn(`pnpm run test:all`);
|
|
46
43
|
|
|
47
|
-
await spawn(`
|
|
44
|
+
await spawn(`pnpm run build`);
|
|
48
45
|
|
|
49
46
|
// confirm all files specified exist
|
|
50
47
|
for (const filepath of package_json.files) {
|
|
@@ -61,7 +58,7 @@ console.info("Publishing to NPM requires a one-time password");
|
|
|
61
58
|
const otp = await input("Enter OTP: ");
|
|
62
59
|
await spawn(["npm", "publish", `--otp=${otp}`]);
|
|
63
60
|
|
|
64
|
-
process.chdir(
|
|
61
|
+
process.chdir(REPO_ROOT);
|
|
65
62
|
|
|
66
63
|
await spawn.sync(`git commit -a -m ${version}`);
|
|
67
64
|
await spawn.sync(`git push`);
|
package/src/app/Store.tsx
CHANGED
|
@@ -33,6 +33,11 @@ type SyncGithubState = {
|
|
|
33
33
|
// async function that returns exit code
|
|
34
34
|
type AbortHandler = () => Promise<number>;
|
|
35
35
|
|
|
36
|
+
type ExitArgs = {
|
|
37
|
+
quiet?: boolean;
|
|
38
|
+
clear?: boolean;
|
|
39
|
+
};
|
|
40
|
+
|
|
36
41
|
export type State = {
|
|
37
42
|
// set immediately in `index.tsx` so no `null` scenario
|
|
38
43
|
process_argv: Array<string>;
|
|
@@ -53,7 +58,7 @@ export type State = {
|
|
|
53
58
|
sync_github: null | SyncGithubState;
|
|
54
59
|
is_dirty_check_stash: boolean;
|
|
55
60
|
abort_handler: null | AbortHandler;
|
|
56
|
-
|
|
61
|
+
exit_mode: null | "normal" | "quiet";
|
|
57
62
|
|
|
58
63
|
step:
|
|
59
64
|
| "github-api-error"
|
|
@@ -74,7 +79,7 @@ export type State = {
|
|
|
74
79
|
pr: { [branch: string]: PullRequest };
|
|
75
80
|
|
|
76
81
|
actions: {
|
|
77
|
-
exit(code: number,
|
|
82
|
+
exit(code: number, args?: ExitArgs): void;
|
|
78
83
|
clear(): void;
|
|
79
84
|
unmount(): void;
|
|
80
85
|
newline(): void;
|
|
@@ -124,7 +129,7 @@ const BaseStore = createStore<State>()(
|
|
|
124
129
|
sync_github: null,
|
|
125
130
|
is_dirty_check_stash: false,
|
|
126
131
|
abort_handler: null,
|
|
127
|
-
|
|
132
|
+
exit_mode: null,
|
|
128
133
|
|
|
129
134
|
step: "loading",
|
|
130
135
|
|
|
@@ -134,9 +139,15 @@ const BaseStore = createStore<State>()(
|
|
|
134
139
|
pr: {},
|
|
135
140
|
|
|
136
141
|
actions: {
|
|
137
|
-
exit(code,
|
|
142
|
+
exit(code, args) {
|
|
138
143
|
set((state) => {
|
|
139
|
-
|
|
144
|
+
if (args?.quiet ?? code === 0) {
|
|
145
|
+
state.exit_mode = "quiet";
|
|
146
|
+
} else {
|
|
147
|
+
state.exit_mode = "normal";
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let clear = args?.clear ?? true;
|
|
140
151
|
|
|
141
152
|
const node = <Exit clear={clear} code={code} />;
|
|
142
153
|
state.mutate.output(state, { node });
|
package/src/commands/Fixup.tsx
CHANGED
package/src/commands/Log.tsx
CHANGED
|
@@ -11,17 +11,27 @@ type Props = {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export function ExitingGate(props: Props) {
|
|
14
|
-
const
|
|
14
|
+
const exit_mode = Store.useState((state) => state.exit_mode);
|
|
15
15
|
|
|
16
|
-
if (!
|
|
16
|
+
if (!exit_mode) {
|
|
17
17
|
return props.children;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
switch (exit_mode) {
|
|
21
|
+
case "quiet":
|
|
22
|
+
return null;
|
|
23
|
+
|
|
24
|
+
case "normal":
|
|
25
|
+
return (
|
|
26
|
+
<Ink.Box flexDirection="column">
|
|
27
|
+
<Ink.Text color={colors.red}>
|
|
28
|
+
<FormatText message="🚨 Exiting…" />
|
|
29
|
+
</Ink.Text>
|
|
30
|
+
</Ink.Box>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
default:
|
|
34
|
+
exit_mode satisfies never;
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
27
37
|
}
|
|
@@ -112,7 +112,9 @@ GitReviseTodo.execute = async function grt_execute(args: ExecuteArgs) {
|
|
|
112
112
|
const tmp_git_sequence_editor_path = path.join(os.tmpdir(), "git-sequence-editor.sh");
|
|
113
113
|
|
|
114
114
|
// replaced at build time with literal contents of `scripts/git-sequence-editor.sh`
|
|
115
|
-
const GIT_SEQUENCE_EDITOR_SCRIPT =
|
|
115
|
+
const GIT_SEQUENCE_EDITOR_SCRIPT = process.env.GIT_SEQUENCE_EDITOR_SCRIPT;
|
|
116
|
+
|
|
117
|
+
invariant(GIT_SEQUENCE_EDITOR_SCRIPT, "GIT_SEQUENCE_EDITOR_SCRIPT must exist");
|
|
116
118
|
|
|
117
119
|
// write script to temporary path
|
|
118
120
|
await fs.writeFile(tmp_git_sequence_editor_path, GIT_SEQUENCE_EDITOR_SCRIPT);
|
|
@@ -131,10 +133,10 @@ GitReviseTodo.execute = async function grt_execute(args: ExecuteArgs) {
|
|
|
131
133
|
`revise --edit -i ${args.rebase_merge_base}`,
|
|
132
134
|
];
|
|
133
135
|
|
|
134
|
-
// ignore
|
|
135
|
-
//
|
|
136
|
+
// `ignore` hdies output which helps prevent scrollback clear
|
|
137
|
+
// `pipe` helps see failures when git revise fails
|
|
136
138
|
// https://github.com/magus/git-stack-cli/commit/f9f10e3ac3cd9a35ee75d3e0851a48391967a23f
|
|
137
|
-
await cli(command, { stdio: ["
|
|
139
|
+
await cli(command, { stdio: ["pipe", "pipe", "pipe"] });
|
|
138
140
|
|
|
139
141
|
// cleanup tmp_git_sequence_editor_path
|
|
140
142
|
await safe_rm(tmp_git_sequence_editor_path);
|
package/src/index.tsx
CHANGED
|
@@ -15,6 +15,10 @@ import { pretty_json } from "~/core/pretty_json";
|
|
|
15
15
|
try {
|
|
16
16
|
const argv = await command();
|
|
17
17
|
|
|
18
|
+
// required to get bun working with ink
|
|
19
|
+
// https://github.com/oven-sh/bun/issues/6862#issuecomment-2429444852
|
|
20
|
+
process.stdin.resume();
|
|
21
|
+
|
|
18
22
|
process.on("uncaughtException", (error) => {
|
|
19
23
|
console.error("🚨 uncaughtException");
|
|
20
24
|
console.error(error);
|