@ts-org/jenkins-cli 1.0.0-prior
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/LICENSE +21 -0
- package/README.md +40 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +23 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +15 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
## @ts-org/jenkins-cli
|
|
2
|
+
|
|
3
|
+
### 安装
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm add @ts-org/jenkins-cli
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
### 使用
|
|
10
|
+
|
|
11
|
+
1. 在项目的根目录创建 `jenkins-cli.yaml`:
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
apiToken: https://username:token@jenkins_url
|
|
15
|
+
|
|
16
|
+
job: 'your-job-name'
|
|
17
|
+
|
|
18
|
+
# 分支会通过git命令读取
|
|
19
|
+
|
|
20
|
+
# 部署的环境
|
|
21
|
+
modes:
|
|
22
|
+
- dev
|
|
23
|
+
- sit
|
|
24
|
+
- uat
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
2. 项目的终端执行:`jenkins-cli`
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
🚀 Jenkins CLI - Jenkins Deployment CLI
|
|
32
|
+
|
|
33
|
+
✔ Configuration loaded
|
|
34
|
+
✔ Found 5 branches
|
|
35
|
+
✔ 请选择要打包的分支: origin/develop
|
|
36
|
+
✔ 请选择要打包的环境: dev, sit, uat
|
|
37
|
+
✔ dev - Build triggered successfully
|
|
38
|
+
✔ sit - Build triggered successfully
|
|
39
|
+
✔ uat - Build triggered successfully
|
|
40
|
+
```
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import J from 'inquirer';
|
|
4
|
+
import i from 'chalk';
|
|
5
|
+
import x from 'ora';
|
|
6
|
+
import f from 'fs-extra';
|
|
7
|
+
import k from 'js-yaml';
|
|
8
|
+
import m from 'path';
|
|
9
|
+
import { exec } from 'child_process';
|
|
10
|
+
import { promisify } from 'util';
|
|
11
|
+
import T from 'axios';
|
|
12
|
+
|
|
13
|
+
var l="jenkins-cli.yaml";function E(r=process.cwd()){let e=r;for(;;){let t=m.join(e,l);if(f.existsSync(t))return t;let o=m.dirname(e);if(o===e)return null;e=o;}}async function h(){let r=E();if(!r)throw new Error(`Config file not found: ${l}`);try{let e=await f.readFile(r,"utf-8"),t=k.load(e);if(!t.apiToken||!t.job||!Array.isArray(t.modes))throw new Error("Invalid config: apiToken, job, and modes are required");if(t.modes.length===0)throw new Error("Invalid config: modes cannot be empty");return t}catch(e){throw e.code==="ENOENT"?new Error(`Config file not found: ${l}`):e}}var p=promisify(exec);async function g(){try{let{stdout:r}=await p("git branch --show-current"),e=r.trim();if(!e)throw new Error("Not on any branch (detached HEAD state)");return e}catch{throw new Error("Failed to get current branch. Are you in a git repository?")}}async function w(){try{let{stdout:r}=await p('git branch -r --format="%(refname:short)"');return r.split(`
|
|
14
|
+
`).filter(e=>e.includes("/"))}catch{throw new Error("Failed to list branches. Are you in a git repository?")}}function y(r){let e=r.match(/^(https?):\/\/([^:]+):([^@]+)@(.+)$/);if(!e)throw new Error("Invalid apiToken format. Expected: http://username:token@host:port");let[,t,o,s,c]=e,a=`${t}://${c}`,n=T.create({baseURL:a,auth:{username:o,password:s},proxy:!1,timeout:3e4});return {baseURL:a,auth:{username:o,password:s},axios:n}}async function b(r,e,t){try{let o=await r.axios.post(`/job/${e}/buildWithParameters`,new URLSearchParams({branch:t.branch,mode:t.mode}),{headers:{"Content-Type":"application/x-www-form-urlencoded"}});if(o.status!==201)throw new Error(`Unexpected status: ${o.status}`)}catch(o){throw o.response?o.response.status===403?new Error(`Failed to trigger build: Jenkins rejected the request (HTTP 403).
|
|
15
|
+
This might be due to:
|
|
16
|
+
- Insufficient permissions
|
|
17
|
+
- Jenkins Quiet Period (try again after a few seconds)
|
|
18
|
+
- The job is already queued`):new Error(`Failed to trigger build: HTTP ${o.response.status} - ${o.response.statusText}`):o.code==="ECONNREFUSED"?new Error(`Failed to trigger build: Connection refused to ${r.baseURL}`):new Error(`Failed to trigger build: ${o.message}`)}}async function F(){console.log(i.bold.blue(`
|
|
19
|
+
\u{1F680} Jenkins CLI - Jenkins Deployment CLI
|
|
20
|
+
`));let r=x("Loading configuration...").start(),e=await h().catch(n=>{r.fail(i.red(n.message)),process.exit(1);});r.succeed("Configuration loaded"),r.start("Fetching git branches...");let[t,o]=await Promise.all([w(),g()]).catch(n=>{r.fail(i.red(n.message)),process.exit(1);});r.succeed(`Found ${t.length} branches`);let s;try{s=await J.prompt([{type:"list",name:"branch",message:"\u8BF7\u9009\u62E9\u8981\u6253\u5305\u7684\u5206\u652F:",choices:t,default:t.indexOf(o)},{type:"checkbox",name:"modes",message:"\u8BF7\u9009\u62E9\u8981\u6253\u5305\u7684\u73AF\u5883:",choices:e.modes,validate:n=>n.length===0?"You must select at least one environment":!0}]);}catch{console.log(i.yellow(`
|
|
21
|
+
\u{1F44B} Cancelled by user`)),process.exit(0);}console.log();let c=y(e.apiToken),a=s.modes.map(async n=>{let u=x(`Triggering build for ${i.yellow(n)}...`).start();try{await b(c,e.job,{branch:s.branch,mode:n}),u.succeed(`${i.green(n)} - Build triggered successfully`);}catch(d){throw u.fail(`${i.red(n)} - ${d.message}`),d}});try{await Promise.all(a),console.log();}catch{console.log(i.bold.red(`
|
|
22
|
+
\u274C Some builds failed. Check the output above.
|
|
23
|
+
`)),process.exit(1);}}program.name("jenkins-cli").description("Jenkins Deployment CLI").version("1.0.0").action(F);program.parse();
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
|
|
3
|
+
interface JenkinsConfig {
|
|
4
|
+
apiToken: string;
|
|
5
|
+
job: string;
|
|
6
|
+
modes: string[];
|
|
7
|
+
}
|
|
8
|
+
interface BuildParams {
|
|
9
|
+
branch: string;
|
|
10
|
+
mode: string;
|
|
11
|
+
}
|
|
12
|
+
interface UserChoices {
|
|
13
|
+
branch: string;
|
|
14
|
+
modes: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
declare function loadConfig(): Promise<JenkinsConfig>;
|
|
18
|
+
|
|
19
|
+
declare function getCurrentBranch(): Promise<string>;
|
|
20
|
+
declare function getAllBranches(): Promise<string[]>;
|
|
21
|
+
|
|
22
|
+
interface JenkinsClient {
|
|
23
|
+
baseURL: string;
|
|
24
|
+
auth: {
|
|
25
|
+
username: string;
|
|
26
|
+
password: string;
|
|
27
|
+
};
|
|
28
|
+
axios: AxiosInstance;
|
|
29
|
+
}
|
|
30
|
+
declare function createJenkinsClient(apiToken: string): JenkinsClient;
|
|
31
|
+
declare function triggerBuild(jenkins: JenkinsClient, job: string, params: BuildParams): Promise<void>;
|
|
32
|
+
|
|
33
|
+
export { BuildParams, JenkinsConfig, UserChoices, createJenkinsClient, getAllBranches, getCurrentBranch, loadConfig, triggerBuild };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import c from 'fs-extra';
|
|
2
|
+
import l from 'js-yaml';
|
|
3
|
+
import a from 'path';
|
|
4
|
+
import { exec } from 'child_process';
|
|
5
|
+
import { promisify } from 'util';
|
|
6
|
+
import x from 'axios';
|
|
7
|
+
|
|
8
|
+
var n="jenkins-cli.yaml";function h(e=process.cwd()){let r=e;for(;;){let o=a.join(r,n);if(c.existsSync(o))return o;let t=a.dirname(r);if(t===r)return null;r=t;}}async function p(){let e=h();if(!e)throw new Error(`Config file not found: ${n}`);try{let r=await c.readFile(e,"utf-8"),o=l.load(r);if(!o.apiToken||!o.job||!Array.isArray(o.modes))throw new Error("Invalid config: apiToken, job, and modes are required");if(o.modes.length===0)throw new Error("Invalid config: modes cannot be empty");return o}catch(r){throw r.code==="ENOENT"?new Error(`Config file not found: ${n}`):r}}var f=promisify(exec);async function w(){try{let{stdout:e}=await f("git branch --show-current"),r=e.trim();if(!r)throw new Error("Not on any branch (detached HEAD state)");return r}catch{throw new Error("Failed to get current branch. Are you in a git repository?")}}async function y(){try{let{stdout:e}=await f('git branch -r --format="%(refname:short)"');return e.split(`
|
|
9
|
+
`).filter(r=>r.includes("/"))}catch{throw new Error("Failed to list branches. Are you in a git repository?")}}function E(e){let r=e.match(/^(https?):\/\/([^:]+):([^@]+)@(.+)$/);if(!r)throw new Error("Invalid apiToken format. Expected: http://username:token@host:port");let[,o,t,i,d]=r,s=`${o}://${d}`,u=x.create({baseURL:s,auth:{username:t,password:i},proxy:!1,timeout:3e4});return {baseURL:s,auth:{username:t,password:i},axios:u}}async function b(e,r,o){try{let t=await e.axios.post(`/job/${r}/buildWithParameters`,new URLSearchParams({branch:o.branch,mode:o.mode}),{headers:{"Content-Type":"application/x-www-form-urlencoded"}});if(t.status!==201)throw new Error(`Unexpected status: ${t.status}`)}catch(t){throw t.response?t.response.status===403?new Error(`Failed to trigger build: Jenkins rejected the request (HTTP 403).
|
|
10
|
+
This might be due to:
|
|
11
|
+
- Insufficient permissions
|
|
12
|
+
- Jenkins Quiet Period (try again after a few seconds)
|
|
13
|
+
- The job is already queued`):new Error(`Failed to trigger build: HTTP ${t.response.status} - ${t.response.statusText}`):t.code==="ECONNREFUSED"?new Error(`Failed to trigger build: Connection refused to ${e.baseURL}`):new Error(`Failed to trigger build: ${t.message}`)}}
|
|
14
|
+
|
|
15
|
+
export { E as createJenkinsClient, y as getAllBranches, w as getCurrentBranch, p as loadConfig, b as triggerBuild };
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ts-org/jenkins-cli",
|
|
3
|
+
"version": "1.0.0-prior",
|
|
4
|
+
"description": "Jenkins deployment CLI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"jenkins-cli": "./dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsup",
|
|
12
|
+
"dev": "NODE_ENV=development tsup --watch",
|
|
13
|
+
"prepublishOnly": "npm run build",
|
|
14
|
+
"link:test": "npm run build && npm link"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"jenkins",
|
|
18
|
+
"cli",
|
|
19
|
+
"deployment",
|
|
20
|
+
"automation"
|
|
21
|
+
],
|
|
22
|
+
"author": "Lynn<zmzchn@gmail.com>",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://gitee.com/u-web/jenkins-cli.git"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://gitee.com/u-web/jenkins-cli",
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"axios": "^1.6.7",
|
|
36
|
+
"chalk": "^4.1.2",
|
|
37
|
+
"commander": "11.1.0",
|
|
38
|
+
"fs-extra": "^11.2.0",
|
|
39
|
+
"inquirer": "8.2.7",
|
|
40
|
+
"js-yaml": "^4.1.1",
|
|
41
|
+
"ora": "^5.4.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/fs-extra": "^11.0.4",
|
|
45
|
+
"@types/inquirer": "^8.2.10",
|
|
46
|
+
"@types/js-yaml": "^4.0.9",
|
|
47
|
+
"@types/node": "^16.18.119",
|
|
48
|
+
"tsup": "^6.7.0",
|
|
49
|
+
"typescript": "^5.3.3"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=16"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
}
|
|
57
|
+
}
|