Adds an --immediate flag to ext:uninstall which can be run outside a firebase project dir and immediately tears down GCP resources - #10921
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces an --immediate option to the ext:uninstall command, enabling immediate deletion of an extension instance and its associated GCP resources. The review feedback suggests several improvements: throwing a FirebaseError on deletion failure to ensure non-zero exit codes in CI environments, importing FirebaseError, adding a description to the new --immediate option, avoiding the use of any in catch clauses, and checking if the extension instance exists in the manifest before attempting removal to prevent blocking the teardown process.
| try { | ||
| await deleteInstance(projectId, instanceId); | ||
| } catch (err: any) { | ||
| logLabeledError( | ||
| logPrefix, | ||
| `Error when attempting deletion: ${err instanceof Error ? err.message : err.toString()}`, | ||
| ); | ||
| return; | ||
| } |
There was a problem hiding this comment.
- Correctness: Logging the error and returning
undefinedallows the command to exit with code0(success) even if the deletion failed. To ensure scripts and CI environments can detect failures, we should throw aFirebaseErrorinstead. - Style Guide Adherence: Use
unknowninstead ofanyin the catch clause to maintain type safety.
try {
await deleteInstance(projectId, instanceId);
} catch (err: unknown) {
throw new FirebaseError(
`Error when attempting deletion: ${err instanceof Error ? err.message : String(err)}`,
{ original: err instanceof Error ? err : undefined }
);
}
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| import { Options } from "../options"; | ||
| import { needProjectId } from "../projectUtils"; | ||
| import { confirm } from "../prompt"; |
There was a problem hiding this comment.
To support throwing a FirebaseError when deletion fails, we need to import FirebaseError from ../error.
| import { Options } from "../options"; | |
| import { needProjectId } from "../projectUtils"; | |
| import { confirm } from "../prompt"; | |
| import { Options } from "../options"; | |
| import { needProjectId } from "../projectUtils"; | |
| import { confirm } from "../prompt"; | |
| import { FirebaseError } from "../error"; |
| export const command = new Command("ext:uninstall <extensionInstanceId>") | ||
| .description("uninstall an extension that is installed in your Firebase project by instance ID") | ||
| .option("--local", "deprecated") | ||
| .option("--immediate", "") |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| let config; | ||
| try { | ||
| config = manifest.loadConfig(options); | ||
| } catch (err: any) { | ||
| logLabeledBullet( | ||
| logPrefix, | ||
| "No firebase.json found. Proceeding to immediate extension instance teardown.", | ||
| ); | ||
| } | ||
| if (config) { | ||
| manifest.removeFromManifest(instanceId, config); | ||
| } |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
a589fd1 to
338c91f
Compare
inlined
left a comment
There was a problem hiding this comment.
LGTM after you run the formatter.
| `Error when attempting deletion: ${err instanceof Error ? err.message : String(err)}`, | ||
| { original: err instanceof Error ? err : undefined } | ||
| ); | ||
| return; |
There was a problem hiding this comment.
What the heck does return after throw mean?
There was a problem hiding this comment.
it means i'm an idiot
546126a to
fd1d971
Compare
No description provided.