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

🚧Improve update json version process #22

Merged
merged 5 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion prepare-release-settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@
"prTitle": "🚀Production Release - ${VERSION}"
}],
"githubTokenEnvVarName": "CICD_TOKEN",
"versionFilePath": "./deno.json"
"versionFilePath": "./deno.json",
"versionJSONKeyPath": "version"
}
8 changes: 5 additions & 3 deletions src/csharp-version-updater.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import { ParamGuards } from "./core/param-guards.ts";
import { existsSync } from "../deps.ts";
import { PrepareReleaseSettings } from "./prepare-release-settings.ts";

/**
* Updates versions in csharp project files.
*/
export class CSharpVersionUpdater {
/**
* Updates the version in the csharp project file at the given {@link versionFilePath}.
* @param versionFilePath The full or relative file path to the version file.
* @param settings The prepare release settings.
* @param newVersion The new version.
* @throws {Error} Thrown for the following reasons:
* 1. If the csproj file does not exist.
* 2. If the csproj file does not contain a version XML element.
* 3. If the csproj file does not contain a file version XML element.
*/
public updateVersion(versionFilePath: string, newVersion: string) {
ParamGuards.isNothing(versionFilePath, "versionFilePath null, empty, or undefined.");
public updateVersion(settings: PrepareReleaseSettings, newVersion: string) {
ParamGuards.isNothing(newVersion, "newVersion null, empty, or undefined.");

const versionFilePath = settings.versionFilePath ?? "";

if (!existsSync(versionFilePath, { isFile: true })) {
throw new Error(`The version file path '${versionFilePath}' does not exist.`);
}
Expand Down
62 changes: 47 additions & 15 deletions src/json-version-updater.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,77 @@
import { existsSync } from "../deps.ts";
import { ParamGuards } from "./core/param-guards.ts";
import { PrepareReleaseSettings } from "./prepare-release-settings.ts";

/**
* Updates the version in a JSON file.
*/
export class JsonVersionUpdater {
/**
* Updates the version in the JSON version file at the given {@link versionFilePath}.
* @param versionFilePath The full or relative file path to the version file.
* @param settings The prepare release settings.
* @param newVersion The new version.
* @throws {Error} Thrown if the version file does not exist or the version file does not contain a 'version' property.
*/
public updateVersion(versionFilePath: string, newVersion: string) {
ParamGuards.isNothing(versionFilePath, "versionFilePath null, empty, or undefined.");
public updateVersion(settings: PrepareReleaseSettings, newVersion: string) {
ParamGuards.isNothing(newVersion, "newVersion null, empty, or undefined.");

const versionFilePath = settings.versionFilePath ?? "";

if (!existsSync(versionFilePath, { isFile: true })) {
throw new Error(`The version file path does not exist: ${versionFilePath}`);
}

const versionFileContent = Deno.readTextFileSync(versionFilePath);
const versionConfig = JSON.parse(versionFileContent);

const versionConfig: { version: string } = JSON.parse(versionFileContent);
const propChain = settings.versionJSONKeyPath?.split(".").map((i) => i.trim()) ?? ["version"];

if (!this.containsVersionProp(versionConfig)) {
throw new Error(`The version file does not contain a version property: ${versionFilePath}`);
}
const result = this.setPropertyValue(versionConfig, propChain, newVersion);

versionConfig.version = newVersion;
if (result[0] === false) {
console.log(`%c${result[1]}`, "color: red;");
Deno.exit(1);
}

Deno.writeTextFileSync(versionFilePath, `${JSON.stringify(versionConfig, null, 4)}\n`);
}

/**
* Validates that the given {@link obj} contains a version property.
* @param obj The object to validate.
* @returns True if the object contains a version property; otherwise, false.
* Sets a property in the given {@link propChain} to the given {@link newValue}.
* @param obj The object that might contains the property to update.
* @param propChain The property chain path to the property to update.
* @param newValue The new value to set the last prop in the chain to.
* @returns A tuple where the first item is a boolean indicating if the property was set and the second item is an error message if the property was not set.
*/
private containsVersionProp(obj: unknown): obj is { version: string } {
return obj !== null &&
obj !== undefined &&
typeof obj === "object" && "version" in obj;
private setPropertyValue(obj: any, propChain: string[], newValue: string | number): [boolean, string | undefined] {
if (propChain.length === 0) {
return [false, ""];
}

let currentObj = obj;

for (let i = 0; i < propChain.length - 1; i++) {
const propertyName = propChain[i];

if (!(propertyName in currentObj)) {
return [false, `The property '${propertyName}' does not exist.`];
}

if (currentObj !== null && typeof currentObj === 'object') {
currentObj = currentObj[propertyName];
} else {
return [false, "Cannot set a value on a non-object"];
}
}

const lastPropName = propChain[propChain.length - 1];

if (!(lastPropName in currentObj)) {
return [false, `The property '${lastPropName}' does not exist.`];
}

currentObj[lastPropName] = newValue;

return [true, undefined];
}
}
5 changes: 5 additions & 0 deletions src/prepare-release-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@ export interface PrepareReleaseSettings {
* @remarks If undefined, null, or empty, then the version will not be updated.
*/
versionFilePath?: string;

/**
* Gets the dot separated path to the JSON key that contains the version.
*/
versionJSONKeyPath?: string;
}
12 changes: 7 additions & 5 deletions src/release-prepper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export class ReleasePrepper {

if (!Guards.isNothing(settings.versionFilePath)) {
try {
this.updateVersion(settings.versionFilePath, chosenVersion);
this.updateVersion(settings, chosenVersion);
} catch (error) {
console.log(crayon.lightRed(error.message));
}
Expand Down Expand Up @@ -208,22 +208,24 @@ export class ReleasePrepper {

/**
* Updates the version in the version file at the given {@link versionFilePath} to the given {@link newVersion}.
* @param versionFilePath The full or relative file path to the version file.
* @param settings The prepare release settings.
* @param newVersion The new version.
*/
private updateVersion(versionFilePath: string, newVersion: string) {
private updateVersion(settings: PrepareReleaseSettings, newVersion: string) {
const versionFilePath = settings.versionFilePath ?? "";

const extension = extname(versionFilePath).toLowerCase().trim();
newVersion = newVersion.trim();

switch (extension) {
case ".json": {
const jsonUpdater = new JsonVersionUpdater();
jsonUpdater.updateVersion(versionFilePath, newVersion);
jsonUpdater.updateVersion(settings, newVersion);
break;
}
case ".csproj": {
const csharpUpdater = new CSharpVersionUpdater();
csharpUpdater.updateVersion(versionFilePath, newVersion);
csharpUpdater.updateVersion(settings, newVersion);
break;
}
default: {
Expand Down
Loading