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 +22 -3
- package/bin/git-bump.ts +2 -1
- package/bin/git-jira-issue.ts +6 -3
- package/bin/git-jira-issues.ts +2 -1
- package/bin/git-jira-start.ts +2 -1
- package/bin/git-jira.ts +9 -12
- package/bin/git-lab-projects.ts +38 -0
- package/bin/git-lab-whoami.ts +34 -0
- package/bin/git-lab.ts +22 -0
- package/bin/gitj.ts +16 -13
- package/build.ts +17 -0
- package/bun.lockb +0 -0
- package/dist/bin/git-bump.js +79 -110
- package/dist/bin/git-jira-issue.js +55 -75
- package/dist/bin/git-jira-issues.js +74 -95
- package/dist/bin/git-jira-start.js +56 -78
- package/dist/bin/git-jira.js +82 -146
- package/dist/bin/git-lab-mergetrain.js +1906 -0
- package/dist/bin/git-lab-projects.js +1935 -0
- package/dist/bin/git-lab-whoami.js +1932 -0
- package/dist/bin/git-lab.js +1969 -0
- package/dist/bin/gitj.js +306 -93
- package/dist/index.js +106 -47
- package/index.ts +2 -0
- package/lib/git.ts +4 -13
- package/lib/gitlab.ts +86 -0
- package/lib/jira.ts +24 -15
- package/lib/json.ts +6 -0
- package/lib/spawn.ts +30 -4
- package/package.json +14 -7
- package/tests/git.test.ts +25 -0
- package/tests/gitj.test.ts +43 -0
- package/dist/bin/bundo.js +0 -45
package/lib/gitlab.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { getConfig, getRemote } from "./git"
|
|
2
|
+
import type { JSONValue } from "./json"
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
export interface GitlabConfig {
|
|
6
|
+
host: string
|
|
7
|
+
user: string
|
|
8
|
+
token: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function getGitlabConfig(): Promise<GitlabConfig> {
|
|
12
|
+
const host = await getConfig("gitlab.host")
|
|
13
|
+
if (!host) throw new Error("gitlab.host not in git config")
|
|
14
|
+
const user = await getConfig("user.email")
|
|
15
|
+
if (!user) throw new Error("user.email not in git config")
|
|
16
|
+
const token = await getConfig("gitlab.token")
|
|
17
|
+
if (!token) throw new Error("gitlab.token not in git config")
|
|
18
|
+
return { host, user, token }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function get(endpoint: string): Promise<JSONValue> {
|
|
22
|
+
const method = "GET"
|
|
23
|
+
const { host, token } = await getGitlabConfig()
|
|
24
|
+
const base = `https://${host}/api/v4`
|
|
25
|
+
const uri = `${base}/${endpoint}`
|
|
26
|
+
const headers = new Headers()
|
|
27
|
+
headers.append("Accept", "application/json")
|
|
28
|
+
headers.append('Private-Token', token)
|
|
29
|
+
const options = {
|
|
30
|
+
method,
|
|
31
|
+
headers,
|
|
32
|
+
}
|
|
33
|
+
const request = new Request(uri, options)
|
|
34
|
+
const response = await fetch(request)
|
|
35
|
+
return await response.json()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type User = JSONValue & {
|
|
39
|
+
id: number
|
|
40
|
+
name: string
|
|
41
|
+
username: string
|
|
42
|
+
email: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function whoami(): Promise<User> {
|
|
46
|
+
return await get("/user") as User
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type Project = JSONValue & {
|
|
50
|
+
id: number
|
|
51
|
+
name: string
|
|
52
|
+
path: string
|
|
53
|
+
path_with_namespace: string
|
|
54
|
+
visibility: string
|
|
55
|
+
ssh_url_to_repo: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function getProjects(paths: string[]): Promise<Array<Project>> {
|
|
59
|
+
let search: string = ""
|
|
60
|
+
if (paths.length > 0) {
|
|
61
|
+
search = '&search=' + paths.join(",")
|
|
62
|
+
}
|
|
63
|
+
return await get(`/projects?visibility=private&membership=true&simple=true${search}`) as Array<Project>
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// git@gitlab.com:etagen-internal/linear-generator-config.git
|
|
67
|
+
export async function findProject(ssh_url: string): Promise<Project> {
|
|
68
|
+
const parts = ssh_url.split(':')
|
|
69
|
+
if (parts.length != 2) {
|
|
70
|
+
throw new Error(`${ssh_url} is invalid, could not be split into two parts at :`)
|
|
71
|
+
}
|
|
72
|
+
const name = path.basename(parts[1], '.git')
|
|
73
|
+
|
|
74
|
+
const projects = await getProjects([name])
|
|
75
|
+
const project = projects.find((p: Project): boolean => {
|
|
76
|
+
return p.ssh_url_to_repo === ssh_url
|
|
77
|
+
})
|
|
78
|
+
if (!project) {
|
|
79
|
+
throw new Error(`No project with ssh_url_to_repo ${ssh_url} found`)
|
|
80
|
+
}
|
|
81
|
+
return project
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function getMergeRequest(id: string): Promise<JSONValue> {
|
|
85
|
+
return await get(`/merge_requests/${id}`)
|
|
86
|
+
}
|
package/lib/jira.ts
CHANGED
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import { getConfig } from "../lib/git"
|
|
3
|
+
import type { JSONValue } from "../lib/json"
|
|
3
4
|
|
|
4
|
-
type JSONValue
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
export type Issue = JSONValue & {
|
|
6
|
+
key: string,
|
|
7
|
+
self: string,
|
|
8
|
+
fields: {
|
|
9
|
+
summary: string
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export interface JiraConfig {
|
|
13
|
+
host: string
|
|
14
|
+
token: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function getJiraConfig(): Promise<JiraConfig> {
|
|
18
|
+
const host = await getConfig("jira.host")
|
|
19
|
+
if (!host) throw new Error("jira.host not in git config")
|
|
20
|
+
const user = await getConfig("jira.user") || await getConfig("user.email")
|
|
21
|
+
if (!user) throw new Error("jira.user or user.email not in git config")
|
|
22
|
+
const pat = await getConfig("jira.pat")
|
|
23
|
+
if (!pat) throw new Error("jira.pat not in git config")
|
|
24
|
+
const token = Buffer.from(`${user}:${pat}`).toString('base64')
|
|
25
|
+
return { host, token }
|
|
26
|
+
}
|
|
10
27
|
|
|
11
28
|
export async function get(endpoint: string): Promise<JSONValue> {
|
|
12
29
|
const method = "GET"
|
|
@@ -26,14 +43,6 @@ export async function get(endpoint: string): Promise<JSONValue> {
|
|
|
26
43
|
return await response.json()
|
|
27
44
|
}
|
|
28
45
|
|
|
29
|
-
type Issue = JSONValue & {
|
|
30
|
-
key: string,
|
|
31
|
-
self: string,
|
|
32
|
-
fields: {
|
|
33
|
-
summary: string
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
46
|
export async function getIssue(issue: string): Promise<Issue> {
|
|
38
47
|
return await get(`/issue/${issue}`) as Issue
|
|
39
48
|
}
|
package/lib/json.ts
ADDED
package/lib/spawn.ts
CHANGED
|
@@ -1,10 +1,36 @@
|
|
|
1
|
+
import { Subprocess } from "bun"
|
|
1
2
|
|
|
3
|
+
export interface SpawnResult {
|
|
4
|
+
out: string
|
|
5
|
+
err: string
|
|
6
|
+
code: number
|
|
7
|
+
}
|
|
2
8
|
|
|
3
|
-
export
|
|
4
|
-
|
|
9
|
+
export interface SpawnOptions {
|
|
10
|
+
expectQuiet?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const defaultOptions: SpawnOptions = {
|
|
14
|
+
expectQuiet: false,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function spawn(args: string[], options: SpawnOptions = defaultOptions): Promise<SpawnResult> {
|
|
18
|
+
const proc: Subprocess<"ignore", "pipe", "pipe"> = Bun.spawn(args, { stdout: "pipe", stderr: "pipe" })
|
|
5
19
|
const stdout = new Response(proc.stdout)
|
|
6
20
|
const stderr = new Response(proc.stderr)
|
|
7
|
-
const [out, err] = await Promise.all([stdout.text(), stderr.text()])
|
|
21
|
+
const [out, err, exitCode, signal] = await Promise.all([stdout.text(), stderr.text(), proc.exitCode, proc.signalCode])
|
|
22
|
+
let code = 0
|
|
23
|
+
if (exitCode !== null) {
|
|
24
|
+
code = exitCode
|
|
25
|
+
}
|
|
26
|
+
if (!out && !err && !options.expectQuiet) {
|
|
27
|
+
console.warn(`No output from ${args.join(" ")}`)
|
|
28
|
+
}
|
|
29
|
+
return { out: out.trim(), err: err.trim(), code }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function doCommand(args: string[]): Promise<string> {
|
|
33
|
+
const { out, err } = await spawn(args)
|
|
8
34
|
if (err) console.error(err)
|
|
9
|
-
return out
|
|
35
|
+
return out
|
|
10
36
|
}
|
package/package.json
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ya-git-jira",
|
|
3
3
|
"description": "git extensions for Jira integration. Assumes bun is installed.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"
|
|
9
|
-
"git-jira": "dist/bin/git-jira.js",
|
|
10
|
-
"git-jira-start": "dist/bin/git-jira-start.js",
|
|
8
|
+
"git-bump": "dist/bin/git-bump.js",
|
|
9
|
+
"git-jira-issue": "dist/bin/git-jira-issue.js",
|
|
11
10
|
"git-jira-issues": "dist/bin/git-jira-issues.js",
|
|
12
|
-
"git-
|
|
11
|
+
"git-jira-start": "dist/bin/git-jira-start.js",
|
|
12
|
+
"git-jira": "dist/bin/git-jira.js",
|
|
13
|
+
"git-lab-projects": "dist/bin/git-lab-projects.js",
|
|
14
|
+
"git-lab-whoami": "dist/bin/git-lab-whoami.js",
|
|
15
|
+
"git-lab": "dist/bin/git-lab.js",
|
|
16
|
+
"gitj": "dist/bin/gitj.js"
|
|
13
17
|
},
|
|
14
18
|
"scripts": {
|
|
15
|
-
"preinstall": "bun build
|
|
19
|
+
"preinstall": "bun run build.ts",
|
|
20
|
+
"build": "bun run build.ts"
|
|
16
21
|
},
|
|
17
22
|
"devDependencies": {
|
|
18
23
|
"@types/commander": "^2.12.2",
|
|
@@ -25,7 +30,9 @@
|
|
|
25
30
|
"typescript": "^5.0.0"
|
|
26
31
|
},
|
|
27
32
|
"dependencies": {
|
|
28
|
-
"commander": "^11.0.0"
|
|
33
|
+
"commander": "^11.0.0",
|
|
34
|
+
"cuid": "^3.0.0",
|
|
35
|
+
"glob": "^10.3.4"
|
|
29
36
|
},
|
|
30
37
|
"main": "dist/start.js dist/bump.js",
|
|
31
38
|
"repository": {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { test, expect } from "bun:test"
|
|
2
|
+
import { findProject, getRemote } from ".."
|
|
3
|
+
|
|
4
|
+
test("testing works", async (): Promise<void> => {
|
|
5
|
+
expect(true).toBe(true)
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
test("getRemote", async (): Promise<void> => {
|
|
9
|
+
const url = await getRemote()
|
|
10
|
+
expect(url).toBe("git@github.com:jimlloyd/ya-git-jira.git")
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
test("findProject linear-generator", async (): Promise<void> => {
|
|
14
|
+
const ssh_url = "git@gitlab.com:etagen-internal/linear-generator.git"
|
|
15
|
+
const project = await findProject(ssh_url)
|
|
16
|
+
expect(project.ssh_url_to_repo).toBe(ssh_url)
|
|
17
|
+
expect(project.id).toBe(4053065)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test("findProject eta-lib/base", async (): Promise<void> => {
|
|
21
|
+
const ssh_url = "git@gitlab.com:etagen-internal/eta-lib/base.git"
|
|
22
|
+
const project = await findProject(ssh_url)
|
|
23
|
+
expect(project.ssh_url_to_repo).toBe(ssh_url)
|
|
24
|
+
expect(project.id).toBe(42470523)
|
|
25
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { test, expect, describe, beforeEach, afterEach } from "bun:test"
|
|
2
|
+
import { getCurrentBranch, spawn, type SpawnResult } from ".."
|
|
3
|
+
import cuid from "cuid"
|
|
4
|
+
|
|
5
|
+
test("testing works", async (): Promise<void> => {
|
|
6
|
+
expect(true).toBe(true)
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test("gitj works", async (): Promise<void> => {
|
|
10
|
+
const { out, code }: SpawnResult = await spawn(["bun", "run", "bin/gitj.ts"])
|
|
11
|
+
expect(out).toMatch("Usage:")
|
|
12
|
+
expect(out).toMatch("Bump the version number in the current branch")
|
|
13
|
+
expect(out).toMatch("A set of commands for working with Jira")
|
|
14
|
+
expect(code).toBe(0)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test("gitj bump --help works", async (): Promise<void> => {
|
|
18
|
+
const { out, code }: SpawnResult = await spawn(["bun", "run", "bin/gitj.ts", "bump", "--help"])
|
|
19
|
+
expect(out).toMatch("Usage:")
|
|
20
|
+
expect(out).toMatch("Bump the version number in the current branch")
|
|
21
|
+
expect(code).toBe(0)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
describe("gitj bump", (): void => {
|
|
25
|
+
let priorBranch: string
|
|
26
|
+
let testBranch = cuid()
|
|
27
|
+
beforeEach(async (): Promise<void> => {
|
|
28
|
+
priorBranch = await getCurrentBranch()
|
|
29
|
+
await spawn(["git", "checkout", "-b", testBranch])
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test("gitj bump works", async (): Promise<void> => {
|
|
33
|
+
const { code }: SpawnResult = await spawn(["bun", "run", "bin/gitj.ts", "bump"])
|
|
34
|
+
expect(code).toBe(0)
|
|
35
|
+
expect(await getCurrentBranch()).toMatch(testBranch + '.v1')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
afterEach(async (): Promise<void> => {
|
|
39
|
+
await spawn(["git", "checkout", priorBranch])
|
|
40
|
+
await spawn(["git", "branch", "-D", testBranch])
|
|
41
|
+
await spawn(["git", "branch", "-D", testBranch + '.v1'])
|
|
42
|
+
})
|
|
43
|
+
})
|
package/dist/bin/bundo.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun run
|
|
2
|
-
// @bun
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __toESM = (mod, isNodeMode, target) => {
|
|
9
|
-
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
10
|
-
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
11
|
-
for (let key of __getOwnPropNames(mod))
|
|
12
|
-
if (!__hasOwnProp.call(to, key))
|
|
13
|
-
__defProp(to, key, {
|
|
14
|
-
get: () => mod[key],
|
|
15
|
-
enumerable: true
|
|
16
|
-
});
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
20
|
-
var __require = (id) => {
|
|
21
|
-
return import.meta.require(id);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// lib/debug.ts
|
|
25
|
-
function dargv() {
|
|
26
|
-
if (Bun.env.DEBUG && Bun.env.DEBUG.toLowerCase().includes("gitjira")) {
|
|
27
|
-
console.log(Bun.argv);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// lib/spawn.ts
|
|
32
|
-
async function doCommand(args) {
|
|
33
|
-
const proc = Bun.spawn(args);
|
|
34
|
-
const stdout = new Response(proc.stdout);
|
|
35
|
-
const stderr = new Response(proc.stderr);
|
|
36
|
-
const [out, err] = await Promise.all([stdout.text(), stderr.text()]);
|
|
37
|
-
if (err)
|
|
38
|
-
console.error(err);
|
|
39
|
-
return out.trim();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// bin/bundo.ts
|
|
43
|
-
dargv();
|
|
44
|
-
var args = ["sh", "-c", ...Bun.argv.slice(2)];
|
|
45
|
-
await doCommand(args);
|