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
27 changes: 27 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#
# Logging
#

LOG_LEVEL=info
# Set this to `true` to have Studio Activity print log messages to the Output window.
ENABLE_OUTPUT_LOGGING=false

#
# Backend
#

API_HOST=activity.brooke.sh

#
# Discord
#

DISCORD_CLIENT_ID=

#
# Open Cloud
#

ROBLOX_API_KEY=
ROBLOX_UNIT_TESTING_PLACE_ID=137718969043315
ROBLOX_UNIT_TESTING_UNIVERSE_ID=10128045586
4 changes: 1 addition & 3 deletions .github/workflows/analyze.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ jobs:
run: rokit list

- name: Run Lune setup
run: |
lune setup
rm -f .luaurc
run: lune setup

- name: 📦 Setup project
run: lune run setup
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Run Lune setup
run: |
lune setup
rm -f .luaurc
run: lune setup

- name: 📦 Setup project
run: lune run setup
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ jobs:
run: lute run test
env:
ROBLOX_API_KEY: ${{ secrets.ROBLOX_API_KEY }}
ROBLOX_UNIT_TESTING_UNIVERSE_ID: "10128045586"
ROBLOX_UNIT_TESTING_PLACE_ID: "137718969043315"
12 changes: 12 additions & 0 deletions .luaurc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"languageMode": "strict",
"aliases": {
"lune": "~/.lune/.typedefs/0.10.4/",
"lint": "~/.lute/typedefs/1.0.0/lint",
"lute": "~/.lute/typedefs/1.0.0/lute",
"std": "~/.lute/typedefs/1.0.0/std",
"pkg": "./Packages",
"repo": ".",
"scripts": "./.lute"
}
}
6 changes: 0 additions & 6 deletions .lune/.luaurc

This file was deleted.

1 change: 1 addition & 0 deletions .lune/utils/inject-build-vars.luau
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ local function injectBuildVars(config: Config)
build = {
version = version,
channel = "live",
target = "",
hash = gitHash,
isDev = not isProd,
},
Expand Down
1 change: 0 additions & 1 deletion .lute/.config.luau
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ return {
aliases = {
batteries = "../Packages/lute@v1.0.0/batteries",
dotenv = "../Packages/dotenv@v0.1.2/src",
std = "~/.lute/typedefs/1.0.0/std",
},
},
}
53 changes: 53 additions & 0 deletions .lute/analyze.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
local fs = require("@std/fs")
local path = require("@std/path")

local project = require("@repo/project")
local run = require("@scripts/lib/run")

local globalDefsPath = path.resolve("./plugin/generated/globalTypes.d.luau")

if not fs.exists(globalDefsPath) then
run("curl", {
"-s",
"-o",
globalDefsPath,
"-O",
"https://raw.githubusercontent.com/JohnnyMorganz/luau-lsp/master/scripts/globalTypes.d.lua",
})
end

run("rojo", {
"sourcemap",
project.ROJO_BUILD_PROJECT,
"-o",
project.SOURCEMAP_PATH,
"--absolute",
})

local defaultArgs: { string | path.Pathlike } = {
"analyze",
`--defs={globalDefsPath}`,
"--settings=./.vscode/settings.json",
}

-- New solver analysis
-- TODO: Work out why Lute doesn't analyze
-- do
-- local args = table.clone(defaultArgs)
-- table.insert(args, "--platform=standard")
-- table.insert(args, "--flag:LuauSolverV2=true")
-- table.insert(args, path.resolve("./.lute"))

-- run("luau-lsp", { table.unpack(args) })
-- end

-- Old solver analysis
do
local args = table.clone(defaultArgs)
table.insert(args, `--sourcemap={project.SOURCEMAP_PATH}`)
table.insert(args, path.resolve("./.lute"))
table.insert(args, path.resolve("./plugin/src"))
table.insert(args, path.resolve("./plugin/bin"))

run("luau-lsp", { table.unpack(args) })
end
183 changes: 183 additions & 0 deletions .lute/build.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
local cli = require("@batteries/cli")
local dotenv = require("@dotenv")
local fs = require("@std/fs")
local path = require("@std/path")
local pp = require("@batteries/pp")
local process = require("@std/process")
local richterm = require("@batteries/richterm")
local toml = require("@batteries/toml")

local buildSystem = require("@scripts/lib/build-system")
local copyInto = require("@scripts/lib/copyInto")
local getStudioPluginsPath = require("@scripts/lib/getStudioPluginsPath")
local project = require("@repo/project")
local run = require("@scripts/lib/run")
local watch = require("@scripts/lib/watch")

local WALLY_MANIFEST_PATH = path.resolve("plugin/wally.toml")

type BuildContext = buildSystem.BuildContext

pcall(dotenv.config)

local args = cli.parser()

args:add("channel", "option", {
help = "Channel to build for",
aliases = { "c" },
default = "prod",
})
args:add("target", "option", {
help = "Target to build for",
aliases = { "t" },
default = "local",
})
args:add("output", "option", {
help = "Full path to the rbxm file to build",
aliases = { "o" },
default = tostring(path.join(getStudioPluginsPath(), project.PLUGIN_FILENAME)),
})
args:add("watch", "flag", {
help = "Watch for changes and recompile automatically",
aliases = { "w" },
})
args:add("skip-reload", "flag", {
help = "Skip reloading the plugin in Roblox Studio",
})
args:add("clean", "flag", {
help = "Performs a full rebuild of the project",
})

args:parse({ ... })

local channel = args:get("channel")
assert(channel == "dev" or channel == "prod", `bad value for channel (must be one of "dev" or "prod", got "{channel}")`)

local target = args:get("target")
assert(
target == "creator-store" or target == "local",
`bad value for target (must be one of "creator-store" or "local", got "{target}")`
)

local output = args:get("output")
assert(typeof(output) == "string", `bad value for output (string expected, got {typeof(output)})`)

local function readWallyManifestAsync()
return toml.deserialize(fs.readFileToString(WALLY_MANIFEST_PATH))
end

local function getCommitHash()
local commitHash = run("git", { "rev-parse", "--short", "HEAD" }, {
captureOutput = true,
})
assert(commitHash ~= nil and commitHash ~= "", "commit hash is empty")
return commitHash
end

-- This environment variable comes from `.env` and is required to be set. This
-- condition just makes sure if it's _not_ set that the user will then go and
-- get their `.env` file in order
if not process.env.API_HOST then
error(table.concat({
"One or more critical environment variables are not set.",
"Please make sure to copy `.env.template` to `.env`. If you already have a `.env` file, make sure the environment variables from the template match your local copy",
}, "\n\n"))
end

local context: BuildContext = {
channel = channel,
target = target,
shouldRebuild = args:has("clean"),
dest = path.join(project.BUILD_PATH, channel, target),
vars = {
build = {
version = (readWallyManifestAsync() :: any).package.version,
channel = channel,
target = target,
isDev = channel ~= "prod",
hash = getCommitHash(),
},

api = {
secure = channel == "prod",
host = process.env.API_HOST,
},

discord = {
clientId = process.env.DISCORD_CLIENT_ID,
},
},
cache = buildSystem.readBuildCacheAsync(),
}

local function buildPluginBinary()
buildSystem.runBuildGroupAsync({
name = "🔌 plugin binary",
paths = { context.dest },
context = context,
step = function()
local projectPath = path.resolve(path.join(context.dest, "default.project.json"))
copyInto(project.ROJO_BUILD_PROJECT, projectPath)

local dest = path.resolve(path.join(context.dest, "..", project.PLUGIN_FILENAME))

run("rojo", {
"build",
projectPath,
"-o",
dest,
})

fs.remove(projectPath)

if args:has("skip-reload") then
if output:match(tostring(getStudioPluginsPath())) then
return
end
end

copyInto(dest, output)
end,
})
end

local function build()
local startTime = os.clock()

local contextNoCache = table.clone(context)
contextNoCache.cache = nil :: any
print(richterm.dim(`build context: {pp(contextNoCache)}`))

buildSystem.compileAsync(context)
buildSystem.writeBuildCacheAsync(context.cache)

buildPluginBinary()

print(`build completed in {("%.2f"):format(os.clock() - startTime)}s`)
end

build()

if args:has("watch") then
local function onChanged(filePath: path.Path)
print("change?", filePath)
if tostring(filePath):match(tostring(project.PLUGIN_PATH)) then
buildSystem.writeBuildCacheAsync(context.cache)
buildPluginBinary()
else
build()
end
end

watch({
roots = {
"./plugin",
"./protos",
},
excludedFilePatterns = {
".*Packages",
"build",
},
onChanged = onChanged,
})
end
66 changes: 66 additions & 0 deletions .lute/lib/build-system/compileAsync.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
local fs = require("@std/fs")
local path = require("@std/path")

local copyInto = require("@scripts/lib/copyInto")
local project = require("@repo/project")
local run = require("@scripts/lib/run")
local runBuildGroupAsync = require("@scripts/lib/build-system/runBuildGroupAsync")
local types = require("@scripts/lib/build-system/types")
local writeBuildVarsAsync = require("@scripts/lib/build-system/writeBuildVarsAsync")

type BuildContext = types.BuildContext

local function compileAsync(context: BuildContext)
if context.shouldRebuild then
fs.removeDirectory(context.dest, {
recursive = true,
})
end
fs.createDirectory(context.dest, {
makeParents = true,
})

copyInto("plugin/bin", path.join(context.dest, "bin"))
copyInto("plugin/src", path.join(context.dest, "src"))
copyInto("plugin/resources", path.join(context.dest, "resources"))

writeBuildVarsAsync(context)

runBuildGroupAsync({
name = "🚚 dependencies",
paths = {
project.PACKAGES_PATH,
project.DEV_PACKAGES_PATH,
},
context = context,
step = function(group)
for _, filePath in group.paths do
local relativePath = path.relative(project.PLUGIN_PATH, filePath)
copyInto(filePath, path.join(context.dest, relativePath))
end
end,
})

if context.channel == "prod" then
runBuildGroupAsync({
name = `✂️ prune build`,
paths = { context.dest },
context = context,
step = function()
for _, pattern in project.PROD_CONFIG.prunedFiles do
run("find", { context.dest, "-type", "f", "-name", `"{pattern}"`, "-delete" })
end
end,
})

for _, dir in project.PROD_CONFIG.prunedDirs do
local relativePath = path.relative(project.PLUGIN_PATH, dir)

fs.removeDirectory(path.join(context.dest, relativePath), {
recursive = true,
})
end
end
end

return compileAsync
Loading
Loading