in src/extensions/extensionsHelper.ts [384:516]
export async function publishExtensionVersionFromLocalSource(args: {
publisherId: string;
extensionId: string;
rootDirectory: string;
nonInteractive: boolean;
force: boolean;
}): Promise<ExtensionVersion | undefined> {
const extensionSpec = await getLocalExtensionSpec(args.rootDirectory);
if (extensionSpec.name != args.extensionId) {
throw new FirebaseError(
`Extension ID '${clc.bold(
args.extensionId
)}' does not match the name in extension.yaml '${clc.bold(extensionSpec.name)}'.`
);
}
// Substitute deepcopied spec with autopopulated params, and make sure that it passes basic extension.yaml validation.
const subbedSpec = JSON.parse(JSON.stringify(extensionSpec));
subbedSpec.params = substituteParams<Param[]>(
extensionSpec.params || [],
AUTOPOULATED_PARAM_PLACEHOLDERS
);
validateSpec(subbedSpec);
let extension;
try {
extension = await getExtension(`${args.publisherId}/${args.extensionId}`);
} catch (err: any) {
// Silently fail and continue the publish flow if extension not found.
}
let notes: string;
try {
const changes = getLocalChangelog(args.rootDirectory);
notes = changes[extensionSpec.version];
} catch (err: any) {
throw new FirebaseError(
"No CHANGELOG.md file found. " +
"Please create one and add an entry for this version. " +
marked(
"See https://firebase.google.com/docs/extensions/alpha/create-user-docs#writing-changelog for more details."
)
);
}
if (!notes && extension) {
// If this is not the first version of this extension, we require release notes
throw new FirebaseError(
`No entry for version ${extensionSpec.version} found in CHANGELOG.md. ` +
"Please add one so users know what has changed in this version. " +
marked(
"See https://firebase.google.com/docs/extensions/alpha/create-user-docs#writing-changelog for more details."
)
);
}
displayReleaseNotes(args.publisherId, args.extensionId, extensionSpec.version, notes);
if (
!(await confirm({
nonInteractive: args.nonInteractive,
force: args.force,
default: false,
}))
) {
return;
}
if (
extension &&
extension.latestVersion &&
semver.lt(extensionSpec.version, extension.latestVersion)
) {
// publisher's version is less than current latest version.
throw new FirebaseError(
`The version you are trying to publish (${clc.bold(
extensionSpec.version
)}) is lower than the current version (${clc.bold(
extension.latestVersion
)}) for the extension '${clc.bold(
`${args.publisherId}/${args.extensionId}`
)}'. Please make sure this version is greater than the current version (${clc.bold(
extension.latestVersion
)}) inside of extension.yaml.\n`
);
} else if (
extension &&
extension.latestVersion &&
semver.eq(extensionSpec.version, extension.latestVersion)
) {
// publisher's version is equal to the current latest version.
throw new FirebaseError(
`The version you are trying to publish (${clc.bold(
extensionSpec.version
)}) already exists for the extension '${clc.bold(
`${args.publisherId}/${args.extensionId}`
)}'. Please increment the version inside of extension.yaml.\n`,
{ exit: 103 }
);
}
const ref = `${args.publisherId}/${args.extensionId}@${extensionSpec.version}`;
let packageUri: string;
let objectPath = "";
const uploadSpinner = ora(" Archiving and uploading extension source code");
try {
uploadSpinner.start();
objectPath = await archiveAndUploadSource(args.rootDirectory, EXTENSIONS_BUCKET_NAME);
uploadSpinner.succeed(" Uploaded extension source code");
packageUri = storageOrigin + objectPath + "?alt=media";
} catch (err: any) {
uploadSpinner.fail();
throw err;
}
const publishSpinner = ora(`Publishing ${clc.bold(ref)}`);
let res;
try {
publishSpinner.start();
res = await publishExtensionVersion(ref, packageUri);
publishSpinner.succeed(` Successfully published ${clc.bold(ref)}`);
} catch (err: any) {
publishSpinner.fail();
if (err.status == 404) {
throw new FirebaseError(
marked(
`Couldn't find publisher ID '${clc.bold(
args.publisherId
)}'. Please ensure that you have registered this ID. To register as a publisher, you can check out the [Firebase documentation](https://firebase.google.com/docs/extensions/alpha/share#register_as_an_extensions_publisher) for step-by-step instructions.`
)
);
}
throw err;
}
await deleteUploadedSource(objectPath);
return res;
}