ya-git-jira 1.2.0 → 1.4.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.
Files changed (48) hide show
  1. package/README.md +22 -3
  2. package/bin/git-bump.ts +5 -4
  3. package/bin/{git-jira-issues.ts → git-jira-issue-list.ts} +8 -7
  4. package/bin/git-jira-issue-show.ts +37 -0
  5. package/bin/git-jira-issue.ts +13 -23
  6. package/bin/git-jira-start.ts +6 -5
  7. package/bin/git-jira.ts +12 -15
  8. package/bin/git-lab-group-list.ts +32 -0
  9. package/bin/git-lab-group.ts +22 -0
  10. package/bin/git-lab-merge-active.ts +35 -0
  11. package/bin/git-lab-merge-todo.ts +33 -0
  12. package/bin/git-lab-merge-train.ts +19 -0
  13. package/bin/git-lab-merge.ts +22 -0
  14. package/bin/git-lab-namespace-list.ts +23 -0
  15. package/bin/git-lab-namespace.ts +22 -0
  16. package/bin/git-lab-project-list.ts +38 -0
  17. package/bin/git-lab-project-pipeline-list.ts +40 -0
  18. package/bin/git-lab-project-pipeline.ts +22 -0
  19. package/bin/git-lab-project-whereami.ts +40 -0
  20. package/bin/git-lab-project.ts +26 -0
  21. package/bin/git-lab-whoami.ts +34 -0
  22. package/bin/git-lab.ts +30 -0
  23. package/bin/gitj.ts +17 -14
  24. package/build.ts +17 -0
  25. package/bun.lockb +0 -0
  26. package/dist/bin/git-bump.js +79 -110
  27. package/dist/bin/git-jira-issue.js +55 -75
  28. package/dist/bin/git-jira-issues.js +74 -95
  29. package/dist/bin/git-jira-start.js +56 -78
  30. package/dist/bin/git-jira.js +82 -146
  31. package/dist/bin/git-lab-mergetrain.js +1906 -0
  32. package/dist/bin/git-lab-projects.js +1935 -0
  33. package/dist/bin/git-lab-whoami.js +1932 -0
  34. package/dist/bin/git-lab.js +1969 -0
  35. package/dist/bin/gitj.js +306 -93
  36. package/dist/index.js +106 -47
  37. package/index.ts +2 -0
  38. package/lib/git.ts +4 -13
  39. package/lib/gitlab.ts +209 -0
  40. package/lib/is_main.ts +21 -2
  41. package/lib/jira.ts +36 -22
  42. package/lib/json.ts +6 -0
  43. package/lib/spawn.ts +30 -4
  44. package/package.json +27 -8
  45. package/tests/all-help.test.ts +19 -0
  46. package/tests/git.test.ts +25 -0
  47. package/tests/gitj.test.ts +43 -0
  48. package/dist/bin/bundo.js +0 -45
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
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env bun run
1
+ #!/usr/bin/env bun
2
2
 
3
3
  import { createBranch, getCurrentBranch } from "../lib/git"
4
4
  import { Command } from 'commander'
@@ -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
 
@@ -26,8 +27,8 @@ export function create(): Command {
26
27
  return program
27
28
  }
28
29
 
30
+ export default create
31
+
29
32
  if (isMain('git-bump')) {
30
- create().parse(process.argv)
33
+ await create().parseAsync(Bun.argv)
31
34
  }
32
-
33
- export default create
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env bun run
1
+ #!/usr/bin/env bun
2
2
 
3
3
  import { Command } from 'commander'
4
4
  import { myUnresolvedIssues } from "../lib/jira"
@@ -7,8 +7,9 @@ import { isMain } from '../lib/is_main'
7
7
  export function create(): Command {
8
8
  const program = new Command()
9
9
  program
10
- .name('issues')
11
- .action(async (options) => {
10
+ .name('list')
11
+ .description('List your unresolved issues')
12
+ .action(async () => {
12
13
  const issues = await myUnresolvedIssues()
13
14
  console.log(`You have ${issues.length} unresolved issues`)
14
15
  issues.forEach(issue => {
@@ -18,8 +19,8 @@ export function create(): Command {
18
19
  return program
19
20
  }
20
21
 
21
- if (isMain('git-jira-issues')) {
22
- create().parse(process.argv)
23
- }
24
-
25
22
  export default create
23
+
24
+ if (isMain('git-jira-issue-list')) {
25
+ await create().parseAsync(Bun.argv)
26
+ }
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { getIssue } from "../lib/jira"
5
+ import { isMain } from '../lib/is_main'
6
+ import { getJiraConfig } from '../lib/jira'
7
+
8
+ export function create(): Command {
9
+ const program = new Command()
10
+ program
11
+ .name('show')
12
+ .description('Show information about one issue')
13
+ .argument('issue', 'Issue ID')
14
+ .option('-v, --verbose', 'Verbose output')
15
+ .action(async (issueId: string, options) => {
16
+ const issue = await getIssue(issueId)
17
+ if (!issue) {
18
+ console.error(`Issue ${issueId} not found`)
19
+ process.exit(1)
20
+ }
21
+ if (options.verbose) {
22
+ console.log(issue)
23
+ } else {
24
+ const { host } = await getJiraConfig()
25
+ const summary = issue.fields.summary
26
+ const url = `https://${host}/browse/${issueId}`
27
+ console.log({ issueId, summary, url })
28
+ }
29
+ })
30
+ return program
31
+ }
32
+
33
+ export default create
34
+
35
+ if (isMain('git-jira-issue-show')) {
36
+ await create().parseAsync(Bun.argv)
37
+ }
@@ -1,35 +1,25 @@
1
- #!/usr/bin/env bun run
1
+ #!/usr/bin/env bun
2
2
 
3
3
  import { Command } from 'commander'
4
- import { getIssue } from "../lib/jira"
5
4
  import { isMain } from '../lib/is_main'
6
5
 
7
- export function create() {
6
+ import list from './git-jira-issue-list'
7
+ import show from './git-jira-issue-show'
8
+
9
+ export function create(): Command {
8
10
  const program = new Command()
9
11
  program
10
12
  .name('issue')
11
- .argument('issue', 'Issue ID')
12
- .option('-v, --verbose', 'Verbose output')
13
- .option('-u, --url', 'Show the URL of the issue')
14
- .action(async (issueId: string, options) => {
15
- const issue = await getIssue(issueId)
16
- if (!issue) {
17
- console.error(`Issue ${issueId} not found`)
18
- process.exit(1)
19
- }
20
- if (options.verbose) {
21
- console.log(issue)
22
- process.exit(0)
23
- }
24
- if (options.url) {
25
- console.log(issue.self)
26
- }
27
- })
13
+ .description('Commands for working with issues')
14
+ .addCommand(list())
15
+ .addCommand(show())
16
+ .action(() => program.help()
17
+ )
28
18
  return program
29
19
  }
30
20
 
21
+ export default create
22
+
31
23
  if (isMain('git-jira-issue')) {
32
- create().parse(process.argv)
24
+ await create().parseAsync(Bun.argv)
33
25
  }
34
-
35
- export default create
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env bun run
1
+ #!/usr/bin/env bun
2
2
 
3
3
  import { Command } from 'commander'
4
4
  import { createBranch } from "../lib/git"
@@ -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)
@@ -31,8 +32,8 @@ export function create(): Command {
31
32
  return program
32
33
  }
33
34
 
34
- if (isMain('git-jira-issues')) {
35
- create().parse(process.argv)
36
- }
37
-
38
35
  export default create
36
+
37
+ if (isMain('git-jira-start')) {
38
+ await create().parseAsync(Bun.argv)
39
+ }
package/bin/git-jira.ts CHANGED
@@ -1,27 +1,24 @@
1
- #!/usr/bin/env bun run
1
+ #!/usr/bin/env bun
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-issue-list'
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('Commands for working with Jira')
14
+ .addCommand(start())
15
+ .addCommand(issue())
16
+ .addCommand(issues())
20
17
  return program
21
18
  }
22
19
 
20
+ export default create
21
+
23
22
  if (isMain('git-jira')) {
24
- create().parse(process.argv)
23
+ await create().parseAsync(Bun.argv)
25
24
  }
26
-
27
- export default create
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { isMain } from '../lib/is_main'
5
+ import { getGroups } from '../lib/gitlab'
6
+
7
+ export function create(): Command {
8
+ const program = new Command()
9
+ program
10
+ .name('list')
11
+ .description('List groups for the current user')
12
+ .option("-v, --verbose", "Verbose output")
13
+ .action(async (options) => {
14
+ const groups = await getGroups()
15
+ if (options.verbose)
16
+ console.log(groups)
17
+ else {
18
+ const filtered = groups.map(g => {
19
+ const { id, name, full_path } = g
20
+ return { id, name, full_path }
21
+ })
22
+ console.log(filtered)
23
+ }
24
+ })
25
+ return program
26
+ }
27
+
28
+ export default create
29
+
30
+ if (isMain('git-lab-group-list')) {
31
+ await create().parseAsync(Bun.argv)
32
+ }
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { isMain } from '../lib/is_main'
5
+
6
+ import list from './git-lab-group-list'
7
+
8
+ export function create(): Command {
9
+ const program = new Command()
10
+ program
11
+ .name('group')
12
+ .description('Commands for working with GitLab groups')
13
+ .addCommand(list())
14
+ .action(() => program.help())
15
+ return program
16
+ }
17
+
18
+ export default create
19
+
20
+ if (isMain('git-lab-group')) {
21
+ await create().parseAsync(Bun.argv)
22
+ }
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bun
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('active')
11
+ .description('List my active MRs')
12
+ .option('-v, --verbose', 'Verbose output')
13
+
14
+ .action(async (options) => {
15
+ const user: User = await whoami()
16
+ if (!user) {
17
+ console.error(`No user!`)
18
+ process.exit(1)
19
+ }
20
+ if (options.verbose) {
21
+ console.log(user)
22
+ process.exit(0)
23
+ }
24
+ else {
25
+ console.log(user.username)
26
+ }
27
+ })
28
+ return program
29
+ }
30
+
31
+ export default create
32
+
33
+ if (isMain('git-lab-merge-active')) {
34
+ await create().parseAsync(Bun.argv)
35
+ }
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { getMergeRequestsAssignedToMe, type MergeRequest } 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('todo')
11
+ .description('MRs needing my review')
12
+ .option('-v, --verbose', 'Verbose output')
13
+ .action(async (options) => {
14
+ const mrs: MergeRequest[] = await getMergeRequestsAssignedToMe()
15
+ if (options.verbose) {
16
+ console.log(mrs)
17
+ }
18
+ else {
19
+ const filtered = mrs.map(mr => {
20
+ const { id, title, web_url, source_branch, target_branch, merge_status } = mr
21
+ return { id, title, web_url, source_branch, target_branch, merge_status }
22
+ })
23
+ console.log(filtered)
24
+ }
25
+ })
26
+ return program
27
+ }
28
+
29
+ export default create
30
+
31
+ if (isMain('git-lab-merge-todo')) {
32
+ await create().parseAsync(Bun.argv)
33
+ }
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { isMain } from '../lib/is_main'
5
+
6
+ export function create(): Command {
7
+ const program = new Command()
8
+ program
9
+ .name('train')
10
+ .description('Commands for working with GitLab merge trains')
11
+ .action(() => program.help())
12
+ return program
13
+ }
14
+
15
+ export default create
16
+
17
+ if (isMain('git-lab-merge-train')) {
18
+ await create().parseAsync(Bun.argv)
19
+ }
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { isMain } from '../lib/is_main'
5
+
6
+ import todo from './git-lab-merge-todo'
7
+
8
+ export function create(): Command {
9
+ const program = new Command()
10
+ program
11
+ .name('merge')
12
+ .description('Commands for working with GitLab merge requests')
13
+ .addCommand(todo())
14
+ .action(() => program.help())
15
+ return program
16
+ }
17
+
18
+ export default create
19
+
20
+ if (isMain('git-lab-merge')) {
21
+ await create().parseAsync(Bun.argv)
22
+ }
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { isMain } from '../lib/is_main'
5
+ import { getNamespaces } from '../lib/gitlab'
6
+
7
+ export function create(): Command {
8
+ const program = new Command()
9
+ program
10
+ .name('list')
11
+ .description('List namespaces for the current user')
12
+ .action(async () => {
13
+ const namespaces = await getNamespaces()
14
+ console.log(namespaces)
15
+ })
16
+ return program
17
+ }
18
+
19
+ export default create
20
+
21
+ if (isMain('git-lab-namespace-list')) {
22
+ await create().parseAsync(Bun.argv)
23
+ }
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { isMain } from '../lib/is_main'
5
+
6
+ import list from './git-lab-namespace-list'
7
+
8
+ export function create(): Command {
9
+ const program = new Command()
10
+ program
11
+ .name('namespace')
12
+ .description('Commands for working with GitLab namespaces')
13
+ .addCommand(list())
14
+ .action(() => program.help())
15
+ return program
16
+ }
17
+
18
+ export default create
19
+
20
+ if (isMain('git-lab-namespace')) {
21
+ await create().parseAsync(Bun.argv)
22
+ }
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bun
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('list')
11
+ .description('List projects for current user')
12
+ .option('-v, --verbose', 'Verbose output')
13
+ .option('-m, --match <match>', 'Match projects with paths containing <match>')
14
+ .action(async (options) => {
15
+ const projects: Array<Project> = await getProjects(options.match)
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
+ export default create
35
+
36
+ if (isMain('git-lab-project-list')) {
37
+ await create().parseAsync(Bun.argv)
38
+ }
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { getProjectPipelines, type Pipeline } 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('list')
11
+ .description('List recent successful pipelines')
12
+ .option('-v, --verbose', 'Verbose output')
13
+ .option('-d, --days <days>', 'Number of days to look back', '7')
14
+ .option('-s, --status <status>', 'Status of pipelines to list: success | runnning | ', 'success')
15
+ .action(async (options) => {
16
+ const pipelines: Array<Pipeline> = await getProjectPipelines(options)
17
+ console.debug(`pipelines: ${pipelines}`)
18
+ if (!pipelines) {
19
+ console.error(`No pipelines!`)
20
+ process.exit(1)
21
+ }
22
+ if (options.verbose) {
23
+ console.log(pipelines)
24
+ }
25
+ else {
26
+ let filtered = pipelines.map((p: Pipeline) => {
27
+ const { id, web_url, updated_at, ref, sha } = p
28
+ return { id, web_url, updated_at, ref, sha }
29
+ })
30
+ console.log(filtered)
31
+ }
32
+ })
33
+ return program
34
+ }
35
+
36
+ export default create
37
+
38
+ if (isMain('git-lab-project-pipeline-list')) {
39
+ await create().parseAsync(Bun.argv)
40
+ }
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { isMain } from '../lib/is_main'
5
+
6
+ import list from './git-lab-project-pipeline-list'
7
+
8
+ export function create(): Command {
9
+ const program = new Command()
10
+ program
11
+ .name('pipeline')
12
+ .description('Commands for working with GitLab pipelines')
13
+ .addCommand(list())
14
+ .action(() => program.help())
15
+ return program
16
+ }
17
+
18
+ export default create
19
+
20
+ if (isMain('git-lab-project-pipeline')) {
21
+ await create().parseAsync(Bun.argv)
22
+ }
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { findProject } from "../lib/gitlab"
5
+ import { getRemote } from '../lib/git'
6
+ import { isMain } from '../lib/is_main'
7
+
8
+ export function create(): Command {
9
+ const program = new Command()
10
+ program
11
+ .name('whereami')
12
+ .description('Show current project based on current directory')
13
+ .option('-v, --verbose', 'Verbose output')
14
+ .action(async (options) => {
15
+ const ssh_url = await getRemote();
16
+ if (!ssh_url) {
17
+ console.error(`No remote!`)
18
+ process.exit(1)
19
+ }
20
+ console.log(`Remote: ${ssh_url}`)
21
+ const project = await findProject(ssh_url);
22
+ if (!project) {
23
+ console.error(`No project!`)
24
+ process.exit(1)
25
+ }
26
+ if (options.verbose) {
27
+ console.log(project)
28
+ } else {
29
+ const { id, name, path_with_namespace, ssh_url_to_repo } = project
30
+ console.log({id, name, path_with_namespace, ssh_url_to_repo })
31
+ }
32
+ })
33
+ return program
34
+ }
35
+
36
+ export default create
37
+
38
+ if (isMain('git-lab-project-whereami')) {
39
+ await create().parseAsync(Bun.argv)
40
+ }
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { Command } from 'commander'
4
+ import { isMain } from '../lib/is_main'
5
+
6
+ import list from './git-lab-project-list'
7
+ import whereami from './git-lab-project-whereami'
8
+
9
+ export function create(): Command {
10
+ const program = new Command()
11
+ program
12
+ .name('projects')
13
+ .description('Commands for working with GitLab projects')
14
+ .addCommand(list())
15
+ .addCommand(whereami())
16
+ .action(() => {
17
+ program.help()
18
+ })
19
+ return program
20
+ }
21
+
22
+ export default create
23
+
24
+ if (isMain('git-lab-project')) {
25
+ await create().parseAsync(Bun.argv)
26
+ }
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env bun
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
+ export default create
31
+
32
+ if (isMain('git-lab-whoami')) {
33
+ await create().parseAsync(Bun.argv)
34
+ }