diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index b3dfee7..0000000 --- a/.editorconfig +++ /dev/null @@ -1,7 +0,0 @@ -root = true - -[*] -end_of_line = lf -insert_final_newline = true -indent_style = space -indent_size = 2 diff --git a/README.md b/README.md index f73783c..87b93a0 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,10 @@ This projects allows to perform automatically tasks required at release time like for example: -- Creating a new tag based on existing ones -- Updating versions number in a file, according to the new tag. +- Updating version numbers in the readme, according to the new tag. - Updating links in readme. - Creating a changelog. +- Creating a new tag based on existing ones - Pushing a release to github. Most changes are optionals and configurable. @@ -75,11 +75,20 @@ enabled. To enable them, either "github": { "release": true }, - "regex": { - "patterns": [ - "(?<=@)(.*)(?=\/cli)" - ] - }, + "regex": [ + { + "file": "README.md", + "patterns": [ + "(?<=@)(.*)(?=\/cli)" + ] + }, + { + "file": "deno.json", + "patterns": [ + "(?<=version=\")(.*)\n" + ] + } + ], "versionFile": {}, "myRemotePlugin": { "path": "./plugins/testRemote/mod.ts" diff --git a/cli.ts b/cli.ts index 407e4df..e854283 100644 --- a/cli.ts +++ b/cli.ts @@ -11,10 +11,12 @@ import changelog from "./plugins/changelog/mod.ts"; import regex from "./plugins/regex/mod.ts"; import versionFile from "./plugins/versionFile/mod.ts"; -import version from "./version.json" assert { type: "json" }; +import config from "./deno.json" with { type: "json" }; import { ReleasePlugin } from "./plugin.ts"; import { initLogger } from "./src/log.ts"; +const version = config.version; + export type ReleaseType = | "patch" | "minor" @@ -39,7 +41,7 @@ const DEFAULT_CONFIG_PATH = ".release_up.json"; await new Command() .name("release_up") - .version(version.version) + .version(version) .description(` Automate semver releases. Example: release_up major --github @@ -54,15 +56,15 @@ await new Command() * prerelease ${colors.dim("eg: 1.2.3-name.0 -> 1.2.3-name.1")}`) .type("semver", new EnumType(release_type)) .arguments(" [name:string]") - .option("--config ", "Define the path of the config.", { + .option("--config ", "Define the path of the config.", { default: `${DEFAULT_CONFIG_PATH}`, }) .option("--github", "Enable Github plugin.") .option("--changelog", "Enable Changelog plugin.") .option("--versionFile", "Enable VersionFile plugin.") .option( - "--regex ", - "Enable Regex plugin. The regex need to be provided as string. --regex can be specified multiple times", + "--regex ", + "Enable the Regex plugin. The regex argument is of format filepath:::regex eg: --regex 'README.md:::(?<=@)(.*)(?=\/cli)'. --regex can be specified multiple times.", { collect: true }, ) .option("--dry", "Dry run, Does not commit any changes.") @@ -108,8 +110,23 @@ await new Command() if (opts.changelog) pluginsList.changelog = changelog; if (opts.regex) { pluginsList.regex = regex; + const regs = opts.regex?.map((s) => { + const cf = s.split(":::"); + if (cf.length === 1) { + // assume it is readme + return { + file: "README.md", + patterns: [cf[0]], + }; + } else { + return { + file: cf[0], + patterns: [cf[1]], + }; + } + }); // deno-lint-ignore no-explicit-any - (config as any).regex = { patterns: opts.regex }; + (config as any).regex = regs; } if (opts.versionFile) pluginsList.versionFile = versionFile; @@ -123,7 +140,6 @@ await new Command() else if (key === "versionFile" && !pluginsList.versionFile) { pluginsList.versionFile = versionFile; } else { - console.log(key, val); const def = val as { path: string }; if (!def.path) throw Error(`Invalid config entry ${key}, ${val}`); const remotePlugin = await import(def.path); diff --git a/deno.jsonc b/deno.json similarity index 59% rename from deno.jsonc rename to deno.json index d86d826..0ceccaf 100644 --- a/deno.jsonc +++ b/deno.json @@ -1,7 +1,10 @@ { + "name": "@sylc/release_up", + "version": "0.7.0", + "exports": "./cli.ts", "tasks": { - "dev": "deno run -A ./cli.ts --dry --allowUncommitted --regex \"(?<=@)(.*)(?=\/cli)\" --regex \"(?<=Version: )(.*)\n\" --changelog --github", - "release": "deno fmt --check && deno lint && deno run -A ./cli.ts --regex \"(?<=@)(.*)(?=\/cli)\" --regex \"(?<=Version: )(.*)\n\" --github --versionFile --changelog", + "dev": "deno run -A ./cli.ts --dry --allowUncommitted --regex '(?<=@)(.*)(?=\/cli)' --regex '(?<=Version: )(.*)\n' --changelog --github", + "release": "deno fmt --check && deno lint && deno run -A ./cli.ts --config ./tools/.release_up.json", "test": "deno test -A", "check": "deno fmt && deno lint" }, diff --git a/doc/doc.md b/doc/doc.md index 6f25cb1..892b4c2 100644 --- a/doc/doc.md +++ b/doc/doc.md @@ -24,8 +24,8 @@ interface GithubConfig { # Regex -Apply a regex on the `README.md`. The regex can be configure in the config file. -e.g: +Apply a regex on the `README.md` or any other files with the new version or any +other value. The regex can be configured in the config file. e.g: ```json "regex": { diff --git a/plugins/regex/mod.ts b/plugins/regex/mod.ts index 0399efe..f3d2d18 100644 --- a/plugins/regex/mod.ts +++ b/plugins/regex/mod.ts @@ -3,8 +3,9 @@ import { join } from "./deps.ts"; interface RegexConfig { regex: { - patterns: string[]; - }; + file: string; + patterns: string; + }[] | { patterns: string }; } const plugin: ReleasePlugin = { @@ -17,17 +18,48 @@ const plugin: ReleasePlugin = { config, log, ): Promise { - const readmePath = "README.md"; - let text = await Deno.readTextFile(readmePath); - // apply regex. This should come from a config loaded on setup step - // as a prototype, it is harcoded to update versions in urls - for (const pattern of config.regex.patterns) { - text = text.replace(new RegExp(pattern), to); + // the below allow for future expansion to change more files + const changeDefs = []; + if (!Array.isArray(config.regex) && config.regex.patterns.length) { + changeDefs.push({ + filePath: "README.md", + transforms: [ + { value: to, patterns: config.regex.patterns || [] }, + ], + }); } - if (config.options.dry) { - log.info(text); - } else { - await Deno.writeTextFile(join(repo.path, readmePath), text); + if (Array.isArray(config.regex)) { + config.regex.forEach((p) => { + changeDefs.push({ + filePath: p.file, + transforms: [ + { value: to, patterns: p.patterns }, + ], + }); + }); + } + + // aggregate all patterns per file + const t = Object.groupBy(changeDefs, ({ filePath }) => filePath); + + for (const [filePath, changeDefsForFile] of Object.entries(t)) { + log.info(`processing: ${filePath}`); + + let text = await Deno.readTextFile(filePath); + // apply regex. + for (const changeDef of changeDefsForFile!) { + for (const transforms of changeDef.transforms) { + for (const pattern of transforms.patterns) { + log.debug(`regex: ${new RegExp(pattern)}`); + text = text.replace(new RegExp(pattern), transforms.value); + } + } + } + if (config.options.dry) { + log.info(text); + } else { + await Deno.writeTextFile(join(repo.path, filePath), text); + } } }, }; diff --git a/src/git.ts b/src/git.ts index d5dcd64..d5898ea 100644 --- a/src/git.ts +++ b/src/git.ts @@ -4,31 +4,30 @@ import { ReleaseError } from "./error.ts"; const decoder = new TextDecoder(); -export async function git( +export function git( repo: string, args: string[] | string, -): Promise<[Deno.ProcessStatus, string, string]> { +): [boolean, string, string] { const dir = `--git-dir=${join(repo, ".git")}`; if (typeof args === "string") args = args.split(" "); - const process = Deno.run({ - cwd: repo, - cmd: ["git", dir, ...args], - stdout: "piped", - stderr: "piped", + + const cmd = new Deno.Command("git", { + args: [dir, ...args], }); - const output = await process.output(); - const err = await process.stderrOutput(); - const status = await process.status(); - process.close(); - return [status, decoder.decode(output), decoder.decode(err)]; + const process = cmd.outputSync(); + return [ + process.success, + decoder.decode(process.stdout), + decoder.decode(process.stderr), + ]; } -export async function ezgit( +export function ezgit( repo: string, args: string[] | string, -): Promise { - const [status, _, err] = await git(repo, args); - if (!status.success) throw new ReleaseError("GIT_EXE", err); +): void { + const [success, _, err] = git(repo, args); + if (!success) throw new ReleaseError("GIT_EXE", err); } export async function fetchConfig(repo: string): Promise { diff --git a/tools/.release_up.json b/tools/.release_up.json new file mode 100644 index 0000000..88bf04c --- /dev/null +++ b/tools/.release_up.json @@ -0,0 +1,20 @@ +{ + "changelog": {}, + "github": { + "release": true + }, + "regex": [ + { + "file": "README.md", + "patterns": [ + "(?<=@)(.*)(?=\/cli)" + ] + }, + { + "file": "deno.json", + "patterns": [ + "(?<=\"version\": \")(.*)(?=\",)" + ] + } + ] +} diff --git a/version.json b/version.json deleted file mode 100644 index 10a8aa1..0000000 --- a/version.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "version": "0.6.0" -}