Skip to content

Commit

Permalink
allow downloading legacy versions
Browse files Browse the repository at this point in the history
  • Loading branch information
JairusSW committed Oct 9, 2024
1 parent 91ff1f5 commit 3e2043b
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 43 deletions.
5 changes: 4 additions & 1 deletion tools/cli/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Ignore output files
oclif.manifest.json
tsconfig.tsbuildinfo
tsconfig.tsbuildinfo

# Ignore build folders
tmp/
44 changes: 30 additions & 14 deletions tools/cli/src/commands/dev/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import { Args, Command, Flags } from "@oclif/core";
import { expandHomeDir, isRunnable } from "../../util/index.js";
import BuildCommand from "../build/index.js";
import path from "path";
import { copyFileSync, existsSync, readdirSync, readFileSync, watch as watchFolder } from "fs";
import { copyFileSync, existsSync, fstat, readdirSync, readFileSync, watch as watchFolder, writeFileSync } from "fs";
import chalk from "chalk";
import { execSync, spawn, spawnSync } from "child_process";
import { execSync, spawnSync } from "child_process";
import os from "node:os";

export default class Run extends Command {
Expand Down Expand Up @@ -64,6 +64,10 @@ export default class Run extends Command {
hidden: false,
required: false,
default: getLatestRuntime()
}),
legacy: Flags.boolean({
description: "Run if you want a pre-modus release",
default: false
})
};

Expand All @@ -73,8 +77,8 @@ export default class Run extends Command {

async run(): Promise<void> {
const { args, flags } = await this.parse(Run);
const isDev = flags.runtime && (flags.runtime.startsWith("dev-") || flags.runtime.startsWith("link"));
const runtimePath = path.join(expandHomeDir("~/.modus/sdk/" + flags.runtime), (isDev ? "/runtime" : "/runtime" + (os.platform() === "win32" ? ".exe" : "")));
const isDev = flags.legacy || flags.runtime && (flags.runtime.startsWith("dev-") || flags.runtime.startsWith("link"));
const runtimePath = path.join(expandHomeDir("~/.modus/sdk/" + (isDev ? "" : "v") + flags.runtime), flags.legacy ? "" : (isDev ? "/runtime" : "/runtime" + (os.platform() === "win32" ? ".exe" : "")));

const cwd = path.join(process.cwd(), args.path);
const watch = flags.watch;
Expand Down Expand Up @@ -111,7 +115,7 @@ export default class Run extends Command {
}

if (!existsSync(runtimePath)) {
this.logError("Modus Runtime " + (isDev ? "" : "v") + flags.runtime + " not installed!\n Run `modus sdk install " + install_cmd + "` and try again!");
this.logError("Modus Runtime " + runtimePath + " " + (isDev ? "" : "v") + flags.runtime + " not installed!\n Run `modus sdk install v" + install_cmd + "` and try again!");
process.exit(0);
}

Expand All @@ -134,15 +138,27 @@ export default class Run extends Command {
if (!isRunnable("go")) {
this.logError("Cannot find any valid versions of Go! Please install go")
}
execSync("go run ./tools/generate_version", {
cwd: runtimePath,
stdio: "ignore",
env: {
...process.env,
MODUS_ENV: "dev",
MODUS_BUILD_VERSION: "modus-cli/" + flags.runtime
}
});
if (flags.legacy) {
writeFileSync(path.join(runtimePath, "config/version.go"), `package config
func GetProductVersion() string {
return "Hypermode Runtime " + GetVersionNumber()
}
func GetVersionNumber() string {
return "modus-cli/${flags.runtime}"
}`);
} else {
execSync("go run ./tools/generate_version", {
cwd: runtimePath,
stdio: "ignore",
env: {
...process.env,
MODUS_ENV: "dev",
MODUS_BUILD_VERSION: "modus-cli/" + flags.runtime
}
});
}

execSync("go run .", {
cwd: runtimePath,
Expand Down
116 changes: 88 additions & 28 deletions tools/cli/src/commands/sdk/install/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,22 @@ export default class SDKInstallCommand extends Command {

static flags = {
silent: Flags.boolean({
char: "s",
description: "Suppress output logs",
hidden: false,
required: false
}),
// These are meant for developers working on modus itself
// You can link a directory as your runtime
// You can also run a specific branch
// You can also run a specific branch and commit on that branch
repo: Flags.string({
hidden: true,
char: "r",
description: "Change the GitHub owner and repo eg. hypermodeinc/modus",
required: false,
default: "hypermodeinc/modus"
}),
branch: Flags.string({
hidden: true,
char: "b",
Expand All @@ -60,61 +71,108 @@ export default class SDKInstallCommand extends Command {

async run(): Promise<void> {
const ctx = await this.parse(SDKInstallCommand);
if (ctx.flags.branch) this.installCommit(ctx);
else if (ctx.flags.link) this.linkDir(ctx);
if (ctx.args.version) await this.installVersion(ctx);
else if (ctx.flags.branch) await this.installCommit(ctx);
else if (ctx.flags.link) await this.linkDir(ctx);
}

async installCommit(ctx: ParserCtx) {
async installVersion(ctx: ParserCtx) {
const { args, flags } = ctx;
let version = args.version?.toLowerCase();
const release_info = await fetchRelease(flags.repo, version!);
if (version == "latest") {
this.log("[1/4] Getting latest version");
version = release_info["tag_name"];
clearLine();
this.log("[1/4] Latest version: " + chalk.dim(version));
} else {
this.log("[1/4] Getting release info")
}

version = version?.replace("v", "");

this.log("[2/4] Downloading release");
const extension = os.platform() == "win32" ? ".zip" : ".tar.gz";
const filename = "v" + version + extension;
const downloadLink = "https://github.com/" + flags.repo + "/archive/refs/tags/" + filename;

const archiveName = ("modus-" + version + extension).replaceAll("/", "-");
const tempDir = expandHomeDir("~/.modus/.modus-temp");
const archivePath = path.join(tempDir, archiveName);

mkdirSync(tempDir, { recursive: true });
await downloadFile(downloadLink, archivePath);

clearLine();
this.log("[2/4] Downloaded release");

const unpackedDir = tempDir + "/" + archiveName.replace(extension, "");
this.log("[3/4] Unpacking release" + "tar -xf " + archivePath + " -C " + unpackedDir);
await rm(unpackedDir, { recursive: true, force: true });
mkdirSync(unpackedDir, { recursive: true })
execSync("tar -xf " + archivePath + " -C " + unpackedDir);

clearLine();
this.log("[3/4] Unpacked release");

this.log("[4/4] Building");
const installDir = expandHomeDir("~/.modus/sdk/" + version) + "/";
cpSync(unpackedDir + "/modus-" + version?.replace("v", "") + "/", installDir, { recursive: true, force: true });
clearLine();

await rm(tempDir, { recursive: true, force: true });
this.log("[4/4] Successfully installed Modus " + version)
}

async installCommit(ctx: ParserCtx) {
const { flags } = ctx;

flags.commit = flags.commit.slice(0, 7);

let sha = "";
if (!flags.commit) {
flags.commit = "latest";
this.log("[1/4] Getting latest commit");
} else {
const commit_info = await fetchCommit("hypermodeinc", "modus", flags.commit);
sha = commit_info.sha;
this.log("[1/4] Getting commit " + flags.commit);
}
let { id, branch } = await get_branch_info("hypermodeinc", "modus", "main");

const commit_info = await fetchCommit(flags.repo, flags.commit);
sha = commit_info.sha;
this.log("[1/4] Getting commit " + flags.commit);
let { id, branch } = await fetchBranch(flags.repo, "main");
if (sha) id = sha.slice(0, 7);
const version = branch + "/" + id;
clearLine();
this.log("[1/4] Found latest commit");

this.log("[2/4] Fetching Modus from latest commit" + " " + chalk.dim("(" + version + ")"));
const downloadLink = flags.commit == "latest" ? "https://github.com/hypermodeinc/modus/archive/refs/heads/" + branch + ".zip" : "https://github.com/hypermodeinc/modus/archive/" + sha + ".zip";
const downloadLink = flags.commit == "latest" ? "https://github.com/" + flags.repo + "/archive/refs/heads/" + branch + ".zip" : "https://github.com/" + flags.repo + "/archive/" + sha + ".zip";
const archiveName = ("modus-" + version + ".zip").replaceAll("/", "-");
const tempDir = expandHomeDir("~/.modus/.modus-temp");
await downloadFile(downloadLink, archiveName);
//clearLine();
const archivePath = path.join(tempDir, archiveName);
mkdirSync(tempDir, { recursive: true });

await downloadFile(downloadLink, archivePath);
clearLine();
this.log("[2/4] Fetched Modus");

this.log("[3/4] Unpacking archive");
mkdirSync(tempDir, { recursive: true });
const unpackedDir = tempDir + "/" + archiveName.replace(".zip", "");
await rm(unpackedDir, { recursive: true, force: true });
mkdirSync(unpackedDir, { recursive: true });
if (os.platform() === "win32") {
execSync("tar -xf " + archiveName + " -C " + unpackedDir);
execSync("tar -xf " + archivePath + " -C " + unpackedDir);
} else {
execSync("unzip " + archiveName + " -d " + unpackedDir);
execSync("unzip " + archivePath + " -d " + unpackedDir);
}
clearLine();
this.log("[3/4] Unpacked archive");

rmSync(archiveName);
this.log("[4/4] Installing");
const installDir = expandHomeDir("~/.modus/sdk/dev-" + branch + "-" + id) + "/";
cpSync(unpackedDir + "/modus-" + (flags.commit == "latest" ? branch : sha) + "/", installDir, { recursive: true, force: true });
clearLine();

await rm(tempDir, { recursive: true, force: true });
this.log("[4/4] Successfully installed Modus " + version)
}

async linkDir(ctx: ParserCtx) {
const { args, flags } = ctx;
const { flags } = ctx;

const srcDir = path.join(process.cwd(), flags.link!);
if (!existsSync(srcDir)) {
Expand All @@ -133,7 +191,7 @@ export default class SDKInstallCommand extends Command {
if (!(await this.confirmAction(rl, "[2/4] Continue? [y/n]"))) {
process.exit(0);
}

linkDirectories(srcDir, installDir)
clearLine();
clearLine();
Expand All @@ -154,21 +212,23 @@ export default class SDKInstallCommand extends Command {
}
}

async function get_latest_release(): Promise<string> {
const res = (await (await fetch("https://api.github.com/repos/hypermodeinc/modus/releases/latest")).json());
async function fetchRelease(repo: string, version: string): Promise<{
tag_name: string
}> {
const res = (await (await fetch("https://api.github.com/repos/" + repo + "/releases/" + version)).json());
if (!res) {
console.log(chalk.red(" ERROR ") + chalk.dim(": Could not find latest release! Please check your internet connection and try again."));
process.exit(0);
}
return res;
}

async function get_branch_info(owner: string, repo: string, branch: string): Promise<{
async function fetchBranch(repo: string, branch: string): Promise<{
sha: string,
id: string,
branch: string
}> {
const res = (await (await fetch(`https://api.github.com/repos/${owner}/${repo}/branches/${branch}`)).json());
const res = (await (await fetch(`https://api.github.com/repos/${repo}/branches/${branch}`)).json());
if (!res) {
console.log(chalk.red(" ERROR ") + chalk.dim(": Could not find branch! Please check your internet connection and try again."));
process.exit(0);
Expand All @@ -180,10 +240,10 @@ async function get_branch_info(owner: string, repo: string, branch: string): Pro
}
}

async function fetchCommit(owner: string, repo: string, commitSha: string): Promise<{
async function fetchCommit(repo: string, commitSha: string): Promise<{
sha: string
}> {
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/commits/${commitSha}`);
const response = await fetch(`https://api.github.com/repos/${repo}/commits/${commitSha}`);
if (!response.ok) {
console.log(chalk.red(" ERROR ") + chalk.dim(": Could not find commit! Please check your internet connection and try again."));
process.exit(0);
Expand Down

0 comments on commit 3e2043b

Please sign in to comment.