193 lines
5.8 KiB
TypeScript
193 lines
5.8 KiB
TypeScript
export const CURRENT_GITZONE_CLI_SCHEMA_VERSION = 2;
|
|
|
|
export interface ISmartconfigMigrationResult {
|
|
migrated: boolean;
|
|
fromVersion: number;
|
|
toVersion: number;
|
|
}
|
|
|
|
const CLI_NAMESPACE = "@git.zone/cli";
|
|
|
|
const isPlainObject = (value: unknown): value is Record<string, any> => {
|
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
};
|
|
|
|
const ensureObject = (parent: Record<string, any>, key: string): Record<string, any> => {
|
|
if (!isPlainObject(parent[key])) {
|
|
parent[key] = {};
|
|
}
|
|
return parent[key];
|
|
};
|
|
|
|
const migrateNamespaceKeys = (smartconfigJson: Record<string, any>): boolean => {
|
|
let migrated = false;
|
|
const migrations = [
|
|
{ oldKey: "gitzone", newKey: CLI_NAMESPACE },
|
|
{ oldKey: "tsdoc", newKey: "@git.zone/tsdoc" },
|
|
{ oldKey: "npmdocker", newKey: "@git.zone/tsdocker" },
|
|
{ oldKey: "npmci", newKey: "@ship.zone/szci" },
|
|
{ oldKey: "szci", newKey: "@ship.zone/szci" },
|
|
];
|
|
|
|
for (const { oldKey, newKey } of migrations) {
|
|
if (!isPlainObject(smartconfigJson[oldKey])) {
|
|
continue;
|
|
}
|
|
if (!isPlainObject(smartconfigJson[newKey])) {
|
|
smartconfigJson[newKey] = smartconfigJson[oldKey];
|
|
} else {
|
|
smartconfigJson[newKey] = {
|
|
...smartconfigJson[oldKey],
|
|
...smartconfigJson[newKey],
|
|
};
|
|
}
|
|
delete smartconfigJson[oldKey];
|
|
migrated = true;
|
|
}
|
|
|
|
return migrated;
|
|
};
|
|
|
|
const migrateToV2 = (smartconfigJson: Record<string, any>): boolean => {
|
|
const cliConfig = ensureObject(smartconfigJson, CLI_NAMESPACE);
|
|
const releaseConfig = ensureObject(cliConfig, "release");
|
|
|
|
let migrated = false;
|
|
const targets = ensureObject(releaseConfig, "targets");
|
|
const shipzoneConfig = smartconfigJson["@ship.zone/szci"];
|
|
|
|
if (isPlainObject(releaseConfig.git) && !isPlainObject(targets.git)) {
|
|
targets.git = releaseConfig.git;
|
|
delete releaseConfig.git;
|
|
migrated = true;
|
|
}
|
|
|
|
if (isPlainObject(releaseConfig.npm) && !isPlainObject(targets.npm)) {
|
|
targets.npm = releaseConfig.npm;
|
|
delete releaseConfig.npm;
|
|
migrated = true;
|
|
}
|
|
|
|
if (isPlainObject(releaseConfig.docker) && !isPlainObject(targets.docker)) {
|
|
targets.docker = releaseConfig.docker;
|
|
delete releaseConfig.docker;
|
|
migrated = true;
|
|
}
|
|
|
|
if (Array.isArray(releaseConfig.registries)) {
|
|
const npmTarget = ensureObject(targets, "npm");
|
|
if (!Array.isArray(npmTarget.registries)) {
|
|
npmTarget.registries = releaseConfig.registries;
|
|
}
|
|
delete releaseConfig.registries;
|
|
migrated = true;
|
|
}
|
|
|
|
if (releaseConfig.accessLevel) {
|
|
const npmTarget = ensureObject(targets, "npm");
|
|
if (!npmTarget.accessLevel) {
|
|
npmTarget.accessLevel = releaseConfig.accessLevel;
|
|
}
|
|
delete releaseConfig.accessLevel;
|
|
migrated = true;
|
|
}
|
|
|
|
if (isPlainObject(shipzoneConfig)) {
|
|
if (shipzoneConfig.npmAccessLevel) {
|
|
const npmTarget = ensureObject(targets, "npm");
|
|
if (!npmTarget.accessLevel) {
|
|
npmTarget.accessLevel = shipzoneConfig.npmAccessLevel;
|
|
}
|
|
delete shipzoneConfig.npmAccessLevel;
|
|
migrated = true;
|
|
}
|
|
|
|
if (shipzoneConfig.npmRegistryUrl) {
|
|
const npmTarget = ensureObject(targets, "npm");
|
|
const registry = normalizeRegistryUrl(shipzoneConfig.npmRegistryUrl);
|
|
const registries = Array.isArray(npmTarget.registries) ? npmTarget.registries : [];
|
|
if (!registries.includes(registry)) {
|
|
registries.push(registry);
|
|
}
|
|
npmTarget.registries = registries;
|
|
delete shipzoneConfig.npmRegistryUrl;
|
|
migrated = true;
|
|
}
|
|
}
|
|
|
|
if (Array.isArray(releaseConfig.steps)) {
|
|
const steps = releaseConfig.steps as string[];
|
|
const preflight = ensureObject(releaseConfig, "preflight");
|
|
if (steps.includes("test") && preflight.test === undefined) {
|
|
preflight.test = true;
|
|
}
|
|
if (steps.includes("build") && preflight.build === undefined) {
|
|
preflight.build = true;
|
|
}
|
|
if (steps.includes("push")) {
|
|
const gitTarget = ensureObject(targets, "git");
|
|
if (gitTarget.enabled === undefined) {
|
|
gitTarget.enabled = true;
|
|
}
|
|
}
|
|
if (steps.includes("publishNpm")) {
|
|
const npmTarget = ensureObject(targets, "npm");
|
|
if (npmTarget.enabled === undefined) {
|
|
npmTarget.enabled = true;
|
|
}
|
|
}
|
|
if (steps.includes("publishDocker")) {
|
|
const dockerTarget = ensureObject(targets, "docker");
|
|
if (dockerTarget.enabled === undefined) {
|
|
dockerTarget.enabled = true;
|
|
}
|
|
}
|
|
delete releaseConfig.steps;
|
|
migrated = true;
|
|
}
|
|
|
|
if (releaseConfig.changelog) {
|
|
delete releaseConfig.changelog;
|
|
migrated = true;
|
|
}
|
|
|
|
cliConfig.schemaVersion = 2;
|
|
return migrated || true;
|
|
};
|
|
|
|
const normalizeRegistryUrl = (url: string): string => {
|
|
let normalizedUrl = url.trim();
|
|
if (!normalizedUrl.startsWith("http://") && !normalizedUrl.startsWith("https://")) {
|
|
normalizedUrl = `https://${normalizedUrl}`;
|
|
}
|
|
return normalizedUrl.endsWith("/") ? normalizedUrl.slice(0, -1) : normalizedUrl;
|
|
};
|
|
|
|
export const migrateSmartconfigData = (
|
|
smartconfigJson: Record<string, any>,
|
|
targetVersion = CURRENT_GITZONE_CLI_SCHEMA_VERSION,
|
|
): ISmartconfigMigrationResult => {
|
|
let migrated = false;
|
|
migrated = migrateNamespaceKeys(smartconfigJson) || migrated;
|
|
|
|
const cliConfig = ensureObject(smartconfigJson, CLI_NAMESPACE);
|
|
const fromVersion = typeof cliConfig.schemaVersion === "number" ? cliConfig.schemaVersion : 1;
|
|
let currentVersion = fromVersion;
|
|
|
|
if (currentVersion < 2 && targetVersion >= 2) {
|
|
migrated = migrateToV2(smartconfigJson) || migrated;
|
|
currentVersion = 2;
|
|
}
|
|
|
|
if (targetVersion === CURRENT_GITZONE_CLI_SCHEMA_VERSION && cliConfig.schemaVersion !== targetVersion) {
|
|
cliConfig.schemaVersion = targetVersion;
|
|
migrated = true;
|
|
}
|
|
|
|
return {
|
|
migrated,
|
|
fromVersion,
|
|
toVersion: Math.min(targetVersion, CURRENT_GITZONE_CLI_SCHEMA_VERSION),
|
|
};
|
|
};
|