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: 1 addition & 1 deletion scripts/build.luau
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ fs.write(versionFile, `return \{ version="{version}", hash="{hash}" \}`)
fs.close(versionFile)

log.info("Building rocale-cli...")
runProcess({ "lute", "compile", "src/cli.luau", "--output", output_path, "--show-require-graph", "--bundle-stats" })
runProcess("lute", "compile", "src/cli.luau", "--output", output_path, "--show-require-graph", "--bundle-stats")
log.info("Build complete: " .. output_path)
12 changes: 6 additions & 6 deletions scripts/test.luau
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ log.setLevel("debug")

local runProcess = require("../src/util/runProcess")

runProcess({
runProcess(
"build/rocale-cli",
"run",
"--script",
Expand All @@ -21,16 +21,16 @@ runProcess({
"HELLO_GLOBAL=hello,WORLD_GLOBAL=world!",
"--binaryOutput",
"build/testOutput.txt",
"--verbose",
})
"--verbose"
)

local testOutput = fs.readFileToString("build/testOutput.txt")
fs.remove("build/testOutput.txt")
assert(testOutput == "hello world!", `Expected binary output to be "hello world!"`)

log.info("Rerunning tests using load.version and without optional variables")

runProcess({
runProcess(
"build/rocale-cli",
"run",
"--script",
Expand All @@ -41,5 +41,5 @@ runProcess({
process.env.TEST_UNIVERSE_ID,
"--load.version",
"0",
"--verbose",
})
"--verbose"
)
21 changes: 13 additions & 8 deletions src/commands/run.luau
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ FLAGS:
]])
end

local function toBoolNum(v: any): number
return if v then 1 else 0
end

return function(...)
local fs = require("@std/fs")
local process = require("@lute/process")
Expand Down Expand Up @@ -83,7 +87,7 @@ return function(...)
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
for _, pair in string.split(globals, ",") do
local key, value = pair:match("([^=]+)=([^=]+)")
if key and value then
luaGlobals[key] = value
Expand All @@ -98,11 +102,12 @@ return function(...)
placeId = tonumber(args:get("placeId")) or log.fatal("Missing a place ID"),
}

--stylua: ignore
if
(
(args:get("load.place") and 1 or 0)
+ (args:get("load.version") and 1 or 0)
+ (args:get("load.project") and 1 or 0)
toBoolNum(args:get("load.place"))
+ toBoolNum(args:get("load.version"))
+ toBoolNum(args:get("load.project"))
) > 1
then
log.fatal("Cannot specify more than one --load option")
Expand All @@ -126,16 +131,16 @@ return function(...)
assert(outputPath, "Missing output file path")

if projectFile:match("%.project%.json$") then
runProcess({ "rojo", "build", projectFile, "--output", outputPath })
runProcess("rojo", "build", projectFile, "--output", outputPath)
elseif projectFile:match("%.rbxp$") then
runProcess({
runProcess(
"robloxdev-cli",
"pack",
"--input",
projectFile,
"--output",
outputPath,
})
outputPath
)
else
log.fatal(`Unsupported project file: '{projectFile}'. Must be a 'project.json' or '.rbxp' file.`)
end
Expand Down
46 changes: 25 additions & 21 deletions src/core/ocaleSdk.luau
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ local task = require("@lute/task")
local log = require("../util/log")
local richterm = require("@batteries/richterm")

local boldYellowFormatter = richterm.combine(richterm.yellow, richterm.bold)
local spinnerChars = table.freeze({ "|", "/", "-", "\\" })

local function formatSeconds(s: number): string
return string.format("%.1fs", s)
end

local OcaleSDK = {}

export type BinaryInputResponse = { path: string, size: number, uploadUri: string }
Expand Down Expand Up @@ -104,14 +111,12 @@ function OcaleSDK.createTask(

-- inject globals at the top of the entry script
if luaGlobals and next(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))
local globalAssignments: { string } = {}

for key, value in luaGlobals do
table.insert(globalAssignments, `_G["{key}"]="{value}";`)
end
local assignGlobals = table.concat(keys, ",") .. "=" .. table.concat(values, ",") .. " "
entryScript = assignGlobals .. entryScript
entryScript = table.concat(globalAssignments) .. entryScript
end

local req: client.Metadata = {
Expand Down Expand Up @@ -143,21 +148,19 @@ function OcaleSDK.pollTaskCompletion(
local timeRemaining = timeout or 300
local interval = pollInterval or 2

local spinnerChars = { "|", "/", "-", "\\" }
local spinnerIndex = 1
local spinner = richterm.yellow(spinnerChars[spinnerIndex], log.noColor())

local startTime = os.clock()
local elapsed = string.format("%.1f", os.clock() - startTime)
log.info(`Polling for OCALE task completion`)

if not log.noColor() then
task.spawn(function()
local spinnerIndex = 1

while timeRemaining > 0 do
spinner = richterm.bold(richterm.yellow(spinnerChars[spinnerIndex], log.noColor()))
elapsed = string.format("%.1f", os.clock() - startTime)
log.update(`{spinner} {richterm.dim(`[{elapsed}s]`, log.noColor())} Polling for OCALE task completion`)
spinnerIndex = spinnerIndex % #spinnerChars + 1
local spinner = boldYellowFormatter(spinnerChars[spinnerIndex], log.noColor())
local elapsed = formatSeconds(os.clock() - startTime)

log.update(`{spinner} {richterm.dim(`[{elapsed}]`, log.noColor())} Polling for OCALE task completion`)
spinnerIndex = (spinnerIndex % 4) + 1
task.wait(0.1)
end
end)
Expand All @@ -179,9 +182,9 @@ function OcaleSDK.pollTaskCompletion(
if body.state ~= "PROCESSING" then
timeRemaining = 0
task.wait(0.1)
elapsed = string.format("%.1f", os.clock() - startTime)
local elapsed = formatSeconds(os.clock() - startTime)
log.info(
`{richterm.green("✓", log.noColor())} {richterm.dim(`[{elapsed}s]`, log.noColor())} OCALE task completed`
`{richterm.green("✓", log.noColor())} {richterm.dim(`[{elapsed}]`, log.noColor())} OCALE task completed`
)
return body
end
Expand All @@ -190,9 +193,10 @@ function OcaleSDK.pollTaskCompletion(
end

timeRemaining = 0
elapsed = string.format("%.1f", os.clock() - startTime)
local elapsed = formatSeconds(os.clock() - startTime)
--stylua: ignore
return log.fatal(
`{richterm.red("✗", log.noColor())} {richterm.dim(`[{elapsed}s]`, log.noColor())} Task timed out`
`{richterm.red("✗", log.noColor())} {richterm.dim(`[{elapsed}]`, log.noColor())} Task timed out`
)
end

Expand All @@ -219,4 +223,4 @@ function OcaleSDK.getTaskLogs(apiKey: string, taskPath: string): { string }
return logs
end

return OcaleSDK
return table.freeze(OcaleSDK)
134 changes: 42 additions & 92 deletions src/util/log.luau
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local log = {}

type Level = "trace" | "debug" | "info" | "warn" | "error"

local dimBlueFormatter = richterm.combine(richterm.blue, richterm.dim)
local currentLevel: Level = "info"

local colorsEnabled = true -- set to false to disable colors
Expand All @@ -18,122 +19,69 @@ end

local showCaller = true -- set to false to disable caller information

local levels = {
local levels = table.freeze({
trace = 1,
debug = 2,
info = 3,
warn = 4,
error = 5,
} :: { [Level]: number }
}) :: { [Level]: number }

function log.should(level: Level)
return levels[level] >= levels[currentLevel]
local function stringifyVararg(...: any): string
return table.concat({ ... }, " ")
end

-- Get caller information from debug traceback.
local function getCallerInfo()
if not showCaller then
return ""
end
local traceback = debug.traceback()
local lines = string.split(traceback, "\n")

-- Look for the first line that's not in this logger module.
for _, line in ipairs(lines) do
if line:find("util/log") then
continue
end

return line
end

return "[unknown]"
function log.should(level: Level)
return levels[level] >= levels[currentLevel]
end

function log.trace(...)
if log.should("trace") then
local l: string = ""
if colorsEnabled then
l = richterm.combine(richterm.blue, richterm.dim)("[TRACE] ")
print(l .. richterm.dim(... or ""))
else
l = "[TRACE] "
print(l .. (... or ""))
end
local prefix = dimBlueFormatter("[TRACE] ")
print(prefix .. richterm.dim(stringifyVararg(...), colorsEnabled))
end
end

function log.debug(...)
if log.should("debug") then
local l: string = ""
if colorsEnabled then
l = richterm.cyan("[DEBUG] ")
print(l .. richterm.dim(... or ""))
else
l = "[DEBUG] "
print(l .. (... or ""))
end
local prefix = richterm.cyan("[DEBUG] ", colorsEnabled)
print(prefix .. richterm.dim(stringifyVararg(...), colorsEnabled))
end
end

function log.info(...)
if log.should("info") then
local l: string = ""
if colorsEnabled then
l = richterm.green("[INFO] ")
else
l = "[INFO] "
end
print(l .. (... or ""))
local prefix = richterm.green("[INFO] ", colorsEnabled)
print(prefix .. stringifyVararg(...))
end
end

function log.update(...)
if log.should("info") then
local l: string = ""
if colorsEnabled then
l = richterm.green("[INFO] ")
print("\x1b[1A\x1b[2K" .. l .. (... or ""))
else
l = "[INFO] "
print(l .. (... or ""))
end
local prefix = richterm.green("[INFO] ", colorsEnabled)
print("\x1b[1A\x1b[2K" .. prefix .. stringifyVararg(...))
end
end

function log.warn(...)
if log.should("warn") then
local l: string = ""
if colorsEnabled then
l = richterm.yellow("[WARN] ")
else
l = "[WARN] "
end
print(l .. (... or ""))
local prefix = richterm.yellow("[WARN] ", colorsEnabled)
print(prefix .. stringifyVararg(...))
end
end

function log.error(...)
if log.should("error") then
local l: string = ""
if colorsEnabled then
l = richterm.red("[ERROR] ")
else
l = "[ERROR] "
end
print(l .. (... or ""))
local prefix = richterm.red("[ERROR] ", colorsEnabled)
print(prefix .. stringifyVararg(...))
end
end

function log.fatal(...): never
local caller = getCallerInfo()
local l: string = ""
if colorsEnabled then
l = richterm.red("[FATAL] ")
else
l = "[FATAL] "
end
print(caller .. " | " .. l .. (... or "") .. "\n")
local prefix = richterm.red("[FATAL] ", colorsEnabled)
local message = prefix .. stringifyVararg(...)

print(if showCaller then debug.traceback(message, 2) else message)
process.exit(1)
return nil :: any
end
Expand Down Expand Up @@ -167,26 +115,28 @@ function log.noColor()
end

function log.pretty(tbl: any, indent: number?): string
local i = indent or 0
local spacing = string.rep(" ", i)
if type(tbl) ~= "table" then
return tostring(tbl)
end
local result = "{\n"
for key, value in pairs(tbl) do
local keyStr = type(key) == "string" and key or "[" .. tostring(key) .. "]"
result = result .. spacing .. " " .. keyStr .. ": "
if type(value) == "table" then
result = result .. log.pretty(value, i + 1)
elseif type(value) == "string" then
result = result .. '"' .. value .. '"'
else
result = result .. tostring(value)
end
result = result .. "\n"

indent = indent or 0
local spacing = string.rep(" ", indent)
local result = { "{" }

for key, value in tbl do
local keyStr = if type(key) == "string" then key else `["{key}"]`
--stylua: ignore
local valueStr = if type(value) == "table" then
log.pretty(value, indent + 1)
elseif type(value) == "string" then
`"{value}"`
else
value

table.insert(result, `{keyStr}: {valueStr}`)
end
result = result .. spacing .. "}"
return result
table.insert(result, "}")
return table.concat(result, `\n{spacing}`)
end

return log
return table.freeze(log)
Loading
Loading