From 3e3f768fe2fc3d19f24cfb0d2cdfce0296a63621 Mon Sep 17 00:00:00 2001 From: Micah Date: Fri, 13 Feb 2026 18:04:26 -0800 Subject: [PATCH] Add Lune script for uploading plugin --- .gitmodules | 3 ++ .lune/.config.luau | 8 ++++ .lune/opencloud-execute | 1 + .lune/scripts/plugin-upload.luau | 51 +++++++++++++++++++++++ .lune/upload-plugin.luau | 71 ++++++++++++++++++++++++++++++++ plugin.project.json | 3 ++ plugin/UploadDetails.json | 7 ++++ rokit.toml | 1 + 8 files changed, 145 insertions(+) create mode 100644 .lune/.config.luau create mode 160000 .lune/opencloud-execute create mode 100644 .lune/scripts/plugin-upload.luau create mode 100644 .lune/upload-plugin.luau create mode 100644 plugin/UploadDetails.json diff --git a/.gitmodules b/.gitmodules index 90ebae43..59bf5d32 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "plugin/Packages/msgpack-luau"] path = plugin/Packages/msgpack-luau url = https://github.com/cipharius/msgpack-luau/ +[submodule ".lune/opencloud-execute"] + path = .lune/opencloud-execute + url = https://github.com/Dekkonot/opencloud-luau-execute-lune.git diff --git a/.lune/.config.luau b/.lune/.config.luau new file mode 100644 index 00000000..43665fdb --- /dev/null +++ b/.lune/.config.luau @@ -0,0 +1,8 @@ +return { + luau = { + languagemode = "strict", + aliases = { + lune = "~/.lune/.typedefs/0.10.4/", + }, + }, +} diff --git a/.lune/opencloud-execute b/.lune/opencloud-execute new file mode 160000 index 00000000..8ae86dd3 --- /dev/null +++ b/.lune/opencloud-execute @@ -0,0 +1 @@ +Subproject commit 8ae86dd3ad35eb66b0a4edda7e8771a5986cd0c6 diff --git a/.lune/scripts/plugin-upload.luau b/.lune/scripts/plugin-upload.luau new file mode 100644 index 00000000..edbcb477 --- /dev/null +++ b/.lune/scripts/plugin-upload.luau @@ -0,0 +1,51 @@ +local args: any = ... +assert(args, "no arguments passed to script") + +local input: buffer = args.BinaryInput + +local AssetService = game:GetService("AssetService") +local SerializationService = game:GetService("SerializationService") +local EncodingService = game:GetService("EncodingService") + +local input_hash: buffer = EncodingService:ComputeBufferHash(input, Enum.HashAlgorithm.Sha256) +local hex_hash: { string } = table.create(buffer.len(input_hash)) +for i = 0, buffer.len(input_hash) - 1 do + table.insert(hex_hash, string.format("%02x", buffer.readu8(input_hash, i))) +end + +print(`Deserializing plugin file (size: {buffer.len(input)} bytes, hash: {table.concat(hex_hash, "")})`) +local plugin = SerializationService:DeserializeInstancesAsync(input)[1] + +local UploadDetails = require(plugin.UploadDetails) :: any +local PLUGIN_ID = UploadDetails.assetId +local PLUGIN_NAME = UploadDetails.name +local PLUGIN_DESCRIPTION = UploadDetails.description +local PLUGIN_CREATOR_ID = UploadDetails.creatorId +local PLUGIN_CREATOR_TYPE = UploadDetails.creatorType + +assert(typeof(PLUGIN_ID) == "number", "UploadDetails did not contain a number field 'assetId'") +assert(typeof(PLUGIN_NAME) == "string", "UploadDetails did not contain a string field 'assetId'") +assert(typeof(PLUGIN_DESCRIPTION) == "string", "UploadDetails did not contain a string field 'assetId'") +assert(typeof(PLUGIN_CREATOR_ID) == "number", "UploadDetails did not contain a number field 'assetId'") +assert(typeof(PLUGIN_CREATOR_TYPE) == "string", "UploadDetails did not contain a string field 'assetId'") +assert( + Enum.AssetCreatorType:FromName(PLUGIN_CREATOR_TYPE) ~= nil, + "UploadDetails field 'creatorType' was not a valid member of Enum.AssetCreatorType" +) + +print(`Uploading to {PLUGIN_ID}`) +print(`Plugin Name: {PLUGIN_NAME}`) +print(`Plugin Description: {PLUGIN_DESCRIPTION}`) + +local result, version_or_err = AssetService:CreateAssetVersionAsync(plugin, Enum.AssetType.Plugin, PLUGIN_ID, { + ["Name"] = PLUGIN_NAME, + ["Description"] = PLUGIN_DESCRIPTION, + ["CreatorId"] = PLUGIN_CREATOR_ID, + ["CreatorType"] = Enum.AssetCreatorType:FromName(PLUGIN_CREATOR_TYPE), +}) + +if result ~= Enum.CreateAssetResult.Success then + error(`Plugin failed to upload because: {result.Name} - {version_or_err}`) +end + +print(`Plugin uploaded successfully. New version is {version_or_err}.`) diff --git a/.lune/upload-plugin.luau b/.lune/upload-plugin.luau new file mode 100644 index 00000000..6cdf68b3 --- /dev/null +++ b/.lune/upload-plugin.luau @@ -0,0 +1,71 @@ +local fs = require("@lune/fs") +local process = require("@lune/process") +local stdio = require("@lune/stdio") + +local luau_execute = require("./opencloud-execute") + +local UNIVERSE_ID = process.env["RBX_UNIVERSE_ID"] +local PLACE_ID = process.env["RBX_PLACE_ID"] + +local plugin_path = process.args[1] +assert( + typeof(plugin_path) == "string", + "no plugin path provided, expected usage is `lune run upload-plugin [PATH TO RBXM]`." +) + +-- For local testing +if process.env["CI"] ~= "true" then + local rojo = process.exec("rojo", { "build", "plugin.project.json", "--output", plugin_path }) + if not rojo.ok then + stdio.ewrite("plugin upload failed because: could not build plugin.rbxm\n\n") + stdio.ewrite(rojo.stderr) + stdio.ewrite("\n") + process.exit(1) + end +else + assert(fs.isFile(plugin_path), `Plugin file did not exist at {plugin_path}`) +end +local plugin_content = fs.readFile(plugin_path) + +local engine_script = fs.readFile(".lune/scripts/plugin-upload.luau") + +print("Creating task to upload plugin") +local task = luau_execute.create_task_latest(UNIVERSE_ID, PLACE_ID, engine_script, 300, false, plugin_content) + +print("Waiting for task to finish") +local success = luau_execute.await_finish(task) +if not success then + local error = luau_execute.get_error(task) + assert(error, "could not fetch error from task") + stdio.ewrite("plugin upload failed because: task did not finish successfully\n\n") + stdio.ewrite(error.code) + stdio.ewrite("\n") + stdio.ewrite(error.message) + stdio.ewrite("\n") + process.exit(1) +end + +print("Output from task:\n") +for _, log in luau_execute.get_structured_logs(task) do + if log.messageType == "ERROR" then + stdio.write(stdio.color("red")) + stdio.write(log.message) + stdio.write("\n") + stdio.write(stdio.color("reset")) + elseif log.messageType == "INFO" then + stdio.write(stdio.color("cyan")) + stdio.write(log.message) + stdio.write("\n") + stdio.write(stdio.color("reset")) + elseif log.messageType == "WARNING" then + stdio.write(stdio.color("yellow")) + stdio.write(log.message) + stdio.write("\n") + stdio.write(stdio.color("reset")) + else + stdio.write(stdio.color("reset")) + stdio.write(log.message) + stdio.write("\n") + stdio.write(stdio.color("reset")) + end +end diff --git a/plugin.project.json b/plugin.project.json index 83265250..1742547b 100644 --- a/plugin.project.json +++ b/plugin.project.json @@ -22,6 +22,9 @@ }, "Version": { "$path": "plugin/Version.txt" + }, + "UploadDetails": { + "$path": "plugin/UploadDetails.json" } } } diff --git a/plugin/UploadDetails.json b/plugin/UploadDetails.json new file mode 100644 index 00000000..c4c4e0a3 --- /dev/null +++ b/plugin/UploadDetails.json @@ -0,0 +1,7 @@ +{ + "assetId": 13916111004, + "name": "Rojo", + "description": "The plugin portion of Rojo, a tool to enable professional tooling for Roblox developers.", + "creatorId": 8725819037, + "creatorType": "Group" +} \ No newline at end of file diff --git a/rokit.toml b/rokit.toml index 6fbd8746..67dafa12 100644 --- a/rokit.toml +++ b/rokit.toml @@ -3,3 +3,4 @@ rojo = "rojo-rbx/rojo@7.5.1" selene = "Kampfkarren/selene@0.29.0" stylua = "JohnnyMorganz/stylua@2.1.0" run-in-roblox = "rojo-rbx/run-in-roblox@0.3.0" +lune = "lune-org/lune@0.10.4"