Load remote config file
This commit is contained in:
@@ -64,7 +64,9 @@ event_file.close
|
||||
|
||||
action_inputs = {
|
||||
"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 = {
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
SeveritySchema,
|
||||
SCOPES
|
||||
} from './schemas'
|
||||
import {isSPDXValid} from './utils'
|
||||
import {isSPDXValid, octokitClient} from './utils'
|
||||
|
||||
type licenseKey = 'allow-licenses' | 'deny-licenses'
|
||||
|
||||
@@ -47,19 +47,29 @@ function validateLicenses(
|
||||
}
|
||||
}
|
||||
|
||||
export function readConfig(): ConfigurationOptions {
|
||||
const externalConfig = getOptionalInput('config-file')
|
||||
if (externalConfig !== undefined) {
|
||||
const config = readConfigFile(externalConfig)
|
||||
// the reasoning behind reading the inline config when an external
|
||||
// config file is provided is that we still want to allow users to
|
||||
// pass inline options in the presence of an external config file.
|
||||
const inlineConfig = readInlineConfig()
|
||||
// the external config takes precedence
|
||||
return Object.assign({}, inlineConfig, config)
|
||||
} else {
|
||||
return readInlineConfig()
|
||||
export async function readConfig(): Promise<ConfigurationOptions> {
|
||||
const externalToken = getOptionalInput('config-repository-token')
|
||||
const remoteConfigFile = getOptionalInput('remote-config-file')
|
||||
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
|
||||
// config file is provided is that we still want to allow users to
|
||||
// pass inline options in the presence of an external config file.
|
||||
// TO DO check order of precedence
|
||||
return {...inlineConfig, ...remoteConfig, ...repoConfig}
|
||||
}
|
||||
|
||||
export function readInlineConfig(): ConfigurationOptions {
|
||||
@@ -110,16 +120,8 @@ export function readInlineConfig(): ConfigurationOptions {
|
||||
}
|
||||
}
|
||||
|
||||
export function readConfigFile(filePath: string): ConfigurationOptions {
|
||||
let data
|
||||
|
||||
try {
|
||||
data = fs.readFileSync(path.resolve(filePath), 'utf-8')
|
||||
} catch (error: unknown) {
|
||||
throw error
|
||||
}
|
||||
data = YAML.parse(data)
|
||||
|
||||
export function readConfigFile(configData: string): ConfigurationOptions {
|
||||
const data = YAML.parse(configData)
|
||||
for (const key of Object.keys(data)) {
|
||||
if (key === 'allow-licenses' || key === 'deny-licenses') {
|
||||
validateLicenses(key, data[key])
|
||||
@@ -133,3 +135,42 @@ export function readConfigFile(filePath: string): ConfigurationOptions {
|
||||
const values = ConfigurationOptionsSchema.parse(data)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import * as core from '@actions/core'
|
||||
import spdxSatisfies from 'spdx-satisfies'
|
||||
import {Octokit} from 'octokit'
|
||||
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
|
||||
@@ -76,12 +74,11 @@ const fetchGHLicense = async (
|
||||
owner: string,
|
||||
repo: string
|
||||
): Promise<string | null> => {
|
||||
const octokit = new Octokit({
|
||||
auth: core.getInput('repo-token', {required: true})
|
||||
})
|
||||
|
||||
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
|
||||
} catch (_) {
|
||||
return null
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import * as core from '@actions/core'
|
||||
import {Octokit} from 'octokit'
|
||||
import spdxParse from 'spdx-expression-parse'
|
||||
import {Changes} from './schemas'
|
||||
|
||||
@@ -38,3 +40,9 @@ export function isSPDXValid(license: string): boolean {
|
||||
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