chore: add tests, merge cookiecutter.json

Co-authored-by: Ben Lambert <ben@blam.sh>
This commit is contained in:
Ivan Shmidt
2020-06-23 14:17:28 +02:00
parent bc15e7a710
commit 12db9bc694
4 changed files with 154 additions and 11 deletions
+1
View File
@@ -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;
}
}