Skip to content

Commit 953a7b5

Browse files
committed
Updates plugin manager to de-dupe within it's own repo
1 parent 9e6acc4 commit 953a7b5

2 files changed

Lines changed: 38 additions & 5 deletions

File tree

.github/actions/find/src/pluginManager.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export async function loadCustomPlugins() {
6666

6767
// - currently, the plugin manager will abort loading
6868
// all plugins if there's an error
69-
// - the problem with this is that if a scanner user doesnt
69+
// - the problem with this is that if a scanner user doesn't
7070
// have custom plugins, they won't have a 'scanner-plugins' folder
7171
// which will cause an error and abort loading all plugins, including built-in ones
7272
// - so for custom plugins, if the path doesn't exist, we can return early
@@ -88,7 +88,13 @@ export async function loadPluginsFromPath({pluginsPath}: {pluginsPath: string})
8888

8989
if (fs.existsSync(pluginFolderPath) && fs.lstatSync(pluginFolderPath).isDirectory()) {
9090
core.info(`Found plugin: ${pluginFolder}`)
91-
plugins.push(await dynamicImport(path.join(pluginsPath, pluginFolder, 'index.js')))
91+
const plugin = await dynamicImport(path.join(pluginsPath, pluginFolder, 'index.js'))
92+
// Prevents a plugin from running twice
93+
if (plugins.some(p => p.name === plugin.name)) {
94+
core.info(`Skipping duplicate plugin: ${plugin.name}`)
95+
continue
96+
}
97+
plugins.push(plugin)
9298
}
9399
}
94100
} catch (e) {

.github/actions/find/tests/pluginManager.test.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,17 @@ vi.mock('../src/pluginManager.js', {spy: true})
1212
vi.mock('@actions/core', {spy: true})
1313

1414
describe('loadPlugins', () => {
15-
vi.spyOn(dynamicImportModule, 'dynamicImport').mockImplementation(path => Promise.resolve(path))
15+
let dynamicImportCallCount = 0
16+
vi.spyOn(dynamicImportModule, 'dynamicImport').mockImplementation(() => {
17+
dynamicImportCallCount++
18+
return Promise.resolve({name: `plugin-${dynamicImportCallCount}`, default: vi.fn()})
19+
})
1620
beforeEach(() => {
21+
dynamicImportCallCount = 0
1722
// @ts-expect-error - we don't need the full fs readdirsync
1823
// method signature here
19-
vi.spyOn(fs, 'readdirSync').mockImplementation(readPath => {
20-
return [readPath + '/plugin-1', readPath + '/plugin-2']
24+
vi.spyOn(fs, 'readdirSync').mockImplementation(() => {
25+
return ['folder-a', 'folder-b']
2126
})
2227
vi.spyOn(fs, 'lstatSync').mockImplementation(() => {
2328
return {
@@ -61,4 +66,26 @@ describe('loadPlugins', () => {
6166
expect(logSpy).toHaveBeenCalledWith(pluginManager.abortError)
6267
})
6368
})
69+
70+
describe('when built-in and custom plugins share the same name', () => {
71+
beforeEach(() => {
72+
// @ts-expect-error - we don't need the full fs readdirsync
73+
// method signature here
74+
vi.spyOn(fs, 'readdirSync').mockImplementation(() => {
75+
return ['reflow-scan']
76+
})
77+
vi.spyOn(dynamicImportModule, 'dynamicImport').mockImplementation(() => {
78+
return Promise.resolve({name: 'reflow-scan', default: vi.fn()})
79+
})
80+
})
81+
82+
it('skips the duplicate and only loads the plugin once', async () => {
83+
pluginManager.clearCache()
84+
const infoSpy = vi.spyOn(core, 'info').mockImplementation(() => {})
85+
const plugins = await pluginManager.loadPlugins()
86+
expect(plugins.length).toBe(1)
87+
expect(plugins[0].name).toBe('reflow-scan')
88+
expect(infoSpy).toHaveBeenCalledWith('Skipping duplicate plugin: reflow-scan')
89+
})
90+
})
6491
})

0 commit comments

Comments
 (0)