screwdriver-coverage-sonar 3.1.5 → 3.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/commands.txt +1 -1
  2. package/index.js +82 -76
  3. package/package.json +11 -12
package/commands.txt CHANGED
@@ -15,7 +15,7 @@ SCANNER_PATH="/opt/sd/sonarscanner-cli-${TARGET_OS}/bin/sonar-scanner"
15
15
  if [ -s ${SCANNER_PATH} ] && [ -x ${SCANNER_PATH} ]; then eval $SCANNER_PATH $SCANNER_OPTION || true; exit 0; fi
16
16
  if unzip -version > /dev/null 2>&1; then SD_UNZIP_CMD_WRAPPER="eval"; else SD_UNZIP_CMD_WRAPPER="sd-step exec --pkg-version 6.0 core/unzip"; fi
17
17
  export SD_UNZIP_CMD_WRAPPER
18
- SD_SONAR_SCANNER_CLI_VERSION=4.4.0.2170
18
+ SD_SONAR_SCANNER_CLI_VERSION=4.6.2.2472
19
19
  $SD_CURL_CMD_WRAPPER "curl -o ./sonarscanner.zip -L https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SD_SONAR_SCANNER_CLI_VERSION}-${TARGET_OS}.zip"
20
20
  $SD_UNZIP_CMD_WRAPPER "unzip -q ./sonarscanner.zip"
21
21
  SCANNER_PATH="sonar-scanner-${SD_SONAR_SCANNER_CLI_VERSION}-${TARGET_OS}/bin/sonar-scanner"
package/index.js CHANGED
@@ -6,7 +6,7 @@ const fs = require('fs');
6
6
  const joi = require('joi');
7
7
  const hoek = require('@hapi/hoek');
8
8
  const path = require('path');
9
- const request = require('request-promise-native');
9
+ const request = require('screwdriver-request');
10
10
  const uuidv4 = require('uuid/v4');
11
11
  const logger = require('screwdriver-logger');
12
12
  const CoverageBase = require('screwdriver-coverage-base');
@@ -28,14 +28,10 @@ let sonarGitAppName;
28
28
  */
29
29
  function createProject(projectKey) {
30
30
  return request({
31
- json: true,
32
31
  method: 'POST',
33
- // eslint-disable-next-line max-len
34
- uri: `${sonarHost}/api/projects/create?project=${projectKey}&name=${projectKey}`,
35
- auth: {
36
- username: adminToken
37
- }
38
- }).catch((err) => {
32
+ url: `${sonarHost}/api/projects/create?project=${projectKey}&name=${projectKey}`,
33
+ username: adminToken
34
+ }).catch(err => {
39
35
  if (err.statusCode === 400 && err.message.includes('already exists')) {
40
36
  return {};
41
37
  }
@@ -53,14 +49,10 @@ function createProject(projectKey) {
53
49
  */
54
50
  function createUser(username, password) {
55
51
  return request({
56
- json: true,
57
52
  method: 'POST',
58
- // eslint-disable-next-line max-len
59
- uri: `${sonarHost}/api/users/create?login=${username}&name=${username}&password=${password}`,
60
- auth: {
61
- username: adminToken
62
- }
63
- }).catch((err) => {
53
+ url: `${sonarHost}/api/users/create?login=${username}&name=${username}&password=${password}`,
54
+ username: adminToken
55
+ }).catch(err => {
64
56
  if (err.statusCode === 400 && err.message.includes('already exists')) {
65
57
  return {};
66
58
  }
@@ -82,12 +74,9 @@ function configureGitApp(projectKey, projectName) {
82
74
 
83
75
  // Check if binding exists
84
76
  return request({
85
- json: true,
86
77
  method: 'GET',
87
- uri: `${sonarHost}/api/alm_settings/get_binding?project=${componentId}`,
88
- auth: {
89
- username: adminToken
90
- }
78
+ url: `${sonarHost}/api/alm_settings/get_binding?project=${componentId}`,
79
+ username: adminToken
91
80
  }).catch(() => {
92
81
  // if binding does not exist, add it
93
82
  logger.info(`Binding does not exist for Sonar project ${projectKey}, adding`);
@@ -96,19 +85,14 @@ function configureGitApp(projectKey, projectName) {
96
85
  return Promise.resolve();
97
86
  }
98
87
 
99
- // eslint-disable-next-line max-len
100
88
  const parameters = `almSetting=${gitAppEncoded}&project=${componentId}&repository=${projectName}&summaryCommentEnabled=true`;
101
89
 
102
90
  return request({
103
- json: true,
104
91
  method: 'POST',
105
- uri: `${sonarHost}/api/alm_settings/set_github_binding?${parameters}`,
106
- auth: {
107
- username: adminToken
108
- }
109
- }).catch((error) => {
92
+ url: `${sonarHost}/api/alm_settings/set_github_binding?${parameters}`,
93
+ username: adminToken
94
+ }).catch(error => {
110
95
  // if cannot configure app, do not throw err
111
- // eslint-disable-next-line max-len
112
96
  logger.error(`Failed to configure Git App ${gitApp} for Sonar project ${projectKey}: ${error.message}`);
113
97
 
114
98
  return Promise.resolve();
@@ -126,14 +110,10 @@ function configureGitApp(projectKey, projectName) {
126
110
  function grantUserPermission(username, projectKey) {
127
111
  // Always return 204 even with duplicate calls
128
112
  return request({
129
- json: true,
130
113
  method: 'POST',
131
- // eslint-disable-next-line
132
- uri: `${sonarHost}/api/permissions/add_user?login=${username}&permission=scan&projectKey=${projectKey}`,
133
- auth: {
134
- username: adminToken
135
- }
136
- }).catch((err) => {
114
+ url: `${sonarHost}/api/permissions/add_user?login=${username}&permission=scan&projectKey=${projectKey}`,
115
+ username: adminToken
116
+ }).catch(err => {
137
117
  throw new Error(`Failed to grant user ${username} permission: ${err.message}`);
138
118
  });
139
119
  }
@@ -148,13 +128,10 @@ function generateToken(username) {
148
128
  const tokenName = uuidv4();
149
129
 
150
130
  return request({
151
- json: true,
152
131
  method: 'POST',
153
- uri: `${sonarHost}/api/user_tokens/generate?login=${username}&name=${tokenName}`,
154
- auth: {
155
- username: adminToken
156
- }
157
- }).catch((err) => {
132
+ url: `${sonarHost}/api/user_tokens/generate?login=${username}&name=${tokenName}`,
133
+ username: adminToken
134
+ }).catch(err => {
158
135
  throw new Error(`Failed to generate user ${username} token: ${err.message}`);
159
136
  });
160
137
  }
@@ -178,7 +155,6 @@ function getMetrics({ projectKey, startTime, endTime, prNum, sonarEnterprise: en
178
155
  const parsedEndTime = endTime.replace(/\.(.*)/, timezoneOffset);
179
156
  const from = encodeURIComponent(parsedStartTime);
180
157
  const to = encodeURIComponent(parsedEndTime);
181
- // eslint-disable-next-line max-len
182
158
  let coverageUrl = `${sonarHost}/api/measures/search_history?component=${componentId}&metrics=tests,test_errors,test_failures,coverage&from=${from}&to=${to}&ps=1`;
183
159
 
184
160
  if (enterpriseEnabled && prNum) {
@@ -186,18 +162,15 @@ function getMetrics({ projectKey, startTime, endTime, prNum, sonarEnterprise: en
186
162
  }
187
163
 
188
164
  return request({
189
- json: true,
190
165
  method: 'GET',
191
- uri: coverageUrl,
192
- auth: {
193
- username: adminToken
194
- }
166
+ url: coverageUrl,
167
+ username: adminToken
195
168
  })
196
- .then((result) => {
169
+ .then(result => {
197
170
  const measures = {};
198
171
 
199
172
  // measures in result is an array, covert it to an object with metric name as key
200
- (hoek.reach(result, 'measures') || []).forEach((measure) => {
173
+ (hoek.reach(result, 'body.measures') || []).forEach(measure => {
201
174
  measures[measure.metric] = measure;
202
175
  });
203
176
 
@@ -219,12 +192,13 @@ function getMetrics({ projectKey, startTime, endTime, prNum, sonarEnterprise: en
219
192
 
220
193
  return metrics;
221
194
  })
222
- .catch((err) => {
195
+ .catch(err => {
223
196
  // if there is no coverage measurement target, 404 and 'Component key not found' are returned and this is not an error
224
197
  if (err.statusCode !== 404 || !/Component key '.*' not found/.test(err.message)) {
225
198
  // if cannot get coverage, do not throw err
226
- // eslint-disable-next-line max-len
227
- logger.error(`Failed to get coverage and tests percentage for Sonar project ${projectKey}: ${err.message}`);
199
+ logger.error(
200
+ `Failed to get coverage and tests percentage for Sonar project ${projectKey}: ${err.message}`
201
+ );
228
202
  }
229
203
 
230
204
  return {
@@ -251,16 +225,24 @@ function getMetrics({ projectKey, startTime, endTime, prNum, sonarEnterprise: en
251
225
  * @param {String} [config.prParentJobId] Screwdriver PR parent job ID
252
226
  * @return {Object} Sonar project key, project name, and username
253
227
  */
254
- function getProjectData({ scope, enterpriseEnabled, jobId: buildJobId,
255
- jobName: buildJobName, pipelineId, pipelineName, projectKey, prParentJobId, prNum }) {
228
+ function getProjectData({
229
+ scope,
230
+ enterpriseEnabled,
231
+ jobId: buildJobId,
232
+ jobName: buildJobName,
233
+ pipelineId,
234
+ pipelineName,
235
+ projectKey,
236
+ prParentJobId,
237
+ prNum
238
+ }) {
256
239
  let jobId = buildJobId;
257
240
  let jobName = buildJobName;
258
241
 
259
242
  // Determine scope based on projectKey
260
243
  if (projectKey) {
261
244
  const [projectScope, id] = projectKey.split(':');
262
- const projectName = projectScope === 'pipeline' ?
263
- pipelineName : `${pipelineName}:${jobName}`;
245
+ const projectName = projectScope === 'pipeline' ? pipelineName : `${pipelineName}:${jobName}`;
264
246
  const username = `user-${projectScope}-${id}`;
265
247
 
266
248
  return {
@@ -272,7 +254,7 @@ function getProjectData({ scope, enterpriseEnabled, jobId: buildJobId,
272
254
  }
273
255
 
274
256
  // Use user-configured scope; otherwise figure out default scope: pipeline scope for enterprise edition, job scope for everything else
275
- const userScope = (scope && scope !== 'undefined') ? scope : undefined;
257
+ const userScope = scope && scope !== 'undefined' ? scope : undefined;
276
258
  const coverageScope = userScope || (enterpriseEnabled ? 'pipeline' : 'job');
277
259
 
278
260
  if (coverageScope === 'pipeline') {
@@ -316,14 +298,30 @@ class CoverageSonar extends CoverageBase {
316
298
  constructor(config) {
317
299
  super();
318
300
 
319
- this.config = joi.attempt(config, joi.object().keys({
320
- sdApiUrl: joi.string().uri().required(),
321
- sdUiUrl: joi.string().uri().required(),
322
- sonarHost: joi.string().uri().required(),
323
- adminToken: joi.string().required(),
324
- sonarEnterprise: joi.boolean().default(false),
325
- sonarGitAppName: joi.string().default(DEFAULT_GIT_APP_NAME)
326
- }).unknown(true), 'Invalid config for sonar coverage plugin');
301
+ this.config = joi.attempt(
302
+ config,
303
+ joi
304
+ .object()
305
+ .keys({
306
+ sdApiUrl: joi
307
+ .string()
308
+ .uri()
309
+ .required(),
310
+ sdUiUrl: joi
311
+ .string()
312
+ .uri()
313
+ .required(),
314
+ sonarHost: joi
315
+ .string()
316
+ .uri()
317
+ .required(),
318
+ adminToken: joi.string().required(),
319
+ sonarEnterprise: joi.boolean().default(false),
320
+ sonarGitAppName: joi.string().default(DEFAULT_GIT_APP_NAME)
321
+ })
322
+ .unknown(true),
323
+ 'Invalid config for sonar coverage plugin'
324
+ );
327
325
 
328
326
  sdCoverageAuthUrl = `${this.config.sdApiUrl}/v4/coverage/token`;
329
327
  adminToken = this.config.adminToken;
@@ -331,8 +329,7 @@ class CoverageSonar extends CoverageBase {
331
329
  sonarEnterprise = this.config.sonarEnterprise;
332
330
  sonarGitAppName = this.config.sonarGitAppName;
333
331
 
334
- this.uploadCommands = COMMANDS
335
- .replace('$SD_SONAR_HOST', sonarHost)
332
+ this.uploadCommands = COMMANDS.replace('$SD_SONAR_HOST', sonarHost)
336
333
  .replace('$SD_UI_URL', this.config.sdUiUrl)
337
334
  .replace('$SD_SONAR_ENTERPRISE', sonarEnterprise)
338
335
  .split('\n');
@@ -354,8 +351,7 @@ class CoverageSonar extends CoverageBase {
354
351
  * @return {Promise} An access token that build can use
355
352
  * to talk to coverage server
356
353
  */
357
- _getAccessToken({ scope, username, projectKey, projectName, jobName, pipelineName,
358
- buildCredentials }) {
354
+ _getAccessToken({ scope, username, projectKey, projectName, jobName, pipelineName, buildCredentials }) {
359
355
  const { jobId, pipelineId, prParentJobId } = buildCredentials;
360
356
  let projectData = { username, projectKey, projectName };
361
357
 
@@ -379,7 +375,7 @@ class CoverageSonar extends CoverageBase {
379
375
  .then(() => createUser(projectData.username, password))
380
376
  .then(() => grantUserPermission(projectData.username, projectData.projectKey))
381
377
  .then(() => generateToken(projectData.username))
382
- .then(res => res.token);
378
+ .then(res => res.body.token);
383
379
  }
384
380
 
385
381
  /**
@@ -402,8 +398,18 @@ class CoverageSonar extends CoverageBase {
402
398
  * - project url
403
399
  * - Sonar env vars
404
400
  */
405
- _getInfo({ scope, jobId, jobName, startTime, endTime, pipelineId,
406
- pipelineName, prNum, projectKey: coverageProjectKey, prParentJobId }) {
401
+ _getInfo({
402
+ scope,
403
+ jobId,
404
+ jobName,
405
+ startTime,
406
+ endTime,
407
+ pipelineId,
408
+ pipelineName,
409
+ prNum,
410
+ projectKey: coverageProjectKey,
411
+ prParentJobId
412
+ }) {
407
413
  const { projectScope, projectKey, projectName, username } = getProjectData({
408
414
  enterpriseEnabled: sonarEnterprise,
409
415
  jobId,
@@ -418,7 +424,6 @@ class CoverageSonar extends CoverageBase {
418
424
 
419
425
  const infoObject = {
420
426
  envVars: {
421
- // eslint-disable-next-line max-len
422
427
  SD_SONAR_AUTH_URL: `${sdCoverageAuthUrl}?projectKey=${projectKey}&projectName=${projectName}&username=${username}&scope=${projectScope}`,
423
428
  SD_SONAR_HOST: sonarHost,
424
429
  SD_SONAR_ENTERPRISE: sonarEnterprise,
@@ -429,8 +434,8 @@ class CoverageSonar extends CoverageBase {
429
434
 
430
435
  // Only get coverage percentage if the steps are finished
431
436
  if (projectKey && startTime && endTime) {
432
- return getMetrics({ projectKey, startTime, endTime, prNum, sonarEnterprise })
433
- .then(({ coverage, tests }) => {
437
+ return getMetrics({ projectKey, startTime, endTime, prNum, sonarEnterprise }).then(
438
+ ({ coverage, tests }) => {
434
439
  const componentId = encodeURIComponent(projectKey);
435
440
  let projectUrl = `${this.config.sonarHost}/dashboard?id=${componentId}`;
436
441
 
@@ -443,7 +448,8 @@ class CoverageSonar extends CoverageBase {
443
448
  infoObject.projectUrl = projectUrl;
444
449
 
445
450
  return Promise.resolve(infoObject);
446
- });
451
+ }
452
+ );
447
453
  }
448
454
 
449
455
  return Promise.resolve(infoObject);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screwdriver-coverage-sonar",
3
- "version": "3.1.5",
3
+ "version": "3.3.2",
4
4
  "description": "SonarQube implementation of the coverage-base class",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -30,24 +30,23 @@
30
30
  "Tiffany Kyi <tiffanykyi@gmail.com>"
31
31
  ],
32
32
  "devDependencies": {
33
- "chai": "^3.5.0",
34
- "eslint": "^4.3.0",
35
- "eslint-config-screwdriver": "^3.0.0",
33
+ "chai": "^4.2.0",
34
+ "eslint": "^7.31.0",
35
+ "eslint-config-screwdriver": "^5.0.1",
36
36
  "mocha": "^8.3.2",
37
37
  "mocha-multi-reporters": "^1.5.1",
38
38
  "mocha-sonarqube-reporter": "^1.0.2",
39
39
  "mockery": "^2.1.0",
40
40
  "nyc": "^15.0.0",
41
- "sinon": "^5.1.1"
41
+ "sinon": "^9.0.0"
42
42
  },
43
43
  "dependencies": {
44
- "@hapi/hoek": "^9.0.4",
45
- "joi": "^17.2.1",
46
- "request": "^2.87.0",
47
- "request-promise-native": "^1.0.5",
48
- "screwdriver-coverage-base": "^2.0.0",
49
- "screwdriver-logger": "^1.0.1",
50
- "uuid": "^3.2.1"
44
+ "@hapi/hoek": "^9.2.0",
45
+ "joi": "^17.4.1",
46
+ "screwdriver-coverage-base": "^2.1.0",
47
+ "screwdriver-logger": "^1.1.0",
48
+ "screwdriver-request": "^1.0.1",
49
+ "uuid": "^3.4.0"
51
50
  },
52
51
  "release": {
53
52
  "debug": false,