-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(cli): split cli in actions files (#889)
* refactor(cli): split cli in actions files * typo * Update javascript/packages/cli/src/cli.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * fmt * typo in path * Update javascript/packages/cli/src/actions/convert.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * Update javascript/packages/cli/src/actions/convert.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * Update javascript/packages/cli/src/actions/convert.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * Update javascript/packages/cli/src/actions/convert.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * Update javascript/packages/cli/src/actions/convert.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * Update javascript/packages/cli/src/actions/convert.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * Update javascript/packages/cli/src/actions/convert.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * Update javascript/packages/cli/src/actions/setup.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * Update javascript/packages/cli/src/actions/setup.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * Update javascript/packages/cli/src/actions/setup.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * Update javascript/packages/cli/src/actions/setup.ts Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com> * fix conflicts * types for cli --------- Co-authored-by: Loris Moulin <45130584+l0r1s@users.noreply.github.com>
- Loading branch information
Showing
8 changed files
with
599 additions
and
577 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import type { | ||
NodeConfig, | ||
ParachainConfig, | ||
PolkadotLaunchConfig, | ||
} from "@zombienet/orchestrator"; | ||
import { decorators, getFilePathNameExt } from "@zombienet/utils"; | ||
import fs from "fs"; | ||
import path from "path"; | ||
import { PL_ConfigType, PL_NodesConfig } from "src/types"; | ||
import { DEFAULT_BALANCE } from "../constants"; | ||
|
||
export async function convert(param: string) { | ||
try { | ||
const filePath = param; | ||
|
||
if (!filePath) { | ||
throw Error("Path of configuration file was not provided"); | ||
} | ||
|
||
// Read through the JSON and write to stream sample | ||
await convertInput(filePath); | ||
} catch (err) { | ||
console.log( | ||
`\n ${decorators.red("Error: ")} \t ${decorators.bright(err)}\n`, | ||
); | ||
} | ||
} | ||
|
||
// Convert functions | ||
// Read the input file | ||
async function readInputFile( | ||
ext: string, | ||
fPath: string, | ||
): Promise<PL_ConfigType> { | ||
if (ext === "json" || ext === "js") { | ||
return ext === "json" | ||
? JSON.parse(fs.readFileSync(`${fPath}`, "utf8")) | ||
: await import(path.resolve(fPath)); | ||
} | ||
|
||
throw Error("No valid extension was found."); | ||
} | ||
|
||
async function convertInput(filePath: string) { | ||
const { fullPath, fileName, extension } = getFilePathNameExt(filePath); | ||
|
||
const convertedJson = await readInputFile(extension, filePath); | ||
|
||
const { | ||
relaychain, | ||
parachains = [], | ||
simpleParachains = [], | ||
hrmpChannels = [], | ||
types, | ||
} = convertedJson; | ||
|
||
let jsonOutput: PolkadotLaunchConfig; | ||
const nodes: NodeConfig[] = []; | ||
let paras: ParachainConfig[] = []; | ||
|
||
const DEFAULT_NODE_VALUES = { | ||
validator: true, | ||
invulnerable: true, | ||
balance: DEFAULT_BALANCE, | ||
}; | ||
|
||
paras = paras.concat( | ||
parachains.map(({ id, nodes }) => ({ | ||
id, | ||
collators: ((nodes as PL_NodesConfig[]) || []).map(({ name }) => ({ | ||
name, | ||
command: "adder-collator", | ||
...DEFAULT_NODE_VALUES, | ||
})), | ||
})), | ||
); | ||
|
||
paras = paras.concat( | ||
simpleParachains.map(({ id, name }) => ({ | ||
id, | ||
collators: [{ name, command: "adder-collator", ...DEFAULT_NODE_VALUES }], | ||
})), | ||
); | ||
|
||
if (relaychain?.nodes) { | ||
relaychain.nodes.forEach((n: any) => { | ||
nodes.push({ | ||
name: `"${n.name}"`, | ||
...DEFAULT_NODE_VALUES, | ||
}); | ||
}); | ||
} | ||
|
||
jsonOutput = { | ||
relaychain: { | ||
default_image: "docker.io/paritypr/polkadot-debug:master", | ||
default_command: "polkadot", | ||
default_args: ["-lparachain=debug"], | ||
chain: relaychain?.chain || "", | ||
nodes, | ||
genesis: relaychain?.genesis, | ||
}, | ||
types, | ||
hrmp_channels: hrmpChannels, | ||
parachains: paras, | ||
}; | ||
|
||
fs.writeFile( | ||
`${fullPath}/${fileName}-zombienet.json`, | ||
JSON.stringify(jsonOutput), | ||
(error: any) => { | ||
if (error) throw error; | ||
}, | ||
); | ||
console.log( | ||
`Converted JSON config exists now under: ${fullPath}/${fileName}-zombienet.json`, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
import { askQuestion, convertBytes, decorators } from "@zombienet/utils"; | ||
import cliProgress from "cli-progress"; | ||
import fs from "fs"; | ||
import path from "path"; | ||
|
||
interface OptIf { | ||
[key: string]: { name: string; url?: string; size?: string }; | ||
} | ||
|
||
const options: OptIf = {}; | ||
/** | ||
* Setup - easily download latest artifacts and make them executablein order to use them with zombienet | ||
* Read more here: https://paritytech.github.io/zombienet/cli/setup.html | ||
* @param params binaries that willbe downloaded and set up. Possible values: `polkadot` `polkadot-parachain` | ||
* @returns | ||
*/ | ||
export async function setup(params: any) { | ||
const POSSIBLE_BINARIES = ["polkadot", "polkadot-parachain"]; | ||
|
||
console.log(decorators.green("\n\n🧟🧟🧟 ZombieNet Setup 🧟🧟🧟\n\n")); | ||
if (!["linux", "darwin"].includes(process.platform)) { | ||
console.log( | ||
"Zombienet currently supports linux and MacOS. \n Alternative, you can use k8s or podman. For more read here: https://github.com/paritytech/zombienet#requirements-by-provider", | ||
); | ||
return; | ||
} | ||
|
||
console.log(decorators.green("Gathering latest releases' versions...\n")); | ||
await new Promise<void>((resolve) => { | ||
latestPolkadotReleaseURL("polkadot", "polkadot").then( | ||
(res: [string, string]) => { | ||
options.polkadot = { | ||
name: "polkadot", | ||
url: res[0], | ||
size: res[1], | ||
}; | ||
resolve(); | ||
}, | ||
); | ||
}); | ||
|
||
await new Promise<void>((resolve) => { | ||
latestPolkadotReleaseURL("cumulus", "polkadot-parachain").then( | ||
(res: [string, string]) => { | ||
options["polkadot-parachain"] = { | ||
name: "polkadot-parachain", | ||
url: res[0], | ||
size: res[1], | ||
}; | ||
resolve(); | ||
}, | ||
); | ||
}); | ||
|
||
// If the platform is MacOS then the polkadot repo needs to be cloned and run locally by the user | ||
// as polkadot do not release a binary for MacOS | ||
if (process.platform === "darwin" && params.includes("polkadot")) { | ||
console.log( | ||
`${decorators.yellow( | ||
"Note: ", | ||
)} You are using MacOS. Please, clone the polkadot repo ` + | ||
decorators.cyan("(https://github.com/paritytech/polkadot)") + | ||
` and run it locally.\n At the moment there is no polkadot binary for MacOs.\n\n`, | ||
); | ||
params = params.filter((param: string) => param !== "polkadot"); | ||
} | ||
|
||
if (params.length === 0) { | ||
console.log(decorators.green("No binaries to download. Exiting...")); | ||
return; | ||
} | ||
let count = 0; | ||
console.log("Setup will start to download binaries:"); | ||
params.forEach((a: any) => { | ||
if (!POSSIBLE_BINARIES.includes(a)) { | ||
params = params.filter((param: any) => param !== a); | ||
console.log( | ||
decorators.red( | ||
`"${a}" is not one of the possible options for this setup and will be skipped;`, | ||
), | ||
decorators.green(` Valid options: polkadot polkadot-parachain`), | ||
); | ||
return; | ||
} | ||
const size = parseInt(options[a]?.size || "0", 10); | ||
count += size; | ||
console.log("-", a, "\t Approx. size ", size, " MB"); | ||
}); | ||
console.log("Total approx. size: ", count, "MB"); | ||
const response = await askQuestion( | ||
decorators.yellow("\nDo you want to continue? (y/n)"), | ||
); | ||
if (response.toLowerCase() !== "n" && response.toLowerCase() !== "y") { | ||
console.log("Invalid input. Exiting..."); | ||
return; | ||
} | ||
if (response.toLowerCase() === "n") { | ||
return; | ||
} | ||
downloadBinaries(params); | ||
return; | ||
} | ||
|
||
// helper fns | ||
// Download the binaries | ||
const downloadBinaries = async (binaries: string[]): Promise<void> => { | ||
try { | ||
console.log(decorators.yellow("\nStart download...\n")); | ||
const promises = []; | ||
|
||
const multibar = new cliProgress.MultiBar( | ||
{ | ||
clearOnComplete: false, | ||
hideCursor: true, | ||
format: | ||
decorators.yellow("{bar} - {percentage}%") + | ||
" | " + | ||
decorators.cyan("Binary name:") + | ||
" {filename}", | ||
}, | ||
cliProgress.Presets.shades_grey, | ||
); | ||
|
||
for (let binary of binaries) { | ||
promises.push( | ||
new Promise<void>(async (resolve, reject) => { | ||
let result = options[binary]; | ||
if (!result) { | ||
console.log("options", options, "binary", binary); | ||
throw new Error("Binary is not defined"); | ||
} | ||
const { url, name } = result; | ||
|
||
if (!url) throw new Error("No url for downloading, was provided"); | ||
|
||
const response = await fetch(url); | ||
|
||
if (!response.ok) | ||
throw Error(response.status + " " + response.statusText); | ||
|
||
const contentLength = response.headers.get( | ||
"content-length", | ||
) as string; | ||
let loaded = 0; | ||
|
||
const progressBar = multibar.create(parseInt(contentLength, 10), 0); | ||
const reader = response.body?.getReader(); | ||
const writer = fs.createWriteStream(path.resolve(name)); | ||
|
||
while (true) { | ||
const read = await reader?.read()!; | ||
if (read?.done) { | ||
writer.close(); | ||
resolve(); | ||
break; | ||
} | ||
|
||
loaded += read.value.length; | ||
progressBar.increment(); | ||
progressBar.update(loaded, { | ||
filename: name, | ||
}); | ||
writer.write(read.value); | ||
} | ||
}), | ||
); | ||
} | ||
|
||
await Promise.all(promises); | ||
multibar.stop(); | ||
console.log( | ||
decorators.cyan( | ||
`\n\nPlease add the current dir to your $PATH by running the command:\n`, | ||
), | ||
decorators.blue(`export PATH=${process.cwd()}:$PATH\n\n`), | ||
); | ||
} catch (err) { | ||
console.log( | ||
`\n ${decorators.red("Unexpected error: ")} \t ${decorators.bright( | ||
err, | ||
)}\n`, | ||
); | ||
} | ||
}; | ||
|
||
// Retrieve the latest release for polkadot | ||
const latestPolkadotReleaseURL = async ( | ||
repo: string, | ||
name: string, | ||
): Promise<[string, string]> => { | ||
try { | ||
const releases = await fetch( | ||
`https://api.github.com/repos/paritytech/${repo}/releases`, | ||
); | ||
|
||
let obj: any; | ||
let tag_name; | ||
|
||
const allReleases = await releases.json(); | ||
const release = allReleases.find((r: any) => { | ||
obj = r?.assets?.find((a: any) => a.name === name); | ||
return Boolean(obj); | ||
}); | ||
|
||
tag_name = release.tag_name; | ||
|
||
if (!tag_name) { | ||
throw new Error( | ||
"Should never come to this point. Tag_name should never be undefined!", | ||
); | ||
} | ||
|
||
return [obj.browser_download_url, convertBytes(obj.size)]; | ||
} catch (err: any) { | ||
if (err.code === "ENOTFOUND") { | ||
throw new Error("Network error."); | ||
} else if (err.response && err.response.status === 404) { | ||
throw new Error( | ||
"Could not find a release. Error 404 (not found) detected", | ||
); | ||
} | ||
throw new Error( | ||
`Error status: ${err?.response?.status}. Error message: ${err?.response}`, | ||
); | ||
} | ||
}; |
Oops, something went wrong.