Merge pull request #28777 from gavinclarkeuk/globbing
Add support for file globbing to fs:delete
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': minor
|
||||
---
|
||||
|
||||
Support file globbing in fs:delete
|
||||
@@ -157,6 +157,7 @@ Gitiles
|
||||
gitlab
|
||||
GitLab
|
||||
globals
|
||||
globbing
|
||||
Gource
|
||||
Grafana
|
||||
graphql
|
||||
|
||||
+15
@@ -33,4 +33,19 @@ export const examples: TemplateExample[] = [
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
description: 'Delete files with wildcard',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
action: 'fs:delete',
|
||||
id: 'deleteFiles',
|
||||
name: 'Delete files',
|
||||
input: {
|
||||
files: ['*.txt'],
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -95,6 +95,15 @@ describe('fs:delete', () => {
|
||||
).rejects.toThrow(
|
||||
/Relative path is not allowed to refer to a directory outside its parent/,
|
||||
);
|
||||
|
||||
await expect(
|
||||
action.handler({
|
||||
...mockContext,
|
||||
input: { files: ['../../../**/index.js'] },
|
||||
}),
|
||||
).rejects.toThrow(
|
||||
/Relative path is not allowed to refer to a directory outside its parent/,
|
||||
);
|
||||
});
|
||||
|
||||
it('should call fs.rm with the correct values', async () => {
|
||||
@@ -114,4 +123,25 @@ describe('fs:delete', () => {
|
||||
expect(fileExists).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle wildcards', async () => {
|
||||
const files = ['unit-test-a.js', 'unit-test-b.js'];
|
||||
|
||||
files.forEach(file => {
|
||||
const filePath = resolvePath(workspacePath, file);
|
||||
const fileExists = fs.existsSync(filePath);
|
||||
expect(fileExists).toBe(true);
|
||||
});
|
||||
|
||||
await action.handler({
|
||||
...mockContext,
|
||||
input: { files: ['unit-*.js'] },
|
||||
});
|
||||
|
||||
files.forEach(file => {
|
||||
const filePath = resolvePath(workspacePath, file);
|
||||
const fileExists = fs.existsSync(filePath);
|
||||
expect(fileExists).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,6 +18,7 @@ import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import { InputError } from '@backstage/errors';
|
||||
import { resolveSafeChildPath } from '@backstage/backend-plugin-api';
|
||||
import fs from 'fs-extra';
|
||||
import globby from 'globby';
|
||||
import { examples } from './delete.examples';
|
||||
|
||||
/**
|
||||
@@ -52,14 +53,20 @@ export const createFilesystemDeleteAction = () => {
|
||||
}
|
||||
|
||||
for (const file of ctx.input.files) {
|
||||
const filepath = resolveSafeChildPath(ctx.workspacePath, file);
|
||||
const safeFilepath = resolveSafeChildPath(ctx.workspacePath, file);
|
||||
const resolvedPaths = await globby(safeFilepath, {
|
||||
cwd: ctx.workspacePath,
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
try {
|
||||
await fs.remove(filepath);
|
||||
ctx.logger.info(`File ${filepath} deleted successfully`);
|
||||
} catch (err) {
|
||||
ctx.logger.error(`Failed to delete file ${filepath}:`, err);
|
||||
throw err;
|
||||
for (const filepath of resolvedPaths) {
|
||||
try {
|
||||
await fs.remove(filepath);
|
||||
ctx.logger.info(`File ${filepath} deleted successfully`);
|
||||
} catch (err) {
|
||||
ctx.logger.error(`Failed to delete file ${filepath}:`, err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user