ya-git-jira 1.2.0 → 1.3.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/README.md CHANGED
@@ -1,13 +1,32 @@
1
1
  # ya-git-jira - Yet Another Git Jira
2
2
 
3
- This package installs two applications (for now) that are written to be
3
+ This package installs several scripts that are written to be
4
4
  usable as `git` extensions, i.e. sub-commands of the `git` command.
5
5
  The extensions faciliate workflow when using `git` for source control and `jira`
6
6
  for issue tracking. Other similar packages exist -- thus the "yet another"
7
7
  in the name.
8
8
 
9
- This package will likely evolve over time to include some other workflow cases.
10
- For now, the two commands are:
9
+ This package will likely evolve over time to include more workflow cases.
10
+
11
+ ## gitj -- A test driver to use instead of `git <command>`
12
+
13
+ It can be useful to run these commands as if they were being invoked through
14
+ `git` but using a proxy for `git` than can only execute the commands in this
15
+ package.
16
+
17
+ For example, to see the available top level commands, run `gitj --help`:
18
+
19
+ ```
20
+ $ gitj ---help
21
+ Usage: gitj [options] [command]
22
+
23
+ Options:
24
+ -h, --help display help for command
25
+
26
+ Commands:
27
+ bump
28
+ jira A collection of jira utility commands
29
+ ```
11
30
 
12
31
  ## git-jira-start -- Create a new topic branch for work on an issue
13
32
 
package/bin/git-bump.ts CHANGED
@@ -8,6 +8,7 @@ export function create(): Command {
8
8
  const program = new Command()
9
9
  program
10
10
  .name('bump')
11
+ .description('Bump the version number in the current branch')
11
12
  .action(async () => {
12
13
  const currentBranch = await getCurrentBranch()
13
14
 
@@ -27,7 +28,7 @@ export function create(): Command {
27
28
  }
28
29
 
29
30
  if (isMain('git-bump')) {
30
- create().parse(process.argv)
31
+ await create().parseAsync(Bun.argv)
31
32
  }
32
33
 
33
34
  export default create
@@ -3,15 +3,18 @@
3
3
  import { Command } from 'commander'
4
4
  import { getIssue } from "../lib/jira"
5
5
  import { isMain } from '../lib/is_main'
6
+ import { getJiraConfig } from '../lib/jira'
6
7
 
7
- export function create() {
8
+ export function create(): Command {
8
9
  const program = new Command()
9
10
  program
10
11
  .name('issue')
12
+ .description('Get information about an issue')
11
13
  .argument('issue', 'Issue ID')
12
14
  .option('-v, --verbose', 'Verbose output')
13
15
  .option('-u, --url', 'Show the URL of the issue')
14
16
  .action(async (issueId: string, options) => {
17
+ const { host } = await getJiraConfig()
15
18
  const issue = await getIssue(issueId)
16
19
  if (!issue) {
17
20
  console.error(`Issue ${issueId} not found`)
@@ -22,14 +25,14 @@ export function create() {
22
25
  process.exit(0)
23
26
  }
24
27
  if (options.url) {
25
- console.log(issue.self)
28
+ console.log(`https://${host}/browse/${issueId}`)
26
29
  }
27
30
  })
28
31
  return program
29
32
  }
30
33
 
31
34
  if (isMain('git-jira-issue')) {
32
- create().parse(process.argv)
35
+ await create().parseAsync(Bun.argv)
33
36
  }
34
37
 
35
38
  export default create
@@ -8,6 +8,7 @@ export function create(): Command {
8
8
  const program = new Command()
9
9
  program
10
10
  .name('issues')
11
+ .description('List your unresolved issues')
11
12
  .action(async (options) => {
12
13
  const issues = await myUnresolvedIssues()
13
14
  console.log(`You have ${issues.length} unresolved issues`)
@@ -19,7 +20,7 @@ export function create(): Command {
19
20
  }
20
21
 
21
22
  if (isMain('git-jira-issues')) {
22
- create().parse(process.argv)
23
+ await create().parseAsync(Bun.argv)
23
24
  }
24
25
 
25
26
  export default create
@@ -15,6 +15,7 @@ export function create(): Command {
15
15
  const program = new Command()
16
16
  program
17
17
  .name('start')
18
+ .description('Start working on an issue by creating a branch')
18
19
  .argument('issue', 'Issue ID')
19
20
  .action(async (issueId: string) => {
20
21
  const issue = await getIssue(issueId)
@@ -32,7 +33,7 @@ export function create(): Command {
32
33
  }
33
34
 
34
35
  if (isMain('git-jira-issues')) {
35
- create().parse(process.argv)
36
+ await create().parseAsync(Bun.argv)
36
37
  }
37
38
 
38
39
  export default create
package/bin/git-jira.ts CHANGED
@@ -2,26 +2,23 @@
2
2
 
3
3
  import { Command } from 'commander'
4
4
  import { isMain } from '../lib/is_main'
5
+ import start from './git-jira-start'
6
+ import issue from './git-jira-issue'
7
+ import issues from './git-jira-issues'
5
8
 
6
- const start = (await import('./git-jira-start')).create()
7
- const issue = (await import('./git-jira-issue')).create()
8
- const issues = (await import('./git-jira-issues')).create()
9
-
10
- export function create() {
9
+ export function create(): Command {
11
10
  const program = new Command()
12
11
  program
13
12
  .name('jira')
14
- .addCommand(start)
15
- .addCommand(issue)
16
- .addCommand(issues)
17
- .action(() => {
18
- program.help()
19
- })
13
+ .description('A set of commands for working with Jira')
14
+ .addCommand(start())
15
+ .addCommand(issue())
16
+ .addCommand(issues())
20
17
  return program
21
18
  }
22
19
 
23
20
  if (isMain('git-jira')) {
24
- create().parse(process.argv)
21
+ await create().parseAsync(Bun.argv)
25
22
  }
26
23
 
27
24
  export default create
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bun run
2
+
3
+ import { Command } from 'commander'
4
+ import { getProjects, type Project } from "../lib/gitlab"
5
+ import { isMain } from '../lib/is_main'
6
+
7
+ export function create(): Command {
8
+ const program = new Command()
9
+ program
10
+ .name('projects')
11
+ .description('List projects for current user')
12
+ .option('-v, --verbose', 'Verbose output')
13
+ .argument('[path...]', 'Namespace paths to filter by')
14
+ .action(async (paths: string[], options) => {
15
+ const projects: Array<Project> = await getProjects(paths)
16
+ if (!projects) {
17
+ console.error(`No projects!`)
18
+ process.exit(1)
19
+ }
20
+ if (options.verbose) {
21
+ console.log(projects)
22
+ }
23
+ else {
24
+ let filtered = projects.map((p: Project) => {
25
+ const { id, name, path_with_namespace, ssh_url_to_repo } = p
26
+ return { id, name, path_with_namespace, ssh_url_to_repo }
27
+ })
28
+ console.log(filtered)
29
+ }
30
+ })
31
+ return program
32
+ }
33
+
34
+ if (isMain('git-lab-projects')) {
35
+ await create().parseAsync(Bun.argv)
36
+ }
37
+
38
+ export default create
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env bun run
2
+
3
+ import { Command } from 'commander'
4
+ import { whoami, type User } from "../lib/gitlab"
5
+ import { isMain } from '../lib/is_main'
6
+
7
+ export function create(): Command {
8
+ const program = new Command()
9
+ program
10
+ .name('whoami')
11
+ .description('get GitLab user information for current user')
12
+ .option('-v, --verbose', 'Verbose output')
13
+ .action(async (options) => {
14
+ const user: User = await whoami()
15
+ if (!user) {
16
+ console.error(`No user!`)
17
+ process.exit(1)
18
+ }
19
+ if (options.verbose) {
20
+ console.log(user)
21
+ process.exit(0)
22
+ }
23
+ else {
24
+ console.log(user.username)
25
+ }
26
+ })
27
+ return program
28
+ }
29
+
30
+ if (isMain('git-lab-whoami')) {
31
+ await create().parseAsync(Bun.argv)
32
+ }
33
+
34
+ export default create
package/bin/git-lab.ts ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bun run
2
+
3
+ import { Command } from 'commander'
4
+ import { isMain } from '../lib/is_main'
5
+ import whoami from './git-lab-whoami'
6
+ import projects from './git-lab-projects'
7
+
8
+ export function create(): Command {
9
+ const program = new Command()
10
+ program
11
+ .name('lab')
12
+ .description('A set of commands for working with GitLab')
13
+ .addCommand(whoami())
14
+ .addCommand(projects())
15
+ return program
16
+ }
17
+
18
+ if (isMain('git-jira')) {
19
+ await create().parseAsync(Bun.argv)
20
+ }
21
+
22
+ export default create
package/bin/gitj.ts CHANGED
@@ -1,24 +1,27 @@
1
1
  #!/usr/bin/env bun run
2
2
 
3
- // This is the root of the CLI. It's job is to parse the command
3
+ import bump from './git-bump'
4
+ import jira from './git-jira'
5
+ import lab from './git-lab'
6
+
7
+ // This is the root of the CLI. It's a proxy for git and not strictly
8
+ // necessary, but it's useful to have for testing
9
+ // It's job is to parse the first command
4
10
  // from the command line and then call the appropriate subcommand.
5
11
 
6
12
  import { Command } from 'commander'
7
- import { isMain } from '../lib/is_main'
8
-
9
- if (isMain('gitj')) {
10
-
11
- const program = new Command()
12
- const bump = (await import('./git-bump')).create()
13
-
14
- program
15
- .executableDir('./bin')
16
- .addCommand(bump)
17
- .command('jira', 'A collection of jira utility commands', { executableFile: 'git-jira' })
18
13
 
14
+ export function create(): Command {
15
+ const program: Command = new Command()
19
16
  program
17
+ .addCommand(bump())
18
+ .addCommand(jira())
19
+ .addCommand(lab())
20
20
  .action(() => {
21
21
  program.help()
22
22
  })
23
- .parse(Bun.argv)
23
+ return program
24
24
  }
25
+
26
+ const command = create()
27
+ await command.parseAsync(Bun.argv)
package/build.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { BuildOutput } from 'bun'
2
+ import { glob } from 'glob'
3
+
4
+ const result: BuildOutput = await Bun.build({
5
+ entrypoints: ['./index.ts', ...glob.sync('./bin/*.ts')],
6
+ outdir: './dist',
7
+ target: 'bun'
8
+ })
9
+
10
+ if (result.success) {
11
+ console.log('Build succeeded')
12
+ process.exit(0)
13
+ } else {
14
+ console.error('Build failed')
15
+ console.log(result)
16
+ process.exit(1)
17
+ }
package/bun.lockb CHANGED
Binary file
@@ -20,50 +20,6 @@ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports,
20
20
  var __require = (id) => {
21
21
  return import.meta.require(id);
22
22
  };
23
- var __export = (target, all) => {
24
- for (var name in all)
25
- __defProp(target, name, {
26
- get: all[name],
27
- enumerable: true,
28
- configurable: true,
29
- set: (newValue) => all[name] = () => newValue
30
- });
31
- };
32
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
33
-
34
- // lib/spawn.ts
35
- async function doCommand(args) {
36
- const proc = Bun.spawn(args);
37
- const stdout = new Response(proc.stdout);
38
- const stderr = new Response(proc.stderr);
39
- const [out, err] = await Promise.all([stdout.text(), stderr.text()]);
40
- if (err)
41
- console.error(err);
42
- return out.trim();
43
- }
44
- var init_spawn = __esm(() => {
45
- });
46
-
47
- // lib/git.ts
48
- async function getConfig(key) {
49
- return doCommand(["git", "config", "--get", key]);
50
- }
51
- async function getJiraConfig() {
52
- const host = await getConfig("jira.host");
53
- const user = await getConfig("jira.user") || await getConfig("user.email");
54
- const pat = await getConfig("jira.pat");
55
- const token = Buffer.from(`${user}:${pat}`).toString("base64");
56
- return { host, token };
57
- }
58
- async function createBranch(name) {
59
- return doCommand(["git", "checkout", "-b", name]);
60
- }
61
- async function getCurrentBranch() {
62
- return doCommand(["git", "rev-parse", "--abbrev-ref", "HEAD"]);
63
- }
64
- var init_git = __esm(() => {
65
- init_spawn();
66
- });
67
23
 
68
24
  // node_modules/commander/lib/error.js
69
25
  var require_error = __commonJS((exports) => {
@@ -680,7 +636,7 @@ var require_command = __commonJS((exports) => {
680
636
  var childProcess = import.meta.require("child_process");
681
637
  var path = import.meta.require("path");
682
638
  var fs = import.meta.require("fs");
683
- var process2 = import.meta.require("process");
639
+ var process = import.meta.require("process");
684
640
  var { Argument, humanReadableArgName } = require_argument();
685
641
  var { CommanderError } = require_error();
686
642
  var { Help } = require_help();
@@ -721,10 +677,10 @@ var require_command = __commonJS((exports) => {
721
677
  this._showHelpAfterError = false;
722
678
  this._showSuggestionAfterError = true;
723
679
  this._outputConfiguration = {
724
- writeOut: (str) => process2.stdout.write(str),
725
- writeErr: (str) => process2.stderr.write(str),
726
- getOutHelpWidth: () => process2.stdout.isTTY ? process2.stdout.columns : undefined,
727
- getErrHelpWidth: () => process2.stderr.isTTY ? process2.stderr.columns : undefined,
680
+ writeOut: (str) => process.stdout.write(str),
681
+ writeErr: (str) => process.stderr.write(str),
682
+ getOutHelpWidth: () => process.stdout.isTTY ? process.stdout.columns : undefined,
683
+ getErrHelpWidth: () => process.stderr.isTTY ? process.stderr.columns : undefined,
728
684
  outputError: (str, write) => write(str)
729
685
  };
730
686
  this._hidden = false;
@@ -907,7 +863,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
907
863
  if (this._exitCallback) {
908
864
  this._exitCallback(new CommanderError(exitCode, code, message));
909
865
  }
910
- process2.exit(exitCode);
866
+ process.exit(exitCode);
911
867
  }
912
868
  action(fn) {
913
869
  const listener = (args) => {
@@ -1072,8 +1028,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
1072
1028
  }
1073
1029
  parseOptions = parseOptions || {};
1074
1030
  if (argv === undefined) {
1075
- argv = process2.argv;
1076
- if (process2.versions && process2.versions.electron) {
1031
+ argv = process.argv;
1032
+ if (process.versions && process.versions.electron) {
1077
1033
  parseOptions.from = "electron";
1078
1034
  }
1079
1035
  }
@@ -1086,7 +1042,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1086
1042
  userArgs = argv.slice(2);
1087
1043
  break;
1088
1044
  case "electron":
1089
- if (process2.defaultApp) {
1045
+ if (process.defaultApp) {
1090
1046
  this._scriptPath = argv[1];
1091
1047
  userArgs = argv.slice(2);
1092
1048
  } else {
@@ -1154,23 +1110,23 @@ Expecting one of '${allowedValues.join("', '")}'`);
1154
1110
  }
1155
1111
  launchWithNode = sourceExt.includes(path.extname(executableFile));
1156
1112
  let proc;
1157
- if (process2.platform !== "win32") {
1113
+ if (process.platform !== "win32") {
1158
1114
  if (launchWithNode) {
1159
1115
  args.unshift(executableFile);
1160
- args = incrementNodeInspectorPort(process2.execArgv).concat(args);
1161
- proc = childProcess.spawn(process2.argv[0], args, { stdio: "inherit" });
1116
+ args = incrementNodeInspectorPort(process.execArgv).concat(args);
1117
+ proc = childProcess.spawn(process.argv[0], args, { stdio: "inherit" });
1162
1118
  } else {
1163
1119
  proc = childProcess.spawn(executableFile, args, { stdio: "inherit" });
1164
1120
  }
1165
1121
  } else {
1166
1122
  args.unshift(executableFile);
1167
- args = incrementNodeInspectorPort(process2.execArgv).concat(args);
1168
- proc = childProcess.spawn(process2.execPath, args, { stdio: "inherit" });
1123
+ args = incrementNodeInspectorPort(process.execArgv).concat(args);
1124
+ proc = childProcess.spawn(process.execPath, args, { stdio: "inherit" });
1169
1125
  }
1170
1126
  if (!proc.killed) {
1171
1127
  const signals = ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"];
1172
1128
  signals.forEach((signal) => {
1173
- process2.on(signal, () => {
1129
+ process.on(signal, () => {
1174
1130
  if (proc.killed === false && proc.exitCode === null) {
1175
1131
  proc.kill(signal);
1176
1132
  }
@@ -1179,10 +1135,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
1179
1135
  }
1180
1136
  const exitCallback = this._exitCallback;
1181
1137
  if (!exitCallback) {
1182
- proc.on("close", process2.exit.bind(process2));
1138
+ proc.on("close", process.exit.bind(process));
1183
1139
  } else {
1184
1140
  proc.on("close", () => {
1185
- exitCallback(new CommanderError(process2.exitCode || 0, "commander.executeSubCommandAsync", "(close)"));
1141
+ exitCallback(new CommanderError(process.exitCode || 0, "commander.executeSubCommandAsync", "(close)"));
1186
1142
  });
1187
1143
  }
1188
1144
  proc.on("error", (err) => {
@@ -1197,7 +1153,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1197
1153
  throw new Error(`'${executableFile}' not executable`);
1198
1154
  }
1199
1155
  if (!exitCallback) {
1200
- process2.exit(1);
1156
+ process.exit(1);
1201
1157
  } else {
1202
1158
  const wrappedError = new CommanderError(1, "commander.executeSubCommandAsync", "(error)");
1203
1159
  wrappedError.nestedError = err;
@@ -1549,11 +1505,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1549
1505
  }
1550
1506
  _parseOptionsEnv() {
1551
1507
  this.options.forEach((option) => {
1552
- if (option.envVar && (option.envVar in process2.env)) {
1508
+ if (option.envVar && (option.envVar in process.env)) {
1553
1509
  const optionKey = option.attributeName();
1554
1510
  if (this.getOptionValue(optionKey) === undefined || ["default", "config", "env"].includes(this.getOptionValueSource(optionKey))) {
1555
1511
  if (option.required || option.optional) {
1556
- this.emit(`optionEnv:${option.name()}`, process2.env[option.envVar]);
1512
+ this.emit(`optionEnv:${option.name()}`, process.env[option.envVar]);
1557
1513
  } else {
1558
1514
  this.emit(`optionEnv:${option.name()}`);
1559
1515
  }
@@ -1779,7 +1735,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1779
1735
  }
1780
1736
  help(contextOptions) {
1781
1737
  this.outputHelp(contextOptions);
1782
- let exitCode = process2.exitCode || 0;
1738
+ let exitCode = process.exitCode || 0;
1783
1739
  if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) {
1784
1740
  exitCode = 1;
1785
1741
  }
@@ -1827,24 +1783,60 @@ var require_commander = __commonJS((exports, module) => {
1827
1783
  exports.Option = Option;
1828
1784
  });
1829
1785
 
1786
+ // lib/spawn.ts
1787
+ async function spawn(args, options = defaultOptions) {
1788
+ const proc = Bun.spawn(args, { stdout: "pipe", stderr: "pipe" });
1789
+ const stdout = new Response(proc.stdout);
1790
+ const stderr = new Response(proc.stderr);
1791
+ const [out, err, exitCode, signal] = await Promise.all([stdout.text(), stderr.text(), proc.exitCode, proc.signalCode]);
1792
+ let code = 0;
1793
+ if (exitCode !== null) {
1794
+ code = exitCode;
1795
+ }
1796
+ if (!out && !err && !options.expectQuiet) {
1797
+ console.warn(`No output from ${args.join(" ")}`);
1798
+ }
1799
+ return { out: out.trim(), err: err.trim(), code };
1800
+ }
1801
+ async function doCommand(args) {
1802
+ const { out, err } = await spawn(args);
1803
+ if (err)
1804
+ console.error(err);
1805
+ return out;
1806
+ }
1807
+ var defaultOptions = {
1808
+ expectQuiet: false
1809
+ };
1810
+
1811
+ // lib/git.ts
1812
+ async function getConfig(key) {
1813
+ return doCommand(["git", "config", "--get", key]);
1814
+ }
1815
+ async function createBranch(name) {
1816
+ return doCommand(["git", "checkout", "-b", name]);
1817
+ }
1818
+ async function getCurrentBranch() {
1819
+ return doCommand(["git", "rev-parse", "--abbrev-ref", "HEAD"]);
1820
+ }
1821
+ async function getRemote() {
1822
+ return doCommand(["git", "ls-remote", "--get-url", "origin"]);
1823
+ }
1824
+
1830
1825
  // node_modules/commander/esm.mjs
1831
- var import_, program, createCommand, createArgument, createOption, CommanderError, InvalidArgumentError, InvalidOptionArgumentError, Command, Argument, Option, Help;
1832
- var init_esm = __esm(() => {
1833
- import_ = __toESM(require_commander(), 1);
1834
- ({
1835
- program,
1836
- createCommand,
1837
- createArgument,
1838
- createOption,
1839
- CommanderError,
1840
- InvalidArgumentError,
1841
- InvalidOptionArgumentError,
1842
- Command,
1843
- Argument,
1844
- Option,
1845
- Help
1846
- } = import_.default);
1847
- });
1826
+ var import_ = __toESM(require_commander(), 1);
1827
+ var {
1828
+ program,
1829
+ createCommand,
1830
+ createArgument,
1831
+ createOption,
1832
+ CommanderError,
1833
+ InvalidArgumentError,
1834
+ InvalidOptionArgumentError,
1835
+ Command,
1836
+ Argument,
1837
+ Option,
1838
+ Help
1839
+ } = import_.default;
1848
1840
 
1849
1841
  // lib/is_main.ts
1850
1842
  import path from "path";
@@ -1852,26 +1844,11 @@ function isMain(self) {
1852
1844
  const exe = path.basename(Bun.argv[1]).split(".")[0];
1853
1845
  return exe == self || import.meta.main;
1854
1846
  }
1855
- var init_is_main = __esm(() => {
1856
- });
1857
1847
 
1858
1848
  // bin/git-bump.ts
1859
- var exports_git_bump = {};
1860
- __export(exports_git_bump, {
1861
- default: () => {
1862
- {
1863
- return git_bump_default;
1864
- }
1865
- },
1866
- create: () => {
1867
- {
1868
- return create;
1869
- }
1870
- }
1871
- });
1872
1849
  function create() {
1873
1850
  const program2 = new Command;
1874
- program2.name("bump").action(async () => {
1851
+ program2.name("bump").description("Bump the version number in the current branch").action(async () => {
1875
1852
  const currentBranch = await getCurrentBranch();
1876
1853
  let stem = currentBranch;
1877
1854
  let version = 1;
@@ -1885,18 +1862,10 @@ function create() {
1885
1862
  });
1886
1863
  return program2;
1887
1864
  }
1888
- var git_bump_default;
1889
- var init_git_bump = __esm(() => {
1890
- init_git();
1891
- init_esm();
1892
- init_is_main();
1893
- if (isMain("git-bump")) {
1894
- create().parse(process.argv);
1895
- }
1896
- git_bump_default = create;
1897
- });
1898
- init_git_bump();
1899
-
1865
+ if (isMain("git-bump")) {
1866
+ await create().parseAsync(Bun.argv);
1867
+ }
1868
+ var git_bump_default = create;
1900
1869
  export {
1901
1870
  git_bump_default as default,
1902
1871
  create