From d00f84ad5c3d7d8f1465fa278a029c5a64bd7733 Mon Sep 17 00:00:00 2001 From: Elias Kassell Date: Wed, 26 Jun 2024 14:03:32 +0000 Subject: [PATCH 1/3] Update operation to use config action fields --- core/actions/assertion.ts | 2 - core/actions/declaration.ts | 4 +- core/actions/operation.ts | 156 ++++++++++++++++++------------------ core/actions/table.ts | 4 +- core/column_descriptors.ts | 68 +++++++++++++++- core/main_test.ts | 5 ++ core/session.ts | 7 +- protos/configs.proto | 3 + 8 files changed, 162 insertions(+), 87 deletions(-) diff --git a/core/actions/assertion.ts b/core/actions/assertion.ts index afef3e0fd..30f210308 100644 --- a/core/actions/assertion.ts +++ b/core/actions/assertion.ts @@ -75,8 +75,6 @@ export class Assertion extends ActionBuilder { this.query(nativeRequire(config.filename).query); } - // TODO(ekrekr): load config proto column descriptors. - if (config.dependencyTargets) { this.dependencies( config.dependencyTargets.map(dependencyTarget => diff --git a/core/actions/declaration.ts b/core/actions/declaration.ts index bd878205f..8d2770e26 100644 --- a/core/actions/declaration.ts +++ b/core/actions/declaration.ts @@ -1,6 +1,6 @@ import { verifyObjectMatchesProto, VerifyProtoErrorBehaviour } from "df/common/protos"; import { ActionBuilder } from "df/core/actions"; -import { ColumnDescriptors } from "df/core/column_descriptors"; +import { LegacyColumnDescriptors } from "df/core/column_descriptors"; import { IColumnsDescriptor, IDocumentableConfig, @@ -86,7 +86,7 @@ export class Declaration extends ActionBuilder { if (!this.proto.actionDescriptor) { this.proto.actionDescriptor = {}; } - this.proto.actionDescriptor.columns = ColumnDescriptors.mapToColumnProtoArray( + this.proto.actionDescriptor.columns = LegacyColumnDescriptors.mapToColumnProtoArray( columns, (e: Error) => this.session.compileError(e) ); diff --git a/core/actions/operation.ts b/core/actions/operation.ts index ad7299cd4..416b5512f 100644 --- a/core/actions/operation.ts +++ b/core/actions/operation.ts @@ -28,42 +28,18 @@ import { import { dataform } from "df/protos/ts"; /** - * Configuration options for `operations` action types. + * @hidden + * This maintains backwards compatability with older versions. + * TODO(ekrekr): consider breaking backwards compatability of these in v4. */ -export interface IOperationConfig - extends IActionConfig, - IDependenciesConfig, - IDocumentableConfig, - INamedConfig, - ITargetableConfig { - /** - * Declares that this `operations` action creates a dataset which should be referenceable using the `ref` function. - * - * If set to true, this action should create a dataset with its configured name, using the `self()` context function. - * - * For example: - * ```sql - * create or replace table ${self()} as select ... - * ``` - */ - hasOutput?: boolean; +interface ILegacyOperationConfig extends dataform.ActionConfig.OperationConfig { + dependencies: Resolvable[]; + database: string; + schema: string; + fileName: string; + type: string; } -export const IIOperationConfigProperties = strictKeysOf()([ - "columns", - "database", - "dependencies", - "description", - "disabled", - "hasOutput", - "hermetic", - "name", - "schema", - "tags", - "type", - "dependOnDependencyAssertions" -]); - /** * @hidden */ @@ -80,18 +56,16 @@ export class Operation extends ActionBuilder { // We delay contextification until the final compile step, so hold these here for now. private contextableQueries: Contextable; - constructor( - session?: Session, - config?: dataform.ActionConfig.OperationConfig, - configPath?: string - ) { + constructor(session?: Session, unverifiedConfig?: any, configPath?: string) { super(session); this.session = session; - if (!config) { + if (!unverifiedConfig) { return; } + const config = this.verifyConfig(unverifiedConfig); + if (!config.name) { config.name = Path.basename(config.filename); } @@ -107,37 +81,19 @@ export class Operation extends ActionBuilder { config.filename = resolveActionsConfigFilename(config.filename, configPath); this.proto.fileName = config.filename; - // TODO(ekrekr): load config proto column descriptors. - this.config({ - dependencies: config.dependencyTargets.map(dependencyTarget => - actionConfigToCompiledGraphTarget(dataform.ActionConfig.Target.create(dependencyTarget)) - ), - tags: config.tags, - disabled: config.disabled, - hasOutput: config.hasOutput, - description: config.description, - dependOnDependencyAssertions: config.dependOnDependencyAssertions - }); - - this.queries(nativeRequire(config.filename).query); - } - - public config(config: IOperationConfig) { - checkExcessProperties( - (e: Error) => this.session.compileError(e), - config, - IIOperationConfigProperties, - "operation config" - ); if (config.dependOnDependencyAssertions) { this.setDependOnDependencyAssertions(config.dependOnDependencyAssertions); } - if (config.dependencies) { - this.dependencies(config.dependencies); - } - if (config.hermetic !== undefined) { - this.hermetic(config.hermetic); + if (config.dependencyTargets) { + this.dependencies( + config.dependencyTargets.map(dependencyTarget => + actionConfigToCompiledGraphTarget(dataform.ActionConfig.Target.create(dependencyTarget)) + ) + ); } + // if (config.hermetic !== undefined) { + // this.hermetic(config.hermetic); + // } if (config.disabled) { this.disabled(); } @@ -150,15 +106,20 @@ export class Operation extends ActionBuilder { if (config.description) { this.description(config.description); } - if (config.columns) { - this.columns(config.columns); + if (config.columns?.length) { + this.columns( + config.columns.map(columnDescriptor => + dataform.ActionConfig.ColumnDescriptor.create(columnDescriptor) + ) + ); } - if (config.database) { - this.database(config.database); + if (config.project) { + this.database(config.project); } - if (config.schema) { - this.schema(config.schema); + if (config.dataset) { + this.schema(config.dataset); } + this.queries(nativeRequire(config.filename).query); return this; } @@ -209,13 +170,12 @@ export class Operation extends ActionBuilder { return this; } - public columns(columns: IColumnsDescriptor) { + public columns(columns: dataform.ActionConfig.ColumnDescriptor[]) { if (!this.proto.actionDescriptor) { this.proto.actionDescriptor = {}; } - this.proto.actionDescriptor.columns = ColumnDescriptors.mapToColumnProtoArray( - columns, - (e: Error) => this.session.compileError(e) + this.proto.actionDescriptor.columns = ColumnDescriptors.mapConfigProtoToCompilationProto( + columns ); return this; } @@ -282,6 +242,50 @@ export class Operation extends ActionBuilder { VerifyProtoErrorBehaviour.SUGGEST_REPORTING_TO_DATAFORM_TEAM ); } + + private verifyConfig( + unverifiedConfig: ILegacyOperationConfig + ): dataform.ActionConfig.OperationConfig { + if (unverifiedConfig.dependencies) { + unverifiedConfig.dependencyTargets = unverifiedConfig.dependencies.map( + (dependency: string | object) => + typeof dependency === "string" ? { name: dependency } : dependency + ); + delete unverifiedConfig.dependencies; + } + if (unverifiedConfig.database) { + unverifiedConfig.project = unverifiedConfig.database; + delete unverifiedConfig.database; + } + if (unverifiedConfig.schema) { + unverifiedConfig.dataset = unverifiedConfig.schema; + delete unverifiedConfig.schema; + } + if (unverifiedConfig.fileName) { + unverifiedConfig.filename = unverifiedConfig.fileName; + delete unverifiedConfig.fileName; + } + if (unverifiedConfig.columns) { + // TODO(ekrekr) columns in their current config format are a difficult structure to represent + // as protos. They are nested, and use the object keys as the names. Consider a forced + // migration to the proto style column names. + unverifiedConfig.columns = ColumnDescriptors.mapLegacyObjectToConfigProto( + unverifiedConfig.columns as any + ); + } + + // TODO(ekrekr): consider moving this to a shared location after all action builders have proto + // config verifiers. + if (unverifiedConfig.type) { + delete unverifiedConfig.type; + } + + return verifyObjectMatchesProto( + dataform.ActionConfig.OperationConfig, + unverifiedConfig, + VerifyProtoErrorBehaviour.SHOW_DOCS_LINK + ); + } } /** diff --git a/core/actions/table.ts b/core/actions/table.ts index 52fe1c4f5..d9aa032b9 100644 --- a/core/actions/table.ts +++ b/core/actions/table.ts @@ -1,7 +1,7 @@ import { verifyObjectMatchesProto, VerifyProtoErrorBehaviour } from "df/common/protos"; import { ActionBuilder } from "df/core/actions"; import { Assertion } from "df/core/actions/assertion"; -import { ColumnDescriptors } from "df/core/column_descriptors"; +import { LegacyColumnDescriptors } from "df/core/column_descriptors"; import { Contextable, IActionConfig, @@ -606,7 +606,7 @@ export class Table extends ActionBuilder { if (!this.proto.actionDescriptor) { this.proto.actionDescriptor = {}; } - this.proto.actionDescriptor.columns = ColumnDescriptors.mapToColumnProtoArray( + this.proto.actionDescriptor.columns = LegacyColumnDescriptors.mapToColumnProtoArray( columns, (e: Error) => this.session.compileError(e) ); diff --git a/core/column_descriptors.ts b/core/column_descriptors.ts index 92227186f..f64109f14 100644 --- a/core/column_descriptors.ts +++ b/core/column_descriptors.ts @@ -6,13 +6,77 @@ import { dataform } from "df/protos/ts"; * @hidden */ export class ColumnDescriptors { + public static mapConfigProtoToCompilationProto( + columns: dataform.ActionConfig.ColumnDescriptor[] + ): dataform.IColumnDescriptor[] { + return columns.map(column => { + return dataform.ColumnDescriptor.create({ + path: column.path, + description: column.description, + tags: column.tags, + bigqueryPolicyTags: column.bigqueryPolicyTags + }); + }); + } + + public static mapLegacyObjectToConfigProto( + columns: IColumnsDescriptor + ): dataform.ActionConfig.ColumnDescriptor[] { + return Object.keys(columns) + .map(column => ColumnDescriptors.mapColumnDescriptionToProto([column], columns[column])) + .flat(); + } + + public static mapColumnDescriptionToProto( + currentPath: string[], + description: string | IRecordDescriptor + ): dataform.ActionConfig.ColumnDescriptor[] { + if (typeof description === "string") { + return [ + dataform.ColumnDescriptor.create({ + description, + path: currentPath + }) + ]; + } + const columnDescriptor: dataform.ActionConfig.ColumnDescriptor[] = !!description + ? [ + dataform.ActionConfig.ColumnDescriptor.create({ + path: currentPath, + description: description.description, + tags: typeof description.tags === "string" ? [description.tags] : description.tags, + bigqueryPolicyTags: + typeof description.bigqueryPolicyTags === "string" + ? [description.bigqueryPolicyTags] + : description.bigqueryPolicyTags + }) + ] + : []; + const nestedColumns = description.columns ? Object.keys(description.columns) : []; + return columnDescriptor.concat( + nestedColumns + .map(nestedColumn => + ColumnDescriptors.mapColumnDescriptionToProto( + currentPath.concat([nestedColumn]), + description.columns[nestedColumn] + ) + ) + .flat() + ); + } +} + +/** + * @hidden + */ +export class LegacyColumnDescriptors { public static mapToColumnProtoArray( columns: IColumnsDescriptor, reportError: (e: Error) => void ): dataform.IColumnDescriptor[] { return Object.keys(columns) .map(column => - ColumnDescriptors.mapColumnDescriptionToProto([column], columns[column], reportError) + LegacyColumnDescriptors.mapColumnDescriptionToProto([column], columns[column], reportError) ) .flat(); } @@ -54,7 +118,7 @@ export class ColumnDescriptors { return columnDescriptor.concat( nestedColumns .map(nestedColumn => - ColumnDescriptors.mapColumnDescriptionToProto( + LegacyColumnDescriptors.mapColumnDescriptionToProto( currentPath.concat([nestedColumn]), description.columns[nestedColumn], reportError diff --git a/core/main_test.ts b/core/main_test.ts index f21d0c8c0..3d3a3ce55 100644 --- a/core/main_test.ts +++ b/core/main_test.ts @@ -181,6 +181,11 @@ actions: const result = runMainInVm(coreExecutionRequestFromPath(projectDir)); + console.log( + "🚀 ~ suite ~ result.compile.compiledGraph.graphErrors.compilationErrors:", + result.compile.compiledGraph.graphErrors.compilationErrors + ); + expect( result.compile.compiledGraph.graphErrors.compilationErrors .map(({ message }) => message) diff --git a/core/session.ts b/core/session.ts index e66b281eb..7504b77c4 100644 --- a/core/session.ts +++ b/core/session.ts @@ -156,9 +156,10 @@ export class Session { ); break; case "operations": - this.operate(sqlxConfig.name) - .config(sqlxConfig) - .queries(actionOptions.sqlContextable); + sqlxConfig.filename = utils.getCallerFile(this.rootDir); + this.actions.push( + new Operation(this, sqlxConfig).queries(ctx => actionOptions.sqlContextable(ctx)[0]) + ); break; case "declaration": this.declare({ diff --git a/protos/configs.proto b/protos/configs.proto index 4acd257ee..140c045d4 100644 --- a/protos/configs.proto +++ b/protos/configs.proto @@ -79,6 +79,9 @@ message ActionConfig { // A list of BigQuery policy tags that will be applied to the column. repeated string bigquery_policy_tags = 3; + + // A list of tags for this column which will be applied. + repeated string tags = 4; } message TableConfig { From 458ae72d82880d3358b289f28b9110a25df8b6e5 Mon Sep 17 00:00:00 2001 From: Elias Kassell Date: Wed, 26 Jun 2024 14:27:37 +0000 Subject: [PATCH 2/3] Fix tests, tidy filename --- core/actions/operation.ts | 24 ++++++++---------------- core/main_test.ts | 13 ++++--------- core/session.ts | 4 +--- core/utils.ts | 3 ++- 4 files changed, 15 insertions(+), 29 deletions(-) diff --git a/core/actions/operation.ts b/core/actions/operation.ts index 416b5512f..b2e2bd351 100644 --- a/core/actions/operation.ts +++ b/core/actions/operation.ts @@ -1,28 +1,16 @@ import { verifyObjectMatchesProto, VerifyProtoErrorBehaviour } from "df/common/protos"; import { ActionBuilder } from "df/core/actions"; import { ColumnDescriptors } from "df/core/column_descriptors"; -import { - Contextable, - IActionConfig, - IColumnsDescriptor, - ICommonContext, - IDependenciesConfig, - IDocumentableConfig, - INamedConfig, - ITargetableConfig, - Resolvable -} from "df/core/common"; +import { Contextable, ICommonContext, Resolvable } from "df/core/common"; import * as Path from "df/core/path"; import { Session } from "df/core/session"; import { actionConfigToCompiledGraphTarget, addDependenciesToActionDependencyTargets, - checkExcessProperties, nativeRequire, resolvableAsTarget, resolveActionsConfigFilename, setNameAndTarget, - strictKeysOf, toResolvable } from "df/core/utils"; import { dataform } from "df/protos/ts"; @@ -78,8 +66,10 @@ export class Operation extends ActionBuilder { ); this.proto.canonicalTarget = this.applySessionToTarget(target, session.canonicalProjectConfig); - config.filename = resolveActionsConfigFilename(config.filename, configPath); - this.proto.fileName = config.filename; + if (configPath) { + config.filename = resolveActionsConfigFilename(config.filename, configPath); + this.queries(nativeRequire(config.filename).query); + } if (config.dependOnDependencyAssertions) { this.setDependOnDependencyAssertions(config.dependOnDependencyAssertions); @@ -119,7 +109,9 @@ export class Operation extends ActionBuilder { if (config.dataset) { this.schema(config.dataset); } - this.queries(nativeRequire(config.filename).query); + if (config.filename) { + this.proto.fileName = config.filename; + } return this; } diff --git a/core/main_test.ts b/core/main_test.ts index 3d3a3ce55..861de459d 100644 --- a/core/main_test.ts +++ b/core/main_test.ts @@ -181,18 +181,15 @@ actions: const result = runMainInVm(coreExecutionRequestFromPath(projectDir)); - console.log( - "🚀 ~ suite ~ result.compile.compiledGraph.graphErrors.compilationErrors:", - result.compile.compiledGraph.graphErrors.compilationErrors - ); - expect( result.compile.compiledGraph.graphErrors.compilationErrors .map(({ message }) => message) .sort() ).deep.equals([ + `Action target datasets cannot include '.'`, `Action target datasets cannot include '.'`, `Action target names cannot include '.'`, + `Action target names cannot include '.'`, `Action target names cannot include '.'` ]); }); @@ -1350,7 +1347,6 @@ actions: columns: { nestedColumnKey: "nestedColumnVal" }, - displayName: "displayName", tags: ["tag3", "tag4"], bigqueryPolicyTags: ["bigqueryPolicyTag1", "bigqueryPolicyTag2"], } @@ -1364,7 +1360,6 @@ actions: { bigqueryPolicyTags: ["bigqueryPolicyTag1", "bigqueryPolicyTag2"], description: "description", - displayName: "displayName", path: ["column2Key"], tags: ["tag3", "tag4"] }, @@ -1849,6 +1844,7 @@ SELECT 1` path.join(projectDir, "definitions/table.sqlx"), `config {type: "view"} SELECT 1` ); + // TODO(ekrekr): re-add hermetic. fs.writeFileSync( path.join(projectDir, "definitions/operation.sqlx"), ` @@ -1861,7 +1857,6 @@ config { tags: ["tagA", "tagB"], disabled: true, description: "description", - hermetic: true, hasOutput: true, dependOnDependencyAssertions: true, ${exampleActionDescriptor.inputSqlxConfigBlock} @@ -1894,7 +1889,7 @@ SELECT 1` ], disabled: true, fileName: "definitions/operation.sqlx", - hermeticity: "HERMETIC", + // hermeticity: "HERMETIC", hasOutput: true, tags: ["tagA", "tagB"], queries: ["\n\nSELECT 1"], diff --git a/core/session.ts b/core/session.ts index 7504b77c4..961c1f957 100644 --- a/core/session.ts +++ b/core/session.ts @@ -157,9 +157,7 @@ export class Session { break; case "operations": sqlxConfig.filename = utils.getCallerFile(this.rootDir); - this.actions.push( - new Operation(this, sqlxConfig).queries(ctx => actionOptions.sqlContextable(ctx)[0]) - ); + this.actions.push(new Operation(this, sqlxConfig).queries(actionOptions.sqlContextable)); break; case "declaration": this.declare({ diff --git a/core/utils.ts b/core/utils.ts index 33954164e..adadd0d06 100644 --- a/core/utils.ts +++ b/core/utils.ts @@ -309,7 +309,8 @@ export function actionConfigToCompiledGraphTarget( } export function resolveActionsConfigFilename(configFilename: string, configPath: string) { - return Path.normalize(Path.join(Path.dirName(configPath), configFilename)); + const tmp = Path.dirName(configPath); + return Path.normalize(Path.join(tmp, configFilename)); } export function addDependenciesToActionDependencyTargets( From 318686ed21111944db52308d98212cc5b40c1296 Mon Sep 17 00:00:00 2001 From: Elias Kassell Date: Fri, 28 Jun 2024 15:08:18 +0000 Subject: [PATCH 3/3] Tidy --- core/actions/operation.ts | 62 ++++++++++++++++++--------------------- core/actions/view.ts | 3 -- core/main_test.ts | 10 ++++--- core/utils.ts | 3 +- 4 files changed, 35 insertions(+), 43 deletions(-) diff --git a/core/actions/operation.ts b/core/actions/operation.ts index b2e2bd351..416946fc4 100644 --- a/core/actions/operation.ts +++ b/core/actions/operation.ts @@ -81,9 +81,9 @@ export class Operation extends ActionBuilder { ) ); } - // if (config.hermetic !== undefined) { - // this.hermetic(config.hermetic); - // } + if (config.hermetic !== undefined) { + this.hermetic(config.hermetic); + } if (config.disabled) { this.disabled(); } @@ -238,40 +238,34 @@ export class Operation extends ActionBuilder { private verifyConfig( unverifiedConfig: ILegacyOperationConfig ): dataform.ActionConfig.OperationConfig { - if (unverifiedConfig.dependencies) { - unverifiedConfig.dependencyTargets = unverifiedConfig.dependencies.map( - (dependency: string | object) => - typeof dependency === "string" ? { name: dependency } : dependency - ); - delete unverifiedConfig.dependencies; - } - if (unverifiedConfig.database) { - unverifiedConfig.project = unverifiedConfig.database; - delete unverifiedConfig.database; - } - if (unverifiedConfig.schema) { - unverifiedConfig.dataset = unverifiedConfig.schema; - delete unverifiedConfig.schema; - } - if (unverifiedConfig.fileName) { - unverifiedConfig.filename = unverifiedConfig.fileName; - delete unverifiedConfig.fileName; - } - if (unverifiedConfig.columns) { - // TODO(ekrekr) columns in their current config format are a difficult structure to represent - // as protos. They are nested, and use the object keys as the names. Consider a forced - // migration to the proto style column names. - unverifiedConfig.columns = ColumnDescriptors.mapLegacyObjectToConfigProto( - unverifiedConfig.columns as any - ); - } - - // TODO(ekrekr): consider moving this to a shared location after all action builders have proto - // config verifiers. + // The "type" field only exists on legacy view configs. Here we convert them to the new format. if (unverifiedConfig.type) { delete unverifiedConfig.type; + if (unverifiedConfig.dependencies) { + unverifiedConfig.dependencyTargets = unverifiedConfig.dependencies.map( + (dependency: string | object) => + typeof dependency === "string" ? { name: dependency } : dependency + ); + delete unverifiedConfig.dependencies; + } + if (unverifiedConfig.database) { + unverifiedConfig.project = unverifiedConfig.database; + delete unverifiedConfig.database; + } + if (unverifiedConfig.schema) { + unverifiedConfig.dataset = unverifiedConfig.schema; + delete unverifiedConfig.schema; + } + if (unverifiedConfig.fileName) { + unverifiedConfig.filename = unverifiedConfig.fileName; + delete unverifiedConfig.fileName; + } + if (unverifiedConfig.columns) { + unverifiedConfig.columns = ColumnDescriptors.mapLegacyObjectToConfigProto( + unverifiedConfig.columns as any + ); + } } - return verifyObjectMatchesProto( dataform.ActionConfig.OperationConfig, unverifiedConfig, diff --git a/core/actions/view.ts b/core/actions/view.ts index 028f1a836..f2bcebea0 100644 --- a/core/actions/view.ts +++ b/core/actions/view.ts @@ -403,9 +403,6 @@ export class View extends ActionBuilder { delete unverifiedConfig.fileName; } if (unverifiedConfig.columns) { - // TODO(ekrekr) columns in their current config format are a difficult structure to represent - // as protos. They are nested, and use the object keys as the names. Consider a forced - // migration to the proto style column names. unverifiedConfig.columns = ColumnDescriptors.mapLegacyObjectToConfigProto( unverifiedConfig.columns as any ); diff --git a/core/main_test.ts b/core/main_test.ts index 1ae532a43..c654f93f3 100644 --- a/core/main_test.ts +++ b/core/main_test.ts @@ -892,7 +892,8 @@ actions: name: "action" }, fileName: "definitions/action.sql", - queries: ["SELECT 1"] + queries: ["SELECT 1"], + hermeticity: "NON_HERMETIC" } ]) ); @@ -1272,7 +1273,8 @@ actions: name: "utf8characters:私🙂 and some spaces" }, fileName: "definitions/utf8characters:私🙂 and some spaces.sql", - queries: ["SELECT 1"] + queries: ["SELECT 1"], + hermeticity: "NON_HERMETIC" } ]) ); @@ -1859,7 +1861,6 @@ SELECT 1` path.join(projectDir, "definitions/table.sqlx"), `config {type: "view"} SELECT 1` ); - // TODO(ekrekr): re-add hermetic. fs.writeFileSync( path.join(projectDir, "definitions/operation.sqlx"), ` @@ -1872,6 +1873,7 @@ config { tags: ["tagA", "tagB"], disabled: true, description: "description", + hermetic: true, hasOutput: true, dependOnDependencyAssertions: true, ${exampleActionDescriptor.inputSqlxConfigBlock} @@ -1904,7 +1906,7 @@ SELECT 1` ], disabled: true, fileName: "definitions/operation.sqlx", - // hermeticity: "HERMETIC", + hermeticity: "HERMETIC", hasOutput: true, tags: ["tagA", "tagB"], queries: ["\n\nSELECT 1"], diff --git a/core/utils.ts b/core/utils.ts index 716fa7fbd..6b31dc3e5 100644 --- a/core/utils.ts +++ b/core/utils.ts @@ -310,8 +310,7 @@ export function actionConfigToCompiledGraphTarget( } export function resolveActionsConfigFilename(configFilename: string, configPath: string) { - const tmp = Path.dirName(configPath); - return Path.normalize(Path.join(tmp, configFilename)); + return Path.normalize(Path.join(Path.dirName(configPath), configFilename)); } export function addDependenciesToActionDependencyTargets(