From 0b7dd17f9ec82bfd6854775ded6ffb25e53c73f4 Mon Sep 17 00:00:00 2001 From: Matthew Bystedt Date: Mon, 16 Dec 2024 15:57:28 -0800 Subject: [PATCH] fix: package installation actions --- src/intention/action.service.ts | 5 +- .../entity/action-source.embeddable.ts | 5 ++ .../package-installation-action.embeddable.ts | 3 + src/intention/entity/package.embeddable.ts | 2 +- src/intention/intention.service.ts | 63 +++++++++++-------- src/util/action.util.ts | 9 ++- 6 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/intention/action.service.ts b/src/intention/action.service.ts index 86f2da4d..c27e65af 100644 --- a/src/intention/action.service.ts +++ b/src/intention/action.service.ts @@ -409,8 +409,9 @@ export class ActionService { const parsedVersion = this.parseActionVersion(action); if (!this.actionUtil.isStrictSemver(parsedVersion)) { return { - message: - 'Package actions must specify a valid semver version. See: https://semver.org', + message: action.package?.version + ? 'Package actions must specify a valid semver version. See: https://semver.org' + : 'No package version set. If using source intention, check action.source values.', data: { action: action.action, action_id: action.id, diff --git a/src/intention/entity/action-source.embeddable.ts b/src/intention/entity/action-source.embeddable.ts index 2e41af58..6bacc66f 100644 --- a/src/intention/entity/action-source.embeddable.ts +++ b/src/intention/entity/action-source.embeddable.ts @@ -4,6 +4,11 @@ import { ObjectId } from 'mongodb'; @Embeddable() export class ActionSourceEmbeddable { + constructor(action: string, intention: ObjectId) { + this.action = action; + this.intention = intention; + } + @Property({ nullable: true }) action?: string; diff --git a/src/intention/entity/package-installation-action.embeddable.ts b/src/intention/entity/package-installation-action.embeddable.ts index 8799e95f..0a5b3bac 100644 --- a/src/intention/entity/package-installation-action.embeddable.ts +++ b/src/intention/entity/package-installation-action.embeddable.ts @@ -9,6 +9,7 @@ import { TransactionEmbeddable } from './transaction.embeddable'; import { UserEmbeddable } from './user.embeddable'; import { PackageEmbeddable } from './package.embeddable'; import { ActionDto } from '../dto/action.dto'; +import { ActionSourceEmbeddable } from './action-source.embeddable'; @Embeddable({ discriminatorValue: ACTION_NAMES.PACKAGE_INSTALLATION }) export class PackageInstallationActionEmbeddable extends ActionEmbeddable { @@ -19,10 +20,12 @@ export class PackageInstallationActionEmbeddable extends ActionEmbeddable { vaultEnvironment: ENVIRONMENT_NAMES | undefined, trace: TransactionEmbeddable, packageEmbed: PackageEmbeddable, + source: ActionSourceEmbeddable, ) { super(action, actionUser, service, vaultEnvironment, trace); this.action = ACTION_NAMES.PACKAGE_INSTALLATION; this.package = packageEmbed; + this.source = source; } @Embedded({ entity: () => PackageEmbeddable, object: true }) diff --git a/src/intention/entity/package.embeddable.ts b/src/intention/entity/package.embeddable.ts index 0dfd5134..8f427758 100644 --- a/src/intention/entity/package.embeddable.ts +++ b/src/intention/entity/package.embeddable.ts @@ -8,7 +8,7 @@ import { PackageDto } from '../dto/package.dto'; export class PackageEmbeddable { static merge(...theArgs: Array) { const rval = new PackageEmbeddable(); - for (const arg of theArgs) { + for (const arg of theArgs.filter((arg) => arg)) { rval.architecture = arg.architecture ?? rval.architecture; rval.buildGuid = arg.buildGuid ?? rval.buildGuid; rval.buildNumber = arg.buildNumber ?? rval.buildNumber; diff --git a/src/intention/intention.service.ts b/src/intention/intention.service.ts index 41a58597..e2f8f4f4 100644 --- a/src/intention/intention.service.ts +++ b/src/intention/intention.service.ts @@ -68,6 +68,7 @@ import { ServiceDto } from '../persistence/dto/service.dto'; import { CloudObjectEmbeddable } from './entity/cloud-object.embeddable'; import { CloudEmbeddable } from './entity/cloud.embeddable'; import { ValidatorUtil } from '../util/validator.util'; +import { ActionSourceEmbeddable } from './entity/action-source.embeddable'; export interface IntentionOpenResponse { actions: { @@ -229,15 +230,21 @@ export class IntentionService { vaultEnvironment, trace, ); - case 'package-installation': + case 'package-installation': { + const packageSource = await this.sourcePackageFromBuild( + action, + serviceEmbed, + ); return new PackageInstallationActionEmbeddable( action, actionUser, serviceEmbed, vaultEnvironment, trace, - PackageEmbeddable.fromDto(action.package), + packageSource ? packageSource.package : undefined, + packageSource ? packageSource.source : undefined, ); + } case 'package-provision': return new PackageProvisionActionEmbeddable( action, @@ -477,6 +484,7 @@ export class IntentionService { .reduce((pv, cv) => pv.concat(cv), []), }; } catch (e) { + console.log(e); throw new BadRequestException({ statusCode: 400, message: 'Illegal search arguement', @@ -512,13 +520,20 @@ export class IntentionService { return artifactCombos; } - private async annotateActionPackageFromExistingArtifact( - action: ActionEmbeddable, - ) { - if (action.action !== 'package-installation' || !action.service.id) { - // Only annotates package installations + private async sourcePackageFromBuild( + action: ActionDto, + serviceEmbed: IntentionServiceEmbeddable, + ): Promise< + { source?: ActionSourceEmbeddable; package: PackageEmbeddable } | undefined + > { + const defaultVal = action.package + ? { + package: PackageEmbeddable.fromDto(action.package), + } + : undefined; + if (!serviceEmbed.id) { // Only existing services (with service.id set) will have artifacts - return; + return defaultVal; } let artifactSearchResult: ArtifactSearchResult; @@ -542,7 +557,7 @@ export class IntentionService { artifactSearchResult.data.length !== 1 ) { // Skip: Could not uniquely identify artifact based on source - return; + return defaultVal; } } else if (action.package?.name && action.package?.version) { // Find latest artifact for this service with same package name and version @@ -558,29 +573,25 @@ export class IntentionService { limit: 1, }); } else { - return; + return defaultVal; } if (artifactSearchResult.meta.total === 0) { // Could not identify artifact - return; + return defaultVal; } - action.package = PackageEmbeddable.merge( - artifactSearchResult.data[0].action.package ?? {}, - artifactSearchResult.data[0].artifact, - action.package, - ); - if (!action.source) { - action.source = { - intention: new ObjectId( - artifactSearchResult.data[0].intention.id.toString(), - ), - }; - } - // action.source.action = this.actionUtil.actionToIdString( - // artifactSearchResult.data[0].action, - // ); + return { + source: new ActionSourceEmbeddable( + this.actionUtil.actionToIdString(artifactSearchResult.data[0].action), + new ObjectId(artifactSearchResult.data[0].intention.id), + ), + package: PackageEmbeddable.merge( + artifactSearchResult.data[0].action.package ?? {}, + artifactSearchResult.data[0].artifact, + action.package, + ), + }; } private async finalizeIntention( diff --git a/src/util/action.util.ts b/src/util/action.util.ts index d7225900..68259be9 100644 --- a/src/util/action.util.ts +++ b/src/util/action.util.ts @@ -61,7 +61,7 @@ export class ActionUtil { const actionArr = action.split('#'); if (actionArr.length === 2) { if (actionArr[0] !== '') { - if (actionArr[0] in ACTION_NAMES) { + if (ACTION_NAMES.includes(actionArr[0] as any)) { actionOptions.action = actionArr[0] as ActionName; } else { throw new BadRequestException({ @@ -72,7 +72,10 @@ export class ActionUtil { } } actionOptions.id = actionArr[1]; - } else if (actionArr.length === 1 && actionArr[0] in ACTION_NAMES) { + } else if ( + actionArr.length === 1 && + ACTION_NAMES.includes(actionArr[0] as any) + ) { actionOptions.action = actionArr[0] as ActionName; } else { throw new BadRequestException({ @@ -102,7 +105,7 @@ export class ActionUtil { }); } - public actionToIdString(action: ActionEmbeddable) { + public actionToIdString(action: ActionEmbeddable | ActionDto) { return `${action.action}#${action.id}`; }