Load remote config file
This commit is contained in:
+3
-1
@@ -64,7 +64,9 @@ event_file.close
|
|||||||
|
|
||||||
action_inputs = {
|
action_inputs = {
|
||||||
"repo-token": github_token,
|
"repo-token": github_token,
|
||||||
"config-file": config_file
|
"config-file": config_file,
|
||||||
|
"remote-config-file": "actions/dependency-review-action/.github/dependency-review-config.yml@external-config",
|
||||||
|
"config-repository-token": github_token
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_cmd_env = {
|
dev_cmd_env = {
|
||||||
|
|||||||
+62
-21
@@ -9,7 +9,7 @@ import {
|
|||||||
SeveritySchema,
|
SeveritySchema,
|
||||||
SCOPES
|
SCOPES
|
||||||
} from './schemas'
|
} from './schemas'
|
||||||
import {isSPDXValid} from './utils'
|
import {isSPDXValid, octokitClient} from './utils'
|
||||||
|
|
||||||
type licenseKey = 'allow-licenses' | 'deny-licenses'
|
type licenseKey = 'allow-licenses' | 'deny-licenses'
|
||||||
|
|
||||||
@@ -47,19 +47,29 @@ function validateLicenses(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readConfig(): ConfigurationOptions {
|
export async function readConfig(): Promise<ConfigurationOptions> {
|
||||||
const externalConfig = getOptionalInput('config-file')
|
const externalToken = getOptionalInput('config-repository-token')
|
||||||
if (externalConfig !== undefined) {
|
const remoteConfigFile = getOptionalInput('remote-config-file')
|
||||||
const config = readConfigFile(externalConfig)
|
const repoConfigFile = getOptionalInput('config-file')
|
||||||
|
|
||||||
|
const inlineConfig = readInlineConfig()
|
||||||
|
let remoteConfig: ConfigurationOptions = {}
|
||||||
|
let repoConfig: ConfigurationOptions = {}
|
||||||
|
|
||||||
|
if (externalToken !== undefined) {
|
||||||
|
if (remoteConfigFile === undefined) {
|
||||||
|
throw new Error('Missing required parameter: remote-config-file.')
|
||||||
|
}
|
||||||
|
remoteConfig = readConfigFile(await getRemoteConfig(remoteConfigFile))
|
||||||
|
}
|
||||||
|
if (repoConfigFile !== undefined) {
|
||||||
|
repoConfig = readConfigFile(getRepoConfig(repoConfigFile))
|
||||||
|
}
|
||||||
// the reasoning behind reading the inline config when an external
|
// the reasoning behind reading the inline config when an external
|
||||||
// config file is provided is that we still want to allow users to
|
// config file is provided is that we still want to allow users to
|
||||||
// pass inline options in the presence of an external config file.
|
// pass inline options in the presence of an external config file.
|
||||||
const inlineConfig = readInlineConfig()
|
// TO DO check order of precedence
|
||||||
// the external config takes precedence
|
return {...inlineConfig, ...remoteConfig, ...repoConfig}
|
||||||
return Object.assign({}, inlineConfig, config)
|
|
||||||
} else {
|
|
||||||
return readInlineConfig()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readInlineConfig(): ConfigurationOptions {
|
export function readInlineConfig(): ConfigurationOptions {
|
||||||
@@ -110,16 +120,8 @@ export function readInlineConfig(): ConfigurationOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readConfigFile(filePath: string): ConfigurationOptions {
|
export function readConfigFile(configData: string): ConfigurationOptions {
|
||||||
let data
|
const data = YAML.parse(configData)
|
||||||
|
|
||||||
try {
|
|
||||||
data = fs.readFileSync(path.resolve(filePath), 'utf-8')
|
|
||||||
} catch (error: unknown) {
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
data = YAML.parse(data)
|
|
||||||
|
|
||||||
for (const key of Object.keys(data)) {
|
for (const key of Object.keys(data)) {
|
||||||
if (key === 'allow-licenses' || key === 'deny-licenses') {
|
if (key === 'allow-licenses' || key === 'deny-licenses') {
|
||||||
validateLicenses(key, data[key])
|
validateLicenses(key, data[key])
|
||||||
@@ -133,3 +135,42 @@ export function readConfigFile(filePath: string): ConfigurationOptions {
|
|||||||
const values = ConfigurationOptionsSchema.parse(data)
|
const values = ConfigurationOptionsSchema.parse(data)
|
||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRepoConfig(filePath: string): string {
|
||||||
|
try {
|
||||||
|
return fs.readFileSync(path.resolve(filePath), 'utf-8')
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getRemoteConfig(configFile: string): Promise<string> {
|
||||||
|
const format = new RegExp(
|
||||||
|
'(?<owner>[^/]+)/(?<repo>[^/]+)/(?<path>[^@]+)@(?<ref>.*)'
|
||||||
|
)
|
||||||
|
|
||||||
|
const pieces = format.exec(configFile)
|
||||||
|
if (pieces === null || pieces.groups === undefined || pieces.length < 5) {
|
||||||
|
throw new Error('Invalid remote config file format.')
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const {data} = await octokitClient(
|
||||||
|
'config-repository-token'
|
||||||
|
).rest.repos.getContent({
|
||||||
|
mediaType: {
|
||||||
|
format: 'raw'
|
||||||
|
},
|
||||||
|
owner: pieces.groups.owner,
|
||||||
|
repo: pieces.groups.repo,
|
||||||
|
path: pieces.groups.path,
|
||||||
|
ref: pieces.groups.ref
|
||||||
|
})
|
||||||
|
if (data === undefined) {
|
||||||
|
throw new Error('Invalid content')
|
||||||
|
}
|
||||||
|
console.log('Checking data value', data, data === 'fail-on-severity: low\n')
|
||||||
|
return data as unknown as string
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+5
-8
@@ -1,8 +1,6 @@
|
|||||||
import * as core from '@actions/core'
|
|
||||||
import spdxSatisfies from 'spdx-satisfies'
|
import spdxSatisfies from 'spdx-satisfies'
|
||||||
import {Octokit} from 'octokit'
|
|
||||||
import {Change, Changes} from './schemas'
|
import {Change, Changes} from './schemas'
|
||||||
import {isSPDXValid} from './utils'
|
import {isSPDXValid, octokitClient as octokitClient} from './utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loops through a list of changes, filtering and returning the
|
* Loops through a list of changes, filtering and returning the
|
||||||
@@ -76,12 +74,11 @@ const fetchGHLicense = async (
|
|||||||
owner: string,
|
owner: string,
|
||||||
repo: string
|
repo: string
|
||||||
): Promise<string | null> => {
|
): Promise<string | null> => {
|
||||||
const octokit = new Octokit({
|
|
||||||
auth: core.getInput('repo-token', {required: true})
|
|
||||||
})
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await octokit.rest.licenses.getForRepo({owner, repo})
|
const response = await octokitClient().rest.licenses.getForRepo({
|
||||||
|
owner,
|
||||||
|
repo
|
||||||
|
})
|
||||||
return response.data.license?.spdx_id ?? null
|
return response.data.license?.spdx_id ?? null
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
|
import {Octokit} from 'octokit'
|
||||||
import spdxParse from 'spdx-expression-parse'
|
import spdxParse from 'spdx-expression-parse'
|
||||||
import {Changes} from './schemas'
|
import {Changes} from './schemas'
|
||||||
|
|
||||||
@@ -38,3 +40,9 @@ export function isSPDXValid(license: string): boolean {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function octokitClient(token = 'repo-token'): Octokit {
|
||||||
|
return new Octokit({
|
||||||
|
auth: core.getInput(token, {required: true})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user