Merge pull request #10455 from yarodinD/master

Fixed possible type error if jenkins response contains null values
This commit is contained in:
Fredrik Adelöw
2022-03-26 20:31:36 +01:00
committed by GitHub
4 changed files with 220 additions and 4 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-jenkins-backend': patch
---
Fixed possible type error if jenkins response contains null values
+1
View File
@@ -137,6 +137,7 @@ inlinehilite
interop
JaCoCo
JavaScript
jenkins
Jira
jq
js
@@ -352,6 +352,216 @@ describe('JenkinsApi', () => {
const result = await jenkinsApi.getProjects(jenkinsInfo);
expect(result).toHaveLength(1);
expect(result[0].lastBuild!.tests).toEqual({
total: 635,
passed: 632,
skipped: 1,
failed: 2,
testUrl:
'https://jenkins.example.com/job/example-jobName/job/exampleBuild/7/testReport/',
});
});
});
describe('augmented with null values', () => {
const projectWithScmActionsAndNulls: JenkinsProject = {
actions: [
{},
{},
{},
{},
{
_class: 'jenkins.scm.api.metadata.ContributorMetadataAction',
contributor: 'testuser',
contributorDisplayName: 'Mr. T User',
contributorEmail: null,
},
{},
{
_class: 'jenkins.scm.api.metadata.ObjectMetadataAction',
objectDescription: '',
objectDisplayName: 'Add LICENSE, CoC etc',
objectUrl: 'https://github.com/backstage/backstage/pull/1',
},
{},
{},
{
_class: 'com.cloudbees.plugins.credentials.ViewCredentialsAction',
stores: {},
},
],
displayName: 'Example Build',
fullDisplayName: 'Example jobName » Example Build',
fullName: 'example-jobName/exampleBuild',
inQueue: false,
lastBuild: {
actions: [
{
_class: 'hudson.model.CauseAction',
causes: [
{
_class: 'jenkins.branch.BranchIndexingCause',
shortDescription: 'Branch indexing',
},
],
},
null,
{},
{},
{
_class: 'org.jenkinsci.plugins.workflow.cps.EnvActionImpl',
environment: {},
},
{},
{},
{},
{},
{},
{
_class: 'hudson.plugins.git.util.BuildData',
buildsByBranchName: {
'PR-1': {
_class: 'hudson.plugins.git.util.Build',
buildNumber: 5,
buildResult: null,
marked: {
SHA1: '14d31bde346fcad64ab939f82d195db36701cfcb',
branch: [
{
SHA1: '14d31bde346fcad64ab939f82d195db36701cfcb',
name: 'PR-1',
},
],
},
revision: {
SHA1: '6c6b34c0fb91cf077a01fe62d3e8e996b4ea5861',
branch: [
{
SHA1: '14d31bde346fcad64ab939f82d195db36701cfcb',
name: 'PR-1',
},
],
},
},
},
lastBuiltRevision: {
SHA1: '6c6b34c0fb91cf077a01fe62d3e8e996b4ea5861',
branch: [
{
SHA1: '14d31bde346fcad64ab939f82d195db36701cfcb',
name: 'PR-1',
},
],
},
remoteUrls: ['https://github.com/backstage/backstage.git'],
scmName: '',
},
{
_class: 'hudson.plugins.git.util.BuildData',
buildsByBranchName: {
master: {
_class: 'hudson.plugins.git.util.Build',
buildNumber: 5,
buildResult: null,
marked: {
SHA1: '14d31bde346fcad64ab939f82d195db36701cfcb',
branch: [
{
SHA1: '14d31bde346fcad64ab939f82d195db36701cfcb',
name: 'master',
},
],
},
revision: {
SHA1: '6c6b34c0fb91cf077a01fe62d3e8e996b4ea5861',
branch: [
{
SHA1: '14d31bde346fcad64ab939f82d195db36701cfcb',
name: 'master',
},
],
},
},
},
lastBuiltRevision: {
SHA1: '6c6b34c0fb91cf077a01fe62d3e8e996b4ea5861',
branch: [
{
SHA1: '14d31bde346fcad64ab939f82d195db36701cfcb',
name: 'master',
},
],
},
remoteUrls: ['https://github.com/backstage/backstage.git'],
scmName: '',
},
{},
{},
{
_class: 'hudson.tasks.junit.TestResultAction',
failCount: 2,
skipCount: 1,
totalCount: 635,
urlName: 'testReport',
},
{},
{},
{
_class:
'org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction',
restartEnabled: false,
restartableStages: [],
},
{},
],
timestamp: 1,
building: false,
duration: 10,
result: 'success',
displayName: '#7',
fullDisplayName: 'Example jobName » Example Build #7',
url: 'https://jenkins.example.com/job/example-jobName/job/exampleBuild/7/',
number: 7,
},
};
it('augments project', async () => {
mockedJenkinsClient.job.get.mockResolvedValueOnce({
jobs: [projectWithScmActionsAndNulls],
});
const result = await jenkinsApi.getProjects(jenkinsInfo);
expect(result).toHaveLength(1);
expect(result[0].status).toEqual('success');
});
it('augments build', async () => {
mockedJenkinsClient.job.get.mockResolvedValueOnce({
jobs: [projectWithScmActionsAndNulls],
});
const result = await jenkinsApi.getProjects(jenkinsInfo);
expect(result).toHaveLength(1);
// TODO: I am really just asserting the previous behaviour with no understanding here.
// In my 2 Jenkins instances, 1 returns a lot of different and confusing BuildData sections and 1 returns none ☹️
expect(result[0].lastBuild!.source).toEqual({
branchName: 'master',
commit: {
hash: '14d31bde',
},
url: 'https://github.com/backstage/backstage/pull/1',
displayName: 'Add LICENSE, CoC etc',
author: 'Mr. T User',
});
});
it('finds test report', async () => {
mockedJenkinsClient.job.get.mockResolvedValueOnce({
jobs: [projectWithScmActionsAndNulls],
});
const result = await jenkinsApi.getProjects(jenkinsInfo);
expect(result).toHaveLength(1);
expect(result[0].lastBuild!.tests).toEqual({
total: 635,
@@ -211,7 +211,7 @@ export class JenkinsApiImpl {
build.actions
.filter(
(action: any) =>
action._class === 'hudson.plugins.git.util.BuildData',
action?._class === 'hudson.plugins.git.util.BuildData',
)
.map((action: any) => {
const [first]: any = Object.values(action.buildsByBranchName);
@@ -253,7 +253,7 @@ export class JenkinsApiImpl {
const scmInfo: ScmDetails | undefined = project.actions
.filter(
(action: any) =>
action._class === 'jenkins.scm.api.metadata.ObjectMetadataAction',
action?._class === 'jenkins.scm.api.metadata.ObjectMetadataAction',
)
.map((action: any) => {
return {
@@ -272,7 +272,7 @@ export class JenkinsApiImpl {
const author = project.actions
.filter(
(action: any) =>
action._class ===
action?._class ===
'jenkins.scm.api.metadata.ContributorMetadataAction',
)
.map((action: any) => {
@@ -297,7 +297,7 @@ export class JenkinsApiImpl {
return build.actions
.filter(
(action: any) =>
action._class === 'hudson.tasks.junit.TestResultAction',
action?._class === 'hudson.tasks.junit.TestResultAction',
)
.map((action: any) => {
return {