-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathindex.ts
More file actions
126 lines (108 loc) · 3.7 KB
/
index.ts
File metadata and controls
126 lines (108 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import * as fs from 'fs'
import * as path from 'path'
import {fileURLToPath} from 'url'
import * as core from '@actions/core'
import {loadPluginViaJsFile, loadPluginViaTsFile} from './pluginFileLoaders.js'
import type {Plugin, PluginDefaultParams} from './types.js'
// Helper to get __dirname equivalent in ES Modules
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
// Built-in plugin names shipped with the scanner.
// Used to skip duplicates when loading custom plugins.
const BUILT_IN_PLUGINS = ['reflow-scan', 'test-js-file-plugin-load']
export const plugins: Plugin[] = []
// Required for unit tests.
export function getPlugins() {
return plugins
}
let pluginsLoaded = false
export async function loadPlugins() {
try {
if (!pluginsLoaded) {
core.info('loading plugins')
await loadBuiltInPlugins()
await loadCustomPlugins()
}
} catch {
plugins.length = 0
core.error(abortError)
} finally {
pluginsLoaded = true
return plugins
}
}
export const abortError = `
There was an error while loading plugins.
Clearing all plugins and aborting custom plugin scans.
Please check the logs for hints as to what may have gone wrong.
`
export function clearCache() {
pluginsLoaded = false
plugins.length = 0
}
// exported for mocking/testing. not for actual use
export async function loadBuiltInPlugins() {
core.info('Loading built-in plugins')
const pluginsPath = path.join(__dirname, '../../../../scanner-plugins/')
await loadPluginsFromPath({pluginsPath})
}
// exported for mocking/testing. not for actual use
export async function loadCustomPlugins() {
core.info('Loading custom plugins')
const pluginsPath = path.join(process.cwd(), '.github/scanner-plugins/')
// - currently, the plugin manager will abort loading
// all plugins if there's an error
// - the problem with this is that if a scanner user doesn't
// have custom plugins, they won't have a 'scanner-plugins' folder
// which will cause an error and abort loading all plugins, including built-in ones
// - so for custom plugins, if the path doesn't exist, we can return early
// and not abort the loading of built-in plugins
if (!fs.existsSync(pluginsPath)) {
core.info('No custom plugins found.')
return
}
await loadPluginsFromPath({pluginsPath, skipBuiltInPlugins: BUILT_IN_PLUGINS})
}
// exported for mocking/testing. not for actual use
export async function loadPluginsFromPath({
pluginsPath,
skipBuiltInPlugins,
}: {
pluginsPath: string
skipBuiltInPlugins?: string[]
}) {
try {
const folders = fs.readdirSync(pluginsPath)
for (const pluginFolder of folders) {
const pluginFolderPath = path.join(pluginsPath, pluginFolder)
if (fs.existsSync(pluginFolderPath) && fs.lstatSync(pluginFolderPath).isDirectory()) {
let plugin = await loadPluginViaTsFile(pluginFolderPath)
if (!plugin) {
plugin = await loadPluginViaJsFile(pluginFolderPath)
}
if (!plugin) {
core.info(`Skipping plugin without index.ts or index.js file: ${pluginFolder}`)
continue
}
if (skipBuiltInPlugins?.includes(plugin.name)) {
core.info(`Skipping built-in plugin: ${plugin.name}`)
continue
}
core.info(`Found plugin: ${plugin.name}`)
plugins.push(plugin)
}
}
} catch (e) {
// - log errors here for granular info
core.error('error: ')
core.error(e as Error)
// - throw error to handle aborting the plugin scans
throw e
}
}
type InvokePluginParams = PluginDefaultParams & {
plugin: Plugin
}
export function invokePlugin({plugin, page, addFinding}: InvokePluginParams) {
return plugin.default({page, addFinding})
}