diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts index 065ebaefa5..ca5c29e9ce 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts @@ -132,6 +132,16 @@ describe('AzurePreparer', () => { }); it('return the temp directory with the path to the folder if it is specified', async () => { + const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); + mockEntity.spec.path = './template/test/1/2/3'; + const response = await preparer.prepare(mockEntity, {}); + + expect(response.split('\\').join('/')).toMatch( + /\/template\/test\/1\/2\/3$/, + ); + }); + + it('return the working directory with the path to the folder if it is specified', async () => { const preparer = new AzurePreparer(ConfigReader.fromConfigs([])); mockEntity.spec.path = './template/test/1/2/3'; const response = await preparer.prepare(mockEntity, { @@ -139,7 +149,7 @@ describe('AzurePreparer', () => { }); expect(response).toBe( - `/workDir/graphql-starter-static/template/test/1/2/3`, + '/workDir/graphql-starter-static/template/test/1/2/3', ); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts index aaf8508c8e..bd5458b329 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import os from 'os'; import fs from 'fs-extra'; import path from 'path'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; @@ -33,10 +34,10 @@ export class AzurePreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory: string }, + opts: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const { workingDirectory } = opts; + const workingDirectory = opts.workingDirectory ?? os.tmpdir(); if (!['azure/api', 'url'].includes(protocol)) { throw new InputError( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts index 828238ae08..b97e4ae08b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import os from 'os'; import fs from 'fs-extra'; import path from 'path'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; @@ -23,10 +24,10 @@ import { PreparerBase } from './types'; export class FilePreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory: string }, + opts: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const { workingDirectory } = opts; + const workingDirectory = opts.workingDirectory ?? os.tmpdir(); if (protocol !== 'file') { throw new InputError( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts index 29655f7ee9..d652d8aa35 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts @@ -99,7 +99,18 @@ describe('GitHubPreparer', () => { }, ); }); + it('return the temp directory with the path to the folder if it is specified', async () => { + const preparer = new GithubPreparer(); + mockEntity.spec.path = './template/test/1/2/3'; + const response = await preparer.prepare(mockEntity, {}); + + expect(response.split('\\').join('/')).toMatch( + /\/template\/test\/1\/2\/3$/, + ); + }); + + it('return the working directory with the path to the folder if it is specified', async () => { const preparer = new GithubPreparer(); mockEntity.spec.path = './template/test/1/2/3'; const response = await preparer.prepare(mockEntity, { @@ -107,7 +118,7 @@ describe('GitHubPreparer', () => { }); expect(response).toBe( - `/workDir/graphql-starter-static/template/test/1/2/3`, + '/workDir/graphql-starter-static/template/test/1/2/3', ); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index 863b760d03..1987c416b3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import os from 'os'; import fs from 'fs-extra'; import path from 'path'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; @@ -31,10 +32,10 @@ export class GithubPreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory: string }, + opts: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const { workingDirectory } = opts; + const workingDirectory = opts.workingDirectory ?? os.tmpdir(); const { token } = this; if (!['github', 'url'].includes(protocol)) { diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts index 8df853ac06..3ee9dd103d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts @@ -138,12 +138,22 @@ describe('GitLabPreparer', () => { const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); mockEntity = mockEntityWithProtocol(protocol); mockEntity.spec.path = './template/test/1/2/3'; + const response = await preparer.prepare(mockEntity, {}); + + expect(response.split('\\').join('/')).toMatch( + /\/template\/test\/1\/2\/3$/, + ); + }); + + it('return the working directory with the path to the folder if it is specified', async () => { + const preparer = new GitlabPreparer(ConfigReader.fromConfigs([])); + mockEntity.spec.path = './template/test/1/2/3'; const response = await preparer.prepare(mockEntity, { workingDirectory: '/workDir', }); expect(response).toBe( - `/workDir/graphql-starter-static/template/test/1/2/3`, + '/workDir/graphql-starter-static/template/test/1/2/3', ); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts index 5be72f85b5..55fc846bb5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import os from 'os'; import fs from 'fs-extra'; import path from 'path'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; @@ -34,10 +35,10 @@ export class GitlabPreparer implements PreparerBase { async prepare( template: TemplateEntityV1alpha1, - opts: { workingDirectory: string }, + opts: { workingDirectory?: string }, ): Promise { const { protocol, location } = parseLocationAnnotation(template); - const { workingDirectory } = opts; + const workingDirectory = opts.workingDirectory ?? os.tmpdir(); if (!['gitlab', 'gitlab/api', 'url'].includes(protocol)) { throw new InputError( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts index 940d2b4178..1a28b316c6 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts @@ -25,7 +25,7 @@ export type PreparerBase = { */ prepare( template: TemplateEntityV1alpha1, - opts: { logger: Logger; workingDirectory: string }, + opts: { logger: Logger; workingDirectory?: string }, ): Promise; }; diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index bca17aa029..fae7ee8beb 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -25,7 +25,6 @@ jest.doMock('fs-extra', () => ({ }, })); -import os from 'os'; import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import express from 'express'; @@ -114,7 +113,7 @@ describe('createRouter - working directory', () => { }); }); - it('should default to OS temp-dir when no working directory is configured', async () => { + it('should not pass along anything when no working directory is configured', async () => { const router = await createRouter({ logger: getVoidLogger(), preparers: mockPreparers, @@ -132,7 +131,6 @@ describe('createRouter - working directory', () => { expect(mockPrepare).toBeCalledWith(expect.anything(), { logger: expect.anything(), - workingDirectory: os.tmpdir(), }); }); }); diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index e66728ac91..bcb0896c6e 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -60,22 +60,24 @@ export async function createRouter( const logger = parentLogger.child({ plugin: 'scaffolder' }); const jobProcessor = new JobProcessor(); - const workingDirectory = - config.getOptionalString('backend.workingDirectory') ?? os.tmpdir(); - try { - // Check if working directory exists and is writable - await fs.promises.access( - workingDirectory, - fs.constants.F_OK | fs.constants.W_OK, - ); - logger.info(`using working directory: ${workingDirectory}`); - } catch (err) { - logger.error( - `working directory ${workingDirectory} ${ - err.code === 'ENOENT' ? 'does not exist' : 'is not writable' - }`, - ); - throw err; + let workingDirectory: string; + if (config.has('backend.workingDirectory')) { + workingDirectory = config.getString('backend.workingDirectory'); + try { + // Check if working directory exists and is writable + await fs.promises.access( + workingDirectory, + fs.constants.F_OK | fs.constants.W_OK, + ); + logger.info(`using working directory: ${workingDirectory}`); + } catch (err) { + logger.error( + `working directory ${workingDirectory} ${ + err.code === 'ENOENT' ? 'does not exist' : 'is not writable' + }`, + ); + throw err; + } } router