cli/new: add ability to reference built-in templates in config

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2025-02-10 10:19:08 +01:00
parent 6d56c7d6b9
commit 401ca196b0
2 changed files with 94 additions and 9 deletions
@@ -84,6 +84,54 @@ describe('loadPortableTemplateConfig', () => {
});
});
it('should support pointing to built-in templates', async () => {
mockDir.setContent({
'package.json': JSON.stringify({
backstage: {
new: {
templates: [
'backend-plugin',
{ id: 'template1', target: 'path/to/template1' },
'frontend-plugin',
],
globals: {
license: 'MIT',
private: true,
namePrefix: '@acme/',
namePluginInfix: 'backstage-plugin-',
},
},
},
}),
});
await expect(
loadPortableTemplateConfig({
packagePath: mockDir.resolve('package.json'),
}),
).resolves.toEqual({
isUsingDefaultTemplates: false,
templatePointers: [
{
id: 'backend-plugin',
description: 'A new backend plugin',
target: expect.stringMatching(/default-backend-plugin.yaml$/),
},
{ id: 'template1', target: 'path/to/template1' },
{
id: 'frontend-plugin',
description: 'A new frontend plugin',
target: expect.stringMatching(/default-plugin.yaml$/),
},
],
license: 'MIT',
private: true,
version: '0.1.0',
packageNamePrefix: '@acme/',
packageNamePluginInfix: 'backstage-plugin-',
});
});
it('should use default templates if none are specified', async () => {
mockDir.setContent({
'package.json': JSON.stringify({
@@ -129,7 +177,27 @@ describe('loadPortableTemplateConfig', () => {
packagePath: mockDir.resolve('package.json'),
}),
).rejects.toThrow(
/^Failed to load templating configuration from '.*'; caused by Validation error/,
/^Failed to load templating configuration from '.*'; caused by Validation error: Expected array/,
);
});
it('should throw an error if built-in template does not exist', async () => {
mockDir.setContent({
'package.json': JSON.stringify({
backstage: {
new: {
templates: ['invalid'],
},
},
}),
});
await expect(
loadPortableTemplateConfig({
packagePath: mockDir.resolve('package.json'),
}),
).rejects.toThrow(
/^Failed to load templating configuration from '.*'; caused by Validation error: Invalid enum value/,
);
});
@@ -37,13 +37,18 @@ const pkgJsonWithNewConfigSchema = z.object({
.object({
templates: z
.array(
z
.object({
id: z.string(),
description: z.string().optional(),
target: z.string(),
})
.strict(),
z.union([
z.enum(
defaultTemplates.map(t => t.id) as [string, ...string[]],
),
z
.object({
id: z.string(),
description: z.string().optional(),
target: z.string(),
})
.strict(),
]),
)
.optional(),
globals: z
@@ -85,9 +90,21 @@ export async function loadPortableTemplateConfig(
const config = parsed.data.backstage?.new;
const templatePointers =
config?.templates?.map(t => {
if (typeof t === 'string') {
const defaultTemplate = defaultTemplates.find(d => d.id === t);
if (!defaultTemplate) {
throw new Error(`Built-in template '${t}' does not exist`);
}
return defaultTemplate;
}
return t;
}) ?? defaultTemplates;
return {
isUsingDefaultTemplates: !config?.templates,
templatePointers: config?.templates ?? defaultTemplates,
templatePointers,
license: overrides.license ?? config?.globals?.license ?? defaults.license,
version: overrides.version ?? config?.globals?.version ?? defaults.version,
private: overrides.private ?? config?.globals?.private ?? defaults.private,