Skip to content

Commit

Permalink
🚧Improve update json version process (#22)
Browse files Browse the repository at this point in the history
* Start work for issue #21

* enhance: add ability to use a json key path to the json version value

* cleanup: remove unused files

* refactor: change code to meeting coding standards

* chore: improve the setPropertyValue function
  • Loading branch information
CalvinWilkinson authored Jun 20, 2024
1 parent 7f35ca6 commit de793ab
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 111 deletions.
63 changes: 0 additions & 63 deletions .github/cicd/core/EnvVarService.ts

This file was deleted.

24 changes: 0 additions & 24 deletions .github/cicd/core/PATService.ts

This file was deleted.

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
56 changes: 41 additions & 15 deletions src/json-version-updater.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,71 @@
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<T extends { [key: string]: unknown }>(
obj: T,
propChain: string[],
newValue: string | number,
): [boolean, string | undefined] {
let currentObj: Record<string, unknown> = obj; // Start with the entire object

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.`];
}

currentObj = currentObj[propertyName] as Record<string, unknown>;
}

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

if (finalPropName in currentObj) {
(currentObj as Record<string, unknown>)[finalPropName] = newValue; // Set the new value
return [true, undefined];
}

return [false, `The property '${finalPropName}' does not exist.`];
}
}
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

0 comments on commit de793ab

Please sign in to comment.