fix: use zod for input validation

This commit is contained in:
Erik Burton 2024-02-05 10:28:58 -08:00
parent 7302d3bf3c
commit 2be3e926cc
No known key found for this signature in database
4 changed files with 44 additions and 93 deletions

8
dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@ -13,10 +13,10 @@
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.11.5",
"@types/node-fetch": "^2.6.11",
"ajv": "^8.12.0",
"expand-tilde": "^2.0.2",
"fs-extra": "^11.2.0",
"yaml": "^2.3.4"
"yaml": "^2.3.4",
"zod": "^3.22.4"
},
"devDependencies": {
"@vercel/ncc": "^0.38.1",

43
pnpm-lock.yaml generated
View File

@ -23,9 +23,6 @@ dependencies:
'@types/node-fetch':
specifier: ^2.6.11
version: 2.6.11
ajv:
specifier: ^8.12.0
version: 8.12.0
expand-tilde:
specifier: ^2.0.2
version: 2.0.2
@ -35,6 +32,9 @@ dependencies:
yaml:
specifier: ^2.3.4
version: 2.3.4
zod:
specifier: ^3.22.4
version: 3.22.4
devDependencies:
'@vercel/ncc':
@ -107,15 +107,6 @@ packages:
hasBin: true
dev: true
/ajv@8.12.0:
resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
dependencies:
fast-deep-equal: 3.1.3
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
uri-js: 4.4.1
dev: false
/asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
dev: false
@ -139,10 +130,6 @@ packages:
homedir-polyfill: 1.0.3
dev: false
/fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
dev: false
/form-data@4.0.0:
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
engines: {node: '>= 6'}
@ -172,10 +159,6 @@ packages:
parse-passwd: 1.0.0
dev: false
/json-schema-traverse@1.0.0:
resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
dev: false
/jsonfile@6.1.0:
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
dependencies:
@ -207,16 +190,6 @@ packages:
hasBin: true
dev: true
/punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
dev: false
/require-from-string@2.0.2:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
dev: false
/tunnel@0.0.6:
resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==}
engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'}
@ -244,12 +217,6 @@ packages:
engines: {node: '>= 10.0.0'}
dev: false
/uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
dependencies:
punycode: 2.3.1
dev: false
/uuid@8.3.2:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
hasBin: true
@ -259,3 +226,7 @@ packages:
resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==}
engines: {node: '>= 14'}
dev: false
/zod@3.22.4:
resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
dev: false

View File

@ -1,5 +1,6 @@
import { getInput, InputOptions, error } from '@actions/core'
import { parse } from 'yaml'
import { getInput, error } from '@actions/core'
import * as yaml from 'yaml'
import { z, ZodError } from 'zod'
export interface RunInstall {
readonly recursive?: boolean
@ -7,64 +8,43 @@ export interface RunInstall {
readonly args?: readonly string[]
}
const zRunInstall = z.object({
recursive: z.boolean().optional(),
cwd: z.string().optional(),
args: z.array(z.string()).optional(),
})
export type RunInstallInput =
| null
| boolean
| RunInstall
| RunInstall[]
const options: InputOptions = {
required: true,
}
const zRunInstallInput = z.union([
z.null(),
z.boolean(),
zRunInstall,
z.array(zRunInstall),
])
export function parseRunInstall(name: string): RunInstall[] {
const input: any = parse(getInput(name, options))
export function parseRunInstall(inputName: string): RunInstall[] {
const input = getInput(inputName, { required: true })
const parsedInput: unknown = yaml.parse(input)
if (!input) return []
if (input === true) return [{ recursive: true }]
try {
const result: RunInstallInput = zRunInstallInput.parse(parsedInput)
if (!result) return []
if (result === true) return [{ recursive: true }]
if (Array.isArray(result)) return result
return [result]
} catch (exception: unknown) {
error(`Error for input "${inputName}" = ${input}`)
if (!isInputValid(input)) process.exit(1);
return Array.isArray(input) ? input : [input]
}
function isInputValid(input: any) {
if (Array.isArray(input)) {
return input.every(isEntryValid)
} else {
return isEntryValid(input)
}
}
function isEntryValid(input: any): boolean {
if (typeof input !== 'object') {
error(`Invalid input for run_install. Expected object, but got ${typeof input}`)
return false;
}
if (input.recursive !== undefined && typeof input.recursive !== 'boolean') {
error(`Invalid input for run_install.recursive. Expected boolean, but got ${typeof input.recursive}`)
return false;
}
if (input.cwd !== undefined && typeof input.cwd !== 'string') {
error(`Invalid input for run_install.cwd. Expected string, but got ${typeof input.cwd}`)
return false;
}
if (input.args !== undefined) {
if (!Array.isArray(input.args)) {
error(`Invalid input for run_install.args. Expected array, but got ${typeof input.args}`)
return false;
}
const invalidArgs: any[] = input.args.filter((arg: any) => typeof arg !== 'string');
if (invalidArgs.length > 0) {
const invalidArgsMessage = invalidArgs.map((arg: any) => typeof arg).join(', ');
error(`Invalid input for run_install.args. Expected array of strings, but got ${invalidArgsMessage}`)
return false;
if (exception instanceof ZodError) {
error(`Errors: ${exception.errors}`)
} else {
error(`Exception: ${exception}`)
}
process.exit(1)
}
return true;
}