From 496201574ddd1666581d0fe7abe6796281446b5f Mon Sep 17 00:00:00 2001 From: Gabriel Testault Date: Mon, 12 Dec 2022 17:43:23 +0100 Subject: [PATCH 1/5] feature(jenkins-backend): added support for standalone jenkins projects Signed-off-by: Gabriel Testault --- .../src/service/jenkinsApi.test.ts | 31 +++++++++++++++++++ .../jenkins-backend/src/service/jenkinsApi.ts | 14 +++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/plugins/jenkins-backend/src/service/jenkinsApi.test.ts b/plugins/jenkins-backend/src/service/jenkinsApi.test.ts index 4f65e446fd..8413cc6699 100644 --- a/plugins/jenkins-backend/src/service/jenkinsApi.test.ts +++ b/plugins/jenkins-backend/src/service/jenkinsApi.test.ts @@ -75,6 +75,37 @@ describe('JenkinsApi', () => { }, }; + describe('standalone project', () => { + it('should return the only build', async () => { + mockedJenkinsClient.job.get + .mockResolvedValueOnce(project) + .mockResolvedValueOnce(project); + const result = await jenkinsApi.getProjects(jenkinsInfo); + expect(result).toHaveLength(1); + expect(result[0]).toEqual({ + actions: [], + displayName: 'Example Build', + fullDisplayName: 'Example jobName » Example Build', + fullName: 'example-jobName/exampleBuild', + inQueue: false, + lastBuild: { + actions: [], + 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', + number: 7, + status: 'success', + source: {}, + }, + status: 'success', + }); + }); + }); + describe('unfiltered', () => { it('standard github layout', async () => { mockedJenkinsClient.job.get.mockResolvedValueOnce({ jobs: [project] }); diff --git a/plugins/jenkins-backend/src/service/jenkinsApi.ts b/plugins/jenkins-backend/src/service/jenkinsApi.ts index 89c9a41f9c..be8fe1b983 100644 --- a/plugins/jenkins-backend/src/service/jenkinsApi.ts +++ b/plugins/jenkins-backend/src/service/jenkinsApi.ts @@ -89,7 +89,7 @@ export class JenkinsApiImpl { } else { // We aren't filtering // Assume jenkinsInfo.jobFullName is a folder which contains one job per branch. - const folder = await client.job.get({ + const project = await client.job.get({ name: jenkinsInfo.jobFullName, // Filter only be the information we need, instead of loading all fields. // Limit to only show the latest build for each job and only load 50 jobs @@ -99,8 +99,16 @@ export class JenkinsApiImpl { tree: JenkinsApiImpl.jobsTreeSpec.replace(/\s/g, ''), }); - // TODO: support this being a project itself. - for (const jobDetails of folder.jobs) { + const isStandaloneProject = !project.jobs; + if (isStandaloneProject) { + const standaloneProject = await client.job.get({ + name: jenkinsInfo.jobFullName, + tree: JenkinsApiImpl.jobTreeSpec.replace(/\s/g, ''), + }); + projects.push(this.augmentProject(standaloneProject)); + return projects; + } + for (const jobDetails of project.jobs) { // for each branch (we assume) if (jobDetails?.jobs) { // skipping folders inside folders for now From 9447b0fb4659e78ad2dc40d2193d269a3be06230 Mon Sep 17 00:00:00 2001 From: Gabriel Testault Date: Mon, 12 Dec 2022 17:46:14 +0100 Subject: [PATCH 2/5] feature(jenkins-backend): add changeset Signed-off-by: Gabriel Testault --- .changeset/seven-dolphins-tickle.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/seven-dolphins-tickle.md diff --git a/.changeset/seven-dolphins-tickle.md b/.changeset/seven-dolphins-tickle.md new file mode 100644 index 0000000000..b3b7697dd6 --- /dev/null +++ b/.changeset/seven-dolphins-tickle.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-jenkins-backend': minor +--- + +added support for standalone jenkins projects From 98ba60b8b580e1c88ed458c111de88cc6985b220 Mon Sep 17 00:00:00 2001 From: Gabriel Testault Date: Wed, 14 Dec 2022 11:29:44 +0100 Subject: [PATCH 3/5] feature(jenkins-backend): improve test for standalone project test that the client is called twice for unfiltered standalone projects. Signed-off-by: Gabriel Testault --- plugins/jenkins-backend/src/service/jenkinsApi.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/jenkins-backend/src/service/jenkinsApi.test.ts b/plugins/jenkins-backend/src/service/jenkinsApi.test.ts index 8413cc6699..57ce2dbed4 100644 --- a/plugins/jenkins-backend/src/service/jenkinsApi.test.ts +++ b/plugins/jenkins-backend/src/service/jenkinsApi.test.ts @@ -81,6 +81,7 @@ describe('JenkinsApi', () => { .mockResolvedValueOnce(project) .mockResolvedValueOnce(project); const result = await jenkinsApi.getProjects(jenkinsInfo); + expect(mockedJenkinsClient.job.get).toHaveBeenCalledTimes(2); expect(result).toHaveLength(1); expect(result[0]).toEqual({ actions: [], From d657e194245bbf85f0724e8c6e43408ff40066a0 Mon Sep 17 00:00:00 2001 From: Gabriel Testault Date: Wed, 14 Dec 2022 11:30:40 +0100 Subject: [PATCH 4/5] feature(jenkins-backend): downgrade change to patch level Signed-off-by: Gabriel Testault --- .changeset/seven-dolphins-tickle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/seven-dolphins-tickle.md b/.changeset/seven-dolphins-tickle.md index b3b7697dd6..cd3149792c 100644 --- a/.changeset/seven-dolphins-tickle.md +++ b/.changeset/seven-dolphins-tickle.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-jenkins-backend': minor +'@backstage/plugin-jenkins-backend': patch --- added support for standalone jenkins projects From 6c70d769e4af276103bfa805eb9a8b1ca918a22c Mon Sep 17 00:00:00 2001 From: Gabriel Testault Date: Wed, 14 Dec 2022 12:02:27 +0100 Subject: [PATCH 5/5] feature(jenkins-backend): be more precise in jenkins terminology Only explicitly support Multibranch Pipeline and Pipeline projects Signed-off-by: Gabriel Testault --- plugins/jenkins-backend/src/service/jenkinsApi.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/plugins/jenkins-backend/src/service/jenkinsApi.ts b/plugins/jenkins-backend/src/service/jenkinsApi.ts index be8fe1b983..ef4ddc47b0 100644 --- a/plugins/jenkins-backend/src/service/jenkinsApi.ts +++ b/plugins/jenkins-backend/src/service/jenkinsApi.ts @@ -75,7 +75,7 @@ export class JenkinsApiImpl { const projects: BackstageProject[] = []; if (branches) { - // Assume jenkinsInfo.jobFullName is a folder which contains one job per branch. + // Assume jenkinsInfo.jobFullName is a MultiBranch Pipeline project which contains one job per branch. // TODO: extract a strategy interface for this const job = await Promise.any( branches.map(branch => @@ -88,7 +88,9 @@ export class JenkinsApiImpl { projects.push(this.augmentProject(job)); } else { // We aren't filtering - // Assume jenkinsInfo.jobFullName is a folder which contains one job per branch. + // Assume jenkinsInfo.jobFullName is either + // a MultiBranch Pipeline (folder with one job per branch) project + // a Pipeline (standalone) project const project = await client.job.get({ name: jenkinsInfo.jobFullName, // Filter only be the information we need, instead of loading all fields. @@ -110,12 +112,7 @@ export class JenkinsApiImpl { } for (const jobDetails of project.jobs) { // for each branch (we assume) - if (jobDetails?.jobs) { - // skipping folders inside folders for now - // TODO: recurse - } else { - projects.push(this.augmentProject(jobDetails)); - } + projects.push(this.augmentProject(jobDetails)); } } return projects;