From 159cec70437445948d3081a0b1564b436bccb646 Mon Sep 17 00:00:00 2001 From: Adam R <13562139+catenocrypt@users.noreply.github.com> Date: Mon, 22 Feb 2021 16:25:32 +0100 Subject: [PATCH] [Internal] Infrastructure for change management (history) (#5653) * Infrastructure for change management (history). * Always take latest commit from master * Allow history folder. * Lint fixes * Error handling, do not update LATEST if version writing failed Co-authored-by: Catenocrypt --- history/LATEST.json | 5 ++ history/versions/PLACEHOLDER | 1 + package.json | 1 + script/config.ts | 2 +- script/entrypoint/history.ts | 12 +++ script/generic/history.ts | 164 +++++++++++++++++++++++++++++++++++ 6 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 history/LATEST.json create mode 100644 history/versions/PLACEHOLDER create mode 100644 script/entrypoint/history.ts create mode 100644 script/generic/history.ts diff --git a/history/LATEST.json b/history/LATEST.json new file mode 100644 index 000000000..0bd7620be --- /dev/null +++ b/history/LATEST.json @@ -0,0 +1,5 @@ +{ + "versionNum": 1, + "commit": "f5117527c2e1dd89d51b72c3634d94edb5a04780", + "date": "2021-02-22T14:56:47.938Z" +} \ No newline at end of file diff --git a/history/versions/PLACEHOLDER b/history/versions/PLACEHOLDER new file mode 100644 index 000000000..ae971f3a2 --- /dev/null +++ b/history/versions/PLACEHOLDER @@ -0,0 +1 @@ +Individual change descriptor files go to this folder. \ No newline at end of file diff --git a/package.json b/package.json index 4227f54d8..9457526a5 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "fix-sanity": "ts-node ./script/entrypoint/fix-sanity", "updateAuto": "ts-node ./script/entrypoint/updateAuto", "update": "ts-node ./script/entrypoint/updateManual", + "history": "ts-node ./script/entrypoint/history", "lint": "npx eslint . --ext .js,.jsx,.ts,.tsx", "lint:fix": "npx eslint . --ext .js,.jsx,.ts,.tsx --fix" }, diff --git a/script/config.ts b/script/config.ts index 496acfbdb..4d052a843 100644 --- a/script/config.ts +++ b/script/config.ts @@ -3,7 +3,7 @@ export const imageMaxLogoHeight = 512; export const imageMinLogoWidth = 64; export const imageMinLogoHeight = 64; export const imageMaxLogoSizeKb = 100; -export const foldersRootdirAllowedFiles: string[] = [".github", "blockchains", "dapps", "media", "node_modules", "script-old", "script", "test", ".gitignore", "azure-pipelines.yml", "jest.config.js", "LICENSE", "package-lock.json", "package.json", "README.md", ".git", "dangerfile.ts", "Gemfile", "Gemfile.lock", ".eslintignore", ".eslintrc.js"]; +export const foldersRootdirAllowedFiles: string[] = [".github", "blockchains", "dapps", "media", "node_modules", "script-old", "script", "test", "history", ".gitignore", "azure-pipelines.yml", "jest.config.js", "LICENSE", "package-lock.json", "package.json", "README.md", ".git", "dangerfile.ts", "Gemfile", "Gemfile.lock", ".eslintignore", ".eslintrc.js"]; export const binanceUrlTokenAssets = "https://explorer.binance.org/api/v1/assets?page=1&rows=1000"; export const binanceDexURL = 'https://dex-atlantic.binance.org/api' export const assetsURL = 'https://raw.githubusercontent.com/trustwallet/assets/master' diff --git a/script/entrypoint/history.ts b/script/entrypoint/history.ts new file mode 100644 index 000000000..01b250f44 --- /dev/null +++ b/script/entrypoint/history.ts @@ -0,0 +1,12 @@ +import { processChanges } from "../generic/history"; + +export async function main(): Promise { + try { + await processChanges(); + } catch(err) { + console.error(err); + process.exit(1); + } +} + +main(); diff --git a/script/generic/history.ts b/script/generic/history.ts new file mode 100644 index 000000000..b8bcb8721 --- /dev/null +++ b/script/generic/history.ts @@ -0,0 +1,164 @@ +import * as util from "util"; +import { + isPathExistsSync, + readFileSync, + writeFileSync, +} from "./filesystem"; +import * as child_process from "child_process"; + +class VersionInfo { + versionNum: number; + commit: string; + date: string; +} + +const FilenameLatest = "history/LATEST.json"; +const FilenameChangeTemplate = "history/versions/"; +const TooManyChangesLimit = 2; + +//const util = require('util'); +const exec = util.promisify(child_process.exec); + +async function execGit(options: string): Promise { + try { + const cmd = `git ${options}`; + console.log(`executing cmd: ${cmd}`); + const { stdout, stderr } = await exec(cmd); + if (stdout) { + console.log('stdout:'); + console.log(stdout); + } + if (stderr) { + console.log('stderr:', stderr); + } + return stdout; + } catch (err) { + console.log('exception:', err); + return ""; + } +} + +function readLatestVersion(): VersionInfo { + const zeroVer: VersionInfo = {versionNum: 0, commit: "", date: (new Date()).toISOString()}; + try { + const rawdata = readFileSync(FilenameLatest); + const ver: VersionInfo = JSON.parse(rawdata) as VersionInfo; + if (!ver.versionNum && !ver.commit) { + return zeroVer; + } + return ver; + } catch (err) { + console.log('Exception:', err); + return zeroVer; + } +} + +function writeLatestVersion(version: VersionInfo): void { + try { + const content: string = JSON.stringify(version, null, 4); + writeFileSync(FilenameLatest, content); + } catch (err) { + console.log('Exception:', err); + } +} + +async function getCurrentCommit(): Promise { + const raw = await execGit("rev-parse master"); + if (!raw) { + return raw; + } + return raw.split("\n").filter(l => l)[0]; +} + +async function getChangedFiles(commitStart: string, commitEnd: string): Promise{ + const bulk: string = await execGit(`diff --name-only ${commitStart} ${commitEnd}`); + if (!bulk) { + return []; + } + const list: string[] = bulk.split("\n").filter(l => l); + return list; +} + +function changeListToJson(versionStart: VersionInfo, versionEnd: VersionInfo, changes: string[]): unknown { + let fullChanges = false; + if (changes.length > TooManyChangesLimit) { + fullChanges = true; + } + const obj: unknown = { + "versionEnd": versionEnd, + "versionStart": versionStart, + "fullChange": fullChanges, + "changeCount": changes.length, + }; + if (!fullChanges) { + obj["changes"] = changes; + } + return obj; +} + +// return filename +function writeChangeList(version: VersionInfo, changeList: unknown): string { + try { + const filename: string = FilenameChangeTemplate + version.versionNum.toString() + ".json"; + if (isPathExistsSync(filename)) { + throw `Error: file already exists: ${filename}`; + } + const content = JSON.stringify(changeList, null, 4); + writeFileSync(filename, content); + return filename; + } catch (err) { + console.log('exception:', err); + return null; + } +} + +export async function processChanges(): Promise { + console.log("Compiling changes since last commit ..."); + const ver = readLatestVersion(); + if (ver.versionNum == 0 || !ver.versionNum || !ver.commit) { + console.log("Error: Could not obtain latest version"); + return 1; + } + console.log(`Latest version: ${JSON.stringify(ver, null, 4)}`); + + const currCommit = await getCurrentCommit(); + console.log(`Current commit: ${currCommit}`); + if (!currCommit) { + console.log("Error: Could not obtain current commit"); + return 2; + } + + if (currCommit == ver.commit) { + console.log(`Warning: no new commit since ${ver.commit}`); + return 3; + } + + const newVer: VersionInfo = { + versionNum: ver.versionNum + 1, + commit: currCommit, + date: (new Date()).toISOString(), + }; + console.log(`New version: ${JSON.stringify(newVer, null, 4)}`); + + const files: string[] = await getChangedFiles(ver.commit, currCommit); + console.log(`${files.length} changed files found`); + if (!files || files.length == 0) { + console.log(`Error: Could not obtain list of changed files between commits ${ver.commit} and ${currCommit}`); + return 4; + } + if (files.length == 0) { + console.log(`Warning: no changed files bwteewn commits ${ver.commit} ${currCommit}`); + return 5; + } + + const changeList: unknown = changeListToJson(ver, newVer, files); + const newChangeFile = writeChangeList(newVer, changeList); + if (!newChangeFile) { + console.log(`Error: could not write out new change file`); + return 6; + } + writeLatestVersion(newVer); + console.log(`Changes written to ${FilenameLatest} and ${newChangeFile}`); + + return 0; +}