diff --git a/README.md b/README.md index 2630d0b3..66735550 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ You should use the class named sourceTracking ## TODO push: wait and ignoreWarnings logic -consolidate the conflict logic into SourceTrackingOperations. Should return a ChangeResult[] of the conflicts so commands can display. reorganize the getChanges logic to be more use-friendly (nonDeletes, option or to specify return structure) can migrate maxRevision.json to its new home after pushing ebikes, toolbelt shows no remote changes but STL shows the Admin Profile being changed diff --git a/src/commands/source/push.ts b/src/commands/source/push.ts index 37500d72..5e34d063 100644 --- a/src/commands/source/push.ts +++ b/src/commands/source/push.ts @@ -6,22 +6,32 @@ */ import { FlagsConfig, flags, SfdxCommand } from '@salesforce/command'; +import { Duration } from '@salesforce/kit'; import { SfdxProject, Org } from '@salesforce/core'; -import { FileResponse } from '@salesforce/source-deploy-retrieve'; +import { PushPullResponse } from '../../shared/types'; import { SourceTracking } from '../../sourceTracking'; import { writeConflictTable } from '../../writeConflictTable'; export default class SourcePush extends SfdxCommand { public static description = 'get local changes'; protected static readonly flagsConfig: FlagsConfig = { forceoverwrite: flags.boolean({ char: 'f', description: 'overwrite files without prompting' }), + // TODO: use shared flags from plugin-source + wait: flags.minutes({ + char: 'w', + default: Duration.minutes(33), + min: Duration.minutes(0), // wait=0 means deploy is asynchronous + description: 'tbd', + }), }; + protected static requiresUsername = true; protected static requiresProject = true; + protected project!: SfdxProject; // ok because requiresProject protected org!: Org; // ok because requiresUsername // eslint-disable-next-line @typescript-eslint/no-explicit-any - public async run(): Promise { + public async run(): Promise { const tracking = new SourceTracking({ org: this.org, project: this.project, @@ -35,7 +45,7 @@ export default class SourcePush extends SfdxCommand { } const deployResult = await tracking.deployLocalChanges({ ignoreWarnings: this.flags.ignorewarnings as boolean, - wait: this.flags.wait as number, + wait: this.flags.wait as Duration, }); // TODO: convert deployResult to the proper type @@ -44,6 +54,11 @@ export default class SourcePush extends SfdxCommand { this.ux.logJson(deployResult); } - return deployResult; + return deployResult.map((fileResponse) => ({ + state: fileResponse.state, + fullName: fileResponse.fullName, + type: fileResponse.type, + filePath: fileResponse.filePath, + })); } } diff --git a/src/shared/types.ts b/src/shared/types.ts index 8f7e4798..699bed3e 100644 --- a/src/shared/types.ts +++ b/src/shared/types.ts @@ -8,3 +8,5 @@ import { FileResponse } from '@salesforce/source-deploy-retrieve'; export type RemoteSyncInput = Pick; + +export type PushPullResponse = Pick; diff --git a/src/sourceTracking.ts b/src/sourceTracking.ts index 8d584dfb..6b5a70cb 100644 --- a/src/sourceTracking.ts +++ b/src/sourceTracking.ts @@ -6,6 +6,7 @@ */ import * as path from 'path'; import { NamedPackageDir, Logger, Org, SfdxProject } from '@salesforce/core'; +import { Duration } from '@salesforce/kit'; import { ComponentSet, MetadataResolver, @@ -29,6 +30,7 @@ export const getKeyFromObject = (element: RemoteChangeElement | ChangeResult): s // external users of SDR might need to convert a fileResponse to a key export const getKeyFromStrings = getMetadataKey; +export type ChangeOptionTypes = ChangeResult | SourceComponent | string; export interface ChangeOptions { origin?: 'local' | 'remote'; state: 'add' | 'delete' | 'changed' | 'unchanged' | 'moved'; @@ -71,8 +73,7 @@ export class SourceTracking { this.logger = Logger.childFromRoot('SourceTracking'); } - public async deployLocalChanges({ ignoreWarnings = false, wait = 33 }): Promise { - // TODO: this is basically the logic for a push + public async deployLocalChanges({ ignoreWarnings = false, wait = Duration.minutes(33) }): Promise { await this.ensureLocalTracking(); const [nonDeletes, deletes] = await Promise.all([ this.localRepo.getNonDeleteFilenames(), @@ -108,8 +109,8 @@ export class SourceTracking { .map((component) => componentSet.add(component, true)); // make SourceComponents from deletes and add to toDeploy - const deploy = await componentSet.deploy({ usernameOrConnection: this.username }); - const result = await deploy.pollStatus(); + const deploy = await componentSet.deploy({ usernameOrConnection: this.username, apiOptions: { ignoreWarnings } }); + const result = await deploy.pollStatus(30, wait.seconds); const successes = result.getFileResponses().filter((fileResponse) => fileResponse.state !== ComponentStatus.Failed); const successNonDeletes = successes.filter((fileResponse) => fileResponse.state !== ComponentStatus.Deleted);