--!strict local fs = require("@lune/fs") local process = require("@lune/process") local serde = require("@lune/serde") local stdio = require("@lune/stdio") local progress_bar = require("./util/progress") local result = require("./util/result") local shared = require("./shared") local tbl = require("./util/tbl") local types = require("./types") local function make_pesde_manifest(version: string, scope: string): types.PesdeManifest return { name = scope, version = version, authors = { "jecs authors" }, repository = "https://git.devmarked.win/marked/jecs-nightly", license = "MIT", includes = { "init.luau", "pesde.toml", "README.md", "CHANGELOG.md", "LICENSE", ".luaurc", }, target = { environment = "luau", lib = "jecs.luau", }, indices = { default = "https://github.com/pesde-pkg/index", }, } end local function make_wally_manifest(version: string, scope: string): types.WallyManifest return { package = { name = scope, version = version, registry = "https://github.com/UpliftGames/wally-index", realm = "shared", license = "MIT", include = { "default.project.json", "jecs.luau", "wally.toml", "README.md", "CHANGELOG.md", "LICENSE", }, exclude = { "**" }, }, } end local function release(origin: string, scopes: { wally: string?, pesde: string? }, dry: boolean?): result.Identity local begin = os.clock() local progress = progress_bar .new() :withStage("init", "Initializing") :withStage("version", "Pulling version from build metadata") :withStage("prepare", "Preparing manifests") :withStage("release (pesde)", "Releasing on pesde") :withStage("release (wally)", "Releasing on wally") progress:start() -- init if dry == nil then dry = true end if not fs.metadata(origin).exists then progress:stop() stdio.ewrite(`🔥 {origin} is not a valid directory which exists.\n`) return result(false, `{origin} is not a valid directory which exists.`) end progress:nextStage() -- version local version do local encoded_metadata = fs.readFile(`{origin}/build.txt`) local metadata: { version: string } = serde.decode("toml", encoded_metadata) version = metadata.version end progress:nextStage() -- prepare if scopes.pesde then local manifest = make_pesde_manifest(version, scopes.pesde) local encoded = serde.encode("toml", manifest) fs.writeFile(`{origin}/pesde.toml`, encoded) local rbx_manifest = tbl.deep_clone(manifest) rbx_manifest.target = { environment = "roblox", lib = "jecs.luau", build_files = { "jecs.luau" }, } local encoded_rbx = serde.encode("toml", rbx_manifest) fs.writeFile(`{origin}/pesde-rbx.toml`, encoded_rbx) end if scopes.wally then local manifest = make_wally_manifest(version, scopes.wally) local encoded = serde.encode("toml", manifest) fs.writeFile(`{origin}/wally.toml`, encoded) end progress:nextStage() -- release (pesde) local cwd = origin --process.cwd .. origin local res_pesde if scopes.pesde then if not dry then res_pesde = process.spawn("pesde", { "publish", "-y" }, { cwd = cwd }) else res_pesde = process.spawn("pesde", { "publish", "-d", "-y" }, { cwd = cwd }) end if not res_pesde.ok then progress:stop() print(`-- Pesde error:\nstdout\n{res_pesde.stdout}\nstderr\n{res_pesde.stderr}`) return result(false, `Pesde error:\nstdout\n{res_pesde.stdout}\nstderr\n{res_pesde.stderr}`) end end local res_pesde_rbx if scopes.pesde then fs.move(`{origin}/pesde.toml`, `{origin}/pesde-luau.toml`) fs.move(`{origin}/pesde-rbx.toml`, `{origin}/pesde.toml`) process.spawn("pesde", { "install" }, { cwd = cwd }) if not dry then res_pesde_rbx = process.spawn("pesde", { "publish", "-y" }, { cwd = cwd }) else res_pesde_rbx = process.spawn("pesde", { "publish", "-d", "-y" }, { cwd = cwd }) end fs.move(`{origin}/pesde.toml`, `{origin}/pesde-rbx.toml`) fs.move(`{origin}/pesde-luau.toml`, `{origin}/pesde.toml`) process.spawn("pesde", { "install" }, { cwd = cwd }) if not res_pesde_rbx.ok then progress:stop() print(`-- Pesde error:\nstdout\n{res_pesde_rbx.stdout}\nstderr\n{res_pesde_rbx.stderr}`) return result(false, `Pesde error:\nstdout\n{res_pesde_rbx.stdout}\nstderr\n{res_pesde_rbx.stderr}`) end end progress:nextStage() -- release (wally) local res_wally if scopes.wally then if not dry then res_wally = process.spawn("wally", { "publish" }, { cwd = cwd }) else res_wally = process.spawn("wally", { "package", "--output", "wally.tar.gz" }, { cwd = cwd }) end if not res_wally.ok then progress:stop() print(`-- Wally error:\nstdout\n{res_wally.stdout}\nstderr\n{res_wally.stderr}`) return result(false, `Wally error:\nstdout\n{res_wally.stdout}\nstderr\n{res_wally.stderr}`) end end progress:stop() -- finish if res_pesde then print(`-- Pesde out:\nstdout\n{res_pesde.stdout}\nstderr\n{res_pesde.stderr}`) end if res_pesde_rbx then print(`-- Pesde rbx out:\nstdout\n{res_pesde.stdout}\nstderr\n{res_pesde.stderr}`) end if res_wally then print(`-- Wally out:\nstdout\n{res_wally.stdout}\nstderr\n{res_wally.stderr}`) end local took = shared.round_to((os.clock() - begin) * 1_000, 2) if not dry then print(`🚀 Published packages {stdio.style("dim")}(took {took}ms){stdio.style("reset")}`) else print(`📦 Packaged packages {stdio.style("dim")}(took {took}ms){stdio.style("reset")}`) end if scopes.pesde and scopes.wally then print({ pesde = `{scopes.pesde}@{version}`, wally = `{scopes.wally}@{version}`, }) elseif scopes.pesde then print({ pesde = `{scopes.pesde}@{version}`, }) elseif scopes.wally then print({ wally = `{scopes.wally}@{version}`, }) end return result(true, nil) end return release