chore: add tests, merge cookiecutter.json
Co-authored-by: Ben Lambert <ben@blam.sh>
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.1.1-alpha.9",
|
||||
"@backstage/catalog-model": "^0.1.1-alpha.9",
|
||||
"@backstage/config": "^0.1.1-alpha.9",
|
||||
"@types/express": "^4.17.6",
|
||||
"compression": "^1.7.4",
|
||||
"cors": "^2.8.5",
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"_copy_without_render": [".github/workflows/*"]
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { CookieCutter } from './cookiecutter';
|
||||
import fs from 'fs-extra';
|
||||
import os from 'os';
|
||||
|
||||
const mockDocker = { run: jest.fn() };
|
||||
jest.mock(
|
||||
'dockerode',
|
||||
() =>
|
||||
class {
|
||||
constructor() {
|
||||
return mockDocker;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
describe('CookieCutter Templater', () => {
|
||||
const cookie = new CookieCutter();
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('should write a cookiecutter.json file with the values from the entitiy', async () => {
|
||||
const tempdir = os.tmpdir();
|
||||
|
||||
const values = {
|
||||
component_id: 'test',
|
||||
description: 'description',
|
||||
};
|
||||
|
||||
await cookie.run({ directory: tempdir, values });
|
||||
|
||||
const cookieCutterJson = await fs.readJSON(`${tempdir}/cookiecutter.json`);
|
||||
|
||||
expect(cookieCutterJson).toEqual(expect.objectContaining(values));
|
||||
});
|
||||
|
||||
it('should merge any value that is in the cookiecutter.json path already', async () => {
|
||||
const tempdir = os.tmpdir();
|
||||
const existingJson = {
|
||||
_copy_without_render: ['./github/workflows/*'],
|
||||
};
|
||||
await fs.writeJSON(`${tempdir}/cookiecutter.json`, existingJson);
|
||||
|
||||
const values = {
|
||||
component_id: 'hello',
|
||||
description: 'im something cool',
|
||||
};
|
||||
|
||||
await cookie.run({ directory: tempdir, values });
|
||||
|
||||
const cookieCutterJson = await fs.readJSON(`${tempdir}/cookiecutter.json`);
|
||||
|
||||
expect(cookieCutterJson).toEqual({ ...existingJson, ...values });
|
||||
});
|
||||
|
||||
it('should run the correct docker container with the correct bindings for the volumes', async () => {
|
||||
const tempdir = os.tmpdir();
|
||||
|
||||
const values = {
|
||||
component_id: 'test',
|
||||
description: 'description',
|
||||
};
|
||||
|
||||
await cookie.run({ directory: tempdir, values });
|
||||
|
||||
const realpath = await fs.realpath(tempdir);
|
||||
|
||||
// TODO(blam): This might change when we publish our own cookiecutter image
|
||||
// to @backstage/cookiecutter in docker hub.
|
||||
expect(mockDocker.run).toHaveBeenCalledWith(
|
||||
'backstage/cookiecutter',
|
||||
['cookiecutter', '--no-input', '-o', '/result', '/template', '--verbose'],
|
||||
process.stdout,
|
||||
expect.objectContaining({
|
||||
HostConfig: {
|
||||
Binds: expect.arrayContaining([
|
||||
`${realpath}:/template`,
|
||||
`${realpath}/result:/result`,
|
||||
]),
|
||||
},
|
||||
Volumes: {
|
||||
'/template': {},
|
||||
'/result': {},
|
||||
},
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should return the result path to the end templated folder', async () => {
|
||||
const tempdir = os.tmpdir();
|
||||
|
||||
const values = {
|
||||
component_id: 'test',
|
||||
description: 'description',
|
||||
};
|
||||
|
||||
const path = await cookie.run({ directory: tempdir, values });
|
||||
|
||||
const realpath = await fs.realpath(tempdir);
|
||||
|
||||
expect(path).toBe(`${realpath}/result`);
|
||||
});
|
||||
});
|
||||
@@ -17,32 +17,52 @@ import { TemplaterBase, TemplaterRunOptions } from '.';
|
||||
*/
|
||||
import fs from 'fs-extra';
|
||||
import Docker from 'dockerode';
|
||||
import { JsonValue } from '@backstage/config';
|
||||
|
||||
export class CookieCutter implements TemplaterBase {
|
||||
private docker:Docker;
|
||||
private docker: Docker;
|
||||
constructor() {
|
||||
this.docker = new Docker();
|
||||
}
|
||||
|
||||
private async fetchTemplateCookieCutter(
|
||||
directory: string,
|
||||
): Promise<Record<string, JsonValue>> {
|
||||
try {
|
||||
return await fs.readJSON(`${directory}/cookiecutter.json`);
|
||||
} catch (ex) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
public async run(options: TemplaterRunOptions): Promise<string> {
|
||||
|
||||
|
||||
|
||||
// first we need to make cookiecutter.json in the directory provided with the input values.
|
||||
// First lets grab the default cookiecutter.json file
|
||||
const cookieCutterJson = await this.fetchTemplateCookieCutter(
|
||||
options.directory,
|
||||
);
|
||||
|
||||
const cookieInfo = {
|
||||
_copy_without_render: ['.github/workflows/*'],
|
||||
...cookieCutterJson,
|
||||
...options.values,
|
||||
};
|
||||
|
||||
await fs.writeJSON(`${options.directory}/cookiecutter.json`, cookieInfo);
|
||||
|
||||
const realTemplatePath = await fs.promises.realpath(options.directory);
|
||||
const outDir = realTemplatePath + '/result';
|
||||
const outDir = `${realTemplatePath}/result`;
|
||||
|
||||
await this.docker.run(
|
||||
'backstage/cookiecutter',
|
||||
['cookiecutter', '--no-input', '-o', '/result', '/template', '--verbose'],
|
||||
process.stdout,
|
||||
{
|
||||
Volumes: { '/result': {}, '/template': {} },
|
||||
HostConfig: {
|
||||
Binds: [`${outDir}:/result`, `${realTemplatePath}:/template`],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await this.docker.run('backstage/cookiecutter', ['cookiecutter', '--no-input', '-o', '/result', '/template', '--verbose'], process.stdout, {Volumes: { '/result': {}, '/template': {}}, HostConfig: {
|
||||
Binds: [`${outDir}:/result`, `${realTemplatePath}:/template`],
|
||||
}});
|
||||
|
||||
return outDir;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user