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.
- package/README.md +22 -3
- package/bin/git-bump.ts +5 -4
- package/bin/{git-jira-issues.ts → git-jira-issue-list.ts} +8 -7
- package/bin/git-jira-issue-show.ts +37 -0
- package/bin/git-jira-issue.ts +13 -23
- package/bin/git-jira-start.ts +6 -5
- package/bin/git-jira.ts +12 -15
- package/bin/git-lab-group-list.ts +32 -0
- package/bin/git-lab-group.ts +22 -0
- package/bin/git-lab-merge-active.ts +35 -0
- package/bin/git-lab-merge-todo.ts +33 -0
- package/bin/git-lab-merge-train.ts +19 -0
- package/bin/git-lab-merge.ts +22 -0
- package/bin/git-lab-namespace-list.ts +23 -0
- package/bin/git-lab-namespace.ts +22 -0
- package/bin/git-lab-project-list.ts +38 -0
- package/bin/git-lab-project-pipeline-list.ts +40 -0
- package/bin/git-lab-project-pipeline.ts +22 -0
- package/bin/git-lab-project-whereami.ts +40 -0
- package/bin/git-lab-project.ts +26 -0
- package/bin/git-lab-whoami.ts +34 -0
- package/bin/git-lab.ts +30 -0
- package/bin/gitj.ts +17 -14
- 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 +209 -0
- package/lib/is_main.ts +21 -2
- package/lib/jira.ts +36 -22
- package/lib/json.ts +6 -0
- package/lib/spawn.ts +30 -4
- package/package.json +27 -8
- package/tests/all-help.test.ts +19 -0
- 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,209 @@
|
|
|
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
|
+
function getNextLink(link: string | null): string | undefined {
|
|
22
|
+
if (!link) {
|
|
23
|
+
return undefined
|
|
24
|
+
}
|
|
25
|
+
const regex = /<([^>]+)>; rel="next"/
|
|
26
|
+
const match = link.match(regex)
|
|
27
|
+
const next = match ? match[1] : undefined
|
|
28
|
+
return next
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function gitlabApi(endpoint: string): Promise<JSONValue> {
|
|
32
|
+
if (endpoint.startsWith("/")) {
|
|
33
|
+
console.warn(`gitlabApi: endpoint ${endpoint} starts with /, removing it`)
|
|
34
|
+
endpoint = endpoint.slice(1)
|
|
35
|
+
}
|
|
36
|
+
const method = "GET"
|
|
37
|
+
const { host, token } = await getGitlabConfig()
|
|
38
|
+
const base = `https://${host}/api/v4`
|
|
39
|
+
const requested = 100
|
|
40
|
+
const sep = endpoint.includes('?') ? '&' : '?'
|
|
41
|
+
const uri = `${base}/${endpoint}${sep}per_page=${requested}`
|
|
42
|
+
const headers = new Headers()
|
|
43
|
+
headers.append("Accept", "application/json")
|
|
44
|
+
headers.append('Private-Token', token)
|
|
45
|
+
const options = {
|
|
46
|
+
method,
|
|
47
|
+
headers,
|
|
48
|
+
}
|
|
49
|
+
let request = new Request(uri, options)
|
|
50
|
+
const response = await fetch(request)
|
|
51
|
+
let link = getNextLink(response.headers.get('Link'))
|
|
52
|
+
let partial = (await response.json()) as Array<JSONValue>
|
|
53
|
+
let result: Array<JSONValue> = partial
|
|
54
|
+
while (partial.length == requested && link)
|
|
55
|
+
{
|
|
56
|
+
let request = new Request(link, options)
|
|
57
|
+
const next_response = await fetch(request)
|
|
58
|
+
link = getNextLink(next_response.headers.get('Link'))
|
|
59
|
+
partial = (await next_response.json()) as Array<JSONValue>
|
|
60
|
+
result = result.concat(partial)
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type User = JSONValue & {
|
|
66
|
+
id: number
|
|
67
|
+
name: string
|
|
68
|
+
username: string
|
|
69
|
+
email: string
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function whoami(): Promise<User> {
|
|
73
|
+
return await gitlabApi("user") as User
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type Project = JSONValue & {
|
|
77
|
+
id: number
|
|
78
|
+
name: string
|
|
79
|
+
path: string
|
|
80
|
+
path_with_namespace: string
|
|
81
|
+
visibility: string
|
|
82
|
+
ssh_url_to_repo: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function getProjects(match: string): Promise<Array<Project>> {
|
|
86
|
+
let search = ''
|
|
87
|
+
if (match) {
|
|
88
|
+
const m = encodeURIComponent(match)
|
|
89
|
+
search = `&search=${m}`
|
|
90
|
+
}
|
|
91
|
+
const projects = await gitlabApi(`projects?membership=true&simple=true${search}`)
|
|
92
|
+
if (!projects) {
|
|
93
|
+
throw new Error(`No projects!`)
|
|
94
|
+
} else if (!Array.isArray(projects)) {
|
|
95
|
+
console.log(projects)
|
|
96
|
+
throw new Error(`Projects is not an array!`)
|
|
97
|
+
}
|
|
98
|
+
const projs = projects as Array<Project>
|
|
99
|
+
|
|
100
|
+
const filtered = projs.filter((p: Project): boolean => {
|
|
101
|
+
return p.path_with_namespace.toLowerCase().includes(match.toLowerCase())
|
|
102
|
+
})
|
|
103
|
+
return filtered
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// git@gitlab.com:etagen-internal/linear-generator-config.git
|
|
107
|
+
export async function findProject(ssh_url: string): Promise<Project | undefined> {
|
|
108
|
+
const parts = ssh_url.split(':')
|
|
109
|
+
if (parts.length != 2) {
|
|
110
|
+
throw new Error(`${ssh_url} is invalid, could not be split into two parts at :`)
|
|
111
|
+
}
|
|
112
|
+
const name = path.basename(parts[1], '.git')
|
|
113
|
+
|
|
114
|
+
const projects = await getProjects(name) as Array<Project>
|
|
115
|
+
const project = projects.find((p: Project): boolean => {
|
|
116
|
+
return p.ssh_url_to_repo === ssh_url
|
|
117
|
+
})
|
|
118
|
+
return project
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export async function projectScopedGet(endpoint: string): Promise<JSONValue> {
|
|
122
|
+
if (endpoint.startsWith("/")) {
|
|
123
|
+
console.warn(`gitlabApi: endpoint ${endpoint} starts with /, removing it`)
|
|
124
|
+
endpoint = endpoint.slice(1)
|
|
125
|
+
}
|
|
126
|
+
const method = "GET"
|
|
127
|
+
const { host, token } = await getGitlabConfig()
|
|
128
|
+
const remote = await getRemote()
|
|
129
|
+
const project = await findProject(remote)
|
|
130
|
+
if (!project) {
|
|
131
|
+
throw new Error(`Could not find project for remote ${remote}`)
|
|
132
|
+
}
|
|
133
|
+
const base = `https://${host}/api/v4/projects/${project.id}`
|
|
134
|
+
const uri = `${base}/${endpoint}`
|
|
135
|
+
console.debug(`projectScopedGet uri: ${uri}`)
|
|
136
|
+
const headers = new Headers()
|
|
137
|
+
headers.append("Accept", "application/json")
|
|
138
|
+
headers.append('Private-Token', token)
|
|
139
|
+
const options = {
|
|
140
|
+
method,
|
|
141
|
+
headers,
|
|
142
|
+
}
|
|
143
|
+
const request = new Request(uri, options)
|
|
144
|
+
const response = await fetch(request)
|
|
145
|
+
return await response.json()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export async function getMergeRequest(id: string): Promise<JSONValue> {
|
|
149
|
+
return await projectScopedGet(`merge_requests/${id}`)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export async function getNamespaces(): Promise<JSONValue> {
|
|
153
|
+
return await gitlabApi(`namespaces`)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export type Group = JSONValue & {
|
|
157
|
+
id: number
|
|
158
|
+
name: string
|
|
159
|
+
full_path: string
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export async function getGroups(): Promise<Array<Group>> {
|
|
163
|
+
return await gitlabApi(`groups`) as Array<Group>
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export type MergeRequest = JSONValue & {
|
|
167
|
+
id: number
|
|
168
|
+
title : string
|
|
169
|
+
description : string
|
|
170
|
+
state : string
|
|
171
|
+
source_branch: string
|
|
172
|
+
target_branch: string
|
|
173
|
+
web_url: string
|
|
174
|
+
merge_status: string
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export async function getMergeRequestsAssignedToMe() : Promise<Array<MergeRequest>>
|
|
178
|
+
{
|
|
179
|
+
const me = await whoami()
|
|
180
|
+
return await gitlabApi(`merge_requests?state=opened&reviewer_id=${me.id}`) as Array<MergeRequest>
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export type Pipeline = JSONValue & {
|
|
184
|
+
id: number
|
|
185
|
+
status: string
|
|
186
|
+
ref: string
|
|
187
|
+
sha: string
|
|
188
|
+
web_url: string
|
|
189
|
+
updated_at: string // datetime string like "2021-03-18T15:00:00.000Z"
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export type PipelineStatus = 'success' | 'running'
|
|
193
|
+
|
|
194
|
+
export interface GetPipelineOptions {
|
|
195
|
+
days: number
|
|
196
|
+
status: PipelineStatus
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export async function getProjectPipelines(options: GetPipelineOptions): Promise<Array<Pipeline>> {
|
|
200
|
+
const { days, status } = options
|
|
201
|
+
const me = await whoami()
|
|
202
|
+
const username = me.username
|
|
203
|
+
const date = new Date()
|
|
204
|
+
const pastDate = date.getDate() - days;
|
|
205
|
+
date.setDate(pastDate)
|
|
206
|
+
const updated = date.toISOString()
|
|
207
|
+
console.debug(`updated: ${updated}`)
|
|
208
|
+
return await projectScopedGet(`pipelines?status=${status}&username=${username}&updated_after=${updated}`) as Array<Pipeline>
|
|
209
|
+
}
|
package/lib/is_main.ts
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
+
|
|
3
|
+
function justBase(filename: string): string {
|
|
4
|
+
const ext = path.extname(filename)
|
|
5
|
+
const base = path.basename(filename, ext)
|
|
6
|
+
return base
|
|
7
|
+
}
|
|
8
|
+
|
|
2
9
|
export function isMain(self: string): boolean {
|
|
3
|
-
const
|
|
4
|
-
|
|
10
|
+
const arg1 = Bun.argv[1]
|
|
11
|
+
const argv1Base = justBase(arg1)
|
|
12
|
+
const selfBase = justBase(self)
|
|
13
|
+
const result = argv1Base === selfBase
|
|
14
|
+
// if (result) {
|
|
15
|
+
// console.log({
|
|
16
|
+
// arg1,
|
|
17
|
+
// self,
|
|
18
|
+
// argv1Base,
|
|
19
|
+
// selfBase,
|
|
20
|
+
// result,
|
|
21
|
+
// })
|
|
22
|
+
// }
|
|
23
|
+
return result
|
|
5
24
|
}
|
package/lib/jira.ts
CHANGED
|
@@ -1,18 +1,38 @@
|
|
|
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
|
-
export async function
|
|
28
|
+
export async function jiraApi(endpoint: string): Promise<JSONValue> {
|
|
29
|
+
if (endpoint.startsWith("/")) {
|
|
30
|
+
console.warn(`jiraApi: endpoint ${endpoint} starts with /`)
|
|
31
|
+
endpoint = endpoint.slice(1)
|
|
32
|
+
}
|
|
12
33
|
const method = "GET"
|
|
13
34
|
const { host, token } = await getJiraConfig()
|
|
14
|
-
const
|
|
15
|
-
const uri = `${base}/${endpoint}`
|
|
35
|
+
const uri = `https://${host}/rest/api/3/${endpoint}`
|
|
16
36
|
const auth = `Basic ${token}`
|
|
17
37
|
const headers = new Headers()
|
|
18
38
|
headers.append("Authorization", auth)
|
|
@@ -23,19 +43,13 @@ export async function get(endpoint: string): Promise<JSONValue> {
|
|
|
23
43
|
}
|
|
24
44
|
const request = new Request(uri, options)
|
|
25
45
|
const response = await fetch(request)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
type Issue = JSONValue & {
|
|
30
|
-
key: string,
|
|
31
|
-
self: string,
|
|
32
|
-
fields: {
|
|
33
|
-
summary: string
|
|
34
|
-
}
|
|
46
|
+
const result = await response.json()
|
|
47
|
+
return result;
|
|
35
48
|
}
|
|
36
49
|
|
|
37
50
|
export async function getIssue(issue: string): Promise<Issue> {
|
|
38
|
-
|
|
51
|
+
const result = await jiraApi(`issue/${issue}`) as Issue
|
|
52
|
+
return result
|
|
39
53
|
}
|
|
40
54
|
|
|
41
55
|
type Myself = JSONValue & {
|
|
@@ -43,7 +57,7 @@ type Myself = JSONValue & {
|
|
|
43
57
|
}
|
|
44
58
|
|
|
45
59
|
export async function getMyself(): Promise<Myself> {
|
|
46
|
-
return await
|
|
60
|
+
return await jiraApi("/myself") as Myself
|
|
47
61
|
}
|
|
48
62
|
|
|
49
63
|
type SearchResponse = JSONValue & {
|
|
@@ -54,6 +68,6 @@ export async function myUnresolvedIssues(): Promise<Array<Issue>> {
|
|
|
54
68
|
const myself = await getMyself()
|
|
55
69
|
const myselfId = myself.accountId
|
|
56
70
|
const jql = `assignee = ${myselfId} AND resolution = Unresolved`
|
|
57
|
-
const issues = await
|
|
71
|
+
const issues = await jiraApi(`/search?jql=${encodeURIComponent(jql)}`) as SearchResponse
|
|
58
72
|
return issues.issues
|
|
59
73
|
}
|
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,22 +1,39 @@
|
|
|
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.4.0",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"
|
|
9
|
-
"git-jira": "dist/bin/git-jira.js",
|
|
8
|
+
"git-bump": "dist/bin/git-bump.js",
|
|
9
|
+
"git-jira-issue-list": "dist/bin/git-jira-issue-list.js",
|
|
10
|
+
"git-jira-issue-show": "dist/bin/git-jira-issue-show.js",
|
|
11
|
+
"git-jira-issue": "dist/bin/git-jira-issue.js",
|
|
10
12
|
"git-jira-start": "dist/bin/git-jira-start.js",
|
|
11
|
-
"git-jira
|
|
12
|
-
"git-
|
|
13
|
+
"git-jira": "dist/bin/git-jira.js",
|
|
14
|
+
"git-lab-group": "dist/bin/git-lab-group.js",
|
|
15
|
+
"git-lab-merge-active": "dist/bin/git-lab-merge-active.js",
|
|
16
|
+
"git-lab-merge-todo": "dist/bin/git-lab-merge-todo.js",
|
|
17
|
+
"git-lab-merge": "dist/bin/git-lab-merge.js",
|
|
18
|
+
"git-lab-namespace-list": "dist/bin/git-lab-namespace-list.js",
|
|
19
|
+
"git-lab-namespace": "dist/bin/git-lab-namespace.js",
|
|
20
|
+
"git-lab-project-list": "dist/bin/git-lab-project-list.js",
|
|
21
|
+
"git-lab-project-pipeline": "dist/bin/git-lab-project-pipeline.js",
|
|
22
|
+
"git-lab-project-pipeline-list": "dist/bin/git-lab-project-pipeline-list.js",
|
|
23
|
+
"git-lab-project-whereami": "dist/bin/git-lab-project-whereami.js",
|
|
24
|
+
"git-lab-project": "dist/bin/git-lab-project.js",
|
|
25
|
+
"git-lab-whoami": "dist/bin/git-lab-whoami.js",
|
|
26
|
+
"git-lab": "dist/bin/git-lab.js",
|
|
27
|
+
"gitj": "dist/bin/gitj.js"
|
|
13
28
|
},
|
|
14
29
|
"scripts": {
|
|
15
|
-
"preinstall": "bun build
|
|
30
|
+
"preinstall": "bun run build.ts",
|
|
31
|
+
"build": "bun run build.ts"
|
|
16
32
|
},
|
|
17
33
|
"devDependencies": {
|
|
18
34
|
"@types/commander": "^2.12.2",
|
|
19
|
-
"bun-types": "latest"
|
|
35
|
+
"bun-types": "latest",
|
|
36
|
+
"typescript": "latest"
|
|
20
37
|
},
|
|
21
38
|
"directories": {
|
|
22
39
|
"lib": "lib"
|
|
@@ -25,7 +42,9 @@
|
|
|
25
42
|
"typescript": "^5.0.0"
|
|
26
43
|
},
|
|
27
44
|
"dependencies": {
|
|
28
|
-
"commander": "^11.0.0"
|
|
45
|
+
"commander": "^11.0.0",
|
|
46
|
+
"cuid": "^3.0.0",
|
|
47
|
+
"glob": "^10.3.4"
|
|
29
48
|
},
|
|
30
49
|
"main": "dist/start.js dist/bump.js",
|
|
31
50
|
"repository": {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { readdirSync } from 'fs';
|
|
2
|
+
import { describe, expect, test } from 'bun:test';
|
|
3
|
+
import { doCommand } from '..';
|
|
4
|
+
|
|
5
|
+
describe('bin scripts', () => {
|
|
6
|
+
const binDir = './bin';
|
|
7
|
+
|
|
8
|
+
const scripts = readdirSync(binDir).filter((file) => {
|
|
9
|
+
return file.endsWith('.ts');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
scripts.forEach((script) => {
|
|
13
|
+
const stem = script.split('/').pop()?.split('-').pop()?.split('.').shift();
|
|
14
|
+
test(`"${script} --help" should contain 'Usage: ${stem}'"`, async () => {
|
|
15
|
+
const output = await doCommand(['bun', 'run', `${binDir}/${script}`, '--help']);
|
|
16
|
+
expect(output).toContain(`Usage: ${stem}`);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -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
|
+
}, 15000)
|
|
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
|
+
}, 15000)
|
|
@@ -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("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);
|