From c36ffd13c3d859d9a4eadd0e07f6f73ad96b54aa Mon Sep 17 00:00:00 2001 From: alvarius Date: Thu, 13 Jul 2023 19:34:47 +0100 Subject: [PATCH] feat(cli): update set-version to match new release structure, add `--tag`, `--commit` (#1157) * feat(cli): add --tag and --commit options to set-version command * feat(cli): make set-version update all package.json in a project instead of just the current directory --- .changeset/thin-buses-reply.md | 15 ++++ packages/cli/src/commands/set-version.ts | 99 ++++++++++++++++-------- templates/phaser/package.json | 2 +- templates/react/package.json | 2 +- templates/threejs/package.json | 2 +- templates/vanilla/package.json | 2 +- 6 files changed, 86 insertions(+), 36 deletions(-) create mode 100644 .changeset/thin-buses-reply.md diff --git a/.changeset/thin-buses-reply.md b/.changeset/thin-buses-reply.md new file mode 100644 index 0000000000..8e4726cbdc --- /dev/null +++ b/.changeset/thin-buses-reply.md @@ -0,0 +1,15 @@ +--- +"@latticexyz/cli": minor +--- + +- update the `set-version` cli command to work with the new release process by adding two new options: + - `--tag`: install the latest version of the given tag. For snapshot releases tags correspond to the branch name, commits to `main` result in an automatic snapshot release, so `--tag main` is equivalent to what used to be `-v canary` + - `--commit`: install a version based on a given commit hash. Since commits from `main` result in an automatic snapshot release it works for all commits on main, and it works for manual snapshot releases from branches other than main +- `set-version` now updates all `package.json` nested below the current working directory (expect `node_modules`), so no need for running it each workspace of a monorepo separately. + +Example: + +```bash +pnpm mud set-version --tag main && pnpm install +pnpm mud set-version --commit db19ea39 && pnpm install +``` diff --git a/packages/cli/src/commands/set-version.ts b/packages/cli/src/commands/set-version.ts index 283e0687fb..d1afe4a4ec 100644 --- a/packages/cli/src/commands/set-version.ts +++ b/packages/cli/src/commands/set-version.ts @@ -5,12 +5,15 @@ import type { CommandModule } from "yargs"; import { MUDError } from "@latticexyz/common/errors"; import { logError } from "../utils/errors"; import localPackageJson from "../../package.json" assert { type: "json" }; +import glob from "glob"; type Options = { backup?: boolean; force?: boolean; restore?: boolean; mudVersion?: string; + tag?: string; + commit?: string; link?: string; }; @@ -20,7 +23,7 @@ const MUD_PREFIX = "@latticexyz"; const commandModule: CommandModule = { command: "set-version", - describe: "Install a custom MUD version and optionally backup the previously installed version", + describe: "Set MUD version in all package.json files and optionally backup the previously installed version", builder(yargs) { return yargs.options({ @@ -30,36 +33,44 @@ const commandModule: CommandModule = { description: `Backup fails if a "${BACKUP_FILE}" file is found, unless --force is provided`, }, restore: { type: "boolean", description: `Restore the previous MUD versions from "${BACKUP_FILE}"` }, - mudVersion: { alias: "v", type: "string", description: "The MUD version to install" }, + mudVersion: { alias: "v", type: "string", description: "Set MUD to the given version" }, + tag: { + alias: "t", + type: "string", + description: "Set MUD to the latest version with the given tag from npm", + }, + commit: { + alias: "c", + type: "string", + description: "Set MUD to the version based on a given git commit hash from npm", + }, link: { alias: "l", type: "string", description: "Relative path to the local MUD root directory to link" }, }); }, async handler(options) { try { - if (!options.mudVersion && !options.link && !options.restore) { - throw new MUDError("`--mudVersion` or `--link` is required unless --restore is provided."); + const mutuallyExclusiveOptions = ["mudVersion", "link", "tag", "commit", "restore"]; + const numMutuallyExclusiveOptions = mutuallyExclusiveOptions.reduce( + (acc, opt) => (options[opt] ? acc + 1 : acc), + 0 + ); + + if (numMutuallyExclusiveOptions === 0) { + throw new MUDError(`You need to provide one these options: ${mutuallyExclusiveOptions.join(", ")}`); } - // `link` and `mudVersion` are mutually exclusive - if (options.link && options.mudVersion) { - throw new MUDError("Options `--link` and `--mudVersion` are mutually exclusive"); + if (numMutuallyExclusiveOptions > 1) { + throw new MUDError(`These options are mutually exclusive: ${mutuallyExclusiveOptions.join(", ")}`); } - // Resolve the `canary` version number if needed - options.mudVersion = - options.mudVersion === "canary" ? await getCanaryVersion(localPackageJson.name) : options.mudVersion; - - // Read the current package.json - const rootPath = "./package.json"; - const { workspaces } = updatePackageJson(rootPath, options); + // Resolve the version number from available options like `tag` or `commit` + options.mudVersion = await resolveVersion(options); - // Load the package.json of each workspace - if (workspaces) { - for (const workspace of workspaces) { - const filePath = path.join(workspace, "/package.json"); - updatePackageJson(filePath, options); - } + // Update all package.json below the current working directory (except in node_modules) + const packageJsons = glob.sync("**/package.json").filter((p) => !p.includes("node_modules")); + for (const packageJson of packageJsons) { + updatePackageJson(packageJson, options); } } catch (e) { logError(e); @@ -69,6 +80,42 @@ const commandModule: CommandModule = { }, }; +async function resolveVersion(options: Options) { + // Backwards compatibility to previous behavior of this script where passing "canary" as the version resolved to the latest commit on main + if (options.mudVersion === "canary") options.tag = "main"; + + let npmResult; + try { + console.log(chalk.blue(`Fetching available versions`)); + npmResult = await (await fetch(`https://registry.npmjs.org/${localPackageJson.name}`)).json(); + } catch (e) { + throw new MUDError(`Could not fetch available MUD versions`); + } + + if (options.tag) { + const version = npmResult["dist-tags"][options.tag]; + if (!version) { + throw new MUDError(`Could not find npm version with tag "${options.tag}"`); + } + console.log(chalk.green(`Latest version with tag ${options.tag}: ${version}`)); + return version; + } + + if (options.commit) { + // Find a version with this commit hash + const commit = options.commit.substring(0, 8); // changesets uses the first 8 characters of the commit hash as version for prereleases/snapshot releases + const version = Object.keys(npmResult["versions"]).find((v) => (v as string).includes(commit)); + if (!version) { + throw new MUDError(`Could not find npm version based on commit "${options.commit}"`); + } + console.log(chalk.green(`Version from commit ${options.commit}: ${version}`)); + return version; + } + + // If neither a tag nor a commit option is given, return the `mudVersion` + return options.mudVersion; +} + function updatePackageJson(filePath: string, options: Options): { workspaces?: string[] } { const { restore, force, link } = options; let { backup, mudVersion } = options; @@ -167,18 +214,6 @@ function readPackageJson(path: string): { } } -async function getCanaryVersion(pkg: string) { - try { - console.log(chalk.blue("fetching MUD canary version...")); - const result = await (await fetch(`https://registry.npmjs.org/${pkg}`)).json(); - const canary = result["dist-tags"].canary; - console.log(chalk.green("MUD canary version:", canary)); - return canary; - } catch (e) { - throw new MUDError(`Could not fetch canary version of ${pkg}`); - } -} - function logComparison(prev: Record, curr: Record) { for (const key in prev) { if (prev[key] !== curr[key]) { diff --git a/templates/phaser/package.json b/templates/phaser/package.json index a8c9451e5c..4772e9e7f4 100644 --- a/templates/phaser/package.json +++ b/templates/phaser/package.json @@ -7,7 +7,7 @@ "dev:client": "pnpm --filter 'client' run dev", "dev:contracts": "pnpm --filter 'contracts' dev", "foundry:up": "curl -L https://foundry.paradigm.xyz | bash && bash $HOME/.foundry/bin/foundryup", - "mud:up": "pnpm recursive exec mud set-version -v canary && pnpm install", + "mud:up": "pnpm mud set-version --tag main && pnpm install", "prepare": "(forge --version || pnpm foundry:up)", "test": "pnpm recursive run test" }, diff --git a/templates/react/package.json b/templates/react/package.json index 6324825d5a..af3fae33db 100644 --- a/templates/react/package.json +++ b/templates/react/package.json @@ -7,7 +7,7 @@ "dev:client": "pnpm --filter 'client' run dev", "dev:contracts": "pnpm --filter 'contracts' dev", "foundry:up": "curl -L https://foundry.paradigm.xyz | bash && bash $HOME/.foundry/bin/foundryup", - "mud:up": "pnpm recursive exec mud set-version -v canary && pnpm install", + "mud:up": "pnpm mud set-version --tag main && pnpm install", "prepare": "(forge --version || pnpm foundry:up)", "test": "pnpm recursive run test" }, diff --git a/templates/threejs/package.json b/templates/threejs/package.json index 44191185a8..6b2d5bd472 100644 --- a/templates/threejs/package.json +++ b/templates/threejs/package.json @@ -7,7 +7,7 @@ "dev:client": "pnpm --filter 'client' run dev", "dev:contracts": "pnpm --filter 'contracts' dev", "foundry:up": "curl -L https://foundry.paradigm.xyz | bash && bash $HOME/.foundry/bin/foundryup", - "mud:up": "pnpm recursive exec mud set-version -v canary && pnpm install", + "mud:up": "pnpm mud set-version --tag main && pnpm install", "prepare": "(forge --version || pnpm foundry:up)", "test": "pnpm recursive run test" }, diff --git a/templates/vanilla/package.json b/templates/vanilla/package.json index 9368671780..fb21e4e055 100644 --- a/templates/vanilla/package.json +++ b/templates/vanilla/package.json @@ -7,7 +7,7 @@ "dev:client": "pnpm --filter 'client' run dev", "dev:contracts": "pnpm --filter 'contracts' dev", "foundry:up": "curl -L https://foundry.paradigm.xyz | bash && bash $HOME/.foundry/bin/foundryup", - "mud:up": "pnpm recursive exec mud set-version -v canary && pnpm install", + "mud:up": "pnpm mud set-version --tag main && pnpm install", "prepare": "(forge --version || pnpm foundry:up)", "test": "pnpm recursive run test" },