-
Notifications
You must be signed in to change notification settings - Fork 1
Cli: Add mimic config #212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,124 @@ | ||||||
| import { Command, Flags } from '@oclif/core' | ||||||
| import * as fs from 'fs' | ||||||
| import * as yaml from 'js-yaml' | ||||||
| import { z } from 'zod' | ||||||
|
|
||||||
| import log from '../log' | ||||||
| import { FlagsType } from '../types' | ||||||
|
|
||||||
| export type FunctionsFlags = FlagsType<typeof Functions> | ||||||
|
|
||||||
| export const FunctionConfigSchema = z.object({ | ||||||
| name: z.string().min(1, 'Function name is required'), | ||||||
| manifest: z.string().min(1, 'Manifest path is required'), | ||||||
| function: z.string().min(1, 'Function path is required'), | ||||||
| 'build-directory': z.string().min(1, 'Build directory is required'), | ||||||
| 'types-directory': z.string().min(1, 'Types directory is required'), | ||||||
| }) | ||||||
|
|
||||||
| export const MimicConfigSchema = z.object({ | ||||||
| tasks: z.array(FunctionConfigSchema).min(1, 'At least one task is required'), | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| }) | ||||||
|
|
||||||
| export const DefaultFunctionConfig = { | ||||||
| name: '', | ||||||
| manifest: 'manifest.yaml', | ||||||
| function: 'src/function.ts', | ||||||
| 'build-directory': './build', | ||||||
| 'types-directory': './src/types', | ||||||
| } as const | ||||||
|
|
||||||
| export type FunctionConfig = { | ||||||
| name: string | ||||||
| manifest: string | ||||||
| function: string | ||||||
| 'build-directory': string | ||||||
| 'types-directory': string | ||||||
| } | ||||||
|
Comment on lines
+31
to
+37
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alternatively: export type FunctionConfig = z.infer<typeof FunctionConfigSchema> |
||||||
|
|
||||||
| export default class Functions extends Command { | ||||||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||||||
| run(): Promise<any> { | ||||||
| throw new Error('Method not implemented.') | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's weird to have a command that can't be run. console.log('The "functions" command is not intended to be run directly')Same with |
||||||
| } | ||||||
|
|
||||||
| static override description = 'Filters tasks based on a mimic.yaml configuration file' | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| static MIMIC_CONFIG_FILE = 'mimic.yaml' | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It feels a bit disorganized that the |
||||||
|
|
||||||
| static flags = { | ||||||
| 'config-file': Flags.string({ | ||||||
| description: `Path to the ${Functions.MIMIC_CONFIG_FILE} file, this overrides other parameters like build-directory and function`, | ||||||
| default: Functions.MIMIC_CONFIG_FILE, | ||||||
| }), | ||||||
| 'no-config': Flags.boolean({ | ||||||
| description: `Do not read ${Functions.MIMIC_CONFIG_FILE}; use defaults and explicit flags instead`, | ||||||
| default: false, | ||||||
| }), | ||||||
| include: Flags.string({ | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I run: |
||||||
| description: `When ${Functions.MIMIC_CONFIG_FILE} exists, only run tasks with these names (space-separated)`, | ||||||
| multiple: true, | ||||||
| exclusive: ['exclude'], | ||||||
| char: 'i', | ||||||
| }), | ||||||
| exclude: Flags.string({ | ||||||
| description: `When ${Functions.MIMIC_CONFIG_FILE} exists, exclude tasks with these names (space-separated)`, | ||||||
| multiple: true, | ||||||
| exclusive: ['include'], | ||||||
| char: 'e', | ||||||
| }), | ||||||
| } | ||||||
|
|
||||||
| public static async runFunctions<T extends FunctionsFlags & Partial<FunctionConfig>>( | ||||||
| cmd: Command, | ||||||
| flags: T, | ||||||
| cmdLogic: (cmd: Command, flags: T) => Promise<void>, | ||||||
| cmdActions: string | ||||||
| ): Promise<void> { | ||||||
| const functions = Functions.filterFunctions(cmd, flags) | ||||||
| for (const func of functions) { | ||||||
| log.startAction(`Starting ${cmdActions} for function ${func.name}`) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit |
||||||
| await cmdLogic(cmd, { ...flags, ...func } as T) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| public static filterFunctions(cmd: Command, flags: FunctionsFlags & Partial<FunctionConfig>): FunctionConfig[] { | ||||||
| if (flags['no-config']) { | ||||||
| return [{ ...DefaultFunctionConfig, ...flags }] | ||||||
| } | ||||||
|
|
||||||
| if (!fs.existsSync(flags['config-file'])) { | ||||||
| if (flags['config-file'] !== Functions.MIMIC_CONFIG_FILE) { | ||||||
| cmd.error(`Could not find ${flags['config-file']}`, { code: 'ConfigNotFound' }) | ||||||
| } | ||||||
|
|
||||||
| // If doesn't exists return the default with the flags the user added | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo
Suggested change
|
||||||
| return [{ ...DefaultFunctionConfig, ...flags }] | ||||||
| } | ||||||
|
|
||||||
| const fileContents = fs.readFileSync(flags['config-file'], 'utf8') | ||||||
| const rawConfig = yaml.load(fileContents) | ||||||
|
|
||||||
| try { | ||||||
| const config = MimicConfigSchema.parse(rawConfig) | ||||||
|
|
||||||
| let tasks = config.tasks || [] | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| if (flags.include && flags.include.length > 0) { | ||||||
| tasks = tasks.filter((task) => flags.include!.includes(task.name)) | ||||||
| } | ||||||
|
|
||||||
| if (flags.exclude && flags.exclude.length > 0) { | ||||||
| tasks = tasks.filter((task) => !flags.exclude!.includes(task.name)) | ||||||
| } | ||||||
|
|
||||||
| return tasks | ||||||
| } catch (error) { | ||||||
| if (error instanceof z.ZodError) { | ||||||
| const errors = error.errors.map((e) => `${e.path.join('.')}: ${e.message}`).join('\n') | ||||||
| cmd.error(`Invalid ${Functions.MIMIC_CONFIG_FILE} configuration:\n${errors}`, { code: 'InvalidConfig' }) | ||||||
| } | ||||||
| throw error | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shall we create |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import { execBinCommand } from '../lib/packageManager' | |
| import { FlagsType } from '../types' | ||
|
|
||
| import Build from './build' | ||
| import Functions from './functions' | ||
|
|
||
| export type TestFlags = FlagsType<typeof Test> | ||
|
|
||
|
|
@@ -14,6 +15,7 @@ export default class Test extends Command { | |
| static override examples = ['<%= config.bin %> <%= command.id %> --directory ./tests'] | ||
|
|
||
| static override flags = { | ||
| ...Functions.flags, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we add a comment saying that |
||
| ...Build.flags, | ||
| directory: Flags.string({ char: 'd', description: 'Path to the testing directory', default: './tests' }), | ||
| 'skip-build': Flags.boolean({ description: 'Skip build before testing', default: false }), | ||
|
|
@@ -29,7 +31,7 @@ export default class Test extends Command { | |
| const baseDir = path.resolve('./') | ||
| const testPath = path.join(baseDir, directory) | ||
|
|
||
| if (!skipBuild) await Build.build(cmd, flags) | ||
| if (!skipBuild) await Functions.runFunctions(cmd, flags, Build.build, 'building') | ||
|
|
||
| const result = execBinCommand('tsx', ['./node_modules/mocha/bin/mocha.js', `${testPath}/**/*.spec.ts`], baseDir) | ||
| cmd.exit(result.status ?? 1) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: this is redundant because
Codegen.flagsandCompile.flagsalready includeFunctions.flags, but I'd keep it anyway. To be explicit.