(https://github.com/kub1x)"
8 | ],
9 | "license": "MIT",
10 | "keywords": [
11 | "github",
12 | "jenkins"
13 | ],
14 | "engine": {
15 | "node": ">=0.4"
16 | },
17 | "main": "./lib/main.js",
18 | "scripts": {
19 | "build": "babel ./src --out-dir ./lib",
20 | "audit": "nsp check package",
21 | "lint": "#eslint src test",
22 | "check": "npm run audit && ncu && npm outdated --depth 0",
23 | "test": "npm run build && mocha ./test/main.js",
24 | "validate": "npm run lint && npm test",
25 | "prepare": "npm run build && npm run validate && npm run check",
26 | "major": "pmm major",
27 | "minor": "pmm minor",
28 | "patch": "pmm patch"
29 | },
30 | "pre-commit": [
31 | "validate"
32 | ],
33 | "dependencies": {
34 | "request": "^2.81.0"
35 | },
36 | "devDependencies": {
37 | "async": "^2.5.0",
38 | "babel-cli": "^6.24.1",
39 | "babel-eslint": "^7.2.3",
40 | "babel-plugin-transform-function-bind": "^6.22.0",
41 | "babel-preset-es2015": "^6.24.1",
42 | "bluebird": "^3.5.0",
43 | "chai": "^4.1.1",
44 | "chai-like": "^0.2.14",
45 | "chai-things": "^0.2.0",
46 | "eslint": "^4.4.0",
47 | "mocha": "^3.5.0",
48 | "ncu": "^0.2.1",
49 | "nsp": "^2.7.0",
50 | "pmm": "^1.3.1"
51 | },
52 | "repository": {
53 | "type": "git",
54 | "url": "git@github.com:jansepar/node-jenkins-api.git"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/test/test_with_report_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | junit report
5 | false
6 |
7 |
8 | true
9 | false
10 | false
11 | false
12 |
13 | false
14 |
15 |
16 | echo '<?xml version="1.0" encoding="UTF-8"?>
17 | <testsuites>
18 | <testsuite name="JUnitXmlReporter" errors="0" skipped="0" tests="1" failures="0" time="0.006" timestamp="2013-05-24T10:23:58">
19 | <properties>
20 | <property name="java.vendor" value="Sun Microsystems Inc." />
21 | <property name="compiler.debug" value="on" />
22 | <property name="project.jdk.classpath" value="jdk.classpath.1.6" />
23 | </properties>
24 | <testcase classname="JUnitXmlReporter" name="should do" time="0" />
25 | </testsuite>
26 | </testsuites>' > report.xml
27 |
28 |
29 |
30 |
31 | *.xml
32 | false
33 | 1.0
34 | false
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/testjenkinsapi.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This is my poor excuse of a test file. One day, I will write some unit tests.
3 | * Until then, this is all I have :)
4 | */
5 |
6 | var jenkinsapi = require('./lib/main');
7 |
8 |
9 | var jenkins = jenkinsapi.init("http://localhost:8080");
10 |
11 | /*
12 | jenkins.build('test', function(error, data) {
13 | if (error) {
14 | console.log(error);
15 | }
16 | console.log(data);
17 | });
18 | */
19 |
20 | /*
21 | var view_name = "test";
22 | jenkins.all_jobs_in_view(view_name, function (error, data) {
23 | if (error) {
24 | console.log(error);
25 | }
26 | console.log(data);
27 | });
28 | */
29 |
30 | /*
31 | jenkins.all_jobs(function(error, data) { console.log(data)});
32 | */
33 |
34 | /*
35 | jenkins.job_info('test-madness', function(error, data) {
36 | if(!error) {
37 | console.log(data);
38 | }
39 |
40 | });
41 | */
42 |
43 | /*
44 | jenkins.job_info('test', function(error, data) {
45 | if (!error) {
46 | console.log(data);
47 | }
48 |
49 | });
50 | */
51 |
52 | //jenkins.last_build_info('test-development', function(error, data) { console.log(data); });
53 | //jenkins.last_build_report('test-development', function(error, data) { console.log(data); });
54 |
55 | /*
56 | jenkins.get_config_xml('test-development', function(error, data) {
57 | //console.log(data);
58 | jenkins.create_job('test-copy', data, function(error, data) {
59 | //console.log(data);
60 | });
61 | });
62 | */
63 | /*
64 | jenkins.copy_job('test-development'
65 | ,'test-new'
66 | ,function(data) {
67 | return data.replace('development','feature-branch');
68 | }
69 | ,function(error, data) {
70 | //console.log(data);
71 | jenkins.delete_job('test-new', function(error, data) {
72 | if(error) {
73 | console.log("error!");
74 | }
75 | console.log(data);
76 | });
77 | });
78 | */
79 | /*
80 | jenkins.delete_job('test-new', function(error, data) {
81 | if(error) {
82 | console.log("error!");
83 | console.log(data.body, data.statusCode);
84 | */
85 |
86 | //jenkins.computers(function(error, data) { console.log(data)});
87 |
88 | //jenkins.queue(function(error, data) { console.log(data)});
89 |
90 | jenkins.build
91 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "env": {
4 | "es6": true,
5 | "node": true,
6 | "mocha": true,
7 | "browser": true
8 | },
9 | "parserOptions": {
10 | "ecmaVersion": 6,
11 | "sourceType": "module",
12 | "ecmaFeatures": {
13 | "impliedStrict": true
14 | },
15 | },
16 | "rules": {
17 | // possible errors
18 | "comma-dangle": [2, "never"],
19 | "no-cond-assign": [2, "always"],
20 | "no-console": [2],
21 | "no-constant-condition": [2],
22 | "no-control-regex": [2],
23 | "no-debugger": [2],
24 | "no-dupe-args": [2],
25 | "no-dupe-keys": [2],
26 | "no-duplicate-case": [2],
27 | "no-empty": [2],
28 | "no-empty-character-class": [2],
29 | "no-ex-assign": [2],
30 | "no-extra-boolean-cast": [2],
31 | "no-extra-parens": [0],
32 | "no-extra-semi": [2],
33 | "no-func-assign": [2],
34 | "no-inner-declarations": [2],
35 | "no-invalid-regexp": [2],
36 | "no-irregular-whitespace": [2],
37 | "no-negated-in-lhs": [2],
38 | "no-obj-calls": [2],
39 | "no-regex-spaces": [2],
40 | "no-sparse-arrays": [2],
41 | "no-unexpected-multiline": [2],
42 | "no-unreachable": [2],
43 | "use-isnan": [2],
44 | "valid-jsdoc": [2, {
45 | "requireReturn": false,
46 | "requireParamDescription": false,
47 | "requireReturnDescription": false
48 | }],
49 | "valid-typeof": [2],
50 |
51 | // best practices
52 | "accessor-pairs": [2],
53 | "array-callback-return": [2],
54 | "block-scoped-var": [2],
55 | "complexity": [1, 8],
56 | "consistent-return": [0],
57 | "curly": [2, "multi-line"],
58 | "default-case": [2],
59 | "dot-location": [2, "property"],
60 | "dot-notation": [2],
61 | "eqeqeq": [2],
62 | "guard-for-in": [0],
63 | "no-alert": [2],
64 | "no-caller": [2],
65 | "no-case-declarations": [2],
66 | "no-div-regex": [2],
67 | "no-else-return": [2],
68 | "no-empty-function": [2],
69 | "no-empty-pattern": [2],
70 | "no-eq-null": [2],
71 | "no-eval": [2],
72 | "no-extend-native": [2],
73 | "no-extra-bind": [2],
74 | "no-extra-label": [2],
75 | "no-fallthrough": [2],
76 | "no-floating-decimal": [2],
77 | "no-implicit-coercion": [0],
78 | "no-implicit-globals": [2],
79 | "no-implied-eval": [2],
80 | "no-invalid-this": [2],
81 | "no-iterator": [2],
82 | "no-labels": [2],
83 | "no-lone-blocks": [2],
84 | "no-loop-func": [2],
85 | "no-magic-numbers": [1, { "ignoreArrayIndexes": true }],
86 | "no-multi-spaces": [2],
87 | "no-multi-str": [2],
88 | "no-native-reassign": [2],
89 | "no-new": [2],
90 | "no-new-func": [2],
91 | "no-new-wrappers": [2],
92 | "no-octal": [2],
93 | "no-octal-escape": [2],
94 | "no-param-reassign": [0],
95 | "no-process-env": [0],
96 | "no-proto": [2],
97 | "no-redeclare": [2],
98 | "no-return-assign": [2],
99 | "no-script-url": [2],
100 | "no-self-assign": [2],
101 | "no-self-compare": [2],
102 | "no-sequences": [2],
103 | "no-throw-literal": [2],
104 | "no-unmodified-loop-condition": [2],
105 | "no-unused-expressions": [2, { "allowShortCircuit": true }],
106 | "no-unused-labels": [2],
107 | "no-useless-call": [2],
108 | "no-useless-concat": [2],
109 | "no-void": [2],
110 | "no-warning-comments": [0],
111 | "no-with": [2],
112 | "radix": [2],
113 | "vars-on-top": [0],
114 | "wrap-iife": [2, "inside"],
115 | "yoda": [2, "never"],
116 |
117 | // strict
118 | "strict": [0],
119 |
120 | // variables
121 | "init-declarations": [0],
122 | "no-catch-shadow": [2],
123 | "no-delete-var": [2],
124 | "no-label-var": [2],
125 | "no-shadow": [2],
126 | "no-shadow-restricted-names": [2],
127 | "no-undef": [2],
128 | "no-undef-init": [2],
129 | "no-undefined": [2],
130 | "no-unused-vars": [2],
131 | "no-use-before-define": [2],
132 |
133 | // node.js
134 | "callback-return": [0],
135 | "global-require": [0],
136 | "handle-callback-err": [2],
137 | "no-mixed-requires": [2],
138 | "no-new-require": [2],
139 | "no-path-concat": [2],
140 | "no-process-exit": [2],
141 | "no-restricted-imports": [0],
142 | "no-restricted-modules": [0],
143 | "no-sync": [0],
144 |
145 | // stylistic
146 | "array-bracket-spacing": [2, "never"],
147 | "block-spacing": [2],
148 | "brace-style": [2, "1tbs", { "allowSingleLine": true }],
149 | "camelcase": [2, { "properties": "never" }],
150 | "comma-spacing": [2, {
151 | "before": false,
152 | "after": true
153 | }],
154 | "comma-style": [2, "last"],
155 | "computed-property-spacing": [2, "never"],
156 | "consistent-this": [2, "_this"],
157 | "eol-last": [2],
158 | "func-names": [0],
159 | "func-style": [0],
160 | "indent": [2, 2],
161 | "jsx-quotes": [2, "prefer-single"],
162 | "key-spacing": [2, {
163 | "beforeColon": false,
164 | "afterColon": true
165 | }],
166 | "keyword-spacing": [2],
167 | "linebreak-style": [2, "unix"],
168 | "lines-around-comment": [2, {
169 | "beforeBlockComment": true
170 | }],
171 | "max-depth": [2, 4],
172 | "max-len": [2, 120, 4],
173 | "max-nested-callbacks": [2, 4],
174 | "max-params": [0],
175 | "max-statements": [0],
176 | "new-cap": [2],
177 | "new-parens": [2],
178 | "newline-after-var": [2],
179 | "newline-per-chained-call": [0],
180 | "no-array-constructor": [2],
181 | "no-bitwise": [0],
182 | "no-continue": [0],
183 | "no-inline-comments": [0],
184 | "no-lonely-if": [2],
185 | "no-mixed-spaces-and-tabs": [2],
186 | "no-multiple-empty-lines": [2],
187 | "no-negated-condition": [0],
188 | "no-nested-ternary": [2],
189 | "no-new-object": [2],
190 | "no-plusplus": [0],
191 | "no-spaced-func": [2],
192 | "no-ternary": [0],
193 | "no-trailing-spaces": [2],
194 | "no-underscore-dangle": [0],
195 | "no-unneeded-ternary": [2],
196 | "no-whitespace-before-property": [2],
197 | "object-curly-spacing": [2, "always"],
198 | "one-var": [2, {
199 | "uninitialized": "always",
200 | "initialized": "never"
201 | }],
202 | "one-var-declaration-per-line": [0],
203 | "operator-assignment": [0],
204 | "operator-linebreak": [2, "before"],
205 | "padded-blocks": [0],
206 | "quote-props": [2, "as-needed"],
207 | "quotes": [2, "single"],
208 | "require-jsdoc": [0],
209 | "semi": [2, "always"],
210 | "semi-spacing": [2, {
211 | "before": false,
212 | "after": true
213 | }],
214 | "sort-imports": [0],
215 | "sort-vars": [0],
216 | "space-before-blocks": [2, "always"],
217 | "space-before-function-paren": [2, {
218 | "anonymous": "always",
219 | "named": "never"
220 | }],
221 | "space-in-parens": [2, "never"],
222 | "space-infix-ops": [2],
223 | "space-unary-ops": [2],
224 | "spaced-comment": [2, "always"],
225 | "wrap-regex": [2],
226 |
227 | // ecmascript6
228 | "arrow-body-style": [0],
229 | "arrow-parens": [2],
230 | "arrow-spacing": [2, { "before": true, "after": true }],
231 | "constructor-super": [2],
232 | "generator-star-spacing": [2, "after"],
233 | "no-class-assign": [2],
234 | "no-confusing-arrow": [0],
235 | "no-const-assign": [2],
236 | "no-dupe-class-members": [2],
237 | "no-new-symbol": [2],
238 | "no-this-before-super": [2],
239 | "no-useless-constructor": [2],
240 | "no-var": [2],
241 | "object-shorthand": [0],
242 | "prefer-arrow-callback": [0],
243 | "prefer-const": [2],
244 | "prefer-reflect": [0],
245 | "prefer-rest-params": [0],
246 | "prefer-spread": [0],
247 | "prefer-template": [2],
248 | "require-yield": [2],
249 | "template-curly-spacing": [2, "never"]
250 | }
251 | }
252 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | nodejs-jenkins-api
2 | =================
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ## Install
19 |
20 |
21 | npm install jenkins-api
22 |
23 |
24 | ## Usage
25 |
26 | ### Setup
27 |
28 | ```javascript
29 | var jenkinsapi = require('jenkins-api');
30 |
31 | // no auth
32 | var jenkins = jenkinsapi.init("http://jenkins.yoursite.com");
33 |
34 | // username/password
35 | var jenkins = jenkinsapi.init("http://username:password@jenkins.yoursite.com");
36 |
37 | // API Token
38 | var jenkins = jenkinsapi.init('https://username:token@jenkins.company.com');
39 |
40 | // Password that needs to be %-encoded
41 | const { URL } = require('url');
42 | const jenkinsUrl = new URL('https://username@jenkins.company.com');
43 | jenkinsUrl.password = 'some_weirdPASSWORD123!@#$%^&*()~`\\/;\'';
44 | var jenkins = jenkinsapi.init(jenkinsUrl.href);
45 | ```
46 |
47 | If you need additional request parameters you can add them as explained in 'optional' section.
48 |
49 |
50 | ### Builds
51 |
52 | #### build
53 | ```javascript
54 | jenkins.build('job-in-jenkins', (optional){token: 'jenkins-token', ...}, function(err, data) {
55 | if (err){ return console.log(err); }
56 | console.log(data)
57 | });
58 | ```
59 |
60 | #### build_with_params
61 | ```javascript
62 | jenkins.build_with_params('job-in-jenkins', (optional){depth: 1, :, token: 'jenkins-token',...}, function(err, data) {
63 | if (err){ return console.log(err); }
64 | console.log(data)
65 | });
66 | ```
67 |
68 | #### stop build
69 | ```javascript
70 | jenkins.stop_build('job-in-jenkins', 'build-number', (optional){token: 'jenkins-token', ...}, function(err, data) {
71 | if (err){ return console.log(err); }
72 | console.log(data)
73 | });
74 | ```
75 |
76 | #### console output
77 | ```javascript
78 | jenkins.console_output('job-in-jenkins', 'buildname', (optional) {depth: 1, :, ...}, function(err, data) {
79 | if (err){ return console.log(err); }
80 | console.log(data)
81 | });
82 | ```
83 |
84 | #### build info
85 | ```javascript
86 | jenkins.build_info('job-in-jenkins', 'build-number', (optional) {depth: 1, :, ...}, function(err, data) {
87 | if (err){ return console.log(err); }
88 | console.log(data)
89 | });
90 | ```
91 |
92 | #### last build info
93 | ```javascript
94 | jenkins.last_build_info('job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
95 | if (err){ return console.log(err); }
96 | console.log(data)
97 | });
98 | ```
99 |
100 | #### last completed build info
101 | ```javascript
102 | jenkins.last_completed_build_info('job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
103 | if (err){ return console.log(err); }
104 | console.log(data)
105 | });
106 | ```
107 |
108 | #### all builds
109 | ```javascript
110 | jenkins.all_builds('job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
111 | if (err){ return console.log(err); }
112 | console.log(data)
113 | });
114 | ```
115 |
116 | #### test result/report
117 | ```javascript
118 | jenkins.test_result('job-in-jenkins', 'build-number', (optional) {depth: 1, :, ...}, function(err, data) {
119 | if (err){ return console.log(err); }
120 | console.log(data)
121 | });
122 | ```
123 |
124 | #### last build report - OBSOLET use `last_build_info`
125 | ```javascript
126 | // jenkins.last_build_report('job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
127 | // if (err){ return console.log(err); }
128 | // console.log(data)
129 | // });
130 | ```
131 |
132 | #### delete build data for job
133 | ```javascript
134 | jenkins.delete_build('job-in-jenkins', 'build-number', (optional) {depth: 1, :, ...}, function(err, data) {
135 | if (err){ return console.log(err); }
136 | console.log(data)
137 | });
138 | ```
139 |
140 |
141 | ### Jobs
142 |
143 | #### all jobs
144 | ```javascript
145 | jenkins.all_jobs((optional){token: 'jenkins-token', ...}, function(err, data) {
146 | if (err){ return console.log(err); }
147 | console.log(data)
148 | });
149 | ```
150 |
151 | #### get config xml
152 | ```javascript
153 | jenkins.get_config_xml('job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
154 | if (err){ return console.log(err); }
155 | console.log(data)
156 | });
157 | ```
158 |
159 | ### update existing job configuration
160 | ```javascript
161 | jenkins.update_config('job-to-update'
162 | ,function(config) {
163 | // function which takes the config.xml, and returns
164 | // the new config xml for the new job
165 | return config.replace('development','feature-branch');
166 | }
167 | ,(optional){token: 'jenkins-token', ...}
168 | ,function(err, data) {
169 | // if no error, job was copied
170 | if (err){ return console.log(err); }
171 | console.log(data)
172 | });
173 | ```
174 |
175 | #### update job
176 | ```javascript
177 | jenkins.update_job('job-to-update', xmlConfigString, (optional){token: 'jenkins-token', ...}, function(err, data) {
178 | // if no error, job was copied
179 | if (err){ return console.log(err); }
180 | console.log(data)
181 | });
182 | ```
183 |
184 | #### job info
185 | ```javascript
186 | jenkins.job_info('job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
187 | if (err){ return console.log(err); }
188 | console.log(data)
189 | });
190 | ```
191 |
192 | #### create job
193 | ```javascript
194 | jenkins.create_job('job-in-jenkins', xmlConfigString, (optional) {depth: 1, :, ...}, function(err, data) {
195 | if (err){ return console.log(err); }
196 | console.log(data)
197 | });
198 | ```
199 |
200 | #### copy job
201 | ```javascript
202 | jenkins.copy_job('job-to-copy'
203 | ,'new-job-title'
204 | ,function(config) {
205 | // function which takes the config.xml, and returns
206 | // the new config xml for the new job
207 | return config.replace('development','feature-branch');
208 | }
209 | ,(optional){token: 'jenkins-token', ...}
210 | ,function(err, data) {
211 | // if no error, job was copied
212 | if (err){ return console.log(err); }
213 | console.log(data)
214 | });
215 | ```
216 |
217 | #### delete job
218 | ```javascript
219 | jenkins.delete_job('job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
220 | if (err){ return console.log(err); }
221 | console.log(data)
222 | });
223 | ```
224 |
225 | #### enable job
226 | ```javascript
227 | jenkins.enable_job('job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
228 | if (err){ return console.log(err); }
229 | console.log(data)
230 | });
231 | ```
232 |
233 | #### disable job
234 | ```javascript
235 | jenkins.disable_job('job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
236 | if (err){ return console.log(err); }
237 | console.log(data)
238 | });
239 | ```
240 |
241 | #### last success
242 | ```javascript
243 | jenkins.last_success('job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
244 | if (err){ return console.log(err); }
245 | console.log(data)
246 | });
247 | ```
248 |
249 | #### last result
250 | ```javascript
251 | jenkins.last_result('job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
252 | if (err){ return console.log(err); }
253 | console.log(data)
254 | });
255 | ```
256 |
257 |
258 | ### Queue
259 |
260 | #### get all queued items
261 | ```javascript
262 | jenkins.queue((optional){token: 'jenkins-token', ...}, function(err, data) {
263 | if (err){ return console.log(err); }
264 | console.log(data)
265 | });
266 | ```
267 |
268 | #### get one queued item
269 | ```javascript
270 | jenkins.queue_item('queue-item-number', (optional) {depth: 1, :, ...}, function(err, data) {
271 | if (err){ return console.log(err); }
272 | console.log(data)
273 | });
274 | ```
275 |
276 | #### cancel queued item
277 | ```javascript
278 | jenkins.cancel_item('queue-item-number', (optional) {depth: 1, :, ...}, function(err, data) {
279 | if (err){ return console.log(err); }
280 | console.log(data)
281 | });
282 | ```
283 |
284 | #### get all jenkins computers (aka workers)
285 | ```javascript
286 | jenkins.computers((optional){token: 'jenkins-token', ...}, function(err, data) {
287 | if (err){ return console.log(err); }
288 | console.log(data)
289 | });
290 | ```
291 |
292 |
293 | ### Views
294 |
295 | #### get all views
296 | ```javascript
297 | jenkins.all_views((optional) {depth: 1, :, ...}, function(err, data) {
298 | if (err){ return console.log(err); }
299 | console.log(data)
300 | });
301 | ```
302 |
303 | #### create view
304 | ```javascript
305 | jenkins.create_view('new-view-name', (optional)viewMode = 'hudson.model.ListView', (optional){token: 'jenkins-token', ...}, function(err, data) {
306 | if (err){ return console.log(err); }
307 | console.log(data)
308 | });
309 | ```
310 |
311 | #### view info
312 | ```javascript
313 | jenkins.create_view('view-name', (optional){token: 'jenkins-token', ...}, function(err, data) {
314 | if (err){ return console.log(err); }
315 | console.log(data)
316 | });
317 | ```
318 |
319 | #### update view
320 | ```javascript
321 | var viewConfig = {
322 | name: "view-in-jenkins",
323 | "description": "This is the view-in-jenkins View",
324 | "statusFilter": "",
325 | "job-in-jenkins": true,
326 | "useincluderegex": true,
327 | "includeRegex": "prefix.*",
328 | "columns": [{"stapler-class": "hudson.views.StatusColumn", "$class": "hudson.views.StatusColumn"}, {"stapler-class": "hudson.views.WeatherColumn", "$class": "hudson.views.WeatherColumn"}, {"stapler-class": "hudson.views.JobColumn", "$class": "hudson.views.JobColumn"}, {"stapler-class": "hudson.views.LastSuccessColumn", "$class": "hudson.views.LastSuccessColumn"}, {"stapler-class": "hudson.views.LastFailureColumn", "$class": "hudson.views.LastFailureColumn"}, {"stapler-class": "hudson.views.LastDurationColumn", "$class": "hudson.views.LastDurationColumn"}, {"stapler-class": "hudson.views.BuildButtonColumn", "$class": "hudson.views.BuildButtonColumn"}]
329 | };
330 |
331 | jenkins.update_view('view-in-jenkins', viewConfig, (optional){token: 'jenkins-token', ...}, function(err, data) {
332 | if (err){ return console.log(err); }
333 | console.log(data)
334 | });
335 | ```
336 |
337 | #### delete view
338 | ```javascript
339 | jenkins.delete_view('view-in-jenkins', (optional){token: 'jenkins-token', ...}, function(err, data) {
340 | if (err){ return console.log(err); }
341 | console.log(data)
342 | });
343 | ```
344 |
345 | #### add job to view
346 | ```javascript
347 | jenkins.add_job_to_view('view-in-jenkins', 'job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
348 | if (err){ return console.log(err); }
349 | console.log(data)
350 | });
351 | ```
352 |
353 | #### remove job from view
354 | ```javascript
355 | jenkins.remove_job_from_view('view-in-jenkins', 'job-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
356 | if (err){ return console.log(err); }
357 | console.log(data)
358 | });
359 | ```
360 |
361 | #### get all jobs in view
362 | ```javascript
363 | jenkins.all_jobs_in_view('view-in-jenkins', (optional) {depth: 1, :, ...}, function(err, data) {
364 | if (err){ return console.log(err); }
365 | console.log(data)
366 | });
367 | ```
368 |
369 |
370 | ### Plugins
371 |
372 | #### get all installed plugins
373 | ```javascript
374 | jenkins.all_installed_plugins((optional){token: 'jenkins-token', ...}, function(err, data){
375 | if (err){ return console.log(err); }
376 | console.log(data)
377 | })
378 | ```
379 |
380 | #### install a plugin
381 | ```javascript
382 | // var plugin = 'copyartifact@1.3.8';
383 | var plugin = 'copyartifact@current';
384 | jenkins.install_plugin(plugin, (optional){token: 'jenkins-token', ...}, function(err, data){
385 | if (err){ return console.log(err, data); }
386 | console.log(data)
387 | });
388 | ```
389 | NOTE: It will report successful even if the plugin is already installed.
390 | NOTE: Prevent Cross Site Request Forgery exploits need be disabled in Configure Global Security.
391 |
392 |
393 |
394 | ## Default configuration
395 |
396 | You can set the default configuration which will be use in all HTTP requests by calling init with the additional options parameter:
397 |
398 | ```javascript
399 | // default request options
400 | var jenkins = jenkinsapi.init("http://jenkins.yoursite.com", {request: {strictSSL: false}});
401 | ```
402 |
403 | Futhermore, you can set your remote job token for authentication (as well as any other default url params):
404 |
405 | ```javascript
406 | // default request options
407 | var jenkins = jenkinsapi.init("http://jenkins.yoursite.com", {request: {strictSSL: false}}, {token: ''});
408 | ```
409 |
410 | Since node-jenkins-api uses [request/request](https://github.com/request/request) as HTTP client, please refer to the documentation for available options. Default values can be found in the source code (search for "default").
411 |
412 |
413 | ## Notes
414 |
415 | Modeled after the [Python Jenkins API](https://github.com/txels/autojenkins)
416 |
417 |
--------------------------------------------------------------------------------
/test/main.js:
--------------------------------------------------------------------------------
1 | const async = require('async');
2 | const fs = require('fs');
3 | const chai = require('chai');
4 | const expect = chai.expect;
5 |
6 | const chaiLike = require('chai-like');
7 | const chaiThings = require('chai-things');
8 |
9 | chai.use(chaiLike);
10 | chai.use(chaiThings);
11 |
12 | const jenkinsapi = require('../lib/main');
13 | const JENKINS_URL = 'http://localhost:8080';
14 |
15 | // var USER = 'jenkins';
16 | // var TOKEN = 'a5af9f12a1723c2a45c4c6bfd88d0044';
17 | // var JENKINS_URL = "http://" + USER + ":" + TOKEN + "@localhost:8080";
18 |
19 | const JOB_NAME_TEST = 'asrwqersfdzdraser-test';
20 | const JOB_NAME_NEW = 'asrwqersfdzdraser-test-new';
21 | const JOB_NAME_COPY = 'asrwqersfdzdraser-test-copy';
22 | const JOB_NAME_REPORT = 'asrwqersfdzdraser-test-with-report';
23 |
24 | const TEST_CONFIG_XML_FILE = 'test/test_config.xml';
25 | const TEST_WITH_PARAMS_CONFIG_XML_FILE = 'test/test_with_params_config.xml';
26 | const TEST_WITH_REPORT_CONFIG_XML_FILE = 'test/test_with_report_config.xml';
27 | const DEVELOPMENT_PROJECT_XML_CONFIG
28 | = 'development';
29 | const ORIGINAL_DESCRIPTION = 'development';
30 | const REPLACED_DESCRIPTION = 'feature';
31 |
32 | describe('Node Jenkins API', function () {
33 |
34 | let jenkins;
35 |
36 | before(function (done) {
37 |
38 | it('Should exist', function () {
39 | expect(jenkinsapi.init).to.be.a('function');
40 | });
41 |
42 | jenkins = jenkinsapi.init(JENKINS_URL);
43 |
44 | expect(jenkins.delete_job).to.be.a('function');
45 | expect(jenkins.all_jobs).to.be.a('function');
46 |
47 | async.waterfall([
48 | (next) => {
49 | // Ignoring 404 errors
50 | async.parallel([
51 | (cb) => jenkins.delete_job(JOB_NAME_TEST, () => cb()),
52 | (cb) => jenkins.delete_job(JOB_NAME_NEW, () => cb()),
53 | (cb) => jenkins.delete_job(JOB_NAME_COPY, () => cb())
54 | ], () => next());
55 | },
56 | (next) => {
57 | fs.readFile(TEST_CONFIG_XML_FILE, 'utf8', next);
58 | },
59 | (xmlConfig, next) => {
60 | jenkins.create_job(JOB_NAME_TEST, xmlConfig, next);
61 | },
62 | (data, next) => {
63 | jenkins.all_jobs(next);
64 | },
65 | (data, next) => {
66 | expect(data).to.be.an('array').that.contains.something.like({ name: JOB_NAME_TEST });
67 | next();
68 | }
69 | ], done);
70 | });
71 |
72 | it('Should show all jobs', function (done) {
73 | expect(jenkins.all_jobs).to.be.a('function');
74 |
75 | jenkins.all_jobs(function (error, data) {
76 | expect(data).to.be.an('array').that.contains.something.like({ name: JOB_NAME_TEST });
77 | done(error);
78 | }); // all_jobs
79 | });
80 |
81 |
82 | it('Should read xml of existing job', function (done) {
83 | expect(jenkins.get_config_xml).to.be.a('function');
84 |
85 | jenkins.get_config_xml(JOB_NAME_TEST, function (error, data) {
86 | expect(data).to.be.a('string').that.contains(ORIGINAL_DESCRIPTION);
87 | done(error);
88 | }); // get_config_xml
89 | });
90 |
91 |
92 | it('Should show job info', function (done) {
93 | expect(jenkins.job_info).to.be.a('function');
94 |
95 | jenkins.job_info(JOB_NAME_TEST, function (error, data) {
96 | expect(data).to.be.an('object').like({ name: JOB_NAME_TEST, description: ORIGINAL_DESCRIPTION });
97 | done(error);
98 | }); // job_info
99 | });
100 |
101 |
102 | it('Should create and delete job', function (done) {
103 | expect(jenkins.create_job).to.be.a('function');
104 | expect(jenkins.delete_job).to.be.a('function');
105 |
106 | async.waterfall([
107 | (next) => {
108 | jenkins.create_job(JOB_NAME_NEW, DEVELOPMENT_PROJECT_XML_CONFIG, next);
109 | },
110 | (data, next) => {
111 | expect(data).to.be.an('object').like({ name: JOB_NAME_NEW });
112 | jenkins.all_jobs(next);
113 | },
114 | (data, next) => {
115 | expect(data).to.be.an('array').that.contains.something.like({ name: JOB_NAME_NEW });
116 | jenkins.delete_job(JOB_NAME_NEW, next);
117 | },
118 | (data, next) => {
119 | expect(data).to.be.an('object').like({ name: JOB_NAME_NEW });
120 | jenkins.all_jobs(next);
121 | },
122 | (data, next) => {
123 | expect(data).to.be.an('array').that.does.not.contain.something.like({ name: JOB_NAME_NEW });
124 | next();
125 | }
126 | ], done);
127 | });
128 |
129 |
130 | it('Should copy job', function (done) {
131 | expect(jenkins.copy_job).to.be.a('function');
132 |
133 | async.waterfall([
134 | (next) => {
135 | jenkins.copy_job(
136 | JOB_NAME_TEST,
137 | JOB_NAME_COPY,
138 | (data) => data.replace(ORIGINAL_DESCRIPTION, REPLACED_DESCRIPTION),
139 | next);
140 | },
141 | (data, next) => {
142 | expect(data).to.be.an('object').like({ name: JOB_NAME_COPY });
143 | jenkins.get_config_xml(JOB_NAME_COPY, next);
144 | },
145 | (data, next) => {
146 | expect(data).to.be.a('string').that.contains(REPLACED_DESCRIPTION);
147 | jenkins.delete_job(JOB_NAME_COPY, next);
148 | }
149 | ], done);
150 | });
151 |
152 |
153 | it('Should update job config', function (done) {
154 | expect(jenkins.update_config).to.be.a('function');
155 |
156 | async.waterfall([
157 | (next) => {
158 | jenkins.copy_job(JOB_NAME_TEST, JOB_NAME_COPY, (data) => data, () => next());
159 | },
160 | (next) => {
161 | jenkins.update_config(JOB_NAME_COPY, (data) => data.replace(ORIGINAL_DESCRIPTION, REPLACED_DESCRIPTION), next);
162 | },
163 | (data, next) => {
164 | expect(data).to.be.an('object').like({ name: JOB_NAME_COPY });
165 | jenkins.get_config_xml(JOB_NAME_COPY, next);
166 | },
167 | (data, next) => {
168 | expect(data).to.be.a('string').that.contains(REPLACED_DESCRIPTION);
169 | jenkins.delete_job(JOB_NAME_COPY, next);
170 | }
171 | ], done);
172 | });
173 |
174 | it('Should disable/enable job', function (done) {
175 | expect(jenkins.disable_job).to.be.a('function');
176 | expect(jenkins.enable_job).to.be.a('function');
177 |
178 | async.waterfall([
179 | (next) => {
180 | jenkins.copy_job(JOB_NAME_TEST, JOB_NAME_COPY, (data) => data, next);
181 | },
182 | (data, next) => {
183 | jenkins.disable_job(JOB_NAME_COPY, next);
184 | },
185 | (data, next) => {
186 | expect(data).to.be.an('object').like({ name: JOB_NAME_COPY, color: 'disabled', buildable: false });
187 | jenkins.enable_job(JOB_NAME_COPY, next);
188 | },
189 | (data, next) => {
190 | expect(data).to.be.an('object').like({ name: JOB_NAME_COPY }).and.not.like({ color: 'disabled' });
191 | jenkins.delete_job(JOB_NAME_COPY, next);
192 | }
193 | ], done);
194 | });
195 |
196 |
197 | const TEST_VIEW_NAME = 'ewoiurewlkjr-test-view';
198 | const TEST_VIEW_CONF = {
199 | name: TEST_VIEW_NAME,
200 | description: `This is the ${TEST_VIEW_NAME} job-in-jenkins View`,
201 | statusFilter: '',
202 | 'job-in-jenkins': true,
203 | useincluderegex: true,
204 | includeRegex: 'prefix.*',
205 | columns: [{
206 | 'stapler-class': 'hudson.views.StatusColumn',
207 | $class: 'hudson.views.StatusColumn'
208 | },
209 | {
210 | 'stapler-class': 'hudson.views.WeatherColumn',
211 | $class: 'hudson.views.WeatherColumn'
212 | },
213 | {
214 | 'stapler-class': 'hudson.views.JobColumn',
215 | $class: 'hudson.views.JobColumn'
216 | }, {
217 | 'stapler-class': 'hudson.views.LastSuccessColumn',
218 | $class: 'hudson.views.LastSuccessColumn'
219 | },
220 | {
221 | 'stapler-class': 'hudson.views.LastFailureColumn',
222 | $class: 'hudson.views.LastFailureColumn'
223 | },
224 | {
225 | 'stapler-class': 'hudson.views.LastDurationColumn',
226 | $class: 'hudson.views.LastDurationColumn'
227 | },
228 | {
229 | 'stapler-class': 'hudson.views.BuildButtonColumn',
230 | $class: 'hudson.views.BuildButtonColumn'
231 | }]
232 | };
233 |
234 | it('Should CRUD a view', function (done) {
235 | expect(jenkins.create_view).to.be.a('function');
236 | expect(jenkins.view_info).to.be.a('function');
237 | expect(jenkins.all_views).to.be.a('function');
238 | expect(jenkins.update_view).to.be.a('function');
239 | expect(jenkins.delete_view).to.be.a('function');
240 |
241 |
242 | async.waterfall([
243 | (next) => {
244 | jenkins.delete_view(TEST_VIEW_NAME, () => next()); // Ignoring error
245 | },
246 | (next) => {
247 | jenkins.create_view(TEST_VIEW_NAME, next);
248 | },
249 | (data, next) => {
250 | expect(data).to.be.an('object').like({ name: TEST_VIEW_NAME });
251 | jenkins.view_info(TEST_VIEW_NAME, next);
252 | },
253 | (data, next) => {
254 | expect(data).to.be.an('object').like({ name: TEST_VIEW_NAME });
255 | jenkins.all_views(next);
256 | },
257 | (data, next) => {
258 | expect(data).to.be.an('array').that.contains.something.like({ name: TEST_VIEW_NAME });
259 | jenkins.update_view(TEST_VIEW_NAME, TEST_VIEW_CONF, next);
260 | },
261 | (data, next) => {
262 | expect(data).to.be.an('object').like({ name: TEST_VIEW_NAME });
263 | jenkins.delete_view(TEST_VIEW_NAME, next);
264 | },
265 | (data, next) => {
266 | expect(data).to.be.an('object').like({ name: TEST_VIEW_NAME });
267 | jenkins.all_views(next);
268 | },
269 | (data, next) => {
270 | expect(data).to.be.an('array').that.does.not.contain.something.like({ name: TEST_VIEW_NAME });
271 | next();
272 | }
273 | ], done);
274 | });
275 |
276 | it('Should add/remove and list jobs in view', function (done) {
277 | expect(jenkins.all_jobs_in_view).to.be.a('function');
278 | expect(jenkins.add_job_to_view).to.be.a('function');
279 | expect(jenkins.remove_job_from_view).to.be.a('function');
280 |
281 | async.waterfall([
282 | (next) => {
283 | jenkins.delete_view(TEST_VIEW_NAME, () => next()); // Ignoring error
284 | },
285 | (next) => {
286 | jenkins.create_view(TEST_VIEW_NAME, next);
287 | },
288 | (data, next) => {
289 | expect(data).to.be.an('object').like({ name: TEST_VIEW_NAME });
290 | jenkins.add_job_to_view(TEST_VIEW_NAME, JOB_NAME_TEST, next);
291 | },
292 | (data, next) => {
293 | jenkins.all_jobs_in_view(TEST_VIEW_NAME, next);
294 | },
295 | (data, next) => {
296 | expect(data).to.be.an('array').that.contains.something.like({ name: JOB_NAME_TEST });
297 | jenkins.remove_job_from_view(TEST_VIEW_NAME, JOB_NAME_TEST, next);
298 | },
299 | (data, next) => {
300 | jenkins.all_jobs_in_view(TEST_VIEW_NAME, next);
301 | },
302 | (data, next) => {
303 | expect(data).to.be.an('array').that.does.not.contain.something.like({ name: JOB_NAME_TEST });
304 | jenkins.delete_view(TEST_VIEW_NAME, next);
305 | },
306 | (data, next) => {
307 | expect(data).to.be.an('object').like({ name: TEST_VIEW_NAME });
308 | next();
309 | }
310 | ], done);
311 | });
312 |
313 |
314 | const APPROX_JOB_RUN_TIME = 11000;
315 | const APPROX_JOB_STOP_TIME = 2000;
316 | const START_TO_END_JOB_TIME = 14000;
317 |
318 | it('Should start/stop and list builds', function (done) {
319 | expect(jenkins.build).to.be.a('function');
320 | expect(jenkins.job_info).to.be.a('function');
321 | expect(jenkins.queue_item).to.be.a('function');
322 | expect(jenkins.all_builds).to.be.a('function');
323 | expect(jenkins.build_info).to.be.a('function');
324 | expect(jenkins.stop_build).to.be.a('function');
325 | expect(jenkins.console_output).to.be.a('function');
326 | expect(jenkins.last_build_info).to.be.a('function');
327 | expect(jenkins.delete_build).to.be.a('function');
328 |
329 | let queueId, buildId;
330 |
331 | async.waterfall([
332 | (next) => {
333 | jenkins.build(JOB_NAME_TEST, next);
334 | },
335 | (data, next) => {
336 | expect(data).to.be.an('object');
337 | expect(data.queueId).to.be.a('number');
338 | // Store queueId
339 | queueId = data.queueId;
340 | jenkins.job_info(JOB_NAME_TEST, next);
341 | },
342 | (data, next) => {
343 | expect(data).to.be.an('object').like({ name: JOB_NAME_TEST });
344 | expect(data.queueItem).to.be.an('object').like({ _class: 'hudson.model.Queue$WaitingItem', id: queueId });
345 | jenkins.queue_item(queueId, next);
346 | },
347 | (data, next) => {
348 | expect(data).to.be.an('object').like({ id: queueId });
349 | setTimeout(next, APPROX_JOB_RUN_TIME);
350 | },
351 | (next) => {
352 | jenkins.queue_item(queueId, next);
353 | },
354 | (data, next) => {
355 | expect(data).to.be.an('object').like({ id: queueId });
356 | expect(data.executable).to.be.an('object');
357 | expect(data.executable.number).to.be.a('number');
358 | // Store buildId
359 | buildId = data.executable.number;
360 | jenkins.job_info(JOB_NAME_TEST, next);
361 | },
362 | (data, next) => {
363 | expect(data).to.be.an('object').like({ name: JOB_NAME_TEST });
364 | expect(data.lastBuild).to.be.an('object').like({ _class: 'hudson.model.FreeStyleBuild' });
365 | expect(data.lastBuild.number).to.equal(buildId);
366 | jenkins.all_builds(JOB_NAME_TEST, next);
367 | },
368 | (data, next) => {
369 | expect(data).to.be.an('array').that.contains.something.like({ id: `${buildId}` });
370 | jenkins.build_info(JOB_NAME_TEST, buildId, next);
371 | },
372 | (data, next) => {
373 | expect(data).to.be.an('object').like({ number: buildId, building: true, result: null });
374 | jenkins.stop_build(JOB_NAME_TEST, buildId, next);
375 | },
376 | (data, next) => {
377 | expect(data).to.be.an('object').like({ body: `Build ${buildId} stopped.` });
378 | setTimeout(next, APPROX_JOB_STOP_TIME);
379 | },
380 | (next) => {
381 | jenkins.build_info(JOB_NAME_TEST, buildId, next);
382 | },
383 | (data, next) => {
384 | expect(data).to.be.an('object').like({ number: buildId, building: false, result: 'ABORTED' });
385 | jenkins.console_output(JOB_NAME_TEST, buildId, next);
386 | },
387 | (data, next) => {
388 | expect(data).to.be.an('object');
389 | expect(data.body).to.be.a('string').that.contains('sleep 60');
390 | jenkins.last_build_info(JOB_NAME_TEST, next);
391 | },
392 | (data, next) => {
393 | expect(data).to.be.an('object').like({ number: buildId, building: false, result: 'ABORTED' });
394 | jenkins.delete_build(JOB_NAME_TEST, buildId, next);
395 | },
396 | (data, next) => {
397 | jenkins.all_builds(JOB_NAME_TEST, next);
398 | },
399 | (data, next) => {
400 | expect(data).to.be.an('array').that.does.not.contain.something.like({ id: `${buildId}` });
401 | next();
402 | }
403 | ], done);
404 | }).timeout(START_TO_END_JOB_TIME);
405 |
406 |
407 | it('Should build with params', function (done) {
408 | const SLEEP_TIME = 123;
409 | let queueId, buildId;
410 |
411 | async.waterfall([
412 | (next) => {
413 | fs.readFile(TEST_WITH_PARAMS_CONFIG_XML_FILE, 'utf8', next);
414 | },
415 | (xmlConfig, next) => {
416 | jenkins.create_job(JOB_NAME_NEW, xmlConfig, next);
417 | },
418 | (data, next) => {
419 | jenkins.build_with_params(JOB_NAME_NEW, { sleep_time: SLEEP_TIME }, next);
420 | },
421 | (data, next) => {
422 | expect(data).to.be.an('object');
423 | expect(data.queueId).to.be.a('number');
424 | // Store queueId
425 | queueId = data.queueId;
426 | setTimeout(next, APPROX_JOB_RUN_TIME);
427 | },
428 | (next) => {
429 | jenkins.queue_item(queueId, next);
430 | },
431 | (data, next) => {
432 | expect(data).to.be.an('object').like({ id: queueId });
433 | expect(data.executable).to.be.an('object');
434 | expect(data.executable.number).to.be.a('number');
435 | // Store buildId
436 | buildId = data.executable.number;
437 | jenkins.console_output(JOB_NAME_NEW, buildId, next);
438 | },
439 | (data, next) => {
440 | expect(data).to.be.an('object');
441 | expect(data.body).to.be.a('string').that.contains(`sleep ${SLEEP_TIME}`);
442 | jenkins.delete_job(JOB_NAME_NEW, next);
443 | }
444 | ], done);
445 | }).timeout(START_TO_END_JOB_TIME);
446 |
447 | // Use for onetime tasks do this
448 | it('Should show a test report', function (done) {
449 | let queueId, buildId;
450 |
451 | async.waterfall([
452 | (next) => {
453 | fs.readFile(TEST_WITH_REPORT_CONFIG_XML_FILE, 'utf8', next);
454 | },
455 | (xmlConfig, next) => {
456 | jenkins.create_job(JOB_NAME_REPORT, xmlConfig, next);
457 | },
458 | (data, next) => {
459 | jenkins.build(JOB_NAME_REPORT, next);
460 | },
461 | (data, next) => {
462 | expect(data).to.be.an('object');
463 | expect(data.queueId).to.be.a('number');
464 | // Store queueId
465 | queueId = data.queueId;
466 | // Wait for the job to finish
467 | setTimeout(next, APPROX_JOB_RUN_TIME);
468 | },
469 | (next) => {
470 | jenkins.last_build_info(JOB_NAME_REPORT, next);
471 | },
472 | (data, next) => {
473 | expect(data).to.be.an('object').like({ queueId: queueId, result: 'SUCCESS' });
474 | expect(data.number).to.be.a('number');
475 | // Store buildId
476 | buildId = data.number;
477 | jenkins.test_result(JOB_NAME_REPORT, buildId, next);
478 | },
479 | (data, next) => {
480 | expect(data).to.be.an('object')
481 | .like({ duration: 0.006, empty: false, failCount: 0, passCount: 1, skipCount: 0 });
482 | jenkins.delete_job(JOB_NAME_REPORT, next);
483 | }
484 | ], done);
485 | }).timeout(START_TO_END_JOB_TIME);
486 |
487 | // For onetime tasks do this
488 | // it.only('should do this', function(done) {
489 | // jenkins.last_build_report(JOB_NAME_REPORT, function (error, data) {
490 | // done();
491 | // }); // queue_item
492 | // });
493 |
494 | });
495 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const util = require('util');
4 | const qs = require('querystring');
5 | const request = require('request');
6 |
7 | const API = '/api/json';
8 | const LIST = API;
9 | const CREATE = `/createItem${API}`;
10 |
11 | const BUILD_START = `/job/%s/build${API}`;
12 | const BUILD_START_WITHPARAMS = '/job/%s/buildWithParameters'; // TODO how to handle this?
13 | const BUILD_STOP = '/job/%s/%s/stop';
14 | const BUILD_INFO = `/job/%s/%s${API}`;
15 | const BUILD_DELETE = '/job/%s/%s/doDelete';
16 |
17 | const ALL_BUILDS = `/job/%s${API}?tree=allBuilds[%s]`;
18 | const LAST_SUCCESS = `/job/%s/lastSuccessfulBuild${API}`;
19 | const TEST_REPORT = `/job/%s/%s/testReport${API}`;
20 | const LAST_BUILD = `/job/%s/lastBuild${API}`;
21 | const LAST_COMPLETED_BUILD = `/job/%s/lastCompletedBuild${API}`;
22 | // const LAST_REPORT = '/job/%s/lastBuild' + API; //TODO is there url for lastTestReport?
23 |
24 | const COMPUTERS = `/computer${API}`;
25 |
26 | const VIEW_LIST = LIST;
27 | const VIEW_INFO = `/view/%s${API}`;
28 | const VIEW_CREATE = `/createView${API}`;
29 | const VIEW_CONFIG = '/view/%s/configSubmit'; // NOTE form encoded not called via /api/json, TODO fix
30 | const VIEW_DELETE = `/view/%s/doDelete${API}`;
31 | const VIEW_ADD_JOB = `/view/%s/addJobToView${API}`;
32 | const VIEW_REMOVE_JOB = `/view/%s/removeJobFromView${API}`;
33 |
34 | const JOB_LIST = LIST;
35 | const JOB_CREATE = CREATE;
36 | const JOB_INFO = `/job/%s${API}`;
37 | const JOB_CONFIG = `/job/%s/config.xml${API}`;
38 | const JOB_OUTPUT = `/job/%s/%s/consoleText${API}`;
39 | const JOB_DELETE = `/job/%s/doDelete${API}`;
40 | const JOB_DISABLE = '/job/%s/disable';
41 | const JOB_ENABLE = '/job/%s/enable';
42 |
43 | const QUEUE = `/queue${API}`;
44 | const QUEUE_ITEM = `/queue/item/%s${API}`;
45 | const QUEUE_CANCEL_ITEM = `/queue/cancelItem${API}`; // TODO verify this works with API
46 |
47 | const PLUGINS = `/pluginManager${API}`;
48 | const INSTALL_PLUGIN = `/pluginManager/installNecessaryPlugins${API}`;
49 |
50 | const NEWFOLDER = CREATE;
51 |
52 | const HTTP_CODE_200 = 200;
53 | const HTTP_CODE_201 = 201;
54 | const HTTP_CODE_302 = 302;
55 |
56 | // -----------------------------------------------------------------------------
57 | // Helper Functions
58 |
59 | /**
60 | * @param {any} value - variable to detect type of.
61 | * @return {string} - typeof the value param, but 'array' for arrays and 'null' for nulls.
62 | */
63 | function getType(value) {
64 | if (Array.isArray(value)) {
65 | return 'array';
66 | } else if (value === null) {
67 | return 'null';
68 | }
69 | return typeof value;
70 |
71 | }
72 |
73 | /**
74 | * Processes arguments according to the rules defined by the types array.
75 | * Types of arguments are checked, optional arguments are replaced by their
76 | * default values or left undefined.
77 | *
78 | * @param {arguments} values: The arguments object.
79 | * @param {array} types: Array of types, see below.
80 | * @returns {array} the processed arguments in an array.
81 | * @throws {Error} if arguments don't fit, throws an error.
82 | *
83 | * Examples of types:
84 | * ['string'] - function requires one string
85 | * ['string', ['number']] - function requires one string and expects an optional number
86 | * [['object', {}]] - function expects an optional object defaulting to empty object
87 | * ['string|array'] - function requires string or array
88 | *
89 | * Inspired by
90 | * See: https://www.npmjs.com/package/assert-args
91 | * See: https://www.npmjs.com/package/ensurethat
92 | */
93 | function doArgs(values, types) {
94 | let value, type, carry, optional, defaultValue;
95 | const result = [];
96 |
97 | for (type of types) {
98 | // Load value if we don't have one already
99 | if (!carry) {
100 | value = Array.prototype.shift.call(values);
101 | }
102 |
103 | // Handle optional type
104 | if (Array.isArray(type)) {
105 | optional = true;
106 | defaultValue = type[1];
107 | type = type[0];
108 | } else {
109 | optional = false;
110 | }
111 |
112 | // Handle multitype
113 | type = type.split('|');
114 |
115 | // Is it a correct value?
116 | if (type.includes(getType(value))) {
117 | result.push(value);
118 | carry = false;
119 | } else if (optional) {
120 | result.push(defaultValue);
121 | carry = true;
122 | } else {
123 | throw Error('Invalid arguments');
124 | }
125 | }
126 | if (values.length) {
127 | // TODO maybe do some warning..?
128 | // throw Error('Extra arguments ' + values.length, values);
129 | }
130 | return result;
131 | }
132 |
133 | /**
134 | * Parse the passed string as JSON and extract or "manipulate" it using the property.
135 | *
136 | * @param {string} body - string response body
137 | * @param {string|array|function} property - property to get from body or modificator function
138 | * @param {function} callback function to call when all done
139 | */
140 | function tryParseJson(body, property, callback) {
141 | [body, property, callback] = doArgs(arguments, ['string', 'string|array|function|null', 'function']);
142 |
143 | try {
144 | // Won't harm if we replace escape sequence
145 | body = body.replace(/\x1b/g, '');
146 |
147 | // Try to parse
148 | let data = JSON.parse(body.toString());
149 |
150 | // Get the prop name if specified
151 | if (property) {
152 | const type = getType(property);
153 |
154 | if (type === 'array') {
155 | const newData = {};
156 |
157 | for (const p of property) {
158 | newData[p] = data[p];
159 | }
160 | data = newData;
161 | }
162 | if (type === 'string') {
163 | data = data[property];
164 | }
165 | if (type === 'function') {
166 | data = property(data);
167 | }
168 | }
169 |
170 | callback(null, data);
171 | } catch (e) {
172 | callback(e, body);
173 | }
174 | }
175 |
176 |
177 | // -----------------------------------------------------------------------------
178 |
179 | exports.init = function (host, defaultOptions, defaultParams) {
180 |
181 | /**
182 | * Builds the URL to Jenkins from formatstring pattern and params.
183 | *
184 | * @param {string} pattern - URL format string patern.
185 | * @param {string|number} arguments for the formatstring pattern.
186 | * @returns {string} url - the URL formated according to arguments.
187 | */
188 | function formatUrl() {
189 | return host + util.format.apply(null, arguments);
190 | }
191 |
192 | /**
193 | * Build REST params and correctly append them to URL.
194 | *
195 | * @param {string} url to be extended with params.
196 | * @param {object} specificParams key/value pair of params.
197 | * @returns {string} the extended url.
198 | */
199 | const appendParams = function (url, specificParams) {
200 | // Assign default and specific parameters
201 | const params = Object.assign({}, defaultParams, specificParams);
202 |
203 | // Stringify the querystring params
204 | const paramsString = qs.stringify(params);
205 |
206 | // Empty params
207 | if (paramsString === '') {
208 | return url;
209 | }
210 |
211 | // Does url contain parameters already?
212 | const delim = (url.includes('?') ? '&' : '?');
213 |
214 | return url + delim + paramsString;
215 | };
216 |
217 | /**
218 | * Just helper funckion to build the request URL.
219 | *
220 | * @param {array} urlPattern array in format of [urlFormat, arg1, arg2] used to build the URL.
221 | * @param {object} customParams key/value pair of params.
222 | * @returns {string} the URL built.
223 | */
224 | function buildUrl(urlPattern, customParams) {
225 | let url = formatUrl.apply(null, urlPattern);
226 |
227 | url = appendParams(url, customParams);
228 | return url;
229 | }
230 |
231 | /**
232 | * Run the actual HTTP request.
233 | *
234 | * @param {object} specificOptions - options object overriding the default options below.
235 | * @param {object} customParams - custom url params to be added to url.
236 | * @param {function} callback - the callback function to be called when request is finished.
237 | */
238 | const doRequest = function (specificOptions, customParams, callback) {
239 |
240 | // Options - Default values
241 | const options = Object.assign({}, {
242 | urlPattern: ['/'],
243 | method: 'GET',
244 | successStatusCodes: [HTTP_CODE_200],
245 | failureStatusCodes: [],
246 | bodyProp: null,
247 | noparse: false,
248 | request: {}
249 | }, defaultOptions, specificOptions);
250 |
251 | // Create the url
252 | const url = buildUrl(options.urlPattern, customParams);
253 |
254 | // Build the actual request options
255 | const requestOptions = Object.assign({
256 | method: options.method,
257 | url: url,
258 | headers: [],
259 | followAllRedirects: true,
260 | form: null,
261 | body: null
262 | }, options.request);
263 |
264 | // Do the request
265 | request(requestOptions, function (error, response, body) {
266 | if (error) {
267 | callback(error, response);
268 | return;
269 | }
270 |
271 | if ((Array.isArray(options.successStatusCodes) && !options.successStatusCodes.includes(response.statusCode))
272 | || (Array.isArray(options.failureStatusCodes) && options.failureStatusCodes.includes(response.statusCode))) {
273 | callback(`Server returned unexpected status code: ${response.statusCode}`, response);
274 | return;
275 | }
276 |
277 | if (options.noparse) {
278 | // Wrap body in the response object
279 | if (typeof body === 'string') {
280 | body = { body: body };
281 | }
282 |
283 | // Add location
284 | const location = response.headers.Location || response.headers.location;
285 |
286 | if (location) {
287 | body.location = location;
288 | }
289 |
290 | // Add status code
291 | body.statusCode = response.statusCode;
292 |
293 | callback(null, body);
294 | } else {
295 | tryParseJson(body, options.bodyProp, callback);
296 | }
297 | });
298 | };
299 |
300 | return {
301 |
302 | /** ***********************************\
303 | |* Builds *|
304 | \*************************************/
305 |
306 | /** Trigger Jenkins to build.
307 | *
308 | * Return queue location of newly-created job as per
309 | * https://issues.jenkins-ci.org/browse/JENKINS-12827?focusedCommentId=201381#comment-201381
310 | *
311 | * @param {string} jobName
312 | * @param {object|undefined} customParams is optional
313 | * @param {function} callback
314 | */
315 | build: function (jobName, customParams, callback) {
316 | [jobName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
317 |
318 | doRequest({
319 | method: 'POST',
320 | urlPattern: [BUILD_START, jobName],
321 | successStatusCodes: [HTTP_CODE_201, HTTP_CODE_302],
322 | noparse: true
323 | }, customParams, function (error, data) {
324 | if (error) {
325 | callback(error, data);
326 | return;
327 | }
328 |
329 | const queueIdRe = /\/queue\/item\/(\d+)/;
330 | const id = +queueIdRe.exec(data.location)[1];
331 |
332 | data.queueId = id;
333 |
334 | callback(null, data);
335 | });
336 | },
337 |
338 | /**
339 | *
340 | * @param {string} jobName
341 | * @param {object|undefined} customParams is optional
342 | * @param {function} callback
343 | */
344 | build_with_params: function (jobName, customParams, callback) {
345 | [jobName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
346 |
347 | doRequest({
348 | method: 'POST',
349 | urlPattern: [BUILD_START_WITHPARAMS, jobName],
350 | successStatusCodes: [HTTP_CODE_201, HTTP_CODE_302],
351 | noparse: true
352 | }, customParams, function (error, data) {
353 | if (error) {
354 | callback(error, data);
355 | return;
356 | }
357 |
358 | const queueIdRe = /\/queue\/item\/(\d+)/;
359 | const id = +queueIdRe.exec(data.location)[1];
360 |
361 | data.queueId = id;
362 |
363 | callback(null, data);
364 | });
365 | },
366 |
367 | /**
368 | *
369 | * @param {string} jobName
370 | * @param {string} buildNumber
371 | * @param {object|undefined} customParams is optional
372 | * @param {function} callback
373 | */
374 | stop_build: function (jobName, buildNumber, customParams, callback) {
375 | [jobName, buildNumber, customParams, callback] = doArgs(arguments, ['string', 'string|number', ['object', {}], 'function']);
376 |
377 | doRequest({
378 | method: 'POST',
379 | urlPattern: [BUILD_STOP, jobName, buildNumber],
380 | noparse: true
381 | }, customParams, function (error, data) {
382 | if (error) {
383 | callback(error, data);
384 | return;
385 | }
386 |
387 | data.body = `Build ${buildNumber} stopped.`;
388 |
389 | callback(null, data);
390 | });
391 | },
392 |
393 | /**
394 | * Get the output for a job's build
395 | *
396 | * @param {string} jobName
397 | * @param {string} buildNumber
398 | * @param {object|undefined} customParams is optional
399 | * @param {function} callback
400 | */
401 | console_output: function (jobName, buildNumber, customParams, callback) {
402 | [jobName, buildNumber, customParams, callback] = doArgs(arguments, ['string', 'string|number', ['object', {}], 'function']);
403 |
404 | doRequest({
405 | urlPattern: [JOB_OUTPUT, jobName, buildNumber],
406 | noparse: true
407 | }, customParams, callback);
408 | },
409 |
410 | /**
411 | * Get information for the last build of a job
412 | *
413 | * @param {string} jobName
414 | * @param {object|undefined} customParams is optional
415 | * @param {function} callback
416 | */
417 | last_build_info: function (jobName, customParams, callback) {
418 | [jobName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
419 |
420 | doRequest({
421 | urlPattern: [LAST_BUILD, jobName]
422 | }, customParams, callback);
423 | },
424 |
425 | /**
426 | * Get information for the last completed build of a job
427 | *
428 | * @param {string} jobName
429 | * @param {object|undefined} customParams is optional
430 | * @param {function} callback
431 | */
432 | last_completed_build_info: function (jobName, customParams, callback) {
433 | [jobName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
434 |
435 | doRequest({
436 | urlPattern: [LAST_COMPLETED_BUILD, jobName]
437 | }, customParams, callback);
438 | },
439 |
440 | /**
441 | * Get information for the build number of a job
442 | *
443 | * @param {string} jobName
444 | * @param {string} buildNumber
445 | * @param {object|undefined} customParams is optional
446 | * @param {function} callback
447 | */
448 | build_info: function (jobName, buildNumber, customParams, callback) {
449 | [jobName, buildNumber, customParams, callback] = doArgs(arguments, ['string', 'string|number', ['object', {}], 'function']);
450 |
451 | doRequest({
452 | urlPattern: [BUILD_INFO, jobName, buildNumber]
453 | }, customParams, callback);
454 | },
455 |
456 | /**
457 | * Get information for the all builds
458 | *
459 | * @param {string} jobName
460 | * @param {string} param
461 | * @param {object|undefined} customParams is optional
462 | * @param {function} callback
463 | */
464 | all_builds: function (jobName, param, customParams, callback) {
465 | [jobName, param, customParams, callback] = doArgs(arguments, ['string', ['string', 'id,timestamp,result,duration'], ['object', {}], 'function']);
466 |
467 | // TODO better name and handle the "param" ???
468 | doRequest({
469 | urlPattern: [ALL_BUILDS, jobName, param],
470 | bodyProp: 'allBuilds'
471 | }, customParams, callback);
472 | },
473 |
474 | /**
475 | * Get the test results for the build number of a job
476 | *
477 | * @param {string} jobName
478 | * @param {string} buildNumber
479 | * @param {object|undefined} customParams is optional
480 | * @param {function} callback
481 | */
482 | test_result: function (jobName, buildNumber, customParams, callback) {
483 | [jobName, buildNumber, customParams, callback] = doArgs(arguments, ['string', 'string|number', ['object', {}], 'function']);
484 |
485 | doRequest({
486 | urlPattern: [TEST_REPORT, jobName, buildNumber]
487 | }, customParams, callback);
488 | },
489 |
490 | /**
491 | * Get the last build report for a job.
492 | * @obsolete Use last_build_info instead.
493 | * Probly will make this to return the test result.
494 | *
495 | * @param {string} jobName
496 | * @param {object|undefined} customParams is optional
497 | * @param {function} callback
498 | */
499 | last_build_report: function (jobName, customParams, callback) {
500 | this.last_build_info(jobName, customParams, callback);
501 | // doRequest({
502 | // urlPattern: [LAST_REPORT, jobName],
503 | // }, customParams, callback);
504 | },
505 |
506 | /**
507 | * Deletes build data for certain job
508 | *
509 | * @param {string} jobName
510 | * @param {string} buildNumber
511 | * @param {object|undefined} customParams is optional
512 | * @param {function} callback
513 | */
514 | delete_build: function (jobName, buildNumber, customParams, callback) {
515 | [jobName, buildNumber, customParams, callback] = doArgs(arguments, ['string', 'string|number', ['object', {}], 'function']);
516 |
517 | doRequest({
518 | method: 'POST',
519 | urlPattern: [BUILD_DELETE, jobName, buildNumber],
520 | noparse: true
521 | }, customParams, function (error, data) {
522 | if (error) {
523 | callback(error, data);
524 | } else {
525 | data.body = `Build ${buildNumber} deleted.`;
526 | callback(null, data);
527 | }
528 | });
529 | },
530 |
531 | /** ***********************************\
532 | |* Jobs *|
533 | \*************************************/
534 |
535 | /**
536 | * Return a list of object literals containing the name and color of all jobs on the Jenkins server
537 | *
538 | * @param {object|undefined} customParams is optional
539 | * @param {function} callback
540 | */
541 | all_jobs: function (customParams, callback) {
542 | [customParams, callback] = doArgs(arguments, [['object', {}], 'function']);
543 |
544 | doRequest({
545 | urlPattern: [JOB_LIST],
546 | bodyProp: 'jobs'
547 | }, customParams, callback);
548 | },
549 |
550 | /**
551 | * Get jobs config in xml
552 | *
553 | * @param {string} jobName
554 | * @param {object|undefined} customParams is optional
555 | * @param {function} callback
556 | */
557 | get_config_xml: function (jobName, customParams, callback) {
558 | [jobName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
559 |
560 | doRequest({
561 | urlPattern: [JOB_CONFIG, jobName],
562 | noparse: true
563 | }, customParams, function (error, data) {
564 | // Get only the XML response body
565 | if (error) {
566 | callback(error, data);
567 | } else {
568 | callback(null, data.body);
569 | }
570 | });
571 | },
572 |
573 | /**
574 | * Update a job config xml by passing it through your modifyFunction.
575 | *
576 | * @param {string} jobName
577 | * @param {function} modifyFunction
578 | * @param {object|undefined} customParams is optional
579 | * @param {function} callback
580 | */
581 | update_config: function (jobName, modifyFunction, customParams, callback) {
582 | [jobName, modifyFunction, customParams, callback] = doArgs(arguments, ['string', 'function', ['object', {}], 'function']);
583 |
584 | const self = this;
585 |
586 | self.get_config_xml(jobName, customParams, function (error, data) {
587 | if (error) {
588 | callback(error, data);
589 | return;
590 | }
591 |
592 | // Modify the config data
593 | data = modifyFunction(data);
594 |
595 | self.update_job(jobName, data, customParams, callback);
596 | });
597 | },
598 |
599 | /**
600 | * Update a existing job based on a jobConfig xml string
601 | *
602 | * @param {string} jobName
603 | * @param {string} jobConfig
604 | * @param {object|undefined} customParams is optional
605 | * @param {function} callback
606 | */
607 | update_job: function (jobName, jobConfig, customParams, callback) {
608 | [jobName, jobConfig, customParams, callback] = doArgs(arguments, ['string', 'string', ['object', {}], 'function']);
609 |
610 | doRequest({
611 | method: 'POST',
612 | urlPattern: [JOB_CONFIG, jobName],
613 | request: {
614 | body: jobConfig,
615 | headers: { 'Content-Type': 'application/xml' }
616 | },
617 | noparse: true
618 | }, customParams, function (error, data) {
619 | if (error) {
620 | callback(error, data);
621 | return;
622 | }
623 | // TODO rather return job_info ???
624 | // const data = {name: jobName, location: response.headers['Location'] || response.headers['location']};
625 | callback(null, { name: jobName });
626 | });
627 | },
628 |
629 | /**
630 | * Get all information for a job
631 | *
632 | * @param {string} jobName
633 | * @param {object|undefined} customParams is optional
634 | * @param {function} callback
635 | */
636 | job_info: function (jobName, customParams, callback) {
637 | [jobName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
638 |
639 | doRequest({
640 | urlPattern: [JOB_INFO, jobName]
641 | }, customParams, callback);
642 | },
643 |
644 | /**
645 | * Create a new job based on a jobConfig string
646 | *
647 | * @param {string} jobName
648 | * @param {string} jobConfig
649 | * @param {object|undefined} customParams is optional
650 | * @param {function} callback
651 | */
652 | create_job: function (jobName, jobConfig, customParams, callback) {
653 | [jobName, jobConfig, customParams, callback] = doArgs(arguments, ['string', 'string', ['object', {}], 'function']);
654 |
655 | // Set the created job name!
656 | customParams.name = jobName;
657 |
658 | const self = this;
659 |
660 | doRequest({
661 | method: 'POST',
662 | urlPattern: [JOB_CREATE],
663 | request: {
664 | body: jobConfig,
665 | headers: { 'Content-Type': 'application/xml' }
666 | },
667 | noparse: true
668 | }, customParams, function (error, data) {
669 | if (error) {
670 | callback(error, data);
671 | return;
672 | }
673 | self.job_info(jobName, customParams, callback);
674 | });
675 | },
676 |
677 | /**
678 | * Copies a job and allows you to pass in a function to modify the configuration
679 | * of the job you would like to copy
680 | *
681 | * @param {string} jobName
682 | * @param {string} newJobName
683 | * @param {function} modifyFunction
684 | * @param {object|undefined} customParams is optional
685 | * @param {function} callback
686 | */
687 | copy_job: function (jobName, newJobName, modifyFunction, customParams, callback) {
688 | [jobName, newJobName, modifyFunction, customParams, callback] = doArgs(arguments, ['string', 'string', 'function', ['object', {}], 'function']);
689 |
690 | const self = this;
691 |
692 | this.get_config_xml(jobName, customParams, function (error, data) {
693 | if (error) {
694 | callback(error, data);
695 | return;
696 | }
697 |
698 | // Modify the data
699 | data = modifyFunction(data);
700 |
701 | self.create_job(newJobName, data, customParams, callback);
702 | });
703 | },
704 |
705 | /**
706 | * Deletes a job
707 | *
708 | * @param {string} jobName
709 | * @param {object|undefined} customParams is optional
710 | * @param {function} callback
711 | */
712 | delete_job: function (jobName, customParams, callback) {
713 | [jobName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
714 |
715 | doRequest({
716 | method: 'POST',
717 | urlPattern: [JOB_DELETE, jobName],
718 | noparse: true
719 | }, customParams, function (error, data) {
720 | if (error) {
721 | callback(error, data);
722 | return;
723 | }
724 | callback(null, { name: jobName });
725 | });
726 | },
727 |
728 | /**
729 | * Disables a job
730 | *
731 | * @param {string} jobName
732 | * @param {object|undefined} customParams is optional
733 | * @param {function} callback
734 | */
735 | disable_job: function (jobName, customParams, callback) {
736 | [jobName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
737 |
738 | const self = this;
739 |
740 | doRequest({
741 | method: 'POST',
742 | urlPattern: [JOB_DISABLE, jobName],
743 | noparse: true
744 | }, customParams, function (error, data) {
745 | if (error) {
746 | callback(error, data);
747 | return;
748 | }
749 | self.job_info(jobName, customParams, callback);
750 | });
751 | },
752 |
753 | /**
754 | * Enables a job
755 | *
756 | * @param {string} jobName
757 | * @param {object|undefined} customParams is optional
758 | * @param {function} callback
759 | */
760 | enable_job: function (jobName, customParams, callback) {
761 | [jobName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
762 |
763 | const self = this;
764 |
765 | doRequest({
766 | method: 'POST',
767 | urlPattern: [JOB_ENABLE, jobName],
768 | noparse: true
769 | }, customParams, function (error, data) {
770 | if (error) {
771 | callback(error, data);
772 | return;
773 | }
774 | self.job_info(jobName, customParams, callback);
775 | });
776 | },
777 |
778 | /**
779 | * Get the last build report for a job
780 | *
781 | * @param {string} jobName
782 | * @param {object|undefined} customParams is optional
783 | * @param {function} callback
784 | */
785 | last_success: function (jobName, customParams, callback) {
786 | [jobName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
787 |
788 | doRequest({
789 | method: 'POST',
790 | urlPattern: [LAST_SUCCESS, jobName]
791 | }, customParams, callback);
792 | },
793 |
794 | /**
795 | * Get the last result for a job
796 | *
797 | * @param {string} jobName
798 | * @param {object|undefined} customParams is optional
799 | * @param {function} callback
800 | */
801 | last_result: function (jobName, customParams, callback) {
802 | [jobName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
803 |
804 | this.job_info(jobName, function (error, data) {
805 | if (error) {
806 | callback(error, data);
807 | return;
808 | }
809 |
810 | const lastResultUrl = data.lastBuild.url;
811 |
812 | doRequest({
813 | urlPattern: [lastResultUrl + API, jobName]
814 | }, customParams, callback);
815 | });
816 | },
817 |
818 | /** ***********************************\
819 | |* Queues *|
820 | \*************************************/
821 |
822 | /**
823 | * Get all queued items
824 | *
825 | * @param {object|undefined} customParams is optional
826 | * @param {function} callback
827 | */
828 | queue: function (customParams, callback) {
829 | [customParams, callback] = doArgs(arguments, [['object', {}], 'function']);
830 |
831 | doRequest({
832 | urlPattern: [QUEUE]
833 | }, customParams, callback);
834 | },
835 |
836 | /**
837 | * Get one queued item
838 | *
839 | * @param {string} queueNumber
840 | * @param {object|undefined} customParams is optional
841 | * @param {function} callback
842 | */
843 | queue_item: function (queueNumber, customParams, callback) {
844 | [queueNumber, customParams, callback] = doArgs(arguments, ['string|number', ['object', {}], 'function']);
845 |
846 | doRequest({
847 | urlPattern: [QUEUE_ITEM, queueNumber]
848 | }, customParams, callback);
849 | },
850 |
851 | /**
852 | * Cancel a queued item
853 | *
854 | * @param {string} itemId
855 | * @param {object|undefined} customParams is optional
856 | * @param {function} callback
857 | */
858 | cancel_item: function (itemId, customParams, callback) {
859 | [itemId, customParams, callback] = doArgs(arguments, ['string|number', ['object', {}], 'function']);
860 |
861 | customParams.id = itemId;
862 |
863 | doRequest({
864 | method: 'POST',
865 | urlPattern: [QUEUE_CANCEL_ITEM]
866 | }, customParams, callback);
867 | },
868 |
869 | /** ***********************************\
870 | |* Computers *|
871 | \*************************************/
872 |
873 | /**
874 | * Get info about all jenkins workers including currently executing jobs
875 | *
876 | * @param {object|undefined} customParams is optional
877 | * @param {function} callback
878 | */
879 | computers: function (customParams, callback) {
880 | [customParams, callback] = doArgs(arguments, [['object', {}], 'function']);
881 |
882 | doRequest({
883 | urlPattern: [COMPUTERS]
884 | }, customParams, callback);
885 | },
886 |
887 | /** ***********************************\
888 | |* Views *|
889 | \*************************************/
890 |
891 | /**
892 | * Return a list of all the views on the Jenkins server
893 | *
894 | * @param {object|undefined} customParams is optional
895 | * @param {function} callback
896 | */
897 | all_views: function (customParams, callback) {
898 | [customParams, callback] = doArgs(arguments, [['object', {}], 'function']);
899 |
900 | doRequest({
901 | urlPattern: [VIEW_LIST],
902 | bodyProp: 'views'
903 | }, customParams, callback);
904 | },
905 |
906 | /**
907 | *
908 | * @param {string} viewName
909 | * @param {string|undefined} mode
910 | * @param {object|undefined} customParams is optional
911 | * @param {function} callback
912 | */
913 | create_view: function (viewName, mode, customParams, callback) {
914 | [viewName, mode, customParams, callback] = doArgs(arguments, ['string', ['string', 'hudson.model.ListView'], ['object', {}], 'function']);
915 |
916 | const formData = { name: viewName, mode: mode };
917 |
918 | formData.json = JSON.stringify(formData);
919 |
920 | const self = this;
921 |
922 | doRequest({
923 | method: 'POST',
924 | urlPattern: [VIEW_CREATE],
925 | request: {
926 | form: formData
927 | },
928 | noparse: true
929 | }, customParams, function (error, data) {
930 | if (error) {
931 | callback(error, data);
932 | return;
933 | }
934 | self.view_info(viewName, customParams, callback);
935 | });
936 | },
937 |
938 | /**
939 | * @param {string} viewName
940 | * @param {object|undefined} customParams is optional
941 | * @param {function} callback
942 | */
943 | view_info: function (viewName, customParams, callback) {
944 | [viewName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
945 |
946 | doRequest({
947 | urlPattern: [VIEW_INFO, viewName]
948 | }, customParams, callback);
949 | },
950 |
951 | /**
952 | * Update a view based on a viewConfig object
953 | *
954 | * @param {string} viewName
955 | * @param {object} viewConfig
956 | * @param {object|undefined} customParams is optional
957 | * @param {function} callback
958 | */
959 | update_view: function (viewName, viewConfig, customParams, callback) {
960 | [viewName, viewConfig, customParams, callback] = doArgs(arguments, ['string', 'object', ['object', {}], 'function']);
961 |
962 | viewConfig.json = JSON.stringify(viewConfig);
963 |
964 | const self = this;
965 |
966 | doRequest({
967 | method: 'POST',
968 | urlPattern: [VIEW_CONFIG, viewName],
969 | request: {
970 | form: viewConfig
971 | // headers: {'content-type': 'application/x-www-form-urlencoded'},
972 | },
973 | noparse: true
974 | }, customParams, function (error, data) {
975 | if (error) {
976 | callback(error, data);
977 | return;
978 | }
979 | self.view_info(viewName, customParams, callback);
980 | });
981 | },
982 |
983 | /**
984 | * @param {string} viewName
985 | * @param {object|undefined} customParams is optional
986 | * @param {function} callback
987 | */
988 | delete_view: function (viewName, customParams, callback) {
989 | [viewName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
990 |
991 | doRequest({
992 | method: 'POST',
993 | urlPattern: [VIEW_DELETE, viewName],
994 | noparse: true
995 | }, customParams, function (error, data) {
996 | if (error) {
997 | callback(error, data);
998 | return;
999 | }
1000 | callback(null, { name: viewName });
1001 | });
1002 | },
1003 |
1004 | /**
1005 | * @param {string} viewName
1006 | * @param {string} jobName
1007 | * @param {object|undefined} customParams is optional
1008 | * @param {function} callback
1009 | */
1010 | add_job_to_view: function (viewName, jobName, customParams, callback) {
1011 | [viewName, jobName, customParams, callback] = doArgs(arguments, ['string', 'string', ['object', {}], 'function']);
1012 |
1013 | customParams.name = jobName;
1014 |
1015 | doRequest({
1016 | method: 'POST',
1017 | urlPattern: [VIEW_ADD_JOB, viewName],
1018 | noparse: true
1019 | }, customParams, callback);
1020 | },
1021 |
1022 | /**
1023 | * @param {string} viewName
1024 | * @param {string} jobName
1025 | * @param {object|undefined} customParams is optional
1026 | * @param {function} callback
1027 | */
1028 | remove_job_from_view: function (viewName, jobName, customParams, callback) {
1029 | [viewName, jobName, customParams, callback] = doArgs(arguments, ['string', 'string', ['object', {}], 'function']);
1030 |
1031 | customParams.name = jobName;
1032 |
1033 | doRequest({
1034 | method: 'POST',
1035 | urlPattern: [VIEW_REMOVE_JOB, viewName],
1036 | noparse: true
1037 | }, customParams, callback);
1038 | },
1039 |
1040 | /**
1041 | * Return a list of objet literals containing the name and color of all the jobs for a view on the Jenkins server
1042 | *
1043 | * @param {string} viewName
1044 | * @param {object|undefined} customParams is optional
1045 | * @param {function} callback
1046 | */
1047 | all_jobs_in_view: function (viewName, customParams, callback) {
1048 | [viewName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
1049 |
1050 | doRequest({
1051 | urlPattern: [VIEW_INFO, viewName],
1052 | bodyProp: 'jobs'
1053 | }, customParams, callback);
1054 | },
1055 |
1056 | /** ***********************************\
1057 | |* Plugins *|
1058 | \*************************************/
1059 |
1060 | /**
1061 | * Get all installed plugins
1062 | *
1063 | * @param {object|undefined} customParams is optional
1064 | * @param {function} callback
1065 | */
1066 | all_installed_plugins: function (customParams, callback) {
1067 | [customParams, callback] = doArgs(arguments, [['object', {}], 'function']);
1068 |
1069 | customParams.depth = 1;
1070 |
1071 | doRequest({
1072 | urlPattern: [PLUGINS],
1073 | failureStatusCodes: [HTTP_CODE_302],
1074 | noparse: true,
1075 | bodyProp: 'plugins'
1076 | }, customParams, callback);
1077 | },
1078 |
1079 | /**
1080 | * Install a plugin
1081 | *
1082 | * @param {string} pluginName
1083 | * @param {object|undefined} customParams is optional
1084 | * @param {function} callback
1085 | */
1086 | install_plugin: function (pluginName, customParams, callback) {
1087 | [pluginName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
1088 |
1089 | const body = ``;
1090 |
1091 | doRequest({
1092 | method: 'POST',
1093 | urlPattern: [INSTALL_PLUGIN],
1094 | request: {
1095 | body: body,
1096 | headers: { 'Content-Type': 'text/xml' }
1097 | },
1098 | noparse: true,
1099 | bodyProp: 'plugins'
1100 | }, customParams, callback);
1101 | },
1102 |
1103 | /**
1104 | * Create a new folder with given name
1105 | *
1106 | * Requires Folder plugin in Jenkins:
1107 | * @see https://wiki.jenkins-ci.org/display/JENKINS/CloudBees+Folders+Plugin
1108 | * @see https://gist.github.com/stuart-warren/7786892
1109 | *
1110 | * @param {string} folderName
1111 | * @param {object|undefined} customParams is optional
1112 | * @param {function} callback
1113 | */
1114 | create_folder: function (folderName, customParams, callback) {
1115 | [folderName, customParams, callback] = doArgs(arguments, ['string', ['object', {}], 'function']);
1116 |
1117 | const mode = 'com.cloudbees.hudson.plugins.folder.Folder';
1118 |
1119 | customParams.name = folderName;
1120 | customParams.mode = mode;
1121 | customParams.Submit = 'OK';
1122 |
1123 | doRequest({
1124 | method: 'POST',
1125 | urlPattern: [NEWFOLDER]
1126 | }, customParams, callback);
1127 | }
1128 | };
1129 | };
1130 |
--------------------------------------------------------------------------------
/lib/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
4 |
5 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
6 |
7 | var util = require('util');
8 | var qs = require('querystring');
9 | var request = require('request');
10 |
11 | var API = '/api/json';
12 | var LIST = API;
13 | var CREATE = '/createItem' + API;
14 |
15 | var BUILD_START = '/job/%s/build' + API;
16 | var BUILD_START_WITHPARAMS = '/job/%s/buildWithParameters'; // TODO how to handle this?
17 | var BUILD_STOP = '/job/%s/%s/stop';
18 | var BUILD_INFO = '/job/%s/%s' + API;
19 | var BUILD_DELETE = '/job/%s/%s/doDelete';
20 |
21 | var ALL_BUILDS = '/job/%s' + API + '?tree=allBuilds[%s]';
22 | var LAST_SUCCESS = '/job/%s/lastSuccessfulBuild' + API;
23 | var TEST_REPORT = '/job/%s/%s/testReport' + API;
24 | var LAST_BUILD = '/job/%s/lastBuild' + API;
25 | var LAST_COMPLETED_BUILD = '/job/%s/lastCompletedBuild' + API;
26 | // const LAST_REPORT = '/job/%s/lastBuild' + API; //TODO is there url for lastTestReport?
27 |
28 | var COMPUTERS = '/computer' + API;
29 |
30 | var VIEW_LIST = LIST;
31 | var VIEW_INFO = '/view/%s' + API;
32 | var VIEW_CREATE = '/createView' + API;
33 | var VIEW_CONFIG = '/view/%s/configSubmit'; // NOTE form encoded not called via /api/json, TODO fix
34 | var VIEW_DELETE = '/view/%s/doDelete' + API;
35 | var VIEW_ADD_JOB = '/view/%s/addJobToView' + API;
36 | var VIEW_REMOVE_JOB = '/view/%s/removeJobFromView' + API;
37 |
38 | var JOB_LIST = LIST;
39 | var JOB_CREATE = CREATE;
40 | var JOB_INFO = '/job/%s' + API;
41 | var JOB_CONFIG = '/job/%s/config.xml' + API;
42 | var JOB_OUTPUT = '/job/%s/%s/consoleText' + API;
43 | var JOB_DELETE = '/job/%s/doDelete' + API;
44 | var JOB_DISABLE = '/job/%s/disable';
45 | var JOB_ENABLE = '/job/%s/enable';
46 |
47 | var QUEUE = '/queue' + API;
48 | var QUEUE_ITEM = '/queue/item/%s' + API;
49 | var QUEUE_CANCEL_ITEM = '/queue/cancelItem' + API; // TODO verify this works with API
50 |
51 | var PLUGINS = '/pluginManager' + API;
52 | var INSTALL_PLUGIN = '/pluginManager/installNecessaryPlugins' + API;
53 |
54 | var NEWFOLDER = CREATE;
55 |
56 | var HTTP_CODE_200 = 200;
57 | var HTTP_CODE_201 = 201;
58 | var HTTP_CODE_302 = 302;
59 |
60 | // -----------------------------------------------------------------------------
61 | // Helper Functions
62 |
63 | /**
64 | * @param {any} value - variable to detect type of.
65 | * @return {string} - typeof the value param, but 'array' for arrays and 'null' for nulls.
66 | */
67 | function getType(value) {
68 | if (Array.isArray(value)) {
69 | return 'array';
70 | } else if (value === null) {
71 | return 'null';
72 | }
73 | return typeof value === 'undefined' ? 'undefined' : _typeof(value);
74 | }
75 |
76 | /**
77 | * Processes arguments according to the rules defined by the types array.
78 | * Types of arguments are checked, optional arguments are replaced by their
79 | * default values or left undefined.
80 | *
81 | * @param {arguments} values: The arguments object.
82 | * @param {array} types: Array of types, see below.
83 | * @returns {array} the processed arguments in an array.
84 | * @throws {Error} if arguments don't fit, throws an error.
85 | *
86 | * Examples of types:
87 | * ['string'] - function requires one string
88 | * ['string', ['number']] - function requires one string and expects an optional number
89 | * [['object', {}]] - function expects an optional object defaulting to empty object
90 | * ['string|array'] - function requires string or array
91 | *
92 | * Inspired by
93 | * See: https://www.npmjs.com/package/assert-args
94 | * See: https://www.npmjs.com/package/ensurethat
95 | */
96 | function doArgs(values, types) {
97 | var value = void 0,
98 | type = void 0,
99 | carry = void 0,
100 | optional = void 0,
101 | defaultValue = void 0;
102 | var result = [];
103 |
104 | var _iteratorNormalCompletion = true;
105 | var _didIteratorError = false;
106 | var _iteratorError = undefined;
107 |
108 | try {
109 | for (var _iterator = types[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
110 | type = _step.value;
111 |
112 | // Load value if we don't have one already
113 | if (!carry) {
114 | value = Array.prototype.shift.call(values);
115 | }
116 |
117 | // Handle optional type
118 | if (Array.isArray(type)) {
119 | optional = true;
120 | defaultValue = type[1];
121 | type = type[0];
122 | } else {
123 | optional = false;
124 | }
125 |
126 | // Handle multitype
127 | type = type.split('|');
128 |
129 | // Is it a correct value?
130 | if (type.includes(getType(value))) {
131 | result.push(value);
132 | carry = false;
133 | } else if (optional) {
134 | result.push(defaultValue);
135 | carry = true;
136 | } else {
137 | throw Error('Invalid arguments');
138 | }
139 | }
140 | } catch (err) {
141 | _didIteratorError = true;
142 | _iteratorError = err;
143 | } finally {
144 | try {
145 | if (!_iteratorNormalCompletion && _iterator.return) {
146 | _iterator.return();
147 | }
148 | } finally {
149 | if (_didIteratorError) {
150 | throw _iteratorError;
151 | }
152 | }
153 | }
154 |
155 | if (values.length) {
156 | // TODO maybe do some warning..?
157 | // throw Error('Extra arguments ' + values.length, values);
158 | }
159 | return result;
160 | }
161 |
162 | /**
163 | * Parse the passed string as JSON and extract or "manipulate" it using the property.
164 | *
165 | * @param {string} body - string response body
166 | * @param {string|array|function} property - property to get from body or modificator function
167 | * @param {function} callback function to call when all done
168 | */
169 | function tryParseJson(body, property, callback) {
170 | var _doArgs = doArgs(arguments, ['string', 'string|array|function|null', 'function']);
171 |
172 | var _doArgs2 = _slicedToArray(_doArgs, 3);
173 |
174 | body = _doArgs2[0];
175 | property = _doArgs2[1];
176 | callback = _doArgs2[2];
177 |
178 |
179 | try {
180 | // Won't harm if we replace escape sequence
181 | body = body.replace(/\x1b/g, '');
182 |
183 | // Try to parse
184 | var data = JSON.parse(body.toString());
185 |
186 | // Get the prop name if specified
187 | if (property) {
188 | var type = getType(property);
189 |
190 | if (type === 'array') {
191 | var newData = {};
192 |
193 | var _iteratorNormalCompletion2 = true;
194 | var _didIteratorError2 = false;
195 | var _iteratorError2 = undefined;
196 |
197 | try {
198 | for (var _iterator2 = property[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
199 | var p = _step2.value;
200 |
201 | newData[p] = data[p];
202 | }
203 | } catch (err) {
204 | _didIteratorError2 = true;
205 | _iteratorError2 = err;
206 | } finally {
207 | try {
208 | if (!_iteratorNormalCompletion2 && _iterator2.return) {
209 | _iterator2.return();
210 | }
211 | } finally {
212 | if (_didIteratorError2) {
213 | throw _iteratorError2;
214 | }
215 | }
216 | }
217 |
218 | data = newData;
219 | }
220 | if (type === 'string') {
221 | data = data[property];
222 | }
223 | if (type === 'function') {
224 | data = property(data);
225 | }
226 | }
227 |
228 | callback(null, data);
229 | } catch (e) {
230 | callback(e, body);
231 | }
232 | }
233 |
234 | // -----------------------------------------------------------------------------
235 |
236 | exports.init = function (host, defaultOptions, defaultParams) {
237 |
238 | /**
239 | * Builds the URL to Jenkins from formatstring pattern and params.
240 | *
241 | * @param {string} pattern - URL format string patern.
242 | * @param {string|number} arguments for the formatstring pattern.
243 | * @returns {string} url - the URL formated according to arguments.
244 | */
245 | function formatUrl() {
246 | return host + util.format.apply(null, arguments);
247 | }
248 |
249 | /**
250 | * Build REST params and correctly append them to URL.
251 | *
252 | * @param {string} url to be extended with params.
253 | * @param {object} specificParams key/value pair of params.
254 | * @returns {string} the extended url.
255 | */
256 | var appendParams = function appendParams(url, specificParams) {
257 | // Assign default and specific parameters
258 | var params = Object.assign({}, defaultParams, specificParams);
259 |
260 | // Stringify the querystring params
261 | var paramsString = qs.stringify(params);
262 |
263 | // Empty params
264 | if (paramsString === '') {
265 | return url;
266 | }
267 |
268 | // Does url contain parameters already?
269 | var delim = url.includes('?') ? '&' : '?';
270 |
271 | return url + delim + paramsString;
272 | };
273 |
274 | /**
275 | * Just helper funckion to build the request URL.
276 | *
277 | * @param {array} urlPattern array in format of [urlFormat, arg1, arg2] used to build the URL.
278 | * @param {object} customParams key/value pair of params.
279 | * @returns {string} the URL built.
280 | */
281 | function buildUrl(urlPattern, customParams) {
282 | var url = formatUrl.apply(null, urlPattern);
283 |
284 | url = appendParams(url, customParams);
285 | return url;
286 | }
287 |
288 | /**
289 | * Run the actual HTTP request.
290 | *
291 | * @param {object} specificOptions - options object overriding the default options below.
292 | * @param {object} customParams - custom url params to be added to url.
293 | * @param {function} callback - the callback function to be called when request is finished.
294 | */
295 | var doRequest = function doRequest(specificOptions, customParams, callback) {
296 |
297 | // Options - Default values
298 | var options = Object.assign({}, {
299 | urlPattern: ['/'],
300 | method: 'GET',
301 | successStatusCodes: [HTTP_CODE_200],
302 | failureStatusCodes: [],
303 | bodyProp: null,
304 | noparse: false,
305 | request: {}
306 | }, defaultOptions, specificOptions);
307 |
308 | // Create the url
309 | var url = buildUrl(options.urlPattern, customParams);
310 |
311 | // Build the actual request options
312 | var requestOptions = Object.assign({
313 | method: options.method,
314 | url: url,
315 | headers: [],
316 | followAllRedirects: true,
317 | form: null,
318 | body: null
319 | }, options.request);
320 |
321 | // Do the request
322 | request(requestOptions, function (error, response, body) {
323 | if (error) {
324 | callback(error, response);
325 | return;
326 | }
327 |
328 | if (Array.isArray(options.successStatusCodes) && !options.successStatusCodes.includes(response.statusCode) || Array.isArray(options.failureStatusCodes) && options.failureStatusCodes.includes(response.statusCode)) {
329 | callback('Server returned unexpected status code: ' + response.statusCode, response);
330 | return;
331 | }
332 |
333 | if (options.noparse) {
334 | // Wrap body in the response object
335 | if (typeof body === 'string') {
336 | body = { body: body };
337 | }
338 |
339 | // Add location
340 | var location = response.headers.Location || response.headers.location;
341 |
342 | if (location) {
343 | body.location = location;
344 | }
345 |
346 | // Add status code
347 | body.statusCode = response.statusCode;
348 |
349 | callback(null, body);
350 | } else {
351 | tryParseJson(body, options.bodyProp, callback);
352 | }
353 | });
354 | };
355 |
356 | return {
357 |
358 | /** ***********************************\
359 | |* Builds *|
360 | \*************************************/
361 |
362 | /** Trigger Jenkins to build.
363 | *
364 | * Return queue location of newly-created job as per
365 | * https://issues.jenkins-ci.org/browse/JENKINS-12827?focusedCommentId=201381#comment-201381
366 | */
367 | build: function build(jobName, customParams, callback) {
368 | var _doArgs3 = doArgs(arguments, ['string', ['object', {}], 'function']);
369 |
370 | var _doArgs4 = _slicedToArray(_doArgs3, 3);
371 |
372 | jobName = _doArgs4[0];
373 | customParams = _doArgs4[1];
374 | callback = _doArgs4[2];
375 |
376 |
377 | doRequest({
378 | method: 'POST',
379 | urlPattern: [BUILD_START, jobName],
380 | successStatusCodes: [HTTP_CODE_201, HTTP_CODE_302],
381 | noparse: true
382 | }, customParams, function (error, data) {
383 | if (error) {
384 | callback(error, data);
385 | return;
386 | }
387 |
388 | var queueIdRe = /\/queue\/item\/(\d+)/;
389 | var id = +queueIdRe.exec(data.location)[1];
390 |
391 | data.queueId = id;
392 |
393 | callback(null, data);
394 | });
395 | },
396 |
397 | /** */
398 | build_with_params: function build_with_params(jobName, customParams, callback) {
399 | var _doArgs5 = doArgs(arguments, ['string', ['object', {}], 'function']);
400 |
401 | var _doArgs6 = _slicedToArray(_doArgs5, 3);
402 |
403 | jobName = _doArgs6[0];
404 | customParams = _doArgs6[1];
405 | callback = _doArgs6[2];
406 |
407 |
408 | doRequest({
409 | method: 'POST',
410 | urlPattern: [BUILD_START_WITHPARAMS, jobName],
411 | successStatusCodes: [HTTP_CODE_201, HTTP_CODE_302],
412 | noparse: true
413 | }, customParams, function (error, data) {
414 | if (error) {
415 | callback(error, data);
416 | return;
417 | }
418 |
419 | var queueIdRe = /\/queue\/item\/(\d+)/;
420 | var id = +queueIdRe.exec(data.location)[1];
421 |
422 | data.queueId = id;
423 |
424 | callback(null, data);
425 | });
426 | },
427 |
428 | /** */
429 | stop_build: function stop_build(jobName, buildNumber, customParams, callback) {
430 | var _doArgs7 = doArgs(arguments, ['string', 'string|number', ['object', {}], 'function']);
431 |
432 | var _doArgs8 = _slicedToArray(_doArgs7, 4);
433 |
434 | jobName = _doArgs8[0];
435 | buildNumber = _doArgs8[1];
436 | customParams = _doArgs8[2];
437 | callback = _doArgs8[3];
438 |
439 |
440 | doRequest({
441 | method: 'POST',
442 | urlPattern: [BUILD_STOP, jobName, buildNumber],
443 | noparse: true
444 | }, customParams, function (error, data) {
445 | if (error) {
446 | callback(error, data);
447 | return;
448 | }
449 |
450 | data.body = 'Build ' + buildNumber + ' stopped.';
451 |
452 | callback(null, data);
453 | });
454 | },
455 |
456 | /** Get the output for a job's build */
457 | console_output: function console_output(jobName, buildNumber, customParams, callback) {
458 | var _doArgs9 = doArgs(arguments, ['string', 'string|number', ['object', {}], 'function']);
459 |
460 | var _doArgs10 = _slicedToArray(_doArgs9, 4);
461 |
462 | jobName = _doArgs10[0];
463 | buildNumber = _doArgs10[1];
464 | customParams = _doArgs10[2];
465 | callback = _doArgs10[3];
466 |
467 |
468 | doRequest({
469 | urlPattern: [JOB_OUTPUT, jobName, buildNumber],
470 | noparse: true
471 | }, customParams, callback);
472 | },
473 |
474 | /** Get information for the last build of a job */
475 | last_build_info: function last_build_info(jobName, customParams, callback) {
476 | var _doArgs11 = doArgs(arguments, ['string', ['object', {}], 'function']);
477 |
478 | var _doArgs12 = _slicedToArray(_doArgs11, 3);
479 |
480 | jobName = _doArgs12[0];
481 | customParams = _doArgs12[1];
482 | callback = _doArgs12[2];
483 |
484 |
485 | doRequest({
486 | urlPattern: [LAST_BUILD, jobName]
487 | }, customParams, callback);
488 | },
489 |
490 | /** Get information for the last completed build of a job */
491 | last_completed_build_info: function last_completed_build_info(jobName, customParams, callback) {
492 | var _doArgs13 = doArgs(arguments, ['string', ['object', {}], 'function']);
493 |
494 | var _doArgs14 = _slicedToArray(_doArgs13, 3);
495 |
496 | jobName = _doArgs14[0];
497 | customParams = _doArgs14[1];
498 | callback = _doArgs14[2];
499 |
500 |
501 | doRequest({
502 | urlPattern: [LAST_COMPLETED_BUILD, jobName]
503 | }, customParams, callback);
504 | },
505 |
506 | /** Get information for the build number of a job */
507 | build_info: function build_info(jobName, buildNumber, customParams, callback) {
508 | var _doArgs15 = doArgs(arguments, ['string', 'string|number', ['object', {}], 'function']);
509 |
510 | var _doArgs16 = _slicedToArray(_doArgs15, 4);
511 |
512 | jobName = _doArgs16[0];
513 | buildNumber = _doArgs16[1];
514 | customParams = _doArgs16[2];
515 | callback = _doArgs16[3];
516 |
517 |
518 | doRequest({
519 | urlPattern: [BUILD_INFO, jobName, buildNumber]
520 | }, customParams, callback);
521 | },
522 |
523 | /** Get information for the all builds */
524 | all_builds: function all_builds(jobName, param, customParams, callback) {
525 |
526 | // TODO better name and handle the "param" ???
527 | var _doArgs17 = doArgs(arguments, ['string', ['string', 'id,timestamp,result,duration'], ['object', {}], 'function']);
528 |
529 | var _doArgs18 = _slicedToArray(_doArgs17, 4);
530 |
531 | jobName = _doArgs18[0];
532 | param = _doArgs18[1];
533 | customParams = _doArgs18[2];
534 | callback = _doArgs18[3];
535 | doRequest({
536 | urlPattern: [ALL_BUILDS, jobName, param],
537 | bodyProp: 'allBuilds'
538 | }, customParams, callback);
539 | },
540 |
541 | /** Get the test results for the build number of a job */
542 | test_result: function test_result(jobName, buildNumber, customParams, callback) {
543 | var _doArgs19 = doArgs(arguments, ['string', 'string|number', ['object', {}], 'function']);
544 |
545 | var _doArgs20 = _slicedToArray(_doArgs19, 4);
546 |
547 | jobName = _doArgs20[0];
548 | buildNumber = _doArgs20[1];
549 | customParams = _doArgs20[2];
550 | callback = _doArgs20[3];
551 |
552 |
553 | doRequest({
554 | urlPattern: [TEST_REPORT, jobName, buildNumber]
555 | }, customParams, callback);
556 | },
557 |
558 | /** Get the last build report for a job.
559 | * @obsolete Use last_build_info instead.
560 | * Probly will make this to return the test result. */
561 | last_build_report: function last_build_report(jobName, customParams, callback) {
562 | this.last_build_info(jobName, customParams, callback);
563 | // doRequest({
564 | // urlPattern: [LAST_REPORT, jobName],
565 | // }, customParams, callback);
566 | },
567 |
568 | /** Deletes build data for certain job */
569 | delete_build: function delete_build(jobName, buildNumber, customParams, callback) {
570 | var _doArgs21 = doArgs(arguments, ['string', 'string|number', ['object', {}], 'function']);
571 |
572 | var _doArgs22 = _slicedToArray(_doArgs21, 4);
573 |
574 | jobName = _doArgs22[0];
575 | buildNumber = _doArgs22[1];
576 | customParams = _doArgs22[2];
577 | callback = _doArgs22[3];
578 |
579 |
580 | doRequest({
581 | method: 'POST',
582 | urlPattern: [BUILD_DELETE, jobName, buildNumber],
583 | noparse: true
584 | }, customParams, function (error, data) {
585 | if (error) {
586 | callback(error, data);
587 | } else {
588 | data.body = 'Build ' + buildNumber + ' deleted.';
589 | callback(null, data);
590 | }
591 | });
592 | },
593 |
594 | /** ***********************************\
595 | |* Jobs *|
596 | \*************************************/
597 |
598 | /** Return a list of object literals containing the name and color of all jobs on the Jenkins server */
599 | all_jobs: function all_jobs(customParams, callback) {
600 | var _doArgs23 = doArgs(arguments, [['object', {}], 'function']);
601 |
602 | var _doArgs24 = _slicedToArray(_doArgs23, 2);
603 |
604 | customParams = _doArgs24[0];
605 | callback = _doArgs24[1];
606 |
607 |
608 | doRequest({
609 | urlPattern: [JOB_LIST],
610 | bodyProp: 'jobs'
611 | }, customParams, callback);
612 | },
613 |
614 | /** Get jobs config in xml */
615 | get_config_xml: function get_config_xml(jobName, customParams, callback) {
616 | var _doArgs25 = doArgs(arguments, ['string', ['object', {}], 'function']);
617 |
618 | var _doArgs26 = _slicedToArray(_doArgs25, 3);
619 |
620 | jobName = _doArgs26[0];
621 | customParams = _doArgs26[1];
622 | callback = _doArgs26[2];
623 |
624 |
625 | doRequest({
626 | urlPattern: [JOB_CONFIG, jobName],
627 | noparse: true
628 | }, customParams, function (error, data) {
629 | // Get only the XML response body
630 | if (error) {
631 | callback(error, data);
632 | } else {
633 | callback(null, data.body);
634 | }
635 | });
636 | },
637 |
638 | /** Update a job config xml by passing it through your modifyFunction. */
639 | update_config: function update_config(jobName, modifyFunction, customParams, callback) {
640 | var _doArgs27 = doArgs(arguments, ['string', 'function', ['object', {}], 'function']);
641 |
642 | var _doArgs28 = _slicedToArray(_doArgs27, 4);
643 |
644 | jobName = _doArgs28[0];
645 | modifyFunction = _doArgs28[1];
646 | customParams = _doArgs28[2];
647 | callback = _doArgs28[3];
648 |
649 |
650 | var self = this;
651 |
652 | self.get_config_xml(jobName, customParams, function (error, data) {
653 | if (error) {
654 | callback(error, data);
655 | return;
656 | }
657 |
658 | // Modify the config data
659 | data = modifyFunction(data);
660 |
661 | self.update_job(jobName, data, customParams, callback);
662 | });
663 | },
664 |
665 | /** Update a existing job based on a jobConfig xml string */
666 | update_job: function update_job(jobName, jobConfig, customParams, callback) {
667 | var _doArgs29 = doArgs(arguments, ['string', 'string', ['object', {}], 'function']);
668 |
669 | var _doArgs30 = _slicedToArray(_doArgs29, 4);
670 |
671 | jobName = _doArgs30[0];
672 | jobConfig = _doArgs30[1];
673 | customParams = _doArgs30[2];
674 | callback = _doArgs30[3];
675 |
676 |
677 | doRequest({
678 | method: 'POST',
679 | urlPattern: [JOB_CONFIG, jobName],
680 | request: {
681 | body: jobConfig,
682 | headers: { 'Content-Type': 'application/xml' }
683 | },
684 | noparse: true
685 | }, customParams, function (error, data) {
686 | if (error) {
687 | callback(error, data);
688 | return;
689 | }
690 | // TODO rather return job_info ???
691 | // const data = {name: jobName, location: response.headers['Location'] || response.headers['location']};
692 | callback(null, { name: jobName });
693 | });
694 | },
695 |
696 | /** Get all information for a job */
697 | job_info: function job_info(jobName, customParams, callback) {
698 | var _doArgs31 = doArgs(arguments, ['string', ['object', {}], 'function']);
699 |
700 | var _doArgs32 = _slicedToArray(_doArgs31, 3);
701 |
702 | jobName = _doArgs32[0];
703 | customParams = _doArgs32[1];
704 | callback = _doArgs32[2];
705 |
706 |
707 | doRequest({
708 | urlPattern: [JOB_INFO, jobName]
709 | }, customParams, callback);
710 | },
711 |
712 | /** Create a new job based on a jobConfig string */
713 | create_job: function create_job(jobName, jobConfig, customParams, callback) {
714 |
715 | // Set the created job name!
716 | var _doArgs33 = doArgs(arguments, ['string', 'string', ['object', {}], 'function']);
717 |
718 | var _doArgs34 = _slicedToArray(_doArgs33, 4);
719 |
720 | jobName = _doArgs34[0];
721 | jobConfig = _doArgs34[1];
722 | customParams = _doArgs34[2];
723 | callback = _doArgs34[3];
724 | customParams.name = jobName;
725 |
726 | var self = this;
727 |
728 | doRequest({
729 | method: 'POST',
730 | urlPattern: [JOB_CREATE],
731 | request: {
732 | body: jobConfig,
733 | headers: { 'Content-Type': 'application/xml' }
734 | },
735 | noparse: true
736 | }, customParams, function (error, data) {
737 | if (error) {
738 | callback(error, data);
739 | return;
740 | }
741 | self.job_info(jobName, customParams, callback);
742 | });
743 | },
744 |
745 | /** Copies a job and allows you to pass in a function to modify the configuration of the job you would like to copy */
746 | copy_job: function copy_job(jobName, newJobName, modifyFunction, customParams, callback) {
747 | var _doArgs35 = doArgs(arguments, ['string', 'string', 'function', ['object', {}], 'function']);
748 |
749 | var _doArgs36 = _slicedToArray(_doArgs35, 5);
750 |
751 | jobName = _doArgs36[0];
752 | newJobName = _doArgs36[1];
753 | modifyFunction = _doArgs36[2];
754 | customParams = _doArgs36[3];
755 | callback = _doArgs36[4];
756 |
757 |
758 | var self = this;
759 |
760 | this.get_config_xml(jobName, customParams, function (error, data) {
761 | if (error) {
762 | callback(error, data);
763 | return;
764 | }
765 |
766 | // Modify the data
767 | data = modifyFunction(data);
768 |
769 | self.create_job(newJobName, data, customParams, callback);
770 | });
771 | },
772 |
773 | /** Deletes a job */
774 | delete_job: function delete_job(jobName, customParams, callback) {
775 | var _doArgs37 = doArgs(arguments, ['string', ['object', {}], 'function']);
776 |
777 | var _doArgs38 = _slicedToArray(_doArgs37, 3);
778 |
779 | jobName = _doArgs38[0];
780 | customParams = _doArgs38[1];
781 | callback = _doArgs38[2];
782 |
783 |
784 | doRequest({
785 | method: 'POST',
786 | urlPattern: [JOB_DELETE, jobName],
787 | noparse: true
788 | }, customParams, function (error, data) {
789 | if (error) {
790 | callback(error, data);
791 | return;
792 | }
793 | callback(null, { name: jobName });
794 | });
795 | },
796 |
797 | /** Disables a job */
798 | disable_job: function disable_job(jobName, customParams, callback) {
799 | var _doArgs39 = doArgs(arguments, ['string', ['object', {}], 'function']);
800 |
801 | var _doArgs40 = _slicedToArray(_doArgs39, 3);
802 |
803 | jobName = _doArgs40[0];
804 | customParams = _doArgs40[1];
805 | callback = _doArgs40[2];
806 |
807 |
808 | var self = this;
809 |
810 | doRequest({
811 | method: 'POST',
812 | urlPattern: [JOB_DISABLE, jobName],
813 | noparse: true
814 | }, customParams, function (error, data) {
815 | if (error) {
816 | callback(error, data);
817 | return;
818 | }
819 | self.job_info(jobName, customParams, callback);
820 | });
821 | },
822 |
823 | /** Enables a job */
824 | enable_job: function enable_job(jobName, customParams, callback) {
825 | var _doArgs41 = doArgs(arguments, ['string', ['object', {}], 'function']);
826 |
827 | var _doArgs42 = _slicedToArray(_doArgs41, 3);
828 |
829 | jobName = _doArgs42[0];
830 | customParams = _doArgs42[1];
831 | callback = _doArgs42[2];
832 |
833 |
834 | var self = this;
835 |
836 | doRequest({
837 | method: 'POST',
838 | urlPattern: [JOB_ENABLE, jobName],
839 | noparse: true
840 | }, customParams, function (error, data) {
841 | if (error) {
842 | callback(error, data);
843 | return;
844 | }
845 | self.job_info(jobName, customParams, callback);
846 | });
847 | },
848 |
849 | /** Get the last build report for a job */
850 | last_success: function last_success(jobName, customParams, callback) {
851 | var _doArgs43 = doArgs(arguments, ['string', ['object', {}], 'function']);
852 |
853 | var _doArgs44 = _slicedToArray(_doArgs43, 3);
854 |
855 | jobName = _doArgs44[0];
856 | customParams = _doArgs44[1];
857 | callback = _doArgs44[2];
858 |
859 |
860 | doRequest({
861 | method: 'POST',
862 | urlPattern: [LAST_SUCCESS, jobName]
863 | }, customParams, callback);
864 | },
865 |
866 | /** Get the last result for a job */
867 | last_result: function last_result(jobName, customParams, callback) {
868 | var _doArgs45 = doArgs(arguments, ['string', ['object', {}], 'function']);
869 |
870 | var _doArgs46 = _slicedToArray(_doArgs45, 3);
871 |
872 | jobName = _doArgs46[0];
873 | customParams = _doArgs46[1];
874 | callback = _doArgs46[2];
875 |
876 |
877 | this.job_info(jobName, function (error, data) {
878 | if (error) {
879 | callback(error, data);
880 | return;
881 | }
882 |
883 | var lastResultUrl = data.lastBuild.url;
884 |
885 | doRequest({
886 | urlPattern: [lastResultUrl + API, jobName]
887 | }, customParams, callback);
888 | });
889 | },
890 |
891 | /** ***********************************\
892 | |* Queues *|
893 | \*************************************/
894 |
895 | /** Get all queued items */
896 | queue: function queue(customParams, callback) {
897 | var _doArgs47 = doArgs(arguments, [['object', {}], 'function']);
898 |
899 | var _doArgs48 = _slicedToArray(_doArgs47, 2);
900 |
901 | customParams = _doArgs48[0];
902 | callback = _doArgs48[1];
903 |
904 |
905 | doRequest({
906 | urlPattern: [QUEUE]
907 | }, customParams, callback);
908 | },
909 |
910 | /** Get one queued item */
911 | queue_item: function queue_item(queueNumber, customParams, callback) {
912 | var _doArgs49 = doArgs(arguments, ['string|number', ['object', {}], 'function']);
913 |
914 | var _doArgs50 = _slicedToArray(_doArgs49, 3);
915 |
916 | queueNumber = _doArgs50[0];
917 | customParams = _doArgs50[1];
918 | callback = _doArgs50[2];
919 |
920 |
921 | doRequest({
922 | urlPattern: [QUEUE_ITEM, queueNumber]
923 | }, customParams, callback);
924 | },
925 |
926 | /** Cancel a queued item */
927 | cancel_item: function cancel_item(itemId, customParams, callback) {
928 | var _doArgs51 = doArgs(arguments, ['string|number', ['object', {}], 'function']);
929 |
930 | var _doArgs52 = _slicedToArray(_doArgs51, 3);
931 |
932 | itemId = _doArgs52[0];
933 | customParams = _doArgs52[1];
934 | callback = _doArgs52[2];
935 |
936 |
937 | customParams.id = itemId;
938 |
939 | doRequest({
940 | method: 'POST',
941 | urlPattern: [QUEUE_CANCEL_ITEM]
942 | }, customParams, callback);
943 | },
944 |
945 | /** ***********************************\
946 | |* Computers *|
947 | \*************************************/
948 |
949 | /** Get info about all jenkins workers including currently executing jobs */
950 | computers: function computers(customParams, callback) {
951 | var _doArgs53 = doArgs(arguments, [['object', {}], 'function']);
952 |
953 | var _doArgs54 = _slicedToArray(_doArgs53, 2);
954 |
955 | customParams = _doArgs54[0];
956 | callback = _doArgs54[1];
957 |
958 |
959 | doRequest({
960 | urlPattern: [COMPUTERS]
961 | }, customParams, callback);
962 | },
963 |
964 | /** ***********************************\
965 | |* Views *|
966 | \*************************************/
967 |
968 | /** Return a list of all the views on the Jenkins server */
969 | all_views: function all_views(customParams, callback) {
970 | var _doArgs55 = doArgs(arguments, [['object', {}], 'function']);
971 |
972 | var _doArgs56 = _slicedToArray(_doArgs55, 2);
973 |
974 | customParams = _doArgs56[0];
975 | callback = _doArgs56[1];
976 |
977 |
978 | doRequest({
979 | urlPattern: [VIEW_LIST],
980 | bodyProp: 'views'
981 | }, customParams, callback);
982 | },
983 |
984 | /** */
985 | create_view: function create_view(viewName, mode, customParams, callback) {
986 | var _doArgs57 = doArgs(arguments, ['string', ['string', 'hudson.model.ListView'], ['object', {}], 'function']);
987 |
988 | var _doArgs58 = _slicedToArray(_doArgs57, 4);
989 |
990 | viewName = _doArgs58[0];
991 | mode = _doArgs58[1];
992 | customParams = _doArgs58[2];
993 | callback = _doArgs58[3];
994 |
995 |
996 | var formData = { name: viewName, mode: mode };
997 |
998 | formData.json = JSON.stringify(formData);
999 |
1000 | var self = this;
1001 |
1002 | doRequest({
1003 | method: 'POST',
1004 | urlPattern: [VIEW_CREATE],
1005 | request: {
1006 | form: formData
1007 | },
1008 | noparse: true
1009 | }, customParams, function (error, data) {
1010 | if (error) {
1011 | callback(error, data);
1012 | return;
1013 | }
1014 | self.view_info(viewName, customParams, callback);
1015 | });
1016 | },
1017 |
1018 | /** */
1019 | view_info: function view_info(viewId, customParams, callback) {
1020 | var _doArgs59 = doArgs(arguments, ['string', ['object', {}], 'function']);
1021 |
1022 | var _doArgs60 = _slicedToArray(_doArgs59, 3);
1023 |
1024 | viewId = _doArgs60[0];
1025 | customParams = _doArgs60[1];
1026 | callback = _doArgs60[2];
1027 |
1028 |
1029 | doRequest({
1030 | urlPattern: [VIEW_INFO, viewId]
1031 | }, customParams, callback);
1032 | },
1033 |
1034 | /** Update a view based on a viewConfig object */
1035 | update_view: function update_view(viewName, viewConfig, customParams, callback) {
1036 | var _doArgs61 = doArgs(arguments, ['string', 'object', ['object', {}], 'function']);
1037 |
1038 | var _doArgs62 = _slicedToArray(_doArgs61, 4);
1039 |
1040 | viewName = _doArgs62[0];
1041 | viewConfig = _doArgs62[1];
1042 | customParams = _doArgs62[2];
1043 | callback = _doArgs62[3];
1044 |
1045 |
1046 | viewConfig.json = JSON.stringify(viewConfig);
1047 |
1048 | var self = this;
1049 |
1050 | doRequest({
1051 | method: 'POST',
1052 | urlPattern: [VIEW_CONFIG, viewName],
1053 | request: {
1054 | form: viewConfig
1055 | // headers: {'content-type': 'application/x-www-form-urlencoded'},
1056 | },
1057 | noparse: true
1058 | }, customParams, function (error, data) {
1059 | if (error) {
1060 | callback(error, data);
1061 | return;
1062 | }
1063 | self.view_info(viewName, customParams, callback);
1064 | });
1065 | },
1066 |
1067 | /** */
1068 | delete_view: function delete_view(viewName, customParams, callback) {
1069 | var _doArgs63 = doArgs(arguments, ['string', ['object', {}], 'function']);
1070 |
1071 | var _doArgs64 = _slicedToArray(_doArgs63, 3);
1072 |
1073 | viewName = _doArgs64[0];
1074 | customParams = _doArgs64[1];
1075 | callback = _doArgs64[2];
1076 |
1077 |
1078 | doRequest({
1079 | method: 'POST',
1080 | urlPattern: [VIEW_DELETE, viewName],
1081 | noparse: true
1082 | }, customParams, function (error, data) {
1083 | if (error) {
1084 | callback(error, data);
1085 | return;
1086 | }
1087 | callback(null, { name: viewName });
1088 | });
1089 | },
1090 |
1091 | /** */
1092 | add_job_to_view: function add_job_to_view(viewId, jobName, customParams, callback) {
1093 | var _doArgs65 = doArgs(arguments, ['string', 'string', ['object', {}], 'function']);
1094 |
1095 | var _doArgs66 = _slicedToArray(_doArgs65, 4);
1096 |
1097 | viewId = _doArgs66[0];
1098 | jobName = _doArgs66[1];
1099 | customParams = _doArgs66[2];
1100 | callback = _doArgs66[3];
1101 |
1102 |
1103 | customParams.name = jobName;
1104 |
1105 | doRequest({
1106 | method: 'POST',
1107 | urlPattern: [VIEW_ADD_JOB, viewId],
1108 | noparse: true
1109 | }, customParams, callback);
1110 | },
1111 |
1112 | /** */
1113 | remove_job_from_view: function remove_job_from_view(viewId, jobName, customParams, callback) {
1114 | var _doArgs67 = doArgs(arguments, ['string', 'string', ['object', {}], 'function']);
1115 |
1116 | var _doArgs68 = _slicedToArray(_doArgs67, 4);
1117 |
1118 | viewId = _doArgs68[0];
1119 | jobName = _doArgs68[1];
1120 | customParams = _doArgs68[2];
1121 | callback = _doArgs68[3];
1122 |
1123 |
1124 | customParams.name = jobName;
1125 |
1126 | doRequest({
1127 | method: 'POST',
1128 | urlPattern: [VIEW_REMOVE_JOB, viewId],
1129 | noparse: true
1130 | }, customParams, callback);
1131 | },
1132 |
1133 | /* Return a list of objet literals containing the name and color of all the jobs for a view on the Jenkins server */
1134 | all_jobs_in_view: function all_jobs_in_view(viewId, customParams, callback) {
1135 | var _doArgs69 = doArgs(arguments, ['string', ['object', {}], 'function']);
1136 |
1137 | var _doArgs70 = _slicedToArray(_doArgs69, 3);
1138 |
1139 | viewId = _doArgs70[0];
1140 | customParams = _doArgs70[1];
1141 | callback = _doArgs70[2];
1142 |
1143 |
1144 | doRequest({
1145 | urlPattern: [VIEW_INFO, viewId],
1146 | bodyProp: 'jobs'
1147 | }, customParams, callback);
1148 | },
1149 |
1150 | /** ***********************************\
1151 | |* Plugins *|
1152 | \*************************************/
1153 |
1154 | /* Get all installed plugins */
1155 | all_installed_plugins: function all_installed_plugins(customParams, callback) {
1156 | var _doArgs71 = doArgs(arguments, [['object', {}], 'function']);
1157 |
1158 | var _doArgs72 = _slicedToArray(_doArgs71, 2);
1159 |
1160 | customParams = _doArgs72[0];
1161 | callback = _doArgs72[1];
1162 |
1163 |
1164 | customParams.depth = 1;
1165 |
1166 | doRequest({
1167 | urlPattern: [PLUGINS],
1168 | failureStatusCodes: [HTTP_CODE_302],
1169 | noparse: true,
1170 | bodyProp: 'plugins'
1171 | }, customParams, callback);
1172 | },
1173 |
1174 | /* Install a plugin */
1175 | install_plugin: function install_plugin(plugin, customParams, callback) {
1176 | var _doArgs73 = doArgs(arguments, ['string', ['object', {}], 'function']);
1177 |
1178 | var _doArgs74 = _slicedToArray(_doArgs73, 3);
1179 |
1180 | plugin = _doArgs74[0];
1181 | customParams = _doArgs74[1];
1182 | callback = _doArgs74[2];
1183 |
1184 |
1185 | var body = '';
1186 |
1187 | doRequest({
1188 | method: 'POST',
1189 | urlPattern: [INSTALL_PLUGIN],
1190 | request: {
1191 | body: body,
1192 | headers: { 'Content-Type': 'text/xml' }
1193 | },
1194 | noparse: true,
1195 | bodyProp: 'plugins'
1196 | }, customParams, callback);
1197 | },
1198 |
1199 | /* Create a new folder
1200 | * Needs Folder plugin in Jenkins: https://wiki.jenkins-ci.org/display/JENKINS/CloudBees+Folders+Plugin
1201 | * curl -XPOST 'http://jenkins/createItem?name=FolderName&mode=com.cloudbees.hudson.plugins.folder.Folder&from=&json=%7B%22name%22%3A%22FolderName%22%2C%22mode%22%3A%22com.cloudbees.hudson.plugins.folder.Folder%22%2C%22from%22%3A%22%22%2C%22Submit%22%3A%22OK%22%7D&Submit=OK' --user user.name:YourAPIToken -H "Content-Type:application/x-www-form-urlencoded"
1202 | * https://gist.github.com/stuart-warren/7786892
1203 | */
1204 | create_folder: function create_folder(folderName, customParams, callback) {
1205 | var _doArgs75 = doArgs(arguments, ['string', ['object', {}], 'function']);
1206 |
1207 | var _doArgs76 = _slicedToArray(_doArgs75, 3);
1208 |
1209 | folderName = _doArgs76[0];
1210 | customParams = _doArgs76[1];
1211 | callback = _doArgs76[2];
1212 |
1213 |
1214 | var mode = 'com.cloudbees.hudson.plugins.folder.Folder';
1215 |
1216 | customParams.name = folderName;
1217 | customParams.mode = mode;
1218 | customParams.Submit = 'OK';
1219 |
1220 | doRequest({
1221 | method: 'POST',
1222 | urlPattern: [NEWFOLDER]
1223 | }, customParams, callback);
1224 | }
1225 | };
1226 | };
--------------------------------------------------------------------------------