From 9bb9d42ccbba1bf2ff58a947e928216361d31dd2 Mon Sep 17 00:00:00 2001 From: Jon Edvald Date: Thu, 6 Aug 2020 13:31:30 +0200 Subject: [PATCH] refactor: improve type-safety on plugin module handler definitions --- core/src/actions.ts | 10 ++++--- core/src/plugins/conftest/conftest.ts | 12 ++++++-- core/src/plugins/hadolint/hadolint.ts | 4 +-- core/src/types/plugin/plugin.ts | 42 ++++++++++++++++++--------- core/test/unit/src/garden.ts | 12 ++++++++ 5 files changed, 59 insertions(+), 21 deletions(-) diff --git a/core/src/actions.ts b/core/src/actions.ts index a4b8f6d51b..497e4135f3 100644 --- a/core/src/actions.ts +++ b/core/src/actions.ts @@ -19,7 +19,7 @@ import { SetSecretParams, SetSecretResult } from "./types/plugin/provider/setSec import { validateSchema } from "./config/validation" import { defaultProvider } from "./config/provider" import { ParameterError, PluginError, InternalError, RuntimeError } from "./exceptions" -import { Garden } from "./garden" +import { Garden, ModuleActionMap } from "./garden" import { LogEntry } from "./logger/log-entry" import { Module } from "./types/module" import { @@ -60,6 +60,8 @@ import { getPluginActionDescriptions, getModuleActionDescriptions, PluginActionDescriptions, + ModuleActionHandler, + ActionHandler, } from "./types/plugin/plugin" import { CleanupEnvironmentParams } from "./types/plugin/provider/cleanupEnvironment" import { DeleteSecretParams, DeleteSecretResult } from "./types/plugin/provider/deleteSecret" @@ -128,7 +130,7 @@ export interface DeployServicesParams { @Profile() export class ActionRouter implements TypeGuard { private readonly actionHandlers: WrappedPluginActionMap - private readonly moduleActionHandlers: WrappedModuleActionMap + private readonly moduleActionHandlers: ModuleActionMap private readonly loadedPlugins: PluginMap private readonly pluginActionDescriptions: PluginActionDescriptions private readonly moduleActionDescriptions: PluginActionDescriptions @@ -952,7 +954,7 @@ export class ActionRouter implements TypeGuard { // Wrap the handler with identifying attributes const wrapped = Object.assign( - (async (...args: any[]) => { + (async (...args: any[]) => { const result = await handler.apply(plugin, args) if (result === undefined) { throw new PluginError(`Got empty response from ${moduleType}.${actionType} handler on ${pluginName}`, { @@ -987,7 +989,7 @@ export class ActionRouter implements TypeGuard { * Recursively wraps the base handler (if any) on an action handler, such that the base handler receives the _next_ * base handler as the `base` parameter when called from within the handler. */ - private wrapBase | WrappedModuleActionHandler>( + private wrapBase | ModuleActionHandler>( handler?: T ): T | undefined { if (!handler) { diff --git a/core/src/plugins/conftest/conftest.ts b/core/src/plugins/conftest/conftest.ts index 698cb75ce4..77ca81613b 100644 --- a/core/src/plugins/conftest/conftest.ts +++ b/core/src/plugins/conftest/conftest.ts @@ -140,7 +140,7 @@ export const gardenPlugin = createGardenPlugin({ } moduleConfig.include = moduleConfig.spec.files - moduleConfig.testConfigs = [{ name: "test", dependencies: [], spec: {}, timeout: 10 }] + moduleConfig.testConfigs = [{ name: "test", dependencies: [], spec: {}, disabled: false, timeout: 10 }] return { moduleConfig } }, testModule: async ({ ctx, log, module, testConfig }: TestModuleParams) => { @@ -211,7 +211,15 @@ export const gardenPlugin = createGardenPlugin({ configure: async ({ moduleConfig }) => { moduleConfig.build.dependencies.push({ name: moduleConfig.spec.sourceModule, copy: [] }) moduleConfig.include = [] - moduleConfig.testConfigs = [{ name: "test", dependencies: moduleConfig.spec.runtimeDependencies, spec: {} }] + moduleConfig.testConfigs = [ + { + name: "test", + dependencies: moduleConfig.spec.runtimeDependencies, + spec: {}, + disabled: false, + timeout: null, + }, + ] return { moduleConfig } }, testModule: async ({ ctx, log, module, testConfig }: TestModuleParams) => { diff --git a/core/src/plugins/hadolint/hadolint.ts b/core/src/plugins/hadolint/hadolint.ts index c39849a92a..4434d0e471 100644 --- a/core/src/plugins/hadolint/hadolint.ts +++ b/core/src/plugins/hadolint/hadolint.ts @@ -154,10 +154,10 @@ export const gardenPlugin = createGardenPlugin({ handlers: { configure: async ({ moduleConfig }) => { moduleConfig.include = [moduleConfig.spec.dockerfilePath] - moduleConfig.testConfigs = [{ name: "lint", dependencies: [], spec: {}, timeout: 10 }] + moduleConfig.testConfigs = [{ name: "lint", dependencies: [], spec: {}, timeout: 10, disabled: false }] return { moduleConfig } }, - testModule: async ({ ctx, log, module, testConfig }: TestModuleParams) => { + testModule: async ({ ctx, log, module, testConfig }) => { const dockerfilePath = join(module.path, module.spec.dockerfilePath) const startedAt = new Date() let dockerfile: string diff --git a/core/src/types/plugin/plugin.ts b/core/src/types/plugin/plugin.ts index b147d7e734..757294fc0b 100644 --- a/core/src/types/plugin/plugin.ts +++ b/core/src/types/plugin/plugin.ts @@ -49,25 +49,25 @@ export interface ActionHandlerParamsBase { base?: ActionHandler } -export interface ActionHandler

{ - (params: P): Promise +export type ActionHandler

= ((params: P) => Promise) & { actionType?: string pluginName?: string - base?: WrappedActionHandler + base?: ActionHandler } -export interface ModuleActionHandler

extends ActionHandler { - (params: P): Promise +export type ModuleActionHandler

= ((params: P) => Promise) & { + actionType?: string + pluginName?: string moduleType?: string - base?: WrappedModuleActionHandler + base?: ModuleActionHandler } -export interface WrappedActionHandler

extends ActionHandler { +export type WrappedActionHandler

= ActionHandler & { actionType: string pluginName: string } -export interface WrappedModuleActionHandler

extends WrappedActionHandler { +export type WrappedModuleActionHandler

= WrappedActionHandler & { moduleType: string base?: WrappedModuleActionHandler } @@ -95,9 +95,9 @@ export type ModuleAndRuntimeActionHandlers = ModuleAc export type AllActionHandlers = PluginActionHandlers & ModuleAndRuntimeActionHandlers export type PluginActionName = keyof PluginActionHandlers -export type ServiceActionName = keyof ServiceActionHandlers -export type TaskActionName = keyof TaskActionHandlers -export type ModuleActionName = keyof ModuleActionHandlers +export type ServiceActionName = keyof ServiceActionParams +export type TaskActionName = keyof TaskActionParams +export type ModuleActionName = keyof ModuleActionParams export interface PluginActionDescription { description: string @@ -270,6 +270,12 @@ export type ModuleActionParams = { } } +export type ModuleAndRuntimeActionParams = ModuleActionParams & + ServiceActionParams & + TaskActionParams + +export type ModuleAndRuntimeActionOutputs = ModuleActionOutputs & ServiceActionOutputs & TaskActionOutputs + export interface ModuleActionOutputs extends ServiceActionOutputs { configure: ConfigureModuleResult suggestModules: SuggestModulesResult @@ -325,8 +331,18 @@ export function getModuleActionNames() { return Object.keys(getModuleActionDescriptions()) } -export interface ModuleTypeExtension { - handlers: Partial +export interface ModuleTypeExtension { + // Note: This needs to be this verbose because of issues with the TS compiler + handlers: { + [T in keyof ModuleAndRuntimeActionParams]?: (( + params: ModuleAndRuntimeActionParams[T] + ) => Promise) & { + actionType?: string + pluginName?: string + moduleType?: string + base?: ModuleAndRuntimeActionHandlers[T] + } + } name: string } diff --git a/core/test/unit/src/garden.ts b/core/test/unit/src/garden.ts index 7138c3607b..fc20a4ea7a 100644 --- a/core/test/unit/src/garden.ts +++ b/core/test/unit/src/garden.ts @@ -3022,6 +3022,10 @@ describe("Garden", () => { moduleConfig.serviceConfigs = [ { name: moduleConfig.name, + dependencies: [], + disabled: false, + hotReloadable: false, + spec: {}, }, ] return { moduleConfig } @@ -3128,6 +3132,10 @@ describe("Garden", () => { moduleConfig.serviceConfigs = [ { name: moduleConfig.name, + dependencies: [], + disabled: false, + hotReloadable: false, + spec: {}, }, ] return { moduleConfig } @@ -3206,6 +3214,10 @@ describe("Garden", () => { moduleConfig.serviceConfigs = [ { name: moduleConfig.name, + dependencies: [], + disabled: false, + hotReloadable: false, + spec: {}, }, ] return { moduleConfig }