lib/api/job.js

Maintainability

79.63

Lines of code

253

Created with Raphaël 2.1.002550751002025-8-9

2025-8-9
Maintainability: 79.63

Created with Raphaël 2.1.00751502253002025-8-9

2025-8-9
Lines of Code: 253

Difficulty

33.00

Estimated Errors

1.33

Function weight

By Complexity

Created with Raphaël 2.1.0_cb3

By SLOC

Created with Raphaël 2.1.0streamConsole49
1
"use strict";
Column: 1 "Use the function form of "use strict"."
2
import _ from 'lodash';
3
import async from 'async';
4
import ConsoleStream from './consolestream.js';
5
import RssParser from 'rss-parser';
6
 
7
/**
8
 * Create a job with specified configuration.
9
 *
10
 * @param {String} name: Jenkins job name
11
 * @param {String} config: Jenkins job config.xml
12
 * @param {Function} cb: standard cb(err, result) callback
13
 */
14
function create(name, config, cb) {
15
  const opts = {
16
    body: config,
17
    contentType: 'application/xml',
18
  };
19
  this.remoteAccessApi.postCreateItem(name, _.merge(opts, this.opts.headers), cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
Column: 59 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
20
}
21
 
22
/**
23
 * Retrieve information about a job.
24
 * Information contains job status and reports among other things.
25
 *
26
 * @param {String} name: Jenkins job name
27
 * @param {Function} cb: standard cb(err, result) callback
28
 */
29
function read(name, cb) {
30
  this.remoteAccessApi.getJob(name, cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
31
}
32
 
33
/**
34
 * Retrieve information about the latest build of a job.
35
 *
36
 * @param {String} name: Jenkins job name
37
 * @param {Function} cb: standard cb(err, result) callback
38
 */
39
function readLatest(name, cb) {
40
  this.remoteAccessApi.getJobLastBuild(name, cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
41
}
42
 
43
/**
44
 * Update a job with specified configuration
45
 *
46
 * @param {String} name: Jenkins job name
47
 * @param {String} config: Jenkins job config.xml
48
 * @param {Function} cb: standard cb(err, result) callback
49
 */
50
function update(name, config, cb) {
51
  this.remoteAccessApi.postJobConfig(name, config, this.opts.headers, cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
Column: 52 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
52
}
53
 
54
/**
55
 * Delete a job.
56
 *
57
 * @param {String} name: Jenkins job name
58
 * @param {Function} cb: standard cb(err, result) callback
59
 */
60
function _delete(name, cb) {
61
  this.remoteAccessApi.postJobDelete(name, this.opts.headers, cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
Column: 44 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
62
}
63
 
64
/**
65
 * Build a job.
66
 *
67
 * @param {String} name: Jenkins job name
68
 * @param {Object|String} params: build parameters key-value pairs, passed as object or 'a=b&c=d' string
69
 * @param {Function} cb: standard cb(err, result) callback
70
 */
71
function build(name, params, cb) {
72
  const body = { parameter: [] } ;
73
  _.keys(params).forEach(function (key) {
74
    body.parameter.push({ name: key, value: params[key] });
75
  });
76
  const opts = {
77
    token: 'nestor'
78
  };
79
  this.remoteAccessApi.postJobBuild(name, JSON.stringify(body), _.merge(opts, this.opts.headers), cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
Column: 79 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
80
}
81
 
82
function checkStarted(buildUrl, cb) {
83
  // hudson.model.Queue$WaitingItem indicates that the item is still waiting in the queue
84
  // hudson.model.Queue$LeftItem indicates that the item left the queue and the build has started
85
  function _cb(err, result) {
86
    if (result && result._class === 'hudson.model.Queue$LeftItem') {
87
      cb(true);
88
    } else {
89
      cb(false);
90
    }
91
  }
92
  // extracts queue item number from the URL
93
  // e.g. http://localhost:8080/queue/item/12/ , the queue item number is 12
94
  function parseQueueItemNumber(buildUrl) {
95
    const elems = buildUrl.split('/');
96
    return elems[elems.length - 2];
97
  }
98
  this.remoteAccessApi.getQueueItem(parseQueueItemNumber(buildUrl), _cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
99
}
100
 
101
/**
102
 * Stop a running/building job.
103
 *
104
 * @param {String} name: Jenkins job name
105
 * @param {Function} cb: standard cb(err, result) callback
106
 */
107
function stop(name, cb) {
108
  this.remoteAccessApi.postJobLastBuildStop(name, this.opts.headers, cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
Column: 51 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
109
}
110
 
111
/**
112
 * Stream a Jenkins job console output (readable stream).
113
 * Jenkins uses the following headers:
114
 * - x-more-data to determine whether there are still more content coming through
115
 * - x-text-size to determine the starting point of progressive text output (this was obviously badly named, but stayed there for backward compatibility reason)
116
 *
117
 * @param {String} name: Jenkins job name
118
 * @param {Number} buildNumber: Jenkins job's build number
119
 * @param {Number} interval: interval between console requests in milliseconds
120
 * @param {Function} cb: standard cb(err, result) callback
121
 * @return {ConsoleStream} readable console output stream
122
 */
123
function streamConsole(name, buildNumber, interval, cb) {
124
 
125
  buildNumber = buildNumber || 'lastBuild';
126
 
127
  const stream = new ConsoleStream();
128
  const self   = this;
Column: 18 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
129
 
130
  function _processMoreChunks(result, response, cb) {
131
    if (response.text) {
132
      stream.emit('data', response.text);
133
    }
134
    // stream while there are more data
135
    async.whilst(
136
      function (cb) {
137
        cb(null, response.headers['x-more-data'] === 'true');
138
      },
139
      function (cb) {
140
        function _moreChunkCb(err, _result, _response) {
141
          response = _response;
142
          if (_response.text) {
143
            stream.emit('data', _response.text);
144
          }
145
          setTimeout(cb, interval);
Column: 11 "'setTimeout' is not defined."
146
        }
147
        const start = parseInt(response.headers['x-text-size'], 10);
148
        self.remoteAccessApi.getJobProgressiveText(name, buildNumber, start, _moreChunkCb);
149
      },
150
      function (err) {
151
        stream.emit('end');
152
        cb(err);
153
      }
154
    );
155
  }
156
 
157
  process.nextTick(function () {
Column: 3 "'process' is not defined."
158
    // start with value 0 indicates the first chunk of the console output
159
    const start = 0;
160
    function _firstChunkCb(err, result, response) {
161
      if (!err && response.statusCode === 200) {
162
        _processMoreChunks(result, response, cb);
163
      } else {
164
        cb(err, result);
165
      }
166
    }
167
    self.remoteAccessApi.getJobProgressiveText(name, buildNumber, start, _firstChunkCb);
168
  });
169
 
170
  return stream;
171
}
172
 
173
/**
174
 * Enable a job.
175
 * If job was disabled, then it will be enabled.
176
 * If job was already enabled, then it will stay as-is, no error.
177
 *
178
 * @param {String} name: Jenkins job name
179
 * @param {Function} cb: standard cb(err, result) callback
180
 */
181
function enable(name, cb) {
182
  this.remoteAccessApi.postJobEnable(name, this.opts.headers, cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
Column: 44 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
183
}
184
 
185
/**
186
 * Disable a job.
187
 * If job was enabled, then it will be disabled.
188
 * If job was already disabled, then it will stay as-is, no error.
189
 *
190
 * @param {String} jobName: Jenkins job name
191
 * @param {Function} cb: standard cb(err, result) callback
192
 */
193
function disable(name, cb) {
194
  this.remoteAccessApi.postJobDisable(name, this.opts.headers, cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
Column: 45 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
195
}
196
 
197
/**
198
 * Copy an existing job into a new job.
199
 *
200
 * @param {String} existingName: existing Jenkins job name to copy from
201
 * @param {String} newName: new Jenkins job name to copy to
202
 * @param {Function} cb: standard cb(err, result) callback
203
 */
204
function copy(existingName, newName, cb) {
205
  const opts = {
206
    mode: 'copy',
207
    from: existingName,
208
    contentType: 'text/plain',
209
  };
210
  this.remoteAccessApi.postCreateItem(newName, _.merge(opts, this.opts.headers), cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
Column: 62 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
211
}
212
 
213
/**
214
 * Fetch a job configuration.
215
 *
216
 * @param {String} name: Jenkins job name
217
 * @param {Function} cb: standard cb(err, result) callback
218
 */
219
function fetchConfig(name, cb) {
220
  this.remoteAccessApi.getJobConfig(name, cb);
Column: 3 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
221
}
222
 
223
/**
224
 * Parse job feed.
225
 *
226
 * @param {String} name: Jenkins job name
227
 * @param {Function} cb: standard cb(err, result) callback
228
 */
229
function parseFeed(name, cb) {
230
  const url = this.url + '/job/' + name + '/rssAll';
Column: 15 "If a strict mode function is executed using function invocation, its 'this' value will be undefined."
231
  new RssParser().parseURL(url, cb);
232
}
233
 
234
const exports = {
235
  create: create,
236
  read: read,
237
  readLatest: readLatest,
238
  update: update,
239
  delete: _delete,
240
  build: build,
241
  checkStarted: checkStarted,
242
  stop: stop,
243
  streamConsole: streamConsole,
244
  enable: enable,
245
  disable: disable,
246
  copy: copy,
247
  fetchConfig: fetchConfig,
248
  parseFeed: parseFeed
249
};
250
 
251
export {
252
  exports as default
253
};