@ts-org/jenkins-cli 3.0.3 → 3.0.4
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 +44 -17
- package/dist/cli.d.ts +0 -0
- package/dist/cli.js +31 -28
- package/package.json +9 -10
- package/schemas/jenkins.json +1 -1
package/README.md
CHANGED
|
@@ -51,6 +51,7 @@ modes:
|
|
|
51
51
|
- sit
|
|
52
52
|
- uat
|
|
53
53
|
```
|
|
54
|
+
|
|
54
55
|
建议在 `jenkins-cli.yaml` 顶部添加 `# yaml-language-server: $schema=https://cdn.jsdelivr.net/npm/@ts-org/jenkins-cli@latest/schemas/jenkins.json`,以有更好的开发体验,如示例。
|
|
55
56
|
|
|
56
57
|
#### 扩展交互参数
|
|
@@ -109,19 +110,19 @@ export function validateTicket(input: string) {
|
|
|
109
110
|
|
|
110
111
|
### 🤖 命令参考
|
|
111
112
|
|
|
112
|
-
#### `
|
|
113
|
+
#### `build` (非交互式触发)
|
|
113
114
|
|
|
114
115
|
适用于 CI 或其他脚本化场景。
|
|
115
116
|
|
|
116
117
|
```bash
|
|
117
118
|
# 触发 dev 环境构建
|
|
118
|
-
jenkins-cli
|
|
119
|
+
jenkins-cli build -b origin/develop -m dev
|
|
119
120
|
|
|
120
121
|
# 同时触发多个环境
|
|
121
|
-
jenkins-cli
|
|
122
|
+
jenkins-cli build -b origin/develop -m dev,sit
|
|
122
123
|
|
|
123
124
|
# 传入额外参数
|
|
124
|
-
jenkins-cli
|
|
125
|
+
jenkins-cli build -b origin/develop -m dev --param version=1.2.3 --param force=true
|
|
125
126
|
```
|
|
126
127
|
|
|
127
128
|
---
|
|
@@ -130,13 +131,27 @@ jenkins-cli trigger -b origin/develop -m dev --param version=1.2.3 --param force
|
|
|
130
131
|
|
|
131
132
|
```bash
|
|
132
133
|
# 查看最近 20 次构建
|
|
133
|
-
jenkins-cli builds
|
|
134
|
+
jenkins-cli builds
|
|
134
135
|
|
|
135
136
|
# 查看运行中的构建
|
|
136
|
-
jenkins-cli builds
|
|
137
|
+
jenkins-cli builds active
|
|
137
138
|
|
|
138
139
|
# 查看 Jenkins 上所有运行中的构建
|
|
139
|
-
jenkins-cli builds
|
|
140
|
+
jenkins-cli builds active -a
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### `changes` - 变更记录
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# 查看最近 20 次构建的变更记录
|
|
148
|
+
jenkins-cli changes
|
|
149
|
+
|
|
150
|
+
# 查看最近 50 次构建的变更记录
|
|
151
|
+
jenkins-cli changes -n 50
|
|
152
|
+
|
|
153
|
+
# 查看指定构建的变更记录
|
|
154
|
+
jenkins-cli changes 1234
|
|
140
155
|
```
|
|
141
156
|
|
|
142
157
|
#### `job` - Job 管理
|
|
@@ -149,23 +164,23 @@ jenkins-cli job list --search 'project-*'
|
|
|
149
164
|
jenkins-cli job info
|
|
150
165
|
```
|
|
151
166
|
|
|
152
|
-
#### `
|
|
167
|
+
#### `console` - 查看日志
|
|
153
168
|
|
|
154
169
|
```bash
|
|
155
170
|
# 查看指定构建号的日志
|
|
156
|
-
jenkins-cli
|
|
171
|
+
jenkins-cli console 1234
|
|
157
172
|
|
|
158
173
|
# 查看最后一次构建日志
|
|
159
|
-
jenkins-cli
|
|
174
|
+
jenkins-cli console last
|
|
160
175
|
|
|
161
176
|
# 查看最后一次构建成功日志
|
|
162
|
-
jenkins-cli
|
|
177
|
+
jenkins-cli console last -s success
|
|
163
178
|
|
|
164
179
|
# 查看最后一次构建失败日志
|
|
165
|
-
jenkins-cli
|
|
180
|
+
jenkins-cli console last -s failed
|
|
166
181
|
|
|
167
182
|
# 仅输出最后 N 行
|
|
168
|
-
jenkins-cli
|
|
183
|
+
jenkins-cli console 1234 -t 200
|
|
169
184
|
```
|
|
170
185
|
|
|
171
186
|
#### `stop` - 停止构建
|
|
@@ -202,17 +217,29 @@ jenkins-cli params
|
|
|
202
217
|
|
|
203
218
|
```bash
|
|
204
219
|
# 读取当前 Job 的 XML 配置
|
|
205
|
-
jenkins-cli config
|
|
220
|
+
jenkins-cli config show
|
|
206
221
|
|
|
207
222
|
# 以 JSON 格式输出
|
|
208
|
-
jenkins-cli config
|
|
223
|
+
jenkins-cli config show -f json
|
|
224
|
+
|
|
225
|
+
# 备份当前 Job 配置
|
|
226
|
+
jenkins-cli config backup -d ./jenkins-backup
|
|
227
|
+
|
|
228
|
+
# 备份指定 Job 配置
|
|
229
|
+
jenkins-cli config backup -d ./jenkins-backup -j remote-factory-admin
|
|
230
|
+
|
|
231
|
+
# 按 glob 过滤备份多个 Job 配置
|
|
232
|
+
jenkins-cli config backup -d ./jenkins-backup --filter 'remote-*'
|
|
233
|
+
|
|
234
|
+
# 备份所有 Job 配置
|
|
235
|
+
jenkins-cli config backup -d ./jenkins-backup -a
|
|
209
236
|
```
|
|
210
237
|
|
|
211
|
-
#### `
|
|
238
|
+
#### `me` - 用户信息
|
|
212
239
|
|
|
213
240
|
```bash
|
|
214
241
|
# 验证 API Token 并查看当前用户
|
|
215
|
-
jenkins-cli
|
|
242
|
+
jenkins-cli me
|
|
216
243
|
```
|
|
217
244
|
|
|
218
245
|
### ❓ FAQ
|
package/dist/cli.d.ts
CHANGED
|
File without changes
|
package/dist/cli.js
CHANGED
|
@@ -1,36 +1,39 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { program } from 'commander';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
2
|
+
import { program, CommanderError } from 'commander';
|
|
3
|
+
import pt from 'inquirer';
|
|
4
|
+
import b from 'chalk';
|
|
5
|
+
import it from 'ora';
|
|
6
6
|
import { exec } from 'child_process';
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
7
|
+
import ft, { promisify } from 'util';
|
|
8
|
+
import N from 'fs-extra';
|
|
9
|
+
import Ye from 'js-yaml';
|
|
10
|
+
import R from 'path';
|
|
11
|
+
import tt from 'axios';
|
|
12
|
+
import at from 'jiti';
|
|
13
13
|
import { fileURLToPath } from 'url';
|
|
14
|
+
import { promises } from 'fs';
|
|
14
15
|
import { XMLParser } from 'fast-xml-parser';
|
|
15
16
|
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
`)}
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
var se="3.0.4",ae="Jenkins deployment CLI";var p=class extends Error{hint;example;details;exitCode;constructor(e,t={}){super(e),this.name="UserError",this.hint=t.hint,this.example=t.example,this.details=t.details,this.exitCode=t.exitCode??1;}};function Ke(n){return n instanceof p?n:n instanceof CommanderError?new p(n.message,{hint:"Check the command usage and options.",example:"jenkins-cli --help",exitCode:n.exitCode??1}):n instanceof Error?new p(n.message,{hint:"Check your input and try again.",example:"jenkins-cli --help"}):new p("Unknown error",{example:"jenkins-cli --help"})}function J(n){let e=Ke(n);if(console.error(b.red(`
|
|
18
|
+
\u274C ${e.message}
|
|
19
|
+
`)),e.details&&console.error(b.gray(e.details)),e.hint&&console.error(b.yellow(`Hint: ${e.hint}`)),e.example!==""){let t=e.example??"jenkins-cli --help";console.error(b.cyan(`Example: ${t}`));}console.error(b.gray('Run "jenkins-cli --help" for usage.')),process.exitCode=e.exitCode;}var ce=promisify(exec);async function le(){try{let{stdout:n}=await ce("git branch --show-current"),e=n.trim();if(!e)throw new p("Not on any branch (detached HEAD state).",{hint:"Checkout a branch before running this command.",example:"git checkout main"});return e}catch{throw new p("Failed to get current branch.",{hint:"Make sure you are inside a git repository.",example:"cd /path/to/repo && jenkins-cli"})}}async function ue(){try{let{stdout:n}=await ce('git branch -r --format="%(refname:short)"');return n.split(`
|
|
20
|
+
`).filter(e=>e.includes("/")&&!e.includes("HEAD"))}catch{throw new p("Failed to list branches.",{hint:"Make sure you are inside a git repository.",example:"cd /path/to/repo && jenkins-cli"})}}var P="jenkins-cli.yaml",T="package.json",F="jenkins-cli",Ve="jenkinsCli";function pe(n,e=process.cwd()){let t=e;for(;;){let r=R.join(t,n);if(N.existsSync(r))return r;let o=R.dirname(t);if(o===t)return null;t=o;}}function ze(n=process.cwd()){return pe(P,n)}function Xe(n=process.cwd()){let e=pe(T,n);return e?R.dirname(e):null}function Ze(n){return !!(n.apiToken&&n.job&&Array.isArray(n.modes)&&n.modes.length>0)}async function me(n){let e=await N.readFile(n,"utf-8"),t=Ye.load(e);if(!t||typeof t!="object")throw new p(`Invalid config in ${P}. Expected a YAML object.`,{hint:"Top-level config must be key/value pairs.",example:`${P}:
|
|
21
|
+
apiToken: http://user:token@host
|
|
22
|
+
job: my-job
|
|
23
|
+
modes: [dev]`});return t}async function et(n){let e=R.join(n,T);if(!await N.pathExists(e))return {};let t=await N.readFile(e,"utf-8"),r=JSON.parse(t),o=r[F]??r[Ve];if(o==null)return {};if(typeof o!="object"||Array.isArray(o))throw new p(`Invalid ${T} config: "${F}" must be an object.`,{hint:"Use an object for the config section.",example:`"${F}": { "apiToken": "http://user:token@host", "job": "my-job", "modes": ["dev"] }`});return o}async function de(){let n=process.cwd(),e=Xe(n)??n,t=R.join(e,P),r={},o=R.dirname(e),s=ze(o);s&&await N.pathExists(s)&&(r=await me(s));let i=await et(e);r={...r,...i};let a=await N.pathExists(t)?await me(t):{};if(r={...r,...a},!Ze(r))throw new p("Config incomplete or not found.",{hint:`Tried ${P} in project root, "${F}" in ${T}, and walking up from cwd. Required: apiToken, job, modes (non-empty array).`,example:`${P}:
|
|
24
|
+
apiToken: http://user:token@host
|
|
25
|
+
job: my-job
|
|
26
|
+
modes:
|
|
27
|
+
- dev`});return {...r,projectRoot:e}}var Y={maxRedirects:0,validateStatus:n=>n>=200&&n<400};function j(n){return `job/${n.split("/").map(t=>t.trim()).filter(Boolean).map(encodeURIComponent).join("/job/")}`}function D(n){let e=Array.isArray(n)?n.find(o=>o?.parameters):void 0,t=Array.isArray(e?.parameters)?e.parameters:[],r={};for(let o of t)o?.name&&(r[String(o.name)]=o?.value);return r}function nt(n){try{let t=new URL(n).pathname.split("/").filter(Boolean),r=[];for(let o=0;o<t.length-1;o++)t[o]==="job"&&t[o+1]&&r.push(decodeURIComponent(t[o+1]));return r.join("/")}catch{return ""}}async function rt(n,e){let r=(await n.axios.get(new URL("api/json?tree=number,url,building,result,timestamp,duration,estimatedDuration,fullDisplayName,displayName,actions[parameters[name,value]]",e).toString())).data??{};return {...r,parameters:D(r.actions)}}function ot(n,e=400){try{let r=(typeof n=="string"?n:JSON.stringify(n??"",null,2)).trim();return r?r.length>e?`${r.slice(0,e)}...`:r:""}catch{return ""}}function ge(n){let e=n.match(/^(https?):\/\/([^:]+):([^@]+)@(.+)$/);if(!e)throw new p("Invalid apiToken format.",{hint:"Expected: http(s)://username:token@host:port",example:"http://user:token@jenkins.example.com:8080"});let[,t,r,o,s]=e,i=`${t}://${s.replace(/\/$/,"")}/`,a=tt.create({baseURL:i,auth:{username:r,password:o},proxy:!1,timeout:3e4});return {baseURL:i,auth:{username:r,password:o},axios:a,crumbForm:void 0}}async function be(n,e=5e3){try{let t=await n.axios.get("crumbIssuer/api/json",{timeout:e}),{data:r}=t;r?.crumbRequestField&&r?.crumb&&(n.axios.defaults.headers.common[r.crumbRequestField]=r.crumb,n.crumbForm={field:r.crumbRequestField,value:r.crumb});let o=t.headers["set-cookie"];if(o){let s=Array.isArray(o)?o.map(i=>i.split(";")[0].trim()):[String(o).split(";")[0].trim()];n.axios.defaults.headers.common.Cookie=s.join("; ");}}catch{}}function V(n){return n.crumbPromise||(n.crumbPromise=be(n,5e3)),n.crumbPromise}async function z(n){await V(n),n.crumbForm||(n.crumbPromise=be(n,15e3),await n.crumbPromise);}async function A(n,e){let r=(await n.axios.get("queue/api/json?tree=items[id,task[name],actions[parameters[name,value]],why]")).data.items;if(e){let o=e.trim(),s=o.split("/").filter(Boolean).pop();return r.filter(i=>{let a=i.task?.name;return a===o||(s?a===s:!1)})}return r}async function L(n,e){let t=await n.axios.get(`${j(e)}/api/json?tree=builds[number,url,building,result,timestamp,duration,estimatedDuration,actions[parameters[name,value]]]`);return (Array.isArray(t.data?.builds)?t.data.builds:[]).filter(o=>o?.building).map(o=>({...o,parameters:D(o.actions)}))}async function W(n){let e=await n.axios.get("computer/api/json?tree=computer[displayName,executors[currentExecutable[number,url]],oneOffExecutors[currentExecutable[number,url]]]"),t=Array.isArray(e.data?.computer)?e.data.computer:[],r=[];for(let i of t){let a=Array.isArray(i?.executors)?i.executors:[],c=Array.isArray(i?.oneOffExecutors)?i.oneOffExecutors:[];for(let l of [...a,...c]){let u=l?.currentExecutable;u?.url&&r.push({number:Number(u.number),url:String(u.url)});}}let o=new Map;for(let i of r)i.url&&o.set(i.url,i);return (await Promise.all([...o.values()].map(async i=>{let a=await rt(n,i.url),c=nt(String(a?.url??i.url));return {...a,job:c}}))).filter(i=>i?.building)}async function I(n,e){return await z(n),await n.axios.post("queue/cancelItem",new URLSearchParams({id:e.toString()}),Y),!0}async function U(n,e,t){try{await z(n),await n.axios.post(`${j(e)}/${t}/stop/`,new URLSearchParams({}),Y);}catch(r){let o=r.response?.status;if(o===403){let s=typeof r.response?.data=="string"?r.response.data.slice(0,200):JSON.stringify(r.response?.data??"").slice(0,200),i=/crumb|csrf/i.test(s);console.log(b.red("[Error] 403 Forbidden: Jenkins refused the stop request (likely permissions or CSRF).")),console.log(b.yellow('[Hint] Confirm the current user has "Job" -> "Cancel" permission on this job.')),console.log(i?"[Hint] Jenkins returned a crumb/CSRF error. Ensure crumb + session cookie are sent, or use API token (not password).":s?`[Hint] Jenkins response: ${s}`:'[Hint] If "Job/Cancel" is already granted, also try granting "Run" -> "Update" (some versions use it for stop).');return}if(o===404||o===400||o===500){console.log(`[Info] Build #${t} could not be stopped (HTTP ${o}). Assuming it finished.`);return}throw r}}async function M(n,e,t){let r="branch",o="mode",s=t[o];s&&console.log(`Checking for conflicting builds for mode: ${s}...`);let[i,a]=await Promise.all([A(n,e),L(n,e)]),c=(m,d)=>{let h=m.actions?.find(B=>B.parameters);return h?h.parameters.find(B=>B.name===d)?.value:void 0},l=t[r];if(s&&l){let m=i.find(d=>c(d,o)===s&&c(d,r)===l);if(m)return new URL(`queue/item/${m.id}/`,n.baseURL).toString()}let u=!1;if(s)for(let m of a)c(m,o)===s&&(console.log(`Stopping running build #${m.number} (mode=${s})...`),await U(n,e,m.number),u=!0);u&&await new Promise(m=>setTimeout(m,1e3));try{return await z(n),(await n.axios.post(`${j(e)}/buildWithParameters/`,new URLSearchParams({...t}),Y)).headers.location||""}catch(m){let d=m?.response?.status,h=ot(m?.response?.data);if(d===400){let w=h?`Jenkins response (snippet):
|
|
28
|
+
${h}`:void 0;throw new p("Jenkins rejected the request (400).",{hint:`Common causes: job is not parameterized, parameter names do not match, or the job endpoint differs (e.g. multibranch jobs). This CLI sends parameters "${r}" and "${o}".`,example:"jenkins-cli build -b origin/main -m dev",details:w})}if(d){let w=h?`Jenkins response (snippet):
|
|
29
|
+
${h}`:void 0;throw new p(`Request failed with status code ${d}.`,{hint:"Check Jenkins job permissions and parameters.",example:"jenkins-cli me",details:w})}throw m}}async function he(n){return (await n.axios.get("whoAmI/api/json")).data}async function q(n){return (await n.axios.get("api/json?tree=jobs[name,url,color]")).data.jobs??[]}async function Q(n,e){try{let r=(await n.axios.get(`${j(e)}/api/json?tree=name,fullName,url,buildable,inQueue,nextBuildNumber,color,healthReport[description,score],lastBuild[number,url,building,result,timestamp,duration],lastCompletedBuild[number,url,result,timestamp,duration],lastSuccessfulBuild[number,url,building,result,timestamp,duration],lastFailedBuild[number,url,building,result,timestamp,duration]`)).data??{},o=typeof r?.fullName=="string"?r.fullName:"",s=typeof r?.name=="string"?r.name:"",i=String(e??"").trim();if(!o&&!s)throw new p(`Job not found: ${i}`,{hint:"Check the job name or use -j/--job to specify the correct job.",example:"jenkins-cli job show -j my-job"});if(i&&i!==o&&i!==s)throw new p(`Job not found: ${i}`,{hint:`Jenkins returned job "${o||s}".`,example:"jenkins-cli console last -j my-job -s success"});return r}catch(t){if(t?.response?.status===404){let o=String(e??"").trim();throw new p(`Job not found: ${o}`,{hint:"Check the job name or use -j/--job to specify the correct job.",example:"jenkins-cli console last -j my-job -s success"})}throw t}}async function ye(n,e,t){let r=Math.max(1,t?.limit??20);return ((await n.axios.get(`${j(e)}/api/json?tree=builds[number,url,building,result,timestamp,duration,actions[parameters[name,value]]]{0,${r}}`)).data.builds??[]).map(i=>({number:i.number,result:i.result,building:i.building,timestamp:i.timestamp,duration:i.duration,url:i.url,parameters:D(i.actions)}))}async function we(n,e,t){let r=Math.max(1,t?.limit??20);return ((await n.axios.get(`${j(e)}/api/json?tree=builds[number,url,timestamp,changeSet[items[msg,author[fullName,id,absoluteUrl],authorEmail,authorId,date]]]{0,${r}}`)).data.builds??[]).map(i=>({number:i.number,timestamp:i.timestamp,url:i.url,changeSet:i.changeSet??{}}))}async function je(n,e,t){let o=(await n.axios.get(`${j(e)}/${t}/api/json?tree=number,url,building,result,timestamp,duration,estimatedDuration,fullDisplayName,displayName,description,actions[parameters[name,value]],changeSet[items[msg,author[fullName,id,absoluteUrl],authorEmail,authorId,date]],culprits[fullName],executor[number,progress]`)).data??{};return {...o,parameters:D(o.actions)}}async function xe(n,e,t){let r=await n.axios.get(`${j(e)}/${t}/consoleText`,{responseType:"text"});return String(r.data??"")}async function ke(n,e){return ((await n.axios.get(`${j(e)}/api/json?tree=property[parameterDefinitions[name,type,description,defaultParameterValue[value],choices]]`)).data?.property??[]).flatMap(s=>s?.parameterDefinitions??[]).filter(Boolean).map(s=>({name:s.name,type:s.type,description:s.description,default:s.defaultParameterValue?.value,choices:s.choices}))}async function X(n,e){let t=await n.axios.get(`${j(e)}/config.xml`,{responseType:"text"});return String(t.data??"")}async function g(){let n=it("Loading configuration...").start();try{let e=await de();n.succeed("Configuration loaded");let t=ge(e.apiToken);return V(t),{config:e,jenkins:t}}catch(e){J(e),process.exit(1);}}var lt=at(fileURLToPath(import.meta.url),{interopDefault:!0});async function Se(n){return await Promise.resolve(n)}function ut(n){let e=String(n??"").trim();if(!e)return null;let t=e.split(":");if(t.length<2)return null;if(t.length===2){let[s,i]=t;return !s||!i?null:{file:s,exportName:i}}let r=t.at(-1);if(!r)return null;let o=t.slice(0,-2).join(":");return o?{file:o,exportName:r}:null}function mt(n,e){return R.isAbsolute(e)?e:R.join(n,e)}function ve(n){return !!n&&typeof n=="object"&&!Array.isArray(n)}async function Je(n,e){let t=ut(e);if(!t)return null;let r=mt(n,t.file);if(!await N.pathExists(r))throw new p(`configs reference not found: ${t.file}`,{hint:"Check the file path (relative to project root) and file name.",example:'configs: [{ choices: "./scripts/prompts.ts:choices" }]'});let o=lt(r),s=ve(o)?o:{default:o},i=t.exportName==="default"?s.default:s[t.exportName];if(i===void 0)throw new p(`configs reference export not found: ${e}`,{hint:"Make sure the export exists in the referenced file.",example:'export const choices = ["dev", "uat"]'});return {value:i}}async function _(n,e,t){if(typeof e!="string")return e;let r=await Je(n,e);if(!r)return e;if(!t.allow(r.value))throw new p(t.error(e),{hint:t.hint,example:t.example});return r.value}async function $e(n,e){if(typeof e!="string")return e;let t=await Je(n,e);if(!t)return e;if(typeof t.value=="function"){let r=t.value();return await Se(r)}return await Se(t.value)}async function Pe(n,e){let t=Array.isArray(n)?n:[];if(t.length===0)return [];let r=String(e.projectRoot??"").trim()||process.cwd(),o=[];for(let s of t){if(!ve(s))continue;let i={...s};if(i.choices!==void 0){i.choices=await $e(r,i.choices);let a=String(i.type??"").toLowerCase(),c=i.choices;if((a==="list"||a==="rawlist"||a==="checkbox")&&typeof c!="function"&&!Array.isArray(c))if(c==null)i.choices=[];else if(typeof c=="string"||typeof c=="number"||typeof c=="boolean")i.choices=[String(c)];else if(typeof c[Symbol.iterator]=="function")i.choices=Array.from(c).map(u=>String(u));else throw new p(`configs "${String(i.name??"")}" choices must resolve to an array (got ${typeof c}).`,{hint:"Return an array for list/rawlist/checkbox choices.",example:'export const choices = ["dev", "uat"]'})}i.default!==void 0&&(i.default=await $e(r,i.default)),i.when!==void 0&&(i.when=await _(r,i.when,{allow:a=>typeof a=="function"||typeof a=="boolean",error:a=>`when reference must be a function or boolean: ${a}`,hint:"Export a function or boolean from the referenced file.",example:'export const when = (answers) => answers.env === "dev"'})),i.validate!==void 0&&(i.validate=await _(r,i.validate,{allow:a=>typeof a=="function",error:a=>`validate reference must be a function: ${a}`,hint:"Export a function from the referenced file.",example:'export const validate = (input) => !!input || "required"'})),i.filter!==void 0&&(i.filter=await _(r,i.filter,{allow:a=>typeof a=="function",error:a=>`filter reference must be a function: ${a}`,hint:"Export a function from the referenced file.",example:"export const filter = (input) => input.trim()"})),i.transformer!==void 0&&(i.transformer=await _(r,i.transformer,{allow:a=>typeof a=="function",error:a=>`transformer reference must be a function: ${a}`,hint:"Export a function from the referenced file.",example:"export const transformer = (input) => input.toUpperCase()"})),o.push(i);}return o}function Ne(n,e){let t=new Set(e),r={};for(let[o,s]of Object.entries(n))if(!t.has(o)&&s!==void 0){if(s===null){r[o]="";continue}if(Array.isArray(s)){r[o]=s.map(i=>String(i)).join(",");continue}if(typeof s=="object"){try{r[o]=JSON.stringify(s);}catch{r[o]=String(s);}continue}r[o]=String(s);}return r}async function Re(){console.log(b.bold.blue(`
|
|
25
30
|
\u{1F680} Jenkins CLI - Jenkins Deployment CLI
|
|
26
|
-
`));let{config:
|
|
27
|
-
\u{1F44B} Cancelled by user`)),process.exit(130);},
|
|
28
|
-
\u{1F44B} Cancelled by user`)),process.exit(0)),console.log(
|
|
29
|
-
\u274C Prompt failed: ${f}
|
|
30
|
-
`)),process.exit(1);}finally{process.off("SIGINT",o);}console.log();let s=!1,u=()=>{s||(s=!0,console.log());},l=a.modes.map(async c=>{let m=We(`Triggering build for ${g.yellow(c)}...`).start();try{let f=await I(t,e.job,{...i,branch:a.branch,mode:c});u(),m.succeed(`${g.green(c)} - Triggered! Queue: ${f}`);}catch(f){throw u(),m.fail(`${g.red(c)} - ${f.message}`),f}});try{await Promise.all(l);}catch{console.log(g.bold.red(`
|
|
31
|
+
`));let{config:n,jenkins:e}=await g(),[t,r]=await Promise.all([ue(),le()]),o=()=>{console.log(b.yellow(`
|
|
32
|
+
\u{1F44B} Cancelled by user`)),process.exit(130);},s,i={};try{process.prependOnceListener("SIGINT",o);let u=await Pe(n.configs,{projectRoot:n.projectRoot}),m=new Set(["branch","modes","mode"]);for(let h of u){let w=String(h?.name??"").trim();if(m.has(w))throw new p(`configs name "${w}" is reserved.`,{hint:"Use another name in your extra prompt config.",example:"name: env"})}let d=await pt.prompt([{type:"list",name:"branch",message:"\u8BF7\u9009\u62E9\u8981\u6253\u5305\u7684\u5206\u652F:",choices:t,default:t.indexOf(r)},{type:"checkbox",name:"modes",message:"\u8BF7\u9009\u62E9\u8981\u6253\u5305\u7684\u73AF\u5883:",choices:n.modes,validate:h=>h.length===0?"You must select at least one environment":!0},...u]);s={branch:String(d.branch??""),modes:d.modes??[]},i=Ne(d,["branch","modes"]);}catch(u){let m=u,d=m?.message?String(m.message):String(m),h=m?.name?String(m.name):"";(h==="ExitPromptError"||d.toLowerCase().includes("cancelled")||d.toLowerCase().includes("canceled"))&&(console.log(b.yellow(`
|
|
33
|
+
\u{1F44B} Cancelled by user`)),process.exit(0)),J(new p(`Prompt failed: ${d}`,{hint:h?`Error: ${h}`:""})),process.exit(1);}finally{process.off("SIGINT",o);}console.log();let a=!1,c=()=>{a||(a=!0,console.log());},l=s.modes.map(async u=>{let m=it(`Triggering build for ${b.yellow(u)}...`).start();try{let d=await M(e,n.job,{...i,branch:s.branch,mode:u});c(),m.succeed(`${b.green(u)} - Triggered! Queue: ${d}`);}catch(d){throw c(),m.fail(`${b.red(u)} - ${d.message}`),d}});try{await Promise.all(l);}catch{console.log(b.bold.red(`
|
|
31
34
|
\u274C Some builds failed. Check the output above.
|
|
32
|
-
`)),process.exit(1);}}function
|
|
33
|
-
`);console.log(l.slice(Math.max(0,l.length-
|
|
34
|
-
`));return}process.stdout.write(
|
|
35
|
+
`)),process.exit(1);}}function y(n,e){return (e??"").trim()||n}function x(n,e){let t=Number(n);if(!Number.isInteger(t)||t<0)throw new p(`${e} must be a non-negative integer.`,{hint:`Provide a valid ${e}.`,example:`jenkins-cli console ${e==="id"?"123":"last -t 100"}`});return t}function K(n,e){let t=String(e??"").trim();if(!t)return !0;if(!/[*?]/.test(t))return n.includes(t);let s=`^${t.replace(/[$()*+.?[\\\]^{|}]/g,"\\$&").replace(/\\\*/g,".*").replace(/\\\?/g,".")}$`;try{return new RegExp(s).test(n)}catch{return n.includes(t)}}function Ae(n){let e=n.command("queue").description("Operations for the build queue");e.command("list").alias("ls").description("List items waiting in the build queue").option("-j, --job <job>","Show only queue items for the specified job").action(async t=>{let{config:r,jenkins:o}=await g(),s=t.job?y(r.job,t.job):void 0,i=await A(o,s);console.table((i??[]).map(a=>({id:a.id,job:a.task?.name,why:a.why})));}),e.command("cancel").description("Cancel a queued build item").argument("<id...>","Queue id(s)").action(async t=>{let{jenkins:r}=await g(),o=Array.isArray(t)?t:[String(t??"")],s=await Promise.all(o.map(async a=>{let c=x(String(a),"id");try{return await I(r,c),{id:c,ok:!0}}catch(l){return {id:c,ok:!1,message:String(l?.message??l)}}})),i=s.filter(a=>!a.ok);if(i.length===0){console.log(b.green(`Cancelled ${s.length} queue item(s).`));return}console.log(b.yellow(`Cancelled ${s.length-i.length} item(s), failed ${i.length} item(s).`));for(let a of i)console.log(b.red(`- ${a.id}: ${a.message??"Cancel failed"}`));});}function f(n){return {[ft.inspect.custom]:()=>n}}function ee(n,e){return String(n??"").padEnd(e," ")}function k(n){return Math.max(0,...n.map(e=>String(e??"").length))}function v(n,e){return f(ee(n,e))}function C(n){let e=String(n??""),t=e.trim();if(!t)return f(b.gray("-"));let r=s=>f(s),o=t.toLowerCase();if(o.startsWith("http://")||o.startsWith("https://"))try{let i=(new URL(t).hostname??"").toLowerCase(),a=i==="localhost"||i==="127.0.0.1"||i==="::1",c=/^10\./.test(i)||/^192\.168\./.test(i)||/^127\./.test(i)||/^172\.(1[6-9]|2\d|3[0-1])\./.test(i);return r(a||c?b.cyanBright(e):b.hex("#4EA1FF")(e))}catch{return r(b.hex("#4EA1FF")(e))}return o.startsWith("ws://")||o.startsWith("wss://")?r(b.cyan(e)):o.startsWith("ssh://")||o.startsWith("git+ssh://")||o.startsWith("git@")?r(b.magenta(e)):o.startsWith("file://")?r(b.yellow(e)):o.startsWith("mailto:")?r(b.green(e)):o.startsWith("javascript:")||o.startsWith("data:")?r(b.red(e)):t.startsWith("/")||t.startsWith("./")||t.startsWith("../")?r(b.cyan(e)):/^[a-z0-9.-]+(?::\d+)?(\/|$)/i.test(t)?r(b.blue(e)):r(e)}function S(n){let e=new Date(n),t=r=>String(r).padStart(2,"0");return `${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())} ${t(e.getHours())}:${t(e.getMinutes())}:${t(e.getSeconds())}`}function O(n,e){if(e===!0)return f(b.cyan("BUILDING"));let t=String(n??"").toUpperCase();return f(t?t==="SUCCESS"?b.green(t):t==="ABORTED"?b.gray(t):t==="FAILURE"?b.red(t):t==="UNSTABLE"?b.yellow(t):t==="NOT_BUILT"?b.gray(t):t:"-")}function te(n){let e=String(n??"");if(!e)return f("-");let t=e.endsWith("_anime"),r=t?e.slice(0,-6):e,o=(()=>{switch(r){case"blue":return t?b.blueBright(e):b.blue(e);case"red":return t?b.redBright(e):b.red(e);case"yellow":return t?b.yellowBright(e):b.yellow(e);case"aborted":return b.gray(e);case"disabled":case"notbuilt":case"grey":case"gray":return b.gray(e);default:return e}})();return f(o)}function Be(n){let e=Object.entries(n??{}).filter(([r])=>r);return e.length?(e.sort(([r],[o])=>r.localeCompare(o,"en",{sensitivity:"base"})),e.map(([r,o])=>{if(o===void 0)return `${r}=`;if(o===null)return `${r}=null`;if(typeof o=="string"||typeof o=="number"||typeof o=="boolean")return `${r}=${o}`;try{return `${r}=${JSON.stringify(o)}`}catch{return `${r}=${String(o)}`}}).join(", ")):"-"}function Ee(n){let e=n.command("builds").description("Build operations");e.option("-j, --job <job>","Specify job").option("-n, --limit <n>","Limit","20").action(async t=>{let{config:r,jenkins:o}=await g(),s=y(r.job,t.job),a=(await ye(o,s,{limit:Number(t.limit)})).map(l=>({number:l.number,result:O(l.result,l.building),building:l.building,"duration(s)":Number((Number(l.duration??0)/1e3).toFixed(3)),date:f(S(Number(l.timestamp??0))),parameters:Be(l.parameters),url:C(String(l.url??""))})),c=k(a.map(l=>l.parameters));console.table(a.map(l=>({...l,parameters:v(l.parameters,c)})));}),e.command("active").description("List active builds").option("-j, --job <job>","Specify job").option("-a, --all","Query all running builds on Jenkins").action(async t=>{let{config:r,jenkins:o}=await g(),i=((t.all?await W(o):await L(o,y(r.job,t.job)))??[]).map(c=>({...t.all?{job:f(String(c.job??""))}:{},number:c.number,date:f(c.timestamp?S(Number(c.timestamp)):"-"),parameters:Be(c.parameters),url:C(String(c.url??""))})),a=k(i.map(c=>c.parameters));console.table(i.map(c=>({...c,parameters:v(c.parameters,a)})));});}function gt(n){let e=String(n?.authorEmail??"").trim(),t=e?e.split("@")[0]??"":"";return t||e}function Le(n){let e=[];for(let t of n){let r=Number(t?.number),o=Number.isInteger(r)?`#${r}`:f("-"),s=t?.timestamp?S(Number(t.timestamp)):"-",i=t?.changeSet?.items??[];if(!i.length){e.push({build:o,date:f(s),author:f("-"),message:f("-")});continue}for(let a of i){let c=gt(a),l=String(a?.msg??"").trim();e.push({build:o,date:f(s),author:f(c||"-"),message:f(l||"-")});}}return e}function Ie(n){n.command("changes").description("List build changes").argument("[id]").option("-j, --job <job>","Specify job").option("-n, --limit <n>","Limit","20").option("--raw","Output raw changeSet payload").action(async(e,t)=>{let{config:r,jenkins:o}=await g(),s=y(r.job,t.job);if(e){let c=x(e,"id"),l=await je(o,s,c);if(t.raw){console.log(JSON.stringify({build:l.number,changeSet:l.changeSet??{}},null,2));return}console.table(Le([l]));return}let i=Math.max(1,x(t.limit,"limit")),a=await we(o,s,{limit:i});if(t.raw){console.log(JSON.stringify(a.map(c=>({build:c.number,changeSet:c.changeSet??{}})),null,2));return}console.table(Le(a));});}function Ue(){let n=process.argv,e=n.findIndex(r=>r==="-j"||r==="--job");if(e<0)return;let t=n[e+1];return !t||t.startsWith("-")?"":t}function qe(n){let e=n.command("console").description("Fetch build console log"),t=async(r,o,s)=>{let{jenkins:i}=await g(),a=await xe(i,r,o);if(s.tail){let c=x(s.tail,"tail"),l=a.split(`
|
|
36
|
+
`);console.log(l.slice(Math.max(0,l.length-c)).join(`
|
|
37
|
+
`));return}process.stdout.write(a);};e.argument("<id>","Build number").option("-j, --job <job>","Specify job").option("-t, --tail <n>","Only output the last N lines").action(async(r,o)=>{let{config:s}=await g(),i=o.job??Ue();if(i==="")throw new p("Job is required.",{hint:"Provide a job name after -j/--job.",example:"jenkins-cli console 123 -j my-job"});let a=y(s.job,i),c=x(r,"id");await t(a,c,o);}),e.command("last").description("Fetch the latest build log").option("-j, --job <job>","Specify job").option("-s, --status <status>","success | failed | any","any").option("-t, --tail <n>","Only output the last N lines").action(async r=>{let{config:o,jenkins:s}=await g(),i=r.job??Ue();if(i==="")throw new p("Job is required.",{hint:"Provide a job name after -j/--job.",example:"jenkins-cli console last -j my-job -s success"});let a=y(o.job,i),c=String(r.status??"any").toLowerCase();if(!["any","success","failed"].includes(c))throw new p(`Invalid status: ${r.status}.`,{hint:"Use success | failed | any.",example:"jenkins-cli console last -s success"});let l=await Q(s,a),u=c==="success"?l?.lastSuccessfulBuild:c==="failed"?l?.lastFailedBuild:l?.lastBuild,m=Number(u?.number);if(!m){let d=c==="success"?"successful":c==="failed"?"failed":"last";throw new p(`No ${d} build found for job: ${a}`,{hint:"Check the job name or status filter.",example:"jenkins-cli console last -j my-job -s any"})}await t(a,m,r);});}function Oe(n){n.command("stop").description("Clear queued builds and stop running builds").argument("[id]","Build number").option("-j, --job <job>","Specify Jenkins job").option("-a, --all","Cancel queued items for this job and stop all running builds for it").option("-A, --ALL","Cancel all queued items and stop all running builds on Jenkins").action(async(e,t)=>{let{config:r,jenkins:o}=await g(),s=y(r.job,t.job);if(t.ALL){let[i,a]=await Promise.all([A(o),W(o)]),c=(i??[]).map(u=>Number(u.id)).filter(u=>!Number.isNaN(u)),l=(a??[]).map(u=>({number:Number(u.number),job:String(u.job??"")})).filter(u=>u.job&&!Number.isNaN(u.number));for(let u of c)await I(o,u);for(let u of l)await U(o,u.job,u.number);console.log(b.green(`Requested: cancelled ${c.length} queue item(s), stopped ${l.length} running build(s).`));return}if(t.all){let[i,a]=await Promise.all([A(o,s),L(o,s)]),c=(i??[]).map(u=>Number(u.id)).filter(u=>!Number.isNaN(u)),l=(a??[]).map(u=>Number(u.number)).filter(u=>!Number.isNaN(u));for(let u of c)await I(o,u);for(let u of l)await U(o,s,u);console.log(b.green(`Requested: cancelled ${c.length} queue item(s), stopped ${l.length} running build(s).`));return}if(!e){console.log(b.red("Missing build id. Provide <id> or use -a/--all."));return}await U(o,s,x(e,"id")),console.log(b.green("Stop requested"));});}function Fe(n){n.command("params").description("Show job parameter definitions").option("-j, --job <job>","Specify job").action(async e=>{let{config:t,jenkins:r}=await g(),o=y(t.job,e.job),s=await ke(r,o),i=k(s.map(a=>a?.name));console.table((s??[]).map(a=>({name:v(a?.name??"",i),type:f(String(a?.type??"")),description:f(String(a?.description??"")),default:f(a?.default===void 0?"-":String(a.default)),choices:f(Array.isArray(a?.choices)?a.choices.join(", "):a?.choices??"-")})));});}function Te(n){n.command("me").description("Show Jenkins user info for the current token").option("--raw","Print raw response").action(async e=>{let{jenkins:t}=await g(),r=await he(t);if(e.raw){console.log(r&&typeof r=="object"?JSON.stringify(r,null,2):String(r));return}let o=r&&typeof r=="object"?r:{value:r},s=(u,m)=>{let d=u.length;if(d>=m)return u;let h=m-d,w=Math.floor(h/2),B=h-w;return `${" ".repeat(w)}${u}${" ".repeat(B)}`},i=o.name??o.fullName??o.id??"",a=i==null?"":String(i),c=Math.max(20,a.length),l={};l.name=f(s(a,c));for(let u of Object.keys(o).sort((m,d)=>m.localeCompare(d,"en"))){if(u==="name")continue;let m=o[u],d=u.toLowerCase();if((d==="url"||d.endsWith("url")||d.includes("url"))&&(typeof m=="string"||typeof m=="number")){l[u]=C(String(m));continue}let w=m==null?"":typeof m=="object"?JSON.stringify(m):String(m);l[u]=f(w);}console.table([l]);});}function De(n){let e=n.command("config").description("Show Jenkins job configuration");e.command("show").description("Show job configuration").option("-j, --job <job>","Specify job").option("-f, --format <format>","Output format: xml or json","xml").action(async t=>{let{config:r,jenkins:o}=await g(),s=y(r.job,t.job),i=String(t.format??"xml").toLowerCase();if(i!=="xml"&&i!=="json")throw new p(`Invalid format: ${t.format}.`,{hint:"Use xml or json.",example:"jenkins-cli config show -f json"});let a=await X(o,s);if(i==="xml"){process.stdout.write(a);return}let l=new XMLParser({ignoreAttributes:!1,attributeNamePrefix:"@_"}).parse(a);console.log(JSON.stringify(l,null,2));}),e.command("backup").description("Backup job configuration to files").requiredOption("-d, --destination <path>","Destination folder").option("-a, --all","Backup all jobs").option("-j, --job <job>","Specify job").option("--filter <pattern>","Filter jobs by name (supports glob)").action(async t=>{let{config:r,jenkins:o}=await g(),s=String(t.destination??"").trim();if(!s)throw new p("Destination is required.",{hint:"Provide a destination folder with -d or --destination.",example:"jenkins-cli config backup -d ./jenkins-backup"});if(t.all&&t.filter)throw new p("Options --all and --filter are mutually exclusive.",{hint:"Use either -a/--all or --filter, not both.",example:"jenkins-cli config backup -d ./jenkins-backup -a"});let i=String(t.filter??"").trim(),a=t.all?await q(o):i?(await q(o)).filter(l=>K(String(l.name??""),i)):[{name:y(r.job,t.job)}];if(a.length===0)throw new p(`No jobs matched filter: ${i}`,{hint:"Check the pattern or remove --filter to use the default job.",example:"jenkins-cli config backup -d ./jenkins-backup --filter 'remote-*'"});await promises.mkdir(s,{recursive:!0});let c=[];for(let l of a){let u=String(l?.name??"").trim();if(!u)continue;let m=await X(o,u),d=R.join(s,u,"config.xml");await promises.mkdir(R.dirname(d),{recursive:!0}),await promises.writeFile(d,m),c.push(d);}console.log(`Backup completed. ${c.length} file(s) saved to ${R.resolve(s)}`);});}function We(n){let e=n.command("job").description("Job operations");e.command("list").alias("ls").description("List all jobs").option("--search <keyword>","Filter by name (supports glob)").action(async t=>{let{jenkins:r}=await g(),o=await q(r),s=(t.search??"").trim(),i=s?o.filter(l=>K(String(l.name??""),s)):o;i.sort((l,u)=>String(l?.name??"").localeCompare(String(u?.name??""),"en",{sensitivity:"base"}));let a=k(i.map(l=>l?.name)),c=k(i.map(l=>l?.url));console.table((i??[]).map(l=>({name:v(l.name??"",a),color:te(l.color),url:C(ee(l.url??"",c))})));}),e.command("info").description("Show job info").option("-j, --job <job>","Specify job").option("--json","Output raw JSON").action(async t=>{let{config:r,jenkins:o}=await g(),s=y(r.job,t.job),i=await Q(o,s);if(t.json){console.log(JSON.stringify(i,null,2));return}let a=i?.lastBuild,c=i?.lastCompletedBuild,l=Array.isArray(i?.healthReport)?i.healthReport:[];console.table([{name:f(String(i?.name??"")),url:C(String(i?.url??"")),color:te(i?.color),buildable:i?.buildable,inQueue:i?.inQueue,nextBuildNumber:i?.nextBuildNumber,healthScore:l[0]?.score??"-",lastBuild:f(a?.number?`#${a.number}`:"-"),lastResult:O(a?.result,a?.building),"lastDuration(s)":a?.duration===void 0?"-":Number((Number(a.duration)/1e3).toFixed(3)),lastDate:f(a?.timestamp?S(Number(a.timestamp)):"-"),lastCompleted:f(c?.number?`#${c.number}`:"-"),lastCompletedResult:O(c?.result,!1),lastCompletedDate:f(c?.timestamp?S(Number(c.timestamp)):"-")}]);});}function yt(n){return n.split(",").map(e=>e.trim()).filter(Boolean)}function wt(n){let e=n.split("=");if(e.length<2)throw new p(`Invalid --param: "${n}".`,{hint:"Use the format key=value.",example:"jenkins-cli build -b origin/main -m dev --param foo=bar"});let t=e[0].trim(),r=e.slice(1).join("=").trim();if(!t)throw new p(`Invalid --param: "${n}". Key is empty.`,{hint:'Provide a non-empty key before "=".',example:"jenkins-cli build -b origin/main -m dev --param foo=bar"});return {key:t,value:r}}function Me(n){n.command("build").description("Trigger Jenkins builds non-interactively").requiredOption("-b, --branch <branch>","Branch (e.g., origin/develop)").option("-m, --mode <mode>","Deployment environment (repeatable or comma-separated: -m dev -m uat / -m dev,uat)",(e,t)=>t.concat(yt(e)),[]).option("--param <key=value>","Extra parameters (repeatable, e.g., --param foo=bar)",(e,t)=>t.concat(e),[]).option("-j, --job <job>","Specify job").action(async e=>{let{config:t,jenkins:r}=await g(),o=y(t.job,e.job),s=String(e.branch??"").trim();if(!s)throw new p("branch is required.",{hint:"Pass a branch with -b or --branch.",example:"jenkins-cli build -b origin/develop -m dev"});let i=(e.mode??[]).map(String).map(d=>d.trim()).filter(Boolean),a=Array.from(new Set(i));if(a.length===0)throw new p("mode is required.",{hint:"Pass at least one -m/--mode.",example:"jenkins-cli build -b origin/develop -m dev -m uat"});let c={};for(let d of e.param??[]){let{key:h,value:w}=wt(String(d));c[h]=w;}console.log();let l=!1,u=()=>{l||(l=!0,console.log());},m=a.map(async d=>{let h=it(`Triggering build for ${b.yellow(d)}...`).start();try{let w=await M(r,o,{...c,branch:s,mode:d});u(),h.succeed(`${b.green(d)} - Triggered! Queue: ${w}`);}catch(w){throw u(),h.fail(`${b.red(d)} - ${w.message}`),w}});try{await Promise.all(m);}catch{console.log(b.bold.red(`
|
|
35
38
|
\u274C Some builds failed. Check the output above.
|
|
36
|
-
`)),process.exit(1);}});}function
|
|
39
|
+
`)),process.exit(1);}});}function Qe(n){Ee(n),Ie(n),De(n),We(n),qe(n),Fe(n),Ae(n),Oe(n),Me(n),Te(n);}program.name("jenkins-cli").description(ae).version(se,"-v, --version").helpOption("-h, --help").allowExcessArguments(!1).configureHelp({sortSubcommands:!0,sortOptions:!0}).action(Re);Qe(program);async function jt(){try{await program.parseAsync(process.argv);}catch(n){J(n);}}jt();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ts-org/jenkins-cli",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
4
4
|
"description": "Jenkins deployment CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -8,13 +8,6 @@
|
|
|
8
8
|
"jenkins-cli": "dist/cli.js",
|
|
9
9
|
"jc": "dist/cli.js"
|
|
10
10
|
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "tsup",
|
|
13
|
-
"dev": "NODE_ENV=development tsup --watch",
|
|
14
|
-
"prepublishOnly": "npm run build",
|
|
15
|
-
"link:test": "npm run build && npm link",
|
|
16
|
-
"format": "eslint . --fix && prettier . --write"
|
|
17
|
-
},
|
|
18
11
|
"keywords": [
|
|
19
12
|
"jenkins",
|
|
20
13
|
"cli",
|
|
@@ -66,5 +59,11 @@
|
|
|
66
59
|
"directories": {
|
|
67
60
|
"doc": "docs"
|
|
68
61
|
},
|
|
69
|
-
"types": "./dist/index.d.ts"
|
|
70
|
-
|
|
62
|
+
"types": "./dist/index.d.ts",
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsup",
|
|
65
|
+
"dev": "NODE_ENV=development tsup --watch",
|
|
66
|
+
"link:test": "npm run build && npm link",
|
|
67
|
+
"format": "eslint . --fix && prettier . --write"
|
|
68
|
+
}
|
|
69
|
+
}
|
package/schemas/jenkins.json
CHANGED