git-stack-cli 1.0.1 → 1.0.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 +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/package.json +13 -7
- package/rollup.config.mjs +46 -0
- package/scripts/.eslintrc.cjs +61 -0
- package/scripts/core/file.ts +32 -0
- package/scripts/core/spawn.ts +41 -0
- package/scripts/npm-prepublishOnly.ts +8 -0
- package/scripts/prepare-standalone.ts +59 -0
- package/scripts/release-brew.ts +105 -0
- package/scripts/release-npm.ts +109 -0
- package/scripts/tsconfig.json +35 -0
- package/src/__fixtures__/metadata.ts +666 -0
- package/src/app/App.tsx +65 -0
- package/src/app/AutoUpdate.tsx +229 -0
- package/src/app/Await.tsx +82 -0
- package/src/app/Brackets.tsx +22 -0
- package/src/app/Command.tsx +19 -0
- package/src/app/Debug.tsx +52 -0
- package/src/app/DependencyCheck.tsx +155 -0
- package/src/app/Exit.tsx +25 -0
- package/src/app/FormatText.tsx +26 -0
- package/src/app/GatherMetadata.tsx +145 -0
- package/src/app/GithubApiError.tsx +78 -0
- package/src/app/LocalCommitStatus.tsx +70 -0
- package/src/app/LocalMergeRebase.tsx +230 -0
- package/src/app/LogTimestamp.tsx +12 -0
- package/src/app/Main.tsx +52 -0
- package/src/app/ManualRebase.tsx +308 -0
- package/src/app/MultiSelect.tsx +246 -0
- package/src/app/Output.tsx +37 -0
- package/src/app/Parens.tsx +21 -0
- package/src/app/PostRebaseStatus.tsx +33 -0
- package/src/app/PreLocalMergeRebase.tsx +31 -0
- package/src/app/PreSelectCommitRanges.tsx +31 -0
- package/src/app/Providers.tsx +11 -0
- package/src/app/RebaseCheck.tsx +96 -0
- package/src/app/SelectCommitRanges.tsx +372 -0
- package/src/app/Status.tsx +82 -0
- package/src/app/StatusTable.tsx +155 -0
- package/src/app/Store.tsx +252 -0
- package/src/app/Table.tsx +137 -0
- package/src/app/TextInput.tsx +88 -0
- package/src/app/Url.tsx +19 -0
- package/src/app/Waterfall.tsx +37 -0
- package/src/app/YesNoPrompt.tsx +73 -0
- package/src/command.ts +78 -0
- package/src/core/CommitMetadata.ts +212 -0
- package/src/core/Metadata.test.ts +41 -0
- package/src/core/Metadata.ts +51 -0
- package/src/core/StackSummaryTable.test.ts +157 -0
- package/src/core/StackSummaryTable.ts +127 -0
- package/src/core/Timer.ts +44 -0
- package/src/core/assertNever.ts +4 -0
- package/src/core/cache.ts +49 -0
- package/src/core/capitalize.ts +5 -0
- package/src/core/chalk.ts +103 -0
- package/src/core/clamp.ts +6 -0
- package/src/core/cli.ts +161 -0
- package/src/core/colors.ts +23 -0
- package/src/core/date.ts +25 -0
- package/src/core/fetch_json.ts +26 -0
- package/src/core/github.tsx +215 -0
- package/src/core/invariant.ts +5 -0
- package/src/core/is_command_available.ts +21 -0
- package/src/core/is_finite_value.ts +3 -0
- package/src/core/json.ts +32 -0
- package/src/core/match_group.ts +10 -0
- package/src/core/read_json.ts +12 -0
- package/src/core/safe_quote.ts +10 -0
- package/src/core/semver_compare.ts +27 -0
- package/src/core/short_id.ts +87 -0
- package/src/core/sleep.ts +3 -0
- package/src/core/wrap_index.ts +11 -0
- package/src/index.tsx +22 -0
- package/src/types/global.d.ts +7 -0
- package/tsconfig.json +53 -0
package/README.md
CHANGED
package/dist/cjs/index.cjs
CHANGED
|
@@ -34080,7 +34080,7 @@ async function command() {
|
|
|
34080
34080
|
.wrap(null)
|
|
34081
34081
|
// disallow unknown options
|
|
34082
34082
|
.strict()
|
|
34083
|
-
.version("1.0.
|
|
34083
|
+
.version("1.0.3" )
|
|
34084
34084
|
.showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`")
|
|
34085
34085
|
.help("help", "Show usage via `git stack help`").argv);
|
|
34086
34086
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-stack-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "magus",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,22 +13,28 @@
|
|
|
13
13
|
"git-stack": "dist/cjs/index.cjs"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
|
-
"dist/cjs"
|
|
16
|
+
"dist/cjs",
|
|
17
|
+
"scripts",
|
|
18
|
+
"src",
|
|
19
|
+
"package-lock.json",
|
|
20
|
+
"rollup.config.mjs",
|
|
21
|
+
"tsconfig.json"
|
|
17
22
|
],
|
|
18
23
|
"scripts": {
|
|
19
24
|
"dev": "npm run build -- --watch",
|
|
20
25
|
"build": "rollup -c rollup.config.mjs",
|
|
21
26
|
"build:standalone": "bun run scripts/prepare-standalone.ts",
|
|
22
|
-
"release:
|
|
23
|
-
"release:npm": "npm
|
|
27
|
+
"release:brew": "bun run scripts/release-brew.ts",
|
|
28
|
+
"release:npm": "bun run scripts/release-npm.ts",
|
|
24
29
|
"lint:check": "eslint . --cache",
|
|
25
30
|
"lint": "npm run lint:check -- --fix",
|
|
26
31
|
"prettier:check": "prettier ./src --check --cache",
|
|
27
32
|
"prettier": "npm run prettier:check -- --write",
|
|
28
|
-
"test": "bun test
|
|
33
|
+
"test": "bun test",
|
|
29
34
|
"test:watch": "npm run test -- --watch",
|
|
30
|
-
"test:
|
|
31
|
-
"
|
|
35
|
+
"test:types": "tsc",
|
|
36
|
+
"test:all": "npm run prettier:check && npm run lint:check && npm run test:types",
|
|
37
|
+
"prepublishOnly": "bun run scripts/npm-prepublishOnly.ts"
|
|
32
38
|
},
|
|
33
39
|
"dependencies": {
|
|
34
40
|
"chalk": "^5.3.0",
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// npm i -D rollup @rollup/plugin-json @rollup/plugin-node-resolve @rollup/plugin-commonjs
|
|
2
|
+
|
|
3
|
+
import * as fs from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import * as url from "node:url";
|
|
6
|
+
|
|
7
|
+
import alias from "@rollup/plugin-alias";
|
|
8
|
+
import commonjs from "@rollup/plugin-commonjs";
|
|
9
|
+
import json from "@rollup/plugin-json";
|
|
10
|
+
import nodeResolve from "@rollup/plugin-node-resolve";
|
|
11
|
+
import replace from "@rollup/plugin-replace";
|
|
12
|
+
import typescript from "@rollup/plugin-typescript";
|
|
13
|
+
|
|
14
|
+
const SCRIPT_DIR = path.dirname(url.fileURLToPath(import.meta.url));
|
|
15
|
+
const PACKAGE_JSON_PATH = path.join(SCRIPT_DIR, "package.json");
|
|
16
|
+
|
|
17
|
+
const package_json_str = await fs.readFile(PACKAGE_JSON_PATH, "utf-8");
|
|
18
|
+
const package_json = JSON.parse(package_json_str);
|
|
19
|
+
|
|
20
|
+
export default {
|
|
21
|
+
input: "src/index.tsx",
|
|
22
|
+
|
|
23
|
+
output: {
|
|
24
|
+
file: "dist/cjs/index.cjs",
|
|
25
|
+
format: "cjs",
|
|
26
|
+
inlineDynamicImports: true,
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
plugins: [
|
|
30
|
+
// force line break
|
|
31
|
+
typescript(),
|
|
32
|
+
alias({
|
|
33
|
+
entries: [{ find: /^~\//, replacement: "./src/" }],
|
|
34
|
+
}),
|
|
35
|
+
nodeResolve({ exportConditions: ["node"] }),
|
|
36
|
+
commonjs(),
|
|
37
|
+
json(),
|
|
38
|
+
replace({
|
|
39
|
+
preventAssignment: true,
|
|
40
|
+
values: {
|
|
41
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
42
|
+
"process.env.CLI_VERSION": JSON.stringify(String(package_json.version)),
|
|
43
|
+
},
|
|
44
|
+
}),
|
|
45
|
+
],
|
|
46
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const path = require("node:path");
|
|
2
|
+
const import_eslint = require("../config/eslint/import.eslint.cjs");
|
|
3
|
+
|
|
4
|
+
/** @type {import('eslint').Linter.Config} */
|
|
5
|
+
module.exports = {
|
|
6
|
+
root: true,
|
|
7
|
+
|
|
8
|
+
ignorePatterns: [],
|
|
9
|
+
|
|
10
|
+
overrides: [
|
|
11
|
+
{
|
|
12
|
+
files: [".eslintrc.{js,cjs}"],
|
|
13
|
+
|
|
14
|
+
parserOptions: {
|
|
15
|
+
ecmaVersion: 13, // ES2022
|
|
16
|
+
sourceType: "script",
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
env: {
|
|
20
|
+
node: true,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
{
|
|
25
|
+
files: ["**/*.{ts,tsx}"],
|
|
26
|
+
|
|
27
|
+
parser: "@typescript-eslint/parser",
|
|
28
|
+
parserOptions: {
|
|
29
|
+
ecmaVersion: "latest",
|
|
30
|
+
sourceType: "script",
|
|
31
|
+
project: path.resolve(__dirname, "tsconfig.json"),
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
env: {
|
|
35
|
+
node: true,
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
settings: {
|
|
39
|
+
"import/resolver": {
|
|
40
|
+
typescript: true,
|
|
41
|
+
node: true,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
|
46
|
+
|
|
47
|
+
plugins: ["@typescript-eslint", "import"],
|
|
48
|
+
|
|
49
|
+
rules: {
|
|
50
|
+
"@typescript-eslint/consistent-type-imports": [
|
|
51
|
+
"error",
|
|
52
|
+
{ prefer: "type-imports", fixStyle: "separate-type-imports" },
|
|
53
|
+
],
|
|
54
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
55
|
+
"@typescript-eslint/no-floating-promises": ["error"],
|
|
56
|
+
|
|
57
|
+
...import_eslint.rules,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
|
|
3
|
+
export async function read_json(filepath: string) {
|
|
4
|
+
const file = Bun.file(filepath);
|
|
5
|
+
const json = await file.json();
|
|
6
|
+
return json;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function write_json(filepath: string, data: any) {
|
|
10
|
+
const file = Bun.file(filepath);
|
|
11
|
+
await Bun.write(file, JSON.stringify(data, null, 2));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function read_text(filepath: string) {
|
|
15
|
+
const file = Bun.file(filepath);
|
|
16
|
+
const text = await file.text();
|
|
17
|
+
return text;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function write_text(filepath: string, text: string) {
|
|
21
|
+
const file = Bun.file(filepath);
|
|
22
|
+
await Bun.write(file, text);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function exists(filepath: string) {
|
|
26
|
+
try {
|
|
27
|
+
await fs.access(filepath);
|
|
28
|
+
return true;
|
|
29
|
+
} catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export async function spawn(cmd: string) {
|
|
2
|
+
console.debug();
|
|
3
|
+
console.debug("[spawn]", cmd);
|
|
4
|
+
|
|
5
|
+
const env = process.env;
|
|
6
|
+
const proc = await Bun.spawn(cmd.split(" "), {
|
|
7
|
+
env,
|
|
8
|
+
stdout: "inherit",
|
|
9
|
+
stderr: "inherit",
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
await proc.exited;
|
|
13
|
+
|
|
14
|
+
if (proc.exitCode) {
|
|
15
|
+
console.error(`(${proc.exitCode})`, cmd);
|
|
16
|
+
|
|
17
|
+
if (!process.env.GS_NO_CHECK) {
|
|
18
|
+
process.exit(proc.exitCode);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
console.debug("[end]", cmd);
|
|
23
|
+
|
|
24
|
+
return { proc };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
spawn.sync = async function spawnSync(cmd: string) {
|
|
28
|
+
console.debug();
|
|
29
|
+
console.debug("[spawn.sync]", cmd);
|
|
30
|
+
|
|
31
|
+
const env = process.env;
|
|
32
|
+
const proc = await Bun.spawnSync(cmd.split(" "), { env });
|
|
33
|
+
|
|
34
|
+
const stdout = String(proc.stdout).trim();
|
|
35
|
+
const stderr = String(proc.stderr).trim();
|
|
36
|
+
|
|
37
|
+
console.debug("[end]", cmd);
|
|
38
|
+
console.debug({ stdout, stderr });
|
|
39
|
+
|
|
40
|
+
return { proc, stdout, stderr };
|
|
41
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
import * as file from "~/core/file";
|
|
5
|
+
import { spawn } from "~/core/spawn";
|
|
6
|
+
|
|
7
|
+
// get paths relative to this script
|
|
8
|
+
const SCRIPT_DIR = path.dirname(new URL(import.meta.url).pathname);
|
|
9
|
+
const PROJECT_DIR = path.join(SCRIPT_DIR, "..");
|
|
10
|
+
const NODE_MODULES_BIN = path.join(PROJECT_DIR, "node_modules", ".bin");
|
|
11
|
+
const DIST_DIR = path.join(PROJECT_DIR, "dist");
|
|
12
|
+
const CJS_DIR = path.join(DIST_DIR, "cjs");
|
|
13
|
+
const STANDALONE_DIR = path.join(DIST_DIR, "standalone");
|
|
14
|
+
|
|
15
|
+
// clear entire dist output directory
|
|
16
|
+
await fs.rmdir(DIST_DIR, { recursive: true });
|
|
17
|
+
await fs.mkdir(DIST_DIR, { recursive: true });
|
|
18
|
+
|
|
19
|
+
const package_json = await file.read_json(
|
|
20
|
+
path.join(PROJECT_DIR, "package.json")
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
// prettier-ignore
|
|
24
|
+
const { name, version, description, author, license, repository } = package_json;
|
|
25
|
+
|
|
26
|
+
// include fields necessary for standalone executable build
|
|
27
|
+
const standalone_package_json = {
|
|
28
|
+
name,
|
|
29
|
+
version,
|
|
30
|
+
description,
|
|
31
|
+
author,
|
|
32
|
+
license,
|
|
33
|
+
repository,
|
|
34
|
+
bin: {
|
|
35
|
+
"git-stack": "index.js",
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
await file.write_json(
|
|
40
|
+
path.join(STANDALONE_DIR, "package.json"),
|
|
41
|
+
standalone_package_json
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
process.chdir(PROJECT_DIR);
|
|
45
|
+
|
|
46
|
+
Bun.env["NODE_ENV"] = "production";
|
|
47
|
+
|
|
48
|
+
// run typescript build to generate module output
|
|
49
|
+
await spawn("npm run build");
|
|
50
|
+
|
|
51
|
+
await fs.cp(
|
|
52
|
+
path.join(CJS_DIR, "index.cjs"),
|
|
53
|
+
path.join(STANDALONE_DIR, "index.js")
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
process.chdir(STANDALONE_DIR);
|
|
57
|
+
|
|
58
|
+
// run pkg to build standalone executable
|
|
59
|
+
await spawn(`${path.join(NODE_MODULES_BIN, "pkg")} package.json`);
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
import * as file from "~/core/file";
|
|
4
|
+
import { spawn } from "~/core/spawn";
|
|
5
|
+
|
|
6
|
+
// cli args
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
const NO_CHECK = args.includes("--no-check");
|
|
9
|
+
const COMMIT = args.includes("--commit");
|
|
10
|
+
|
|
11
|
+
// get paths relative to this script
|
|
12
|
+
const SCRIPT_DIR = path.dirname(new URL(import.meta.url).pathname);
|
|
13
|
+
const PROJECT_DIR = path.join(SCRIPT_DIR, "..");
|
|
14
|
+
const DIST_DIR = path.join(PROJECT_DIR, "dist");
|
|
15
|
+
const STANDALONE_DIR = path.join(DIST_DIR, "standalone");
|
|
16
|
+
const HOMEBREW_DIR = path.join(PROJECT_DIR, "homebrew");
|
|
17
|
+
|
|
18
|
+
const package_json = await file.read_json(
|
|
19
|
+
path.join(PROJECT_DIR, "package.json")
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const version = package_json.version;
|
|
23
|
+
|
|
24
|
+
process.chdir(STANDALONE_DIR);
|
|
25
|
+
|
|
26
|
+
const linux_asset = await create_asset("git-stack-cli-linux");
|
|
27
|
+
const macos_asset = await create_asset("git-stack-cli-macos");
|
|
28
|
+
const win_asset = await create_asset("git-stack-cli-win.exe");
|
|
29
|
+
|
|
30
|
+
console.debug({ linux_asset, macos_asset, win_asset });
|
|
31
|
+
|
|
32
|
+
const re_token = (name: string) => new RegExp(`{{ ${name} }}`, "g");
|
|
33
|
+
|
|
34
|
+
process.chdir(HOMEBREW_DIR);
|
|
35
|
+
|
|
36
|
+
let formula = await file.read_text("git-stack.rb.template");
|
|
37
|
+
|
|
38
|
+
formula = formula.replace(re_token("version"), version);
|
|
39
|
+
formula = formula.replace(re_token("mac_bin"), macos_asset.name);
|
|
40
|
+
formula = formula.replace(re_token("mac_sha256"), macos_asset.sha256);
|
|
41
|
+
formula = formula.replace(re_token("linux_bin"), linux_asset.name);
|
|
42
|
+
formula = formula.replace(re_token("linux_sha256"), linux_asset.sha256);
|
|
43
|
+
|
|
44
|
+
await file.write_text("git-stack.rb", formula);
|
|
45
|
+
|
|
46
|
+
if (COMMIT) {
|
|
47
|
+
await spawn.sync(`git commit -a -m ${version}`);
|
|
48
|
+
await spawn.sync(`git push`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
process.chdir(PROJECT_DIR);
|
|
52
|
+
|
|
53
|
+
await spawn(`npm i`);
|
|
54
|
+
|
|
55
|
+
if (COMMIT) {
|
|
56
|
+
await spawn.sync(`git commit -a -m ${version}`);
|
|
57
|
+
await spawn.sync(`git push`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// -a: create tag on last commit
|
|
61
|
+
// -m: message
|
|
62
|
+
if (COMMIT) {
|
|
63
|
+
await spawn.sync(`git tag -a ${version} -m ${version}`);
|
|
64
|
+
await spawn.sync(`git push origin ${version}`);
|
|
65
|
+
|
|
66
|
+
await spawn.sync(
|
|
67
|
+
`gh release create ${version} -t ${version} --generate-notes`
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
process.chdir(STANDALONE_DIR);
|
|
71
|
+
|
|
72
|
+
await spawn.sync(`gh release upload ${version} ${linux_asset.name}`);
|
|
73
|
+
await spawn.sync(`gh release upload ${version} ${macos_asset.name}`);
|
|
74
|
+
await spawn.sync(`gh release upload ${version} ${win_asset.name}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.debug();
|
|
78
|
+
console.debug("✅", "published", version);
|
|
79
|
+
console.debug(" COMMIT", COMMIT);
|
|
80
|
+
console.debug(" NO_CHECK", NO_CHECK);
|
|
81
|
+
console.debug();
|
|
82
|
+
console.debug(" https://github.com/magus/git-stack-cli/releases");
|
|
83
|
+
console.debug();
|
|
84
|
+
|
|
85
|
+
console.debug();
|
|
86
|
+
console.debug("Don't forget to run `npm publish` to update the NPM registry!");
|
|
87
|
+
console.debug();
|
|
88
|
+
console.debug(" npm publish");
|
|
89
|
+
console.debug();
|
|
90
|
+
|
|
91
|
+
// https://github.com/magus/git-stack-cli/releases/download/0.8.9/git-stack-cli-linux
|
|
92
|
+
async function create_asset(name: string) {
|
|
93
|
+
const sha256_cmd = await spawn.sync(`shasum -a 256 ${name}`);
|
|
94
|
+
const match = sha256_cmd.stdout.match(/(?<sha256>[^\s]+)/i);
|
|
95
|
+
|
|
96
|
+
if (!match?.groups) {
|
|
97
|
+
throw new Error(`unable to get sha256 for ${name}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const sha256 = match.groups.sha256;
|
|
101
|
+
|
|
102
|
+
const url = `https://github.com/magus/git-stack-cli/releases/download/${version}/${name}`;
|
|
103
|
+
|
|
104
|
+
return { name, sha256, url };
|
|
105
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
import * as file from "~/core/file";
|
|
5
|
+
import { spawn } from "~/core/spawn";
|
|
6
|
+
|
|
7
|
+
process.env.NODE_ENV = "production";
|
|
8
|
+
|
|
9
|
+
// get paths relative to this script
|
|
10
|
+
const SCRIPT_DIR = path.dirname(new URL(import.meta.url).pathname);
|
|
11
|
+
const PROJECT_DIR = path.join(SCRIPT_DIR, "..");
|
|
12
|
+
const DIST_DIR = path.join(PROJECT_DIR, "dist");
|
|
13
|
+
|
|
14
|
+
// clear entire dist output directory
|
|
15
|
+
await fs.rmdir(DIST_DIR, { recursive: true });
|
|
16
|
+
await fs.mkdir(DIST_DIR, { recursive: true });
|
|
17
|
+
|
|
18
|
+
process.chdir(PROJECT_DIR);
|
|
19
|
+
|
|
20
|
+
const package_json = await file.read_json(
|
|
21
|
+
path.join(PROJECT_DIR, "package.json")
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const version = package_json.version;
|
|
25
|
+
|
|
26
|
+
const git_tag = await spawn.sync(`git tag -l ${version}`);
|
|
27
|
+
|
|
28
|
+
if (git_tag.stdout) {
|
|
29
|
+
console.error(`tag [${version}] already exists`);
|
|
30
|
+
if (!process.env.GS_NO_CHECK) {
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// install all dependencies even though we are NODE_ENV=production
|
|
36
|
+
await spawn(`npm install --production=false`);
|
|
37
|
+
|
|
38
|
+
await spawn(`npm run test:all`);
|
|
39
|
+
|
|
40
|
+
await spawn(`npm run build`);
|
|
41
|
+
|
|
42
|
+
// confirm all files specified exist
|
|
43
|
+
for (const filepath of package_json.files) {
|
|
44
|
+
if (!(await file.exists(filepath))) {
|
|
45
|
+
console.error("missing required file in package.json files", filepath);
|
|
46
|
+
if (!process.env.GS_NO_CHECK) {
|
|
47
|
+
process.exit(2);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
process.env["GS_RELEASE_NPM"] = "true";
|
|
53
|
+
console.info("Publishing to NPM requires a one-time password");
|
|
54
|
+
const otp = await input("Enter OTP: ");
|
|
55
|
+
await spawn(`npm publish --otp=${otp}`);
|
|
56
|
+
|
|
57
|
+
process.chdir(PROJECT_DIR);
|
|
58
|
+
|
|
59
|
+
await spawn.sync(`git commit -a -m ${version}`);
|
|
60
|
+
await spawn.sync(`git push`);
|
|
61
|
+
|
|
62
|
+
// -a: create tag on last commit
|
|
63
|
+
// -m: message
|
|
64
|
+
await spawn.sync(`git tag -a ${version} -m ${version}`);
|
|
65
|
+
await spawn.sync(`git push origin ${version}`);
|
|
66
|
+
|
|
67
|
+
console.debug();
|
|
68
|
+
console.debug("✅", "published", version);
|
|
69
|
+
console.debug();
|
|
70
|
+
console.debug(" https://github.com/magus/git-stack-cli/releases");
|
|
71
|
+
console.debug();
|
|
72
|
+
|
|
73
|
+
// // https://github.com/magus/git-stack-cli/releases/download/0.8.9/git-stack-cli-linux
|
|
74
|
+
// async function create_asset(name: string) {
|
|
75
|
+
// const sha256_cmd = await spawn.sync(`shasum -a 256 ${name}`);
|
|
76
|
+
// const match = sha256_cmd.stdout.match(/(?<sha256>[^\s]+)/i);
|
|
77
|
+
|
|
78
|
+
// if (!match?.groups) {
|
|
79
|
+
// throw new Error(`unable to get sha256 for ${name}`);
|
|
80
|
+
// }
|
|
81
|
+
|
|
82
|
+
// const sha256 = match.groups.sha256;
|
|
83
|
+
|
|
84
|
+
// const url = `https://github.com/magus/git-stack-cli/releases/download/${version}/${name}`;
|
|
85
|
+
|
|
86
|
+
// return { name, sha256, url };
|
|
87
|
+
// }
|
|
88
|
+
|
|
89
|
+
// function reFind(list: Array<string>, re: RegExp) {
|
|
90
|
+
// for (const str of list) {
|
|
91
|
+
// const match = str.match(re);
|
|
92
|
+
|
|
93
|
+
// if (match?.groups) {
|
|
94
|
+
// return match.groups.value;
|
|
95
|
+
// }
|
|
96
|
+
// }
|
|
97
|
+
|
|
98
|
+
// return null;
|
|
99
|
+
// }
|
|
100
|
+
|
|
101
|
+
async function input(prompt: string) {
|
|
102
|
+
process.stdout.write(prompt);
|
|
103
|
+
for await (const value of console) {
|
|
104
|
+
if (value) {
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
process.stdout.write(prompt);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"lib": ["ESNext"],
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleDetection": "force",
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"allowJs": true,
|
|
9
|
+
|
|
10
|
+
"baseUrl": ".",
|
|
11
|
+
"paths": {
|
|
12
|
+
"~/*": ["./*"]
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
"types": [
|
|
16
|
+
// add bun-types for resolving imports
|
|
17
|
+
//
|
|
18
|
+
// import { test, expect } from "bun:test";
|
|
19
|
+
//
|
|
20
|
+
"bun-types"
|
|
21
|
+
],
|
|
22
|
+
|
|
23
|
+
/* Bundler mode */
|
|
24
|
+
"moduleResolution": "bundler",
|
|
25
|
+
"allowImportingTsExtensions": true,
|
|
26
|
+
"verbatimModuleSyntax": true,
|
|
27
|
+
"noEmit": true,
|
|
28
|
+
|
|
29
|
+
/* Linting */
|
|
30
|
+
"skipLibCheck": true,
|
|
31
|
+
"strict": true,
|
|
32
|
+
"noFallthroughCasesInSwitch": true,
|
|
33
|
+
"forceConsistentCasingInFileNames": true
|
|
34
|
+
}
|
|
35
|
+
}
|