Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): update set-version to match new release structure, add --tag, --commit #1157

Merged
merged 5 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .changeset/thin-buses-reply.md
Original file line number Diff line number Diff line change
@@ -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
```
99 changes: 67 additions & 32 deletions packages/cli/src/commands/set-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand All @@ -20,7 +23,7 @@ const MUD_PREFIX = "@latticexyz";
const commandModule: CommandModule<Options, Options> = {
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({
Expand All @@ -30,36 +33,44 @@ const commandModule: CommandModule<Options, Options> = {
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);
Expand All @@ -69,6 +80,42 @@ const commandModule: CommandModule<Options, Options> = {
},
};

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;
Expand Down Expand Up @@ -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<string, string>, curr: Record<string, string>) {
for (const key in prev) {
if (prev[key] !== curr[key]) {
Expand Down
2 changes: 1 addition & 1 deletion templates/phaser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
2 changes: 1 addition & 1 deletion templates/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
2 changes: 1 addition & 1 deletion templates/threejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
2 changes: 1 addition & 1 deletion templates/vanilla/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
Loading