Skip to content
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
2 changes: 2 additions & 0 deletions scripts/test.luau
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ runProcess({
process.env.TEST_UNIVERSE_ID,
"--load.project",
"tests/test.project.json",
"--lua.globals",
"HELLO_GLOBAL=hello,WORLD_GLOBAL=world!",
"--binaryOutput",
"build/testOutput.txt",
"--verbose",
Expand Down
67 changes: 47 additions & 20 deletions src/commands/run.luau
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,30 @@ USAGE:
rocale-cli run [options]

REQUIRED:
-u, --universeId <id> Target universe ID to spawn an Open Cloud instance of
-p, --placeId <id> Target place ID to spawn an Open Cloud instance of
--apiKey <key> Roblox API key (or set ROBLOX_API_KEY env var)
-u, --universeId <id> Target universe ID to spawn an Open Cloud instance of
-p, --placeId <id> Target place ID to spawn an Open Cloud instance of
--apiKey <key> Roblox API key (or set ROBLOX_API_KEY env var)

LOAD OPTIONS:
--load.project <file> Rojo project.json/rbxp to build and load (requires rojo or robloxdev-cli)
--load.place <file> Load an rbxl
--load.version <num> Load existing place version without building/uploading
(set to 0 to rerun last uploaded version)
--load.project <file> Rojo project.json/rbxp to build and load (requires rojo or robloxdev-cli)
--load.place <file> Load an rbxl
--load.version <num> Load existing place version without building/uploading
(set to 0 to rerun last uploaded version)

BUILD OPTIONS:
--output <file> Output file path for the built place file
(default: output.rbxl)
--script <file> Luau script to load and set as entrypoint
--output <file> Output file path for the built place file
(default: output.rbxl)
--script <file> Luau script to load and set as entrypoint

EXECUTION OPTIONS:
--timeout <seconds> Timeout for polling task completion (default: 300)
--pollInterval <seconds> Interval between polling attempts (default: 2)
--binaryOutput <file> Path to save binary output from the task
--lua.globals <key=value,...> Comma-separated list of Lua globals to inject
--timeout <seconds> Timeout for polling task completion (default: 300)
--pollInterval <seconds> Interval between polling attempts (default: 2)
--binaryOutput <file> Path to save binary output from the task

FLAGS:
-v, --verbose Enable verbose logging
--help Show this help message
-v, --verbose Enable verbose logging
--help Show this help message
]])
end

Expand All @@ -55,6 +56,7 @@ return function(...)
args:add("load.version", "option")
args:add("load.place", "option")
args:add("apiKey", "option")
args:add("lua.globals", "option", { default = nil })
args:add("timeout", "option", { default = "300" })
args:add("pollInterval", "option", { default = "2" })
args:add("binaryOutput", "option", { default = nil })
Expand All @@ -76,6 +78,21 @@ return function(...)
or args:get("apiKey")
or log.fatal("Missing API Key: Set ROBLOX_API_KEY environment variable or provide it as an argument")

local luaGlobals = {}
if args:get("lua.globals") then
local globals = args:get("lua.globals")
assert(globals, "Expected globals to be a comma-separated list of key=value pairs")

for _, pair in ipairs(string.split(globals, ",")) do
local key, value = pair:match("([^=]+)=([^=]+)")
if key and value then
luaGlobals[key] = value
else
log.fatal("Expected format for globals is key=value")
end
end
end

local placeInfo: ocaleSdk.PlaceInfo = {
universeId = tonumber(args:get("universeId")) or log.fatal("Missing a universe ID"),
placeId = tonumber(args:get("placeId")) or log.fatal("Missing a place ID"),
Expand Down Expand Up @@ -140,12 +157,22 @@ return function(...)
end
assert(entryScript)

local enableBinaryOutput = false
local binaryOutputPath = nil
if args:get("binaryOutput") then
enableBinaryOutput = true
binaryOutputPath = args:get("binaryOutput")
end
assert(binaryOutputPath, "Binary output path should be a valid file path")
local enableBinaryOutput = binaryOutputPath ~= nil

local task = ocaleSdk.createTask(apiKey, placeInfo, entryScript, tonumber(args:get("timeout")), nil, enableBinaryOutput)
local task = ocaleSdk.createTask(
apiKey,
placeInfo,
entryScript,
tonumber(args:get("timeout")),
nil,
enableBinaryOutput,
luaGlobals
)
local completedTask = ocaleSdk.pollTaskCompletion(
apiKey,
task.path,
Expand All @@ -158,8 +185,8 @@ return function(...)

if enableBinaryOutput and completedTask.binaryOutputUri then
local binaryOutput = ocaleSdk.getBinaryOutput(completedTask.binaryOutputUri)
fs.writestringtofile(args:get("binaryOutput"), binaryOutput)
log.info(`{richterm.green("✓", log.noColor())} Binary output saved to '{args:get("binaryOutput")}'`)
fs.writestringtofile(binaryOutputPath, binaryOutput)
log.info(`{richterm.green("✓", log.noColor())} Binary output saved to '{binaryOutputPath}'`)
end

if completedTask.state == "FAILED" then
Expand Down
21 changes: 19 additions & 2 deletions src/core/ocaleSdk.luau
Original file line number Diff line number Diff line change
Expand Up @@ -86,26 +86,43 @@ export type TaskResponse = {
binaryInput: string?,
binaryOutputUri: string?,
}

function OcaleSDK.createTask(
apiKey: string,
placeInfo: PlaceInfo,
scriptPath: string,
timeout: number?,
binaryInputPath: string?,
enableBinaryOutput: boolean?
enableBinaryOutput: boolean?,
luaGlobals: { [string]: string }?
): TaskResponse
log.info(`{richterm.blue("→", log.noColor())} Creating the OCALE task...`)
local url = getCreateTaskPath(placeInfo)
local entryScript = fs.readfiletostring(scriptPath)

-- inject globals at the top of the entry script
if luaGlobals then
local keys: { string } = {}
local values: { string } = {}
for key, value in pairs(luaGlobals) do
table.insert(keys, `_G[{string.format("%q", key)}]`)
table.insert(values, string.format("%q", value))
end
local assignGlobals = table.concat(keys, ",") .. "=" .. table.concat(values, ",") .. " "
entryScript = assignGlobals .. entryScript
end

local req: net.Metadata = {
method = "POST",
headers = { ["x-api-key"] = apiKey, ["content-type"] = "application/json" },
body = json.serialize({
script = fs.readfiletostring(scriptPath),
script = entryScript,
binaryInput = binaryInputPath,
enableBinaryOutput = enableBinaryOutput,
timeout = `{timeout}s`,
}),
}

log.debug(`Request URL: {url}`)
local response = net.request(url, req)
log.fatalif(not response.ok, `{response.status} - {response.body}`)
Expand Down
2 changes: 2 additions & 0 deletions tests/project/init.luau
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
assert(_G.HELLO_GLOBAL == "hello", "_G.HELLO_GLOBAL should be set to 'hello'")
assert(_G.WORLD_GLOBAL == "world!", "_G.WORLD_GLOBAL should be set to 'world!'")
return true