diff --git a/.changeset/wise-rings-hammer.md b/.changeset/wise-rings-hammer.md new file mode 100644 index 0000000000..1515818116 --- /dev/null +++ b/.changeset/wise-rings-hammer.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-jenkins-backend': patch +--- + +Fix the case where lastBuild is null. diff --git a/plugins/jenkins-backend/src/service/jenkinsApi.test.ts b/plugins/jenkins-backend/src/service/jenkinsApi.test.ts index d1c4705225..5f74259eef 100644 --- a/plugins/jenkins-backend/src/service/jenkinsApi.test.ts +++ b/plugins/jenkins-backend/src/service/jenkinsApi.test.ts @@ -284,6 +284,15 @@ describe('JenkinsApi', () => { }, }; + const projectWithoutBuild: JenkinsProject = { + actions: [], + displayName: 'Example Build', + fullDisplayName: 'Example jobName » Example Build', + fullName: 'example-jobName/exampleBuild', + inQueue: false, + lastBuild: null, + }; + it('augments project', async () => { mockedJenkinsClient.job.get.mockResolvedValueOnce({ jobs: [projectWithScmActions], @@ -294,6 +303,16 @@ describe('JenkinsApi', () => { expect(result).toHaveLength(1); expect(result[0].status).toEqual('success'); }); + it('augments project without build', async () => { + mockedJenkinsClient.job.get.mockResolvedValueOnce({ + jobs: [projectWithoutBuild], + }); + + const result = await jenkinsApi.getProjects(jenkinsInfo); + + expect(result).toHaveLength(1); + expect(result[0].status).toEqual('build not found'); + }); it('augments build', async () => { mockedJenkinsClient.job.get.mockResolvedValueOnce({ jobs: [projectWithScmActions], @@ -304,7 +323,7 @@ describe('JenkinsApi', () => { expect(result).toHaveLength(1); // TODO: I am really just asserting the previous behaviour wth 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({ + expect(result[0].lastBuild!.source).toEqual({ branchName: 'master', commit: { hash: '14d31bde', @@ -322,7 +341,7 @@ describe('JenkinsApi', () => { const result = await jenkinsApi.getProjects(jenkinsInfo); expect(result).toHaveLength(1); - expect(result[0].lastBuild.tests).toEqual({ + expect(result[0].lastBuild!.tests).toEqual({ total: 635, passed: 632, skipped: 1, diff --git a/plugins/jenkins-backend/src/service/jenkinsApi.ts b/plugins/jenkins-backend/src/service/jenkinsApi.ts index fac8c95564..13705ce049 100644 --- a/plugins/jenkins-backend/src/service/jenkinsApi.ts +++ b/plugins/jenkins-backend/src/service/jenkinsApi.ts @@ -151,8 +151,11 @@ export class JenkinsApiImpl { private augmentProject(project: JenkinsProject): BackstageProject { let status: string; + if (project.inQueue) { status = 'queued'; + } else if (!project.lastBuild) { + status = 'build not found'; } else if (project.lastBuild.building) { status = 'running'; } else if (!project.lastBuild.result) { @@ -165,7 +168,9 @@ export class JenkinsApiImpl { return { ...project, - lastBuild: this.augmentBuild(project.lastBuild, jobScmInfo), + lastBuild: project.lastBuild + ? this.augmentBuild(project.lastBuild, jobScmInfo) + : null, status, // actions: undefined, }; diff --git a/plugins/jenkins-backend/src/types.ts b/plugins/jenkins-backend/src/types.ts index 2a0c5ae7f9..4dceecd0cc 100644 --- a/plugins/jenkins-backend/src/types.ts +++ b/plugins/jenkins-backend/src/types.ts @@ -63,7 +63,7 @@ export interface BackstageBuild extends CommonBuild { export interface CommonProject { // standard Jenkins - lastBuild: CommonBuild; + lastBuild: CommonBuild | null; displayName: string; fullDisplayName: string; fullName: string; @@ -72,7 +72,7 @@ export interface CommonProject { export interface JenkinsProject extends CommonProject { // standard Jenkins - lastBuild: JenkinsBuild; + lastBuild: JenkinsBuild | null; // read by us from jenkins but not passed to frontend actions: object[]; @@ -80,7 +80,7 @@ export interface JenkinsProject extends CommonProject { export interface BackstageProject extends CommonProject { // standard Jenkins - lastBuild: BackstageBuild; + lastBuild: BackstageBuild | null; // added by us status: string; // == inQueue ? 'queued' : lastBuild.building ? 'running' : lastBuild.result,