Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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)
6 changes: 3 additions & 3 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,8 +21,8 @@ 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")
Expand Down
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