From 8fd79c545990caf8e47a9fbd1bcb33472837ba1a Mon Sep 17 00:00:00 2001 From: Jeffrey Lau <> Date: Thu, 6 Apr 2023 16:06:23 -0700 Subject: [PATCH 1/9] Adding three functions that I need for CI scripts that are used in OLC --- packages/wonder-stuff-ci/CHANGELOG.md | 5 ++ packages/wonder-stuff-ci/README.md | 3 + packages/wonder-stuff-ci/package.json | 20 +++++ .../src/__tests__/release-utils.test.ts | 87 +++++++++++++++++++ packages/wonder-stuff-ci/src/exec-prom.ts | 41 +++++++++ packages/wonder-stuff-ci/src/release-utils.ts | 70 +++++++++++++++ packages/wonder-stuff-ci/tsconfig.json | 10 +++ tsconfig-build.json | 1 + yarn.lock | 5 ++ 9 files changed, 242 insertions(+) create mode 100644 packages/wonder-stuff-ci/CHANGELOG.md create mode 100644 packages/wonder-stuff-ci/README.md create mode 100644 packages/wonder-stuff-ci/package.json create mode 100644 packages/wonder-stuff-ci/src/__tests__/release-utils.test.ts create mode 100644 packages/wonder-stuff-ci/src/exec-prom.ts create mode 100644 packages/wonder-stuff-ci/src/release-utils.ts create mode 100644 packages/wonder-stuff-ci/tsconfig.json diff --git a/packages/wonder-stuff-ci/CHANGELOG.md b/packages/wonder-stuff-ci/CHANGELOG.md new file mode 100644 index 00000000..3bc24a80 --- /dev/null +++ b/packages/wonder-stuff-ci/CHANGELOG.md @@ -0,0 +1,5 @@ +# @khanacademy/wonder-stuff-ci + +## 0.0.1 + +- Initial commit of porting over OLC functions for mobile release management diff --git a/packages/wonder-stuff-ci/README.md b/packages/wonder-stuff-ci/README.md new file mode 100644 index 00000000..50b6f03c --- /dev/null +++ b/packages/wonder-stuff-ci/README.md @@ -0,0 +1,3 @@ +# wonder-stuff-ci + +This Wonder Stuff package contains functions for creating automation and scripts. diff --git a/packages/wonder-stuff-ci/package.json b/packages/wonder-stuff-ci/package.json new file mode 100644 index 00000000..f8529b35 --- /dev/null +++ b/packages/wonder-stuff-ci/package.json @@ -0,0 +1,20 @@ +{ + "publishConfig": { + "access": "public" + }, + "engines": { + "node": ">=16" + }, + "name": "@khanacademy/wonder-stuff-ci", + "version": "0.0.1", + "description": "Functions for creating automation and scripts.", + "scripts": { + "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'" + }, + "devDependencies": { + "@types/node": "^18.15.11", + "ws-dev-build-settings": "^1.1.0" + }, + "author": "", + "license": "MIT" +} diff --git a/packages/wonder-stuff-ci/src/__tests__/release-utils.test.ts b/packages/wonder-stuff-ci/src/__tests__/release-utils.test.ts new file mode 100644 index 00000000..efdba9b9 --- /dev/null +++ b/packages/wonder-stuff-ci/src/__tests__/release-utils.test.ts @@ -0,0 +1,87 @@ +import {compareVersions, isGetReleaseBranch} from "../release-utils"; + +describe("#compareVersions", () => { + it.each(["7.8.1", "7.9.0", "7.10.0", "8.0.0"])( + "return 1 if version 1 is greater than version 2", + (testCase: any) => { + // Arrange + const version1 = testCase; + const version2 = "7.8.0"; + + // Act + const result = compareVersions(version1, version2); + + // Assert + expect(result).toBe(1); + }, + ); + + it.each(["7.7.1", "7.6.0", "6.10.0"])( + "return -1 if version 1 is less than version 2", + (testCase: any) => { + // Arrange + const version1 = testCase; + const version2 = "7.8.0"; + + // Act + const result = compareVersions(version1, version2); + + // Assert + expect(result).toBe(-1); + }, + ); + + it("return 0 if version 1 is equal to version 2", () => { + // Arrange + const version1 = "7.8.0"; + const version2 = "7.8.0"; + + // Act + const result = compareVersions(version1, version2); + + // Assert + expect(result).toBe(0); + }); +}); + +describe("#isGetReleaseBranch", () => { + it.each([ + "release/unified/7.8.0", + "release/android/7.8.0", + "release/ios/7.8.0", + ])("get the version from the release branch", (testCase: any) => { + // Arrange + const releaseBranch = testCase; + + // Act + const result = isGetReleaseBranch(releaseBranch); + + // Assert + expect(result?.version).toBe("7.8.0"); + }); + + it.each(["release/testing", "android/7.8.0", "ios/7.8.0"])( + "return null if the branch is not a release branch", + (testCase: any) => { + // Arrange + const releaseBranch = testCase; + + // Act + const result = isGetReleaseBranch(releaseBranch); + + // Assert + expect(result).toBe(null); + }, + ); + + it("get the correct prefix string", () => { + // Arrange + const branchName = "release/unified/7.8.0"; + + // Act + const result = isGetReleaseBranch(branchName); + + // Assert + expect(result?.prefix).toBe("release/unified/"); + }); +}); diff --git a/packages/wonder-stuff-ci/src/exec-prom.ts b/packages/wonder-stuff-ci/src/exec-prom.ts new file mode 100644 index 00000000..c7cb3f43 --- /dev/null +++ b/packages/wonder-stuff-ci/src/exec-prom.ts @@ -0,0 +1,41 @@ +/** + * A simple promisified version of child_process.exec, so we can `await` it + */ +import {exec, ExecOptions} from "child_process"; + +export const bufferToString = (input: Buffer | string): string => { + if (typeof input === "string") { + return input; + } else { + return input.toString("utf8"); + } +}; + +const execProm = ( + command: string, + rejectOnError: boolean, + options?: ExecOptions, +): Promise<{ + err: Error | null | undefined; + stdout: string; + stderr: string; +}> => + new Promise((res, rej) => + exec(command, options, (err, stdout, stderr) => + err + ? rejectOnError + ? rej(err) + : res({ + err, + stdout: bufferToString(stdout), + stderr: bufferToString(stderr), + }) + : res({ + err: null, + stdout: bufferToString(stdout), + stderr: bufferToString(stderr), + }), + ), + ); + +export default execProm; diff --git a/packages/wonder-stuff-ci/src/release-utils.ts b/packages/wonder-stuff-ci/src/release-utils.ts new file mode 100644 index 00000000..ef768de1 --- /dev/null +++ b/packages/wonder-stuff-ci/src/release-utils.ts @@ -0,0 +1,70 @@ +import execProm from "./exec-prom"; + +/** + * + * @returns all release tags sorted creation time ascending + */ +const getReleaseTags = async (): Promise> => { + const tags = await allReleaseTags(); + return tags + .filter((tag) => + tag.match(/^(ios|android|unified)-(\d+\.\d+\.\d+(-\w*)*)$/i), + ) + .sort(compareVersions); +}; + +/** + * Compares two versions of the form .. + * @param v1 + * @param v2 + * @returns int, 1 if v1 > v2, -1 if v1 < v2, 0 if v1 == v2 + */ +export const compareVersions = (v1: string, v2: string) => { + const v1v = v1.includes("-") ? v1.split("-")[1] : v1; + const v2v = v2.includes("-") ? v2.split("-")[1] : v2; + const v1p = v1v.replace(/^v/g, "").split("."); + const v2p = v2v.replace(/^v/g, "").split("."); + for (let i = 0; i < v1p.length || i < v2p.length; i++) { + const p1 = +v1p[i] || 0; + const p2 = +v2p[i] || 0; + if (+p1 !== +p2) { + return p1 > p2 ? 1 : -1; + } + } + return 0; +}; + +/** + * Matches [release/[unified|ios|android]]/[v]..[-extra] + * @param arg + * @returns match, if found, null otherwise + */ +export const isGetReleaseBranch = (arg: string) => { + if (!arg) { + return null; + } + + const match = arg.match( + /^(release\/(ios|android|unified)\/)?v?(\d+\.\d+\.\d+(-\w*)*)$/i, + ); + return match && match.length >= 3 && match[3] + ? {prefix: match[1] || "release/unified/", version: match[3]} + : null; +}; + +/** + * + * @returns all release tags sorted creation time ascending + */ +const allReleaseTags = async (): Promise> => { + // Why not use simple-git here? Because for some reason it takes like 100x as long. + await execProm("git fetch --tags", true); + const prom: Promise<{ + err: Error | null | undefined; + stdout: string; + stderr: string; + }> = execProm("git tag | grep -E -i -w 'ios|android|unified'", true); + + const {stdout} = await prom; + return stdout.split("\n").filter(Boolean); +}; diff --git a/packages/wonder-stuff-ci/tsconfig.json b/packages/wonder-stuff-ci/tsconfig.json new file mode 100644 index 00000000..9f1ca95e --- /dev/null +++ b/packages/wonder-stuff-ci/tsconfig.json @@ -0,0 +1,10 @@ +{ + "exclude": ["dist"], + "extends": "../tsconfig-shared.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + }, + "references": [ + ] +} diff --git a/tsconfig-build.json b/tsconfig-build.json index 6b7ee573..428dc9f7 100644 --- a/tsconfig-build.json +++ b/tsconfig-build.json @@ -12,5 +12,6 @@ {"path": "./packages/wonder-stuff-sentry"}, {"path": "./packages/wonder-stuff-server"}, {"path": "./packages/wonder-stuff-testing"}, + {"path": "./packages/wonder-stuff-ci"}, ], } diff --git a/yarn.lock b/yarn.lock index 01c7c854..a50397f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2289,6 +2289,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== +"@types/node@^18.15.11": + version "18.15.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" + integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== + "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" From b4a779ed317859d81b6cf117f52572112130602b Mon Sep 17 00:00:00 2001 From: Jeffrey Lau <> Date: Fri, 7 Apr 2023 11:01:26 -0700 Subject: [PATCH 2/9] updated the PR based on comments --- packages/wonder-stuff-ci/CHANGELOG.md | 5 ----- packages/wonder-stuff-ci/package.json | 3 +++ ...ase-utils.test.ts => mobile-release-utils.test.ts} | 11 +++++++---- packages/wonder-stuff-ci/src/exec-prom.ts | 2 +- packages/wonder-stuff-ci/src/index.ts | 6 ++++++ .../src/{release-utils.ts => mobile-release-utils.ts} | 8 ++++---- 6 files changed, 21 insertions(+), 14 deletions(-) delete mode 100644 packages/wonder-stuff-ci/CHANGELOG.md rename packages/wonder-stuff-ci/src/__tests__/{release-utils.test.ts => mobile-release-utils.test.ts} (87%) create mode 100644 packages/wonder-stuff-ci/src/index.ts rename packages/wonder-stuff-ci/src/{release-utils.ts => mobile-release-utils.ts} (88%) diff --git a/packages/wonder-stuff-ci/CHANGELOG.md b/packages/wonder-stuff-ci/CHANGELOG.md deleted file mode 100644 index 3bc24a80..00000000 --- a/packages/wonder-stuff-ci/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# @khanacademy/wonder-stuff-ci - -## 0.0.1 - -- Initial commit of porting over OLC functions for mobile release management diff --git a/packages/wonder-stuff-ci/package.json b/packages/wonder-stuff-ci/package.json index f8529b35..2a23b84b 100644 --- a/packages/wonder-stuff-ci/package.json +++ b/packages/wonder-stuff-ci/package.json @@ -8,6 +8,9 @@ "name": "@khanacademy/wonder-stuff-ci", "version": "0.0.1", "description": "Functions for creating automation and scripts.", + "module": "dist/es/index.js", + "main": "dist/index.js", + "types": "dist/index.d.ts", "scripts": { "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'" }, diff --git a/packages/wonder-stuff-ci/src/__tests__/release-utils.test.ts b/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts similarity index 87% rename from packages/wonder-stuff-ci/src/__tests__/release-utils.test.ts rename to packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts index efdba9b9..0d819721 100644 --- a/packages/wonder-stuff-ci/src/__tests__/release-utils.test.ts +++ b/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts @@ -1,4 +1,7 @@ -import {compareVersions, isGetReleaseBranch} from "../release-utils"; +import { + compareVersions, + extractMobileReleaseBranch, +} from "../mobile-release-utils"; describe("#compareVersions", () => { it.each(["7.8.1", "7.9.0", "7.10.0", "8.0.0"])( @@ -54,7 +57,7 @@ describe("#isGetReleaseBranch", () => { const releaseBranch = testCase; // Act - const result = isGetReleaseBranch(releaseBranch); + const result = extractMobileReleaseBranch(releaseBranch); // Assert expect(result?.version).toBe("7.8.0"); @@ -67,7 +70,7 @@ describe("#isGetReleaseBranch", () => { const releaseBranch = testCase; // Act - const result = isGetReleaseBranch(releaseBranch); + const result = extractMobileReleaseBranch(releaseBranch); // Assert expect(result).toBe(null); @@ -79,7 +82,7 @@ describe("#isGetReleaseBranch", () => { const branchName = "release/unified/7.8.0"; // Act - const result = isGetReleaseBranch(branchName); + const result = extractMobileReleaseBranch(branchName); // Assert expect(result?.prefix).toBe("release/unified/"); diff --git a/packages/wonder-stuff-ci/src/exec-prom.ts b/packages/wonder-stuff-ci/src/exec-prom.ts index c7cb3f43..3fcbf3b6 100644 --- a/packages/wonder-stuff-ci/src/exec-prom.ts +++ b/packages/wonder-stuff-ci/src/exec-prom.ts @@ -11,7 +11,7 @@ export const bufferToString = (input: Buffer | string): string => { } }; -const execProm = ( +export const execProm = ( command: string, rejectOnError: boolean, options?: ExecOptions, diff --git a/packages/wonder-stuff-ci/src/index.ts b/packages/wonder-stuff-ci/src/index.ts new file mode 100644 index 00000000..61a7318c --- /dev/null +++ b/packages/wonder-stuff-ci/src/index.ts @@ -0,0 +1,6 @@ +export { + getMobileReleaseTags, + extractMobileReleaseBranch, + compareVersions, +} from "./mobile-release-utils"; +export {execProm, bufferToString} from "./exec-prom"; diff --git a/packages/wonder-stuff-ci/src/release-utils.ts b/packages/wonder-stuff-ci/src/mobile-release-utils.ts similarity index 88% rename from packages/wonder-stuff-ci/src/release-utils.ts rename to packages/wonder-stuff-ci/src/mobile-release-utils.ts index ef768de1..de804730 100644 --- a/packages/wonder-stuff-ci/src/release-utils.ts +++ b/packages/wonder-stuff-ci/src/mobile-release-utils.ts @@ -4,8 +4,8 @@ import execProm from "./exec-prom"; * * @returns all release tags sorted creation time ascending */ -const getReleaseTags = async (): Promise> => { - const tags = await allReleaseTags(); +export const getMobileReleaseTags = async (): Promise> => { + const tags = await allMobileReleaseTags(); return tags .filter((tag) => tag.match(/^(ios|android|unified)-(\d+\.\d+\.\d+(-\w*)*)$/i), @@ -39,7 +39,7 @@ export const compareVersions = (v1: string, v2: string) => { * @param arg * @returns match, if found, null otherwise */ -export const isGetReleaseBranch = (arg: string) => { +export const extractMobileReleaseBranch = (arg: string) => { if (!arg) { return null; } @@ -56,7 +56,7 @@ export const isGetReleaseBranch = (arg: string) => { * * @returns all release tags sorted creation time ascending */ -const allReleaseTags = async (): Promise> => { +const allMobileReleaseTags = async (): Promise> => { // Why not use simple-git here? Because for some reason it takes like 100x as long. await execProm("git fetch --tags", true); const prom: Promise<{ From ccc5a169f48de1c1dfe5ec97f4031a7a1af3a301 Mon Sep 17 00:00:00 2001 From: Jeffrey Lau <> Date: Fri, 7 Apr 2023 11:24:02 -0700 Subject: [PATCH 3/9] adding changeset record --- .changeset/clean-houses-press.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/clean-houses-press.md diff --git a/.changeset/clean-houses-press.md b/.changeset/clean-houses-press.md new file mode 100644 index 00000000..4e86f9c9 --- /dev/null +++ b/.changeset/clean-houses-press.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/wonder-stuff-ci": patch +--- + +Adding a new wonder-stuff-ci package that contains functions that are useful for the mobile release. From afb8d7daa129f028355f5e1cacf7ab31949e6194 Mon Sep 17 00:00:00 2001 From: Jeffrey Lau <> Date: Fri, 7 Apr 2023 14:50:07 -0700 Subject: [PATCH 4/9] added more unit tests --- .../src/__tests__/exec-prom.test.ts | 18 ++++++++++++ .../__tests__/mobile-release-git-util.test.ts | 22 +++++++++++++++ .../__tests__/mobile-release-utils.test.ts | 22 +++++++++++++++ packages/wonder-stuff-ci/src/exec-prom.ts | 28 ++----------------- .../src/mobile-release-git-utils.ts | 14 ++++++++++ .../src/mobile-release-utils.ts | 20 ++----------- 6 files changed, 80 insertions(+), 44 deletions(-) create mode 100644 packages/wonder-stuff-ci/src/__tests__/exec-prom.test.ts create mode 100644 packages/wonder-stuff-ci/src/__tests__/mobile-release-git-util.test.ts create mode 100644 packages/wonder-stuff-ci/src/mobile-release-git-utils.ts diff --git a/packages/wonder-stuff-ci/src/__tests__/exec-prom.test.ts b/packages/wonder-stuff-ci/src/__tests__/exec-prom.test.ts new file mode 100644 index 00000000..62133759 --- /dev/null +++ b/packages/wonder-stuff-ci/src/__tests__/exec-prom.test.ts @@ -0,0 +1,18 @@ +import {buffer} from "stream/consumers"; +import {execProm, bufferToString} from "../exec-prom"; + +describe("#bufferToString", () => { + it.each(["testing", Buffer.from("testing")])( + "the buffer to string function returns the correct value", + (testCase: any) => { + // Arrange + const input = testCase; + + // Act + const result = bufferToString(input); + + // Assert + expect(result).toBe("testing"); + }, + ); +}); diff --git a/packages/wonder-stuff-ci/src/__tests__/mobile-release-git-util.test.ts b/packages/wonder-stuff-ci/src/__tests__/mobile-release-git-util.test.ts new file mode 100644 index 00000000..127055f9 --- /dev/null +++ b/packages/wonder-stuff-ci/src/__tests__/mobile-release-git-util.test.ts @@ -0,0 +1,22 @@ +import {allMobileReleaseTags} from "../mobile-release-git-utils"; +import execProm from "../exec-prom"; + +jest.mock("../exec-prom"); + +describe("#allMobileReleaseTags", () => { + it("return an array of release tags split by new line", async () => { + // Arrange + jest.spyOn(require("../exec-prom"), "execProm").mockReturnValue({ + stdout: "android-7.10.0\nunified-7.8.0\nunified-7.9.0", + }); + // Act + const result = await allMobileReleaseTags(); + + // Assert + expect(result).toStrictEqual([ + "android-7.10.0", + "unified-7.8.0", + "unified-7.9.0", + ]); + }); +}); diff --git a/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts b/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts index 0d819721..3251fb2e 100644 --- a/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts +++ b/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts @@ -1,7 +1,9 @@ import { compareVersions, extractMobileReleaseBranch, + getMobileReleaseTags, } from "../mobile-release-utils"; +import {allMobileReleaseTags} from "../mobile-release-git-utils"; describe("#compareVersions", () => { it.each(["7.8.1", "7.9.0", "7.10.0", "8.0.0"])( @@ -88,3 +90,23 @@ describe("#isGetReleaseBranch", () => { expect(result?.prefix).toBe("release/unified/"); }); }); + +describe("#getMobileReleaseTags", () => { + it("get the tags in sorted order by ascending version value", async () => { + // Arrange + + jest.spyOn( + require("../mobile-release-git-utils"), + "allMobileReleaseTags", + ).mockReturnValue(["android-7.10.0", "unified-7.8.0", "unified-7.9.0"]); + // Act + const result = await getMobileReleaseTags(); + + // Assert + expect(result).toStrictEqual([ + "unified-7.8.0", + "unified-7.9.0", + "android-7.10.0", + ]); + }); +}); diff --git a/packages/wonder-stuff-ci/src/exec-prom.ts b/packages/wonder-stuff-ci/src/exec-prom.ts index 3fcbf3b6..100c4095 100644 --- a/packages/wonder-stuff-ci/src/exec-prom.ts +++ b/packages/wonder-stuff-ci/src/exec-prom.ts @@ -2,6 +2,7 @@ * A simple promisified version of child_process.exec, so we can `await` it */ import {exec, ExecOptions} from "child_process"; +import util from "util"; export const bufferToString = (input: Buffer | string): string => { if (typeof input === "string") { @@ -11,31 +12,6 @@ export const bufferToString = (input: Buffer | string): string => { } }; -export const execProm = ( - command: string, - rejectOnError: boolean, - options?: ExecOptions, -): Promise<{ - err: Error | null | undefined; - stdout: string; - stderr: string; -}> => - new Promise((res, rej) => - exec(command, options, (err, stdout, stderr) => - err - ? rejectOnError - ? rej(err) - : res({ - err, - stdout: bufferToString(stdout), - stderr: bufferToString(stderr), - }) - : res({ - err: null, - stdout: bufferToString(stdout), - stderr: bufferToString(stderr), - }), - ), - ); +export const execProm = util.promisify(exec); export default execProm; diff --git a/packages/wonder-stuff-ci/src/mobile-release-git-utils.ts b/packages/wonder-stuff-ci/src/mobile-release-git-utils.ts new file mode 100644 index 00000000..3fc2024e --- /dev/null +++ b/packages/wonder-stuff-ci/src/mobile-release-git-utils.ts @@ -0,0 +1,14 @@ +import execProm from "./exec-prom"; + +/** + * + * @returns all release tags sorted creation time ascending + */ +export const allMobileReleaseTags = async (): Promise> => { + // Why not use simple-git here? Because for some reason it takes like 100x as long. + await execProm("git fetch --tags"); + const {stdout} = await execProm( + "git tag | grep -E -i -w 'ios|android|unified'", + ); + return stdout.split("\n").filter(Boolean); +}; diff --git a/packages/wonder-stuff-ci/src/mobile-release-utils.ts b/packages/wonder-stuff-ci/src/mobile-release-utils.ts index de804730..3e4f5512 100644 --- a/packages/wonder-stuff-ci/src/mobile-release-utils.ts +++ b/packages/wonder-stuff-ci/src/mobile-release-utils.ts @@ -1,4 +1,5 @@ import execProm from "./exec-prom"; +import { allMobileReleaseTags } from "./mobile-release-git-utils"; /** * @@ -50,21 +51,4 @@ export const extractMobileReleaseBranch = (arg: string) => { return match && match.length >= 3 && match[3] ? {prefix: match[1] || "release/unified/", version: match[3]} : null; -}; - -/** - * - * @returns all release tags sorted creation time ascending - */ -const allMobileReleaseTags = async (): Promise> => { - // Why not use simple-git here? Because for some reason it takes like 100x as long. - await execProm("git fetch --tags", true); - const prom: Promise<{ - err: Error | null | undefined; - stdout: string; - stderr: string; - }> = execProm("git tag | grep -E -i -w 'ios|android|unified'", true); - - const {stdout} = await prom; - return stdout.split("\n").filter(Boolean); -}; +}; \ No newline at end of file From c9a0fedb38c6ce70fad0a3c63311f5808c67f5a3 Mon Sep 17 00:00:00 2001 From: Jeffrey Lau <> Date: Fri, 7 Apr 2023 15:00:36 -0700 Subject: [PATCH 5/9] updated based on pr comments --- packages/wonder-stuff-ci/src/exec-prom.ts | 6 +----- packages/wonder-stuff-ci/src/mobile-release-utils.ts | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/wonder-stuff-ci/src/exec-prom.ts b/packages/wonder-stuff-ci/src/exec-prom.ts index 100c4095..65ae14d6 100644 --- a/packages/wonder-stuff-ci/src/exec-prom.ts +++ b/packages/wonder-stuff-ci/src/exec-prom.ts @@ -5,11 +5,7 @@ import {exec, ExecOptions} from "child_process"; import util from "util"; export const bufferToString = (input: Buffer | string): string => { - if (typeof input === "string") { - return input; - } else { - return input.toString("utf8"); - } + return typeof input === "string" ? input : input.toString("utf8"); }; export const execProm = util.promisify(exec); diff --git a/packages/wonder-stuff-ci/src/mobile-release-utils.ts b/packages/wonder-stuff-ci/src/mobile-release-utils.ts index 3e4f5512..c3afd706 100644 --- a/packages/wonder-stuff-ci/src/mobile-release-utils.ts +++ b/packages/wonder-stuff-ci/src/mobile-release-utils.ts @@ -15,7 +15,7 @@ export const getMobileReleaseTags = async (): Promise> => { }; /** - * Compares two versions of the form .. + * Compares two versions (of the form .. ) or tags (of the form -..) * @param v1 * @param v2 * @returns int, 1 if v1 > v2, -1 if v1 < v2, 0 if v1 == v2 From 062cbe33581bca13532458cf716f41e28351d464 Mon Sep 17 00:00:00 2001 From: Jeffrey Lau <> Date: Mon, 10 Apr 2023 10:35:20 -0700 Subject: [PATCH 6/9] get 100% coverage --- .../src/__tests__/mobile-release-utils.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts b/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts index 3251fb2e..06ad3587 100644 --- a/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts +++ b/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts @@ -49,7 +49,7 @@ describe("#compareVersions", () => { }); }); -describe("#isGetReleaseBranch", () => { +describe("#extractMobileReleaseBranch", () => { it.each([ "release/unified/7.8.0", "release/android/7.8.0", @@ -65,7 +65,7 @@ describe("#isGetReleaseBranch", () => { expect(result?.version).toBe("7.8.0"); }); - it.each(["release/testing", "android/7.8.0", "ios/7.8.0"])( + it.each(["release/testing", "android/7.8.0", "ios/7.8.0", null])( "return null if the branch is not a release branch", (testCase: any) => { // Arrange From 637aa4623d328720d613387768948c632f00f0c2 Mon Sep 17 00:00:00 2001 From: Jeffrey Lau <> Date: Mon, 10 Apr 2023 14:45:50 -0700 Subject: [PATCH 7/9] updated based on pr comments from jeff --- packages/wonder-stuff-ci/package.json | 2 +- ...-prom.test.ts => buffer-to-string.test.ts} | 5 +- .../src/__tests__/compare-versions.test.ts | 45 +++++++ ...bile-release-info-from-branch-name.test.ts | 44 +++++++ .../__tests__/get-mobile-release-tags.test.ts | 23 ++++ ...util.test.ts => get-tags-from-git.test.ts} | 14 ++- .../__tests__/mobile-release-utils.test.ts | 112 ------------------ .../wonder-stuff-ci/src/buffer-to-string.ts | 10 ++ .../wonder-stuff-ci/src/compare-versions.ts | 20 ++++ packages/wonder-stuff-ci/src/exec-async.ts | 7 ++ packages/wonder-stuff-ci/src/exec-prom.ts | 13 -- ...ct-mobile-release-info-from-branch-name.ts | 24 ++++ .../src/get-mobile-release-tags.ts | 20 ++++ .../wonder-stuff-ci/src/get-tags-from-git.ts | 13 ++ packages/wonder-stuff-ci/src/index.ts | 12 +- .../src/mobile-release-git-utils.ts | 14 --- .../src/mobile-release-utils.ts | 54 --------- 17 files changed, 223 insertions(+), 209 deletions(-) rename packages/wonder-stuff-ci/src/__tests__/{exec-prom.test.ts => buffer-to-string.test.ts} (74%) create mode 100644 packages/wonder-stuff-ci/src/__tests__/compare-versions.test.ts create mode 100644 packages/wonder-stuff-ci/src/__tests__/extract-mobile-release-info-from-branch-name.test.ts create mode 100644 packages/wonder-stuff-ci/src/__tests__/get-mobile-release-tags.test.ts rename packages/wonder-stuff-ci/src/__tests__/{mobile-release-git-util.test.ts => get-tags-from-git.test.ts} (54%) delete mode 100644 packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts create mode 100644 packages/wonder-stuff-ci/src/buffer-to-string.ts create mode 100644 packages/wonder-stuff-ci/src/compare-versions.ts create mode 100644 packages/wonder-stuff-ci/src/exec-async.ts delete mode 100644 packages/wonder-stuff-ci/src/exec-prom.ts create mode 100644 packages/wonder-stuff-ci/src/extract-mobile-release-info-from-branch-name.ts create mode 100644 packages/wonder-stuff-ci/src/get-mobile-release-tags.ts create mode 100644 packages/wonder-stuff-ci/src/get-tags-from-git.ts delete mode 100644 packages/wonder-stuff-ci/src/mobile-release-git-utils.ts delete mode 100644 packages/wonder-stuff-ci/src/mobile-release-utils.ts diff --git a/packages/wonder-stuff-ci/package.json b/packages/wonder-stuff-ci/package.json index 2a23b84b..7945ce15 100644 --- a/packages/wonder-stuff-ci/package.json +++ b/packages/wonder-stuff-ci/package.json @@ -7,7 +7,7 @@ }, "name": "@khanacademy/wonder-stuff-ci", "version": "0.0.1", - "description": "Functions for creating automation and scripts.", + "description": "Functions for automation and scripts.", "module": "dist/es/index.js", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/wonder-stuff-ci/src/__tests__/exec-prom.test.ts b/packages/wonder-stuff-ci/src/__tests__/buffer-to-string.test.ts similarity index 74% rename from packages/wonder-stuff-ci/src/__tests__/exec-prom.test.ts rename to packages/wonder-stuff-ci/src/__tests__/buffer-to-string.test.ts index 62133759..ec3cbd92 100644 --- a/packages/wonder-stuff-ci/src/__tests__/exec-prom.test.ts +++ b/packages/wonder-stuff-ci/src/__tests__/buffer-to-string.test.ts @@ -1,10 +1,9 @@ -import {buffer} from "stream/consumers"; -import {execProm, bufferToString} from "../exec-prom"; +import {bufferToString} from "../buffer-to-string"; describe("#bufferToString", () => { it.each(["testing", Buffer.from("testing")])( "the buffer to string function returns the correct value", - (testCase: any) => { + (testCase: string | Buffer) => { // Arrange const input = testCase; diff --git a/packages/wonder-stuff-ci/src/__tests__/compare-versions.test.ts b/packages/wonder-stuff-ci/src/__tests__/compare-versions.test.ts new file mode 100644 index 00000000..429cc5d2 --- /dev/null +++ b/packages/wonder-stuff-ci/src/__tests__/compare-versions.test.ts @@ -0,0 +1,45 @@ +import {compareVersions} from "../compare-versions"; + +describe("#compareVersions", () => { + it.each(["7.8.1", "7.9.0", "7.10.0", "8.0.0"])( + "return 1 if version 1 is greater than version 2", + (testCase: string) => { + // Arrange + const version1 = testCase; + const version2 = "7.8.0"; + + // Act + const result = compareVersions(version1, version2); + + // Assert + expect(result).toBe(1); + }, + ); + + it.each(["7.7.1", "7.6.0", "6.10.0"])( + "return -1 if version 1 is less than version 2", + (testCase: string) => { + // Arrange + const version1 = testCase; + const version2 = "7.8.0"; + + // Act + const result = compareVersions(version1, version2); + + // Assert + expect(result).toBe(-1); + }, + ); + + it("return 0 if version 1 is equal to version 2", () => { + // Arrange + const version1 = "7.8.0"; + const version2 = "7.8.0"; + + // Act + const result = compareVersions(version1, version2); + + // Assert + expect(result).toBe(0); + }); +}); diff --git a/packages/wonder-stuff-ci/src/__tests__/extract-mobile-release-info-from-branch-name.test.ts b/packages/wonder-stuff-ci/src/__tests__/extract-mobile-release-info-from-branch-name.test.ts new file mode 100644 index 00000000..311fd129 --- /dev/null +++ b/packages/wonder-stuff-ci/src/__tests__/extract-mobile-release-info-from-branch-name.test.ts @@ -0,0 +1,44 @@ +import {extractMobileReleaseInfoFromBranchName} from "../extract-mobile-release-info-from-branch-name"; + +describe("#extractMobileReleaseInfoFromBranchName", () => { + it.each([ + "release/unified/7.8.0", + "release/android/7.8.0", + "release/ios/7.8.0", + ])("get the version from the release branch", (testCase: string | null) => { + // Arrange + const releaseBranch = testCase; + + // Act + const result = extractMobileReleaseInfoFromBranchName(releaseBranch); + + // Assert + expect(result?.version).toBe("7.8.0"); + }); + + it.each(["release/testing", "android/7.8.0", "ios/7.8.0", null])( + "return null if the branch is not a release branch", + (testCase: string | null) => { + // Arrange + const releaseBranch = testCase; + + // Act + const result = + extractMobileReleaseInfoFromBranchName(releaseBranch); + + // Assert + expect(result).toBe(null); + }, + ); + + it("get the correct prefix string", () => { + // Arrange + const branchName = "release/unified/7.8.0"; + + // Act + const result = extractMobileReleaseInfoFromBranchName(branchName); + + // Assert + expect(result?.prefix).toBe("release/unified/"); + }); +}); diff --git a/packages/wonder-stuff-ci/src/__tests__/get-mobile-release-tags.test.ts b/packages/wonder-stuff-ci/src/__tests__/get-mobile-release-tags.test.ts new file mode 100644 index 00000000..95e3ae92 --- /dev/null +++ b/packages/wonder-stuff-ci/src/__tests__/get-mobile-release-tags.test.ts @@ -0,0 +1,23 @@ +import {getMobileReleaseTags} from "../get-mobile-release-tags"; + +jest.mock("../get-tags-from-git"); + +describe("#getMobileReleaseTags", () => { + it("get the tags in sorted order by ascending version value", async () => { + // Arrange + jest.spyOn( + require("../get-tags-from-git"), + "getTagsFromGit", + ).mockReturnValue(["android-7.10.0", "unified-7.8.0", "unified-7.9.0"]); + + // Act + const result = await getMobileReleaseTags(); + + // Assert + expect(result).toStrictEqual([ + "unified-7.8.0", + "unified-7.9.0", + "android-7.10.0", + ]); + }); +}); diff --git a/packages/wonder-stuff-ci/src/__tests__/mobile-release-git-util.test.ts b/packages/wonder-stuff-ci/src/__tests__/get-tags-from-git.test.ts similarity index 54% rename from packages/wonder-stuff-ci/src/__tests__/mobile-release-git-util.test.ts rename to packages/wonder-stuff-ci/src/__tests__/get-tags-from-git.test.ts index 127055f9..7c0e1d22 100644 --- a/packages/wonder-stuff-ci/src/__tests__/mobile-release-git-util.test.ts +++ b/packages/wonder-stuff-ci/src/__tests__/get-tags-from-git.test.ts @@ -1,16 +1,18 @@ -import {allMobileReleaseTags} from "../mobile-release-git-utils"; -import execProm from "../exec-prom"; +import {getTagsFromGit} from "../get-tags-from-git"; -jest.mock("../exec-prom"); +import {execAsync} from "../exec-async"; -describe("#allMobileReleaseTags", () => { +jest.mock("../exec-async"); + +describe("#getTagsFromGit", () => { it("return an array of release tags split by new line", async () => { // Arrange - jest.spyOn(require("../exec-prom"), "execProm").mockReturnValue({ + jest.spyOn(require("../exec-async"), "execAsync").mockReturnValue({ stdout: "android-7.10.0\nunified-7.8.0\nunified-7.9.0", }); + // Act - const result = await allMobileReleaseTags(); + const result = await getTagsFromGit(); // Assert expect(result).toStrictEqual([ diff --git a/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts b/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts deleted file mode 100644 index 06ad3587..00000000 --- a/packages/wonder-stuff-ci/src/__tests__/mobile-release-utils.test.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { - compareVersions, - extractMobileReleaseBranch, - getMobileReleaseTags, -} from "../mobile-release-utils"; -import {allMobileReleaseTags} from "../mobile-release-git-utils"; - -describe("#compareVersions", () => { - it.each(["7.8.1", "7.9.0", "7.10.0", "8.0.0"])( - "return 1 if version 1 is greater than version 2", - (testCase: any) => { - // Arrange - const version1 = testCase; - const version2 = "7.8.0"; - - // Act - const result = compareVersions(version1, version2); - - // Assert - expect(result).toBe(1); - }, - ); - - it.each(["7.7.1", "7.6.0", "6.10.0"])( - "return -1 if version 1 is less than version 2", - (testCase: any) => { - // Arrange - const version1 = testCase; - const version2 = "7.8.0"; - - // Act - const result = compareVersions(version1, version2); - - // Assert - expect(result).toBe(-1); - }, - ); - - it("return 0 if version 1 is equal to version 2", () => { - // Arrange - const version1 = "7.8.0"; - const version2 = "7.8.0"; - - // Act - const result = compareVersions(version1, version2); - - // Assert - expect(result).toBe(0); - }); -}); - -describe("#extractMobileReleaseBranch", () => { - it.each([ - "release/unified/7.8.0", - "release/android/7.8.0", - "release/ios/7.8.0", - ])("get the version from the release branch", (testCase: any) => { - // Arrange - const releaseBranch = testCase; - - // Act - const result = extractMobileReleaseBranch(releaseBranch); - - // Assert - expect(result?.version).toBe("7.8.0"); - }); - - it.each(["release/testing", "android/7.8.0", "ios/7.8.0", null])( - "return null if the branch is not a release branch", - (testCase: any) => { - // Arrange - const releaseBranch = testCase; - - // Act - const result = extractMobileReleaseBranch(releaseBranch); - - // Assert - expect(result).toBe(null); - }, - ); - - it("get the correct prefix string", () => { - // Arrange - const branchName = "release/unified/7.8.0"; - - // Act - const result = extractMobileReleaseBranch(branchName); - - // Assert - expect(result?.prefix).toBe("release/unified/"); - }); -}); - -describe("#getMobileReleaseTags", () => { - it("get the tags in sorted order by ascending version value", async () => { - // Arrange - - jest.spyOn( - require("../mobile-release-git-utils"), - "allMobileReleaseTags", - ).mockReturnValue(["android-7.10.0", "unified-7.8.0", "unified-7.9.0"]); - // Act - const result = await getMobileReleaseTags(); - - // Assert - expect(result).toStrictEqual([ - "unified-7.8.0", - "unified-7.9.0", - "android-7.10.0", - ]); - }); -}); diff --git a/packages/wonder-stuff-ci/src/buffer-to-string.ts b/packages/wonder-stuff-ci/src/buffer-to-string.ts new file mode 100644 index 00000000..a67af25e --- /dev/null +++ b/packages/wonder-stuff-ci/src/buffer-to-string.ts @@ -0,0 +1,10 @@ +/** + * Coerce a buffer or string into a string. + * + * @param {Buffer | string} input The `Buffer` or `string` + * that should be coerced to a string. + * @returns {string} The `string` representation of the given parameter. + */ +export const bufferToString = (input: Buffer | string): string => { + return typeof input === "string" ? input : input.toString("utf8"); +}; diff --git a/packages/wonder-stuff-ci/src/compare-versions.ts b/packages/wonder-stuff-ci/src/compare-versions.ts new file mode 100644 index 00000000..f2a989ad --- /dev/null +++ b/packages/wonder-stuff-ci/src/compare-versions.ts @@ -0,0 +1,20 @@ +/** + * Compare two versions or tags + * @param {string} v1 A version of the form `..` or tag of the form `-..`. + * @param {string} v2 A version of the form `..` or tag of the form `-..`. + * @returns {number} 1 if v1 > v2, -1 if v1 < v2, 0 if v1 == v2 + */ +export const compareVersions = (v1: string, v2: string) => { + const v1v = v1.includes("-") ? v1.split("-")[1] : v1; + const v2v = v2.includes("-") ? v2.split("-")[1] : v2; + const v1p = v1v.replace(/^v/g, "").split("."); + const v2p = v2v.replace(/^v/g, "").split("."); + for (let i = 0; i < v1p.length || i < v2p.length; i++) { + const p1 = +v1p[i] || 0; + const p2 = +v2p[i] || 0; + if (+p1 !== +p2) { + return p1 > p2 ? 1 : -1; + } + } + return 0; +}; diff --git a/packages/wonder-stuff-ci/src/exec-async.ts b/packages/wonder-stuff-ci/src/exec-async.ts new file mode 100644 index 00000000..ac7884d0 --- /dev/null +++ b/packages/wonder-stuff-ci/src/exec-async.ts @@ -0,0 +1,7 @@ +import {exec} from "child_process"; +import util from "util"; + +/** + * A simple promisified version of child_process.exec, so we can `await` it + */ +export const execAsync = util.promisify(exec); diff --git a/packages/wonder-stuff-ci/src/exec-prom.ts b/packages/wonder-stuff-ci/src/exec-prom.ts deleted file mode 100644 index 65ae14d6..00000000 --- a/packages/wonder-stuff-ci/src/exec-prom.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * A simple promisified version of child_process.exec, so we can `await` it - */ -import {exec, ExecOptions} from "child_process"; -import util from "util"; - -export const bufferToString = (input: Buffer | string): string => { - return typeof input === "string" ? input : input.toString("utf8"); -}; - -export const execProm = util.promisify(exec); - -export default execProm; diff --git a/packages/wonder-stuff-ci/src/extract-mobile-release-info-from-branch-name.ts b/packages/wonder-stuff-ci/src/extract-mobile-release-info-from-branch-name.ts new file mode 100644 index 00000000..a46f9355 --- /dev/null +++ b/packages/wonder-stuff-ci/src/extract-mobile-release-info-from-branch-name.ts @@ -0,0 +1,24 @@ +/** + * Extract release version and prefix from mobile release branch. + * + * Example, given the branch `release/unified/v7.8.0`: + * { + * prefix: "release/unified/", + * version: "7.8.0" + * } + * + * @param {string} The release branch of the form `[release/[unified|ios|android]]/[v]..[-extra]`. + * @returns {Object} The release version and prefix, if found; otherwise, `null`. + */ +export const extractMobileReleaseInfoFromBranchName = (arg: string | null) => { + if (!arg) { + return null; + } + + const match = arg.match( + /^(release\/(ios|android|unified)\/)?v?(\d+\.\d+\.\d+(-\w*)*)$/i, + ); + return match && match.length >= 3 && match[3] + ? {prefix: match[1] || "release/unified/", version: match[3]} + : null; +}; diff --git a/packages/wonder-stuff-ci/src/get-mobile-release-tags.ts b/packages/wonder-stuff-ci/src/get-mobile-release-tags.ts new file mode 100644 index 00000000..3f3f4f26 --- /dev/null +++ b/packages/wonder-stuff-ci/src/get-mobile-release-tags.ts @@ -0,0 +1,20 @@ +import {compareVersions} from "./compare-versions"; +import {getTagsFromGit} from "./get-tags-from-git"; + +/** + * Get mobile release tags. + * + * Tags are filtered to only include those matching our tag version format + * (`-..`), then they are sorted by the version information from + * earliest version to most recent. + * + * @returns {Promise>} all release tags sorted creation time ascending + */ +export const getMobileReleaseTags = async (): Promise> => { + const tags = await getTagsFromGit(); + return tags + .filter((tag) => + tag.match(/^(ios|android|unified)-(\d+\.\d+\.\d+(-\w*)*)$/i), + ) + .sort(compareVersions); +}; diff --git a/packages/wonder-stuff-ci/src/get-tags-from-git.ts b/packages/wonder-stuff-ci/src/get-tags-from-git.ts new file mode 100644 index 00000000..55497f66 --- /dev/null +++ b/packages/wonder-stuff-ci/src/get-tags-from-git.ts @@ -0,0 +1,13 @@ +import {execAsync} from "./exec-async"; + +/** + * Get all tags from git. + * + * @returns {Promise>} A promise of all git tags sorted by creation time ascending. + */ +export const getTagsFromGit = async (): Promise> => { + // Why not use simple-git here? Because for some reason it takes like 100x as long. + await execAsync("git fetch --tags"); + const {stdout} = await execAsync("git tag"); + return stdout.split("\n").filter(Boolean); +}; diff --git a/packages/wonder-stuff-ci/src/index.ts b/packages/wonder-stuff-ci/src/index.ts index 61a7318c..fc6e9e1d 100644 --- a/packages/wonder-stuff-ci/src/index.ts +++ b/packages/wonder-stuff-ci/src/index.ts @@ -1,6 +1,6 @@ -export { - getMobileReleaseTags, - extractMobileReleaseBranch, - compareVersions, -} from "./mobile-release-utils"; -export {execProm, bufferToString} from "./exec-prom"; +export {compareVersions} from "./compare-versions"; +export {extractMobileReleaseInfoFromBranchName} from "./extract-mobile-release-info-from-branch-name"; +export {getMobileReleaseTags} from "./get-mobile-release-tags"; +export {getTagsFromGit} from "./get-tags-from-git"; +export {execAsync} from "./exec-async"; +export {bufferToString} from "./buffer-to-string"; diff --git a/packages/wonder-stuff-ci/src/mobile-release-git-utils.ts b/packages/wonder-stuff-ci/src/mobile-release-git-utils.ts deleted file mode 100644 index 3fc2024e..00000000 --- a/packages/wonder-stuff-ci/src/mobile-release-git-utils.ts +++ /dev/null @@ -1,14 +0,0 @@ -import execProm from "./exec-prom"; - -/** - * - * @returns all release tags sorted creation time ascending - */ -export const allMobileReleaseTags = async (): Promise> => { - // Why not use simple-git here? Because for some reason it takes like 100x as long. - await execProm("git fetch --tags"); - const {stdout} = await execProm( - "git tag | grep -E -i -w 'ios|android|unified'", - ); - return stdout.split("\n").filter(Boolean); -}; diff --git a/packages/wonder-stuff-ci/src/mobile-release-utils.ts b/packages/wonder-stuff-ci/src/mobile-release-utils.ts deleted file mode 100644 index c3afd706..00000000 --- a/packages/wonder-stuff-ci/src/mobile-release-utils.ts +++ /dev/null @@ -1,54 +0,0 @@ -import execProm from "./exec-prom"; -import { allMobileReleaseTags } from "./mobile-release-git-utils"; - -/** - * - * @returns all release tags sorted creation time ascending - */ -export const getMobileReleaseTags = async (): Promise> => { - const tags = await allMobileReleaseTags(); - return tags - .filter((tag) => - tag.match(/^(ios|android|unified)-(\d+\.\d+\.\d+(-\w*)*)$/i), - ) - .sort(compareVersions); -}; - -/** - * Compares two versions (of the form .. ) or tags (of the form -..) - * @param v1 - * @param v2 - * @returns int, 1 if v1 > v2, -1 if v1 < v2, 0 if v1 == v2 - */ -export const compareVersions = (v1: string, v2: string) => { - const v1v = v1.includes("-") ? v1.split("-")[1] : v1; - const v2v = v2.includes("-") ? v2.split("-")[1] : v2; - const v1p = v1v.replace(/^v/g, "").split("."); - const v2p = v2v.replace(/^v/g, "").split("."); - for (let i = 0; i < v1p.length || i < v2p.length; i++) { - const p1 = +v1p[i] || 0; - const p2 = +v2p[i] || 0; - if (+p1 !== +p2) { - return p1 > p2 ? 1 : -1; - } - } - return 0; -}; - -/** - * Matches [release/[unified|ios|android]]/[v]..[-extra] - * @param arg - * @returns match, if found, null otherwise - */ -export const extractMobileReleaseBranch = (arg: string) => { - if (!arg) { - return null; - } - - const match = arg.match( - /^(release\/(ios|android|unified)\/)?v?(\d+\.\d+\.\d+(-\w*)*)$/i, - ); - return match && match.length >= 3 && match[3] - ? {prefix: match[1] || "release/unified/", version: match[3]} - : null; -}; \ No newline at end of file From 74c17888ff2d070e2f3e902f9027faf7093493b3 Mon Sep 17 00:00:00 2001 From: Jeffrey Lau <> Date: Mon, 10 Apr 2023 14:47:59 -0700 Subject: [PATCH 8/9] updated readme --- packages/wonder-stuff-ci/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wonder-stuff-ci/README.md b/packages/wonder-stuff-ci/README.md index 50b6f03c..4b579e1b 100644 --- a/packages/wonder-stuff-ci/README.md +++ b/packages/wonder-stuff-ci/README.md @@ -1,3 +1,3 @@ # wonder-stuff-ci -This Wonder Stuff package contains functions for creating automation and scripts. +This Wonder Stuff package contains functions for automation and scripts. From 3ef0056eb9b7515cf82fac6481fb4097a551bee4 Mon Sep 17 00:00:00 2001 From: Jeffrey Lau <> Date: Wed, 12 Apr 2023 11:45:10 -0700 Subject: [PATCH 9/9] added a type for mobile release info --- .../src/extract-mobile-release-info-from-branch-name.ts | 6 ++++-- packages/wonder-stuff-ci/src/types.ts | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 packages/wonder-stuff-ci/src/types.ts diff --git a/packages/wonder-stuff-ci/src/extract-mobile-release-info-from-branch-name.ts b/packages/wonder-stuff-ci/src/extract-mobile-release-info-from-branch-name.ts index a46f9355..fb05b41b 100644 --- a/packages/wonder-stuff-ci/src/extract-mobile-release-info-from-branch-name.ts +++ b/packages/wonder-stuff-ci/src/extract-mobile-release-info-from-branch-name.ts @@ -8,9 +8,11 @@ * } * * @param {string} The release branch of the form `[release/[unified|ios|android]]/[v]..[-extra]`. - * @returns {Object} The release version and prefix, if found; otherwise, `null`. + * @returns {MobileReleaseInfo} The release version and prefix, if found; otherwise, `null`. */ -export const extractMobileReleaseInfoFromBranchName = (arg: string | null) => { +export const extractMobileReleaseInfoFromBranchName = ( + arg: string | null, +): MobileReleaseBranchInfo | null => { if (!arg) { return null; } diff --git a/packages/wonder-stuff-ci/src/types.ts b/packages/wonder-stuff-ci/src/types.ts new file mode 100644 index 00000000..df07acfa --- /dev/null +++ b/packages/wonder-stuff-ci/src/types.ts @@ -0,0 +1,7 @@ +/** + * The information about a release branch. + */ +type MobileReleaseBranchInfo = { + prefix: string; + version: string; +};