Skip to content
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

fix: don't throw when 15 char job ID not in cache #884

Merged
merged 8 commits into from
Jan 30, 2024
Merged
4 changes: 2 additions & 2 deletions src/commands/project/deploy/cancel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export default class DeployMetadataCancel extends SfCommand<DeployResultJson> {
const jobId = cache.resolveLatest(flags['use-most-recent'], flags['job-id']);

// cancel don't care about your tracking conflicts
const deployOpts = { ...cache.get(jobId), 'ignore-conflicts': true };
const deployOpts = { ...cache.maybeGet(jobId), 'ignore-conflicts': true };
// we may already know the job finished
if (
deployOpts.status &&
Expand All @@ -80,7 +80,7 @@ export default class DeployMetadataCancel extends SfCommand<DeployResultJson> {
if (!this.jsonEnabled()) formatter.display();
return formatter.getJson();
} else {
const wait = flags.wait ?? Duration.minutes(deployOpts.wait);
const wait = flags.wait ?? Duration.minutes(deployOpts.wait ?? 33);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we update the command help for cancel, report, and resume to note the 33 minute default?

const result = await cancelDeploy({ ...deployOpts, wait }, jobId);
const formatter = new DeployCancelResultFormatter(result);
if (!this.jsonEnabled()) formatter.display();
Expand Down
2 changes: 1 addition & 1 deletion src/commands/project/deploy/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export default class DeployMetadataReport extends SfCommand<DeployResultJson> {
// if we're using mdapi we won't have a component set
let componentSet = new ComponentSet();
if (!deployOpts?.isMdapi) {
if (!cache.get(jobId)) {
if (!cache.maybeGet(jobId)) {
// If the cache file isn't there, use the project package directories for the CompSet
try {
this.project = await SfProject.resolve();
Expand Down
11 changes: 5 additions & 6 deletions src/commands/project/deploy/resume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/



import chalk from 'chalk';
import { EnvironmentVariable, Messages, Org, SfError } from '@salesforce/core';
import { SfCommand, toHelpSection, Flags } from '@salesforce/sf-plugins-core';
Expand All @@ -20,7 +18,7 @@ import { DeployCache } from '../../../utils/deployCache.js';
import { DEPLOY_STATUS_CODES_DESCRIPTIONS } from '../../../utils/errorCodes.js';
import { coverageFormattersFlag } from '../../../utils/flags.js';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url)
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-deploy-retrieve', 'deploy.metadata.resume');

const testFlags = 'Test';
Expand Down Expand Up @@ -83,10 +81,10 @@ export default class DeployMetadataResume extends SfCommand<DeployResultJson> {

public async run(): Promise<DeployResultJson> {
const [{ flags }, cache] = await Promise.all([this.parse(DeployMetadataResume), DeployCache.create()]);
const jobId = cache.resolveLatest(flags['use-most-recent'], flags['job-id']);
const jobId = cache.resolveLatest(flags['use-most-recent'], flags['job-id'], true);

// if it was async before, then it should not be async now.
const deployOpts = { ...cache.get(jobId), async: false };
const deployOpts = { ...cache.maybeGet(jobId), async: false };

let result: DeployResult;

Expand All @@ -108,7 +106,7 @@ export default class DeployMetadataResume extends SfCommand<DeployResultJson> {
const deployStatus = await mdapiDeploy.checkStatus();
result = new DeployResult(deployStatus, componentSet);
} else {
const wait = flags.wait ?? Duration.minutes(deployOpts.wait);
const wait = flags.wait ?? Duration.minutes(deployOpts.wait ?? 33);
const { deploy } = await executeDeploy(
// there will always be conflicts on a resume if anything deployed--the changes on the server are not synced to local
{
Expand All @@ -134,6 +132,7 @@ export default class DeployMetadataResume extends SfCommand<DeployResultJson> {
if (!deploy.id) {
throw new SfError('The deploy id is not available.');
}

cache.update(deploy.id, { status: result.response.status });
await cache.write();
}
Expand Down
41 changes: 27 additions & 14 deletions src/utils/deployCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,21 @@ export class DeployCache extends TTLConfig<TTLConfig.Options, CachedOptions> {

public static async unset(key: string): Promise<void> {
const cache = await DeployCache.create();
cache.unset(key);
cache.unset(ensure18(key, cache));
await Promise.all([cache.write(), maybeDestroyManifest(key)]);
}

public static async update(key: string, obj: JsonMap): Promise<void> {
const cache = await DeployCache.create();
cache.update(key, obj);
cache.update(ensure18(key, cache), obj);
await cache.write();
}

public update(key: string, obj: JsonMap): void {
super.update(ensure18(key, this), obj);
}

/** will return an 18 character ID if throwOnNotFound is true (because the cache can be used to shift 15 to 18) */
public resolveLatest(useMostRecent: boolean, key: string | undefined, throwOnNotFound?: boolean): string {
const resolvedKey = useMostRecent ? this.getLatestKey() : key;
if (!resolvedKey) throw cacheMessages.createError('error.NoRecentJobId');
Expand All @@ -61,7 +66,7 @@ export class DeployCache extends TTLConfig<TTLConfig.Options, CachedOptions> {
throw cacheMessages.createError('error.NoMatchingJobId', [resolvedKey]);
}

return resolvedKey;
return throwOnNotFound ? ensure18(resolvedKey, this) : resolvedKey;
}

/**
Expand All @@ -70,17 +75,7 @@ export class DeployCache extends TTLConfig<TTLConfig.Options, CachedOptions> {
* returns 15-char ID if it matches a key in the cache, otherwise throws
*/
public resolveLongId(jobId: string): string {
if (jobId.length === 18) {
return jobId;
} else if (jobId.length === 15) {
const match = this.keys().find((k) => k.startsWith(jobId));
if (match) {
return match;
}
throw cacheMessages.createError('error.NoMatchingJobId', [jobId]);
} else {
throw cacheMessages.createError('error.InvalidJobId', [jobId]);
}
return ensure18(jobId, this);
}

/**
Expand All @@ -107,3 +102,21 @@ export class DeployCache extends TTLConfig<TTLConfig.Options, CachedOptions> {
throw cacheMessages.createError('error.InvalidJobId', [jobId]);
}
}

/**
* if the jobId is 15 characters, use the cache to convert to 18
* will throw if the value is not in the cache
*/
const ensure18 = (jobId: string, cache: DeployCache): string => {
if (jobId.length === 18) {
return jobId;
} else if (jobId.length === 15) {
const match = cache.keys().find((k) => k.startsWith(jobId));
if (match) {
return match;
}
throw cacheMessages.createError('error.NoMatchingJobId', [jobId]);
} else {
throw cacheMessages.createError('error.InvalidJobId', [jobId]);
}
};
Loading