mirror of
https://github.com/0x5eal/semver-luau.git
synced 2024-12-12 15:00:36 +00:00
chore: include dev utility scripts and ci workflow
* Includes dev utility scripts for fmt and typecheck. * Includes a CI workflow which checks formatting, runs tests, and does typechecking.
This commit is contained in:
parent
9bde66aed4
commit
f620acee55
6 changed files with 241 additions and 0 deletions
71
.github/workflows/ci.yml
vendored
Normal file
71
.github/workflows/ci.yml
vendored
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
fmt:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install tooling
|
||||||
|
uses: CompeyDev/setup-rokit@v0.1.2
|
||||||
|
with:
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Check formatting
|
||||||
|
run: lune run fmt -- --check
|
||||||
|
|
||||||
|
test:
|
||||||
|
needs: ["fmt"]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install tooling
|
||||||
|
uses: CompeyDev/setup-rokit@v0.1.2
|
||||||
|
with:
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Install pesde
|
||||||
|
uses: ./.github/workflows/pesde.yml
|
||||||
|
with:
|
||||||
|
pesde-token: ${{ secrets.PESDE_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pesde install
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: lune run tests
|
||||||
|
|
||||||
|
typecheck:
|
||||||
|
needs: ["test"]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install tooling
|
||||||
|
uses: CompeyDev/setup-rokit@v0.1.2
|
||||||
|
with:
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Install pesde
|
||||||
|
uses: ./.github/workflows/pesde.yml
|
||||||
|
with:
|
||||||
|
pesde-token: ${{ secrets.PESDE_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pesde install
|
||||||
|
|
||||||
|
- name: Typecheck
|
||||||
|
run: lune run typecheck
|
29
.github/workflows/pesde.yml
vendored
Normal file
29
.github/workflows/pesde.yml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
name: Install pesde
|
||||||
|
description: Installs pesde CLI and authenticates with the registry
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
pesde-token:
|
||||||
|
description: "Token for publishing to the pesde registry"
|
||||||
|
required: false
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Download pesde
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
latest_release=$(curl -s https://api.github.com/repos/daimond113/pesde/releases | jq '[.[] | select(.prerelease == true or .prerelease == false)][0]')
|
||||||
|
download_url=$(echo "$latest_release" | jq -r '.assets[] | select(.name | endswith("linux-x86_64.tar.gz")) | .browser_download_url')
|
||||||
|
|
||||||
|
curl -L -o /tmp/pesde.tar.gz "$download_url"
|
||||||
|
tar -xzvf /tmp/pesde.tar.gz
|
||||||
|
chmod +x pesde
|
||||||
|
|
||||||
|
./pesde self-install
|
||||||
|
rm ./pesde
|
||||||
|
echo "$HOME/.pesde/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- name: Authenticate into pesde registry
|
||||||
|
if: inputs.pesde-token != ''
|
||||||
|
shell: bash
|
||||||
|
run: pesde auth login --token ${{ inputs.pesde-token }}
|
110
.lune/exec.luau
Normal file
110
.lune/exec.luau
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
--> lib: Builder pattern class to spawn child processes
|
||||||
|
|
||||||
|
local stdio = require("@lune/stdio")
|
||||||
|
local process = require("@lune/process")
|
||||||
|
|
||||||
|
local Option = require("../luau_packages/option")
|
||||||
|
type Option<T> = Option.Option<T>
|
||||||
|
|
||||||
|
local CommandBuilder = {}
|
||||||
|
|
||||||
|
export type CommandBuilder = typeof(setmetatable({} :: CommandBuilderFields, { __index = CommandBuilder }))
|
||||||
|
type CommandBuilderFields = {
|
||||||
|
program: string,
|
||||||
|
args: { string },
|
||||||
|
stdioStrategy: Option<IoStrategyMapping>,
|
||||||
|
}
|
||||||
|
export type StdioStrategy = "pipe" | "forward" | "none"
|
||||||
|
export type IoStrategyMapping = {
|
||||||
|
stdout: Option<StdioStrategy>,
|
||||||
|
stderr: Option<StdioStrategy>,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- FIXME: remove unknown usage
|
||||||
|
local DEFAULT_STDIO_STRATEGY: IoStrategyMapping = {
|
||||||
|
stdout = Option.Some("pipe" :: StdioStrategy) :: Option<unknown>,
|
||||||
|
stderr = Option.Some("pipe" :: StdioStrategy) :: Option<unknown>,
|
||||||
|
}
|
||||||
|
function CommandBuilder.new(program: string)
|
||||||
|
return setmetatable(
|
||||||
|
{
|
||||||
|
program = program,
|
||||||
|
args = {},
|
||||||
|
stdioStrategy = Option.None :: Option<IoStrategyMapping>,
|
||||||
|
} :: CommandBuilderFields,
|
||||||
|
{
|
||||||
|
__index = CommandBuilder,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function CommandBuilder.withArg(self: CommandBuilder, arg: string): CommandBuilder
|
||||||
|
table.insert(self.args, arg)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function CommandBuilder.withArgs(self: CommandBuilder, args: { string }): CommandBuilder
|
||||||
|
for _, arg in args do
|
||||||
|
self:withArg(arg)
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function CommandBuilder.withStdioStrategy(
|
||||||
|
self: CommandBuilder,
|
||||||
|
strategy: StdioStrategy | IoStrategyMapping
|
||||||
|
): CommandBuilder
|
||||||
|
-- FIXME: remove unknown usage
|
||||||
|
self.stdioStrategy = Option.Some(if typeof(strategy) == "string"
|
||||||
|
then {
|
||||||
|
stdout = Option.Some(strategy) :: Option<unknown>,
|
||||||
|
stderr = Option.Some(strategy) :: Option<unknown>,
|
||||||
|
}
|
||||||
|
else strategy) :: Option<IoStrategyMapping>
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
local function intoSpawnOptionsStdioKind(strategy: StdioStrategy): process.SpawnOptionsStdioKind
|
||||||
|
if strategy == "pipe" then
|
||||||
|
return "default"
|
||||||
|
end
|
||||||
|
|
||||||
|
if strategy == "forward" then
|
||||||
|
return "forward"
|
||||||
|
end
|
||||||
|
|
||||||
|
if strategy == "none" then
|
||||||
|
return "none"
|
||||||
|
end
|
||||||
|
|
||||||
|
error(`Non-strategy provided: {strategy}`)
|
||||||
|
end
|
||||||
|
|
||||||
|
function CommandBuilder.exec(self: CommandBuilder): process.SpawnResult
|
||||||
|
print("$", self.program, table.concat(self.args, " "))
|
||||||
|
local child = process.spawn(self.program, self.args, {
|
||||||
|
shell = true,
|
||||||
|
stdio = self
|
||||||
|
.stdioStrategy
|
||||||
|
-- FIXME: remove unknown usage
|
||||||
|
:orOpt(Option.Some(DEFAULT_STDIO_STRATEGY) :: Option<unknown>)
|
||||||
|
:map(function(mappings: IoStrategyMapping)
|
||||||
|
local translatedMappings: process.SpawnOptionsStdio = {}
|
||||||
|
for field, value in mappings do
|
||||||
|
translatedMappings[field] = intoSpawnOptionsStdioKind((value :: Option<StdioStrategy>):unwrap())
|
||||||
|
end
|
||||||
|
|
||||||
|
return translatedMappings
|
||||||
|
end)
|
||||||
|
:unwrap(),
|
||||||
|
})
|
||||||
|
|
||||||
|
if not child.ok then
|
||||||
|
print(`\n{stdio.color("red")}[luau-lsp]{stdio.color("reset")} Exited with code`, child.code)
|
||||||
|
end
|
||||||
|
|
||||||
|
return child
|
||||||
|
end
|
||||||
|
|
||||||
|
return CommandBuilder
|
7
.lune/fmt.luau
Normal file
7
.lune/fmt.luau
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
--> Run stylua to check for formatting errors
|
||||||
|
|
||||||
|
local process = require("@lune/process")
|
||||||
|
|
||||||
|
local CommandBuilder = require("./exec")
|
||||||
|
|
||||||
|
process.exit(CommandBuilder.new("stylua"):withArg("."):withArgs(process.args):withStdioStrategy("forward"):exec().code)
|
15
.lune/typecheck.luau
Normal file
15
.lune/typecheck.luau
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
--> Run luau-lsp analysis to check for type errors
|
||||||
|
|
||||||
|
local process = require("@lune/process")
|
||||||
|
|
||||||
|
local CommandBuilder = require("./exec")
|
||||||
|
|
||||||
|
process.exit(
|
||||||
|
CommandBuilder.new("luau-lsp")
|
||||||
|
:withArg("analyze")
|
||||||
|
:withArgs({ "--settings", ".vscode/settings.json" })
|
||||||
|
:withArgs({ "--ignore", "'./**/.pesde/**'" })
|
||||||
|
:withArg(".")
|
||||||
|
:withStdioStrategy("forward")
|
||||||
|
:exec().code
|
||||||
|
)
|
9
rokit.toml
Normal file
9
rokit.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# This file lists tools managed by Rokit, a toolchain manager for Roblox projects.
|
||||||
|
# For more information, see https://github.com/rojo-rbx/rokit
|
||||||
|
|
||||||
|
# New tools can be added by running `rokit add <tool>` in a terminal.
|
||||||
|
|
||||||
|
[tools]
|
||||||
|
lune = "lune-org/lune@0.8.9"
|
||||||
|
stylua = "JohnnyMorganz/StyLua@2.0.1"
|
||||||
|
luau-lsp = "JohnnyMorganz/luau-lsp@1.35.0"
|
Loading…
Reference in a new issue