From 10e06963d25963387998ec9935c489951bcbc10e Mon Sep 17 00:00:00 2001 From: TJ Kolleh Date: Sun, 5 Apr 2026 17:27:16 -0400 Subject: [PATCH 1/3] fix(ci): use lx exec to resolve luastatic build dependency This resolves the 'luastatic: command not found' error by allowing Lux to automatically resolve the local executable instead of modifying the system PATH. --- .github/workflows/release-please.yml | 4 ---- justfile | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 26969eb..bd798e3 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -46,10 +46,6 @@ jobs: sudo mv /tmp/just/just /usr/local/bin/ rm -rf /tmp/just - - name: Add Lux bin to PATH - if: ${{ steps.release.outputs.release_created }} - run: echo "$HOME/.lux/5.4/bin" >> "$GITHUB_PATH" - - name: Build Executable if: ${{ steps.release.outputs.release_created }} env: diff --git a/justfile b/justfile index 1ebafd5..5607d8e 100644 --- a/justfile +++ b/justfile @@ -153,7 +153,7 @@ build-system: prep [private] compile: @echo "Compiling standalone binary..." - cd lua && luastatic ../bin/spin.lua \ + cd lua && lx --lua-version {{ lua_version }} exec -- luastatic ../bin/spin.lua \ roda/init.lua roda/spinners.lua roda/ansi.lua roda/symbols.lua roda/util.lua roda/argp.lua \ ../{{ build_dir / 'libluv.a' }} ../{{ build_dir / 'libuv.a' }} ../{{ build_dir / 'libsystem.a' }} {{ lua_lib }} \ -I{{ lua_include }} && \ From 42d3a0582c1b8e4094e3f856774ec724e4cd7d31 Mon Sep 17 00:00:00 2001 From: TJ Kolleh Date: Wed, 8 Apr 2026 20:41:20 -0400 Subject: [PATCH 2/3] fix(build): add missing CLI entry point and upgrade Lux to v0.28.0 - Create bin/spin.lua with CLI argument parsing using roda.argp - Fix absolute path handling in justfile compile recipe - Upgrade all GitHub Actions workflows from Lux 0.18.8/0.25.3 to 0.28.0 - Update AGENTS.md documentation to reflect new version - Add validation check for bin/spin.lua existence before compilation --- .github/workflows/publish.yml | 7 +- .github/workflows/release-please.yml | 3 +- .github/workflows/tests.yml | 12 +-- .gitignore | 3 + bin/spin.lua | 154 +++++++++++++++++++++++++++ justfile | 5 +- 6 files changed, 171 insertions(+), 13 deletions(-) create mode 100644 bin/spin.lua diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 21fec6e..98e87d3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -27,10 +27,9 @@ jobs: - name: Install Lux uses: lumen-oss/gh-actions-lux@v1 with: - # Using v0.25.3 for publish (not v0.18.8 used in tests) - # Reason: v0.18.8 has bugs with lx upload causing 400 errors - # The publish workflow doesn't run tests, so no busted/penlight issues - version: 0.25.3 + # Using v0.28.0 for publish (consistent with all workflows) + # The busted/penlight dependency issues are resolved in v0.28.0 + version: 0.28.0 - name: Install LuaRocks (for validation) run: | diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index bd798e3..8d3e0cd 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -35,7 +35,8 @@ jobs: if: ${{ steps.release.outputs.release_created }} uses: lumen-oss/gh-actions-lux@v1 with: - version: 0.25.3 + # Using v0.28.0 for consistency with all workflows (busted/penlight issues resolved) + version: 0.28.0 - name: Install just if: ${{ steps.release.outputs.release_created }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bfef524..8de3246 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,11 +17,11 @@ jobs: - name: Install Lux uses: lumen-oss/gh-actions-lux@v1 with: - # Pinned to v0.18.8 due to busted/penlight transitive dependency issues + # Using v0.28.0 (busted/penlight dependency issues resolved in lux-lib 0.8.0+) + # Previously pinned to v0.18.8 due to busted/penlight transitive dependency issues # in newer versions (see lumen-oss/lux#722) - # The publish workflow uses v0.25.3 which doesn't have this issue - # because it doesn't run tests (no busted dependency) - version: 0.18.8 + # All workflows now use v0.28.0 consistently + version: 0.28.0 - name: Install system dependencies run: | @@ -49,8 +49,8 @@ jobs: - name: Install Lux uses: lumen-oss/gh-actions-lux@v1 with: - # See comment in test job above for version pinning rationale - version: 0.18.8 + # See comment in test job above for version upgrade rationale + version: 0.28.0 - name: Install just run: | diff --git a/.gitignore b/.gitignore index 89d4287..e9b855c 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,6 @@ bin_spin.luastatic.c spin.luastatic.c lua/spin.luastatic.c *.luastatic.c + +# Agent documentation (user-specific) +AGENTS.md diff --git a/bin/spin.lua b/bin/spin.lua new file mode 100644 index 0000000..ea2fd23 --- /dev/null +++ b/bin/spin.lua @@ -0,0 +1,154 @@ +#!/usr/bin/env -S lx lua +--- roda CLI entry point +-- Parses command-line arguments and runs a spinner for the given command. + +-- Add local path for development +package.path = "./lua/?.lua;./lua/?/init.lua;" .. package.path +package.cpath = "./.build/?.so;" .. package.cpath + +local argp = require("roda.argp") +local roda = require("roda") + +local parser = argp:new({ + name = "roda", + description = "Elegant terminal spinners for Lua. Wraps commands with visual feedback.", + epilog = "If no command is provided, roda will exit with status 0.", +}) + +parser:options({ + { + short = "t", + long = "title", + description = "Text to display next to the spinner", + type = "string", + count_params = 1, + dest = "title", + }, + { + long = "spinner", + description = "Spinner style to use (e.g., dots, line, arc)", + type = "string", + count_params = 1, + dest = "spinner", + }, + { + long = "show-output", + description = "Display the command's stdout/stderr after it finishes", + type = "boolean", + count_params = 0, + dest = "show_output", + }, + { + short = "c", + long = "color", + description = "Color of the spinner (e.g., cyan, green, yellow)", + type = "string", + count_params = 1, + dest = "color", + }, + { + long = "prefix-text", + description = "Text before spinner", + type = "string", + count_params = 1, + dest = "prefix_text", + }, + { + long = "suffix-text", + description = "Text after spinner text", + type = "string", + count_params = 1, + dest = "suffix_text", + }, + { + short = "h", + long = "help", + description = "Show this help message", + type = "boolean", + count_params = 0, + dest = "help", + }, +}) + +local function main(...) + local args = { ... } + if #args == 0 then + -- No arguments, exit 0 as per test expectation + os.exit(0) + end + + local parsed, err = pcall(function() + return parser:parse(args) + end) + + if not parsed then + io.stderr:write("error: " .. tostring(err) .. "\n") + os.exit(1) + end + + local options = err -- result from pcall + + if options.help then + parser:print_system_help() + os.exit(0) + end + + -- Find the '--' separator + local separator_index = nil + for i, arg in ipairs(args) do + if arg == "--" then + separator_index = i + break + end + end + + local command_args = {} + if separator_index then + for i = separator_index + 1, #args do + table.insert(command_args, args[i]) + end + end + + -- Build spinner options + local spinner_opts = {} + if options.title then + spinner_opts.text = options.title + end + if options.spinner then + spinner_opts.spinner = options.spinner + end + if options.color then + spinner_opts.color = options.color + end + if options.prefix_text then + spinner_opts.prefixText = options.prefix_text + end + if options.suffix_text then + spinner_opts.suffixText = options.suffix_text + end + + local spinner = roda(spinner_opts) + + if #command_args == 0 then + -- No command to execute, just exit (test 6) + os.exit(0) + end + + local command = command_args[1] + local cmd_args = {} + for i = 2, #command_args do + table.insert(cmd_args, command_args[i]) + end + + spinner:execute(command, cmd_args)(function(exit_code, output) + if options.show_output and output and #output > 0 then + io.stdout:write(output) + io.stdout:flush() + end + os.exit(exit_code) + end) + + roda.run() +end + +main(...) \ No newline at end of file diff --git a/justfile b/justfile index bab65ce..8fac6c6 100644 --- a/justfile +++ b/justfile @@ -155,12 +155,13 @@ build-system: prep [group('build')] [private] compile: + @echo {{ assert(path_exists("bin/spin.lua") == "true", "bin/spin.lua not found - CLI entry point missing") }} @echo "Compiling standalone binary..." cd lua && lx --lua-version {{ lua_version }} exec -- luastatic ../bin/spin.lua \ roda/init.lua roda/spinners.lua roda/ansi.lua roda/symbols.lua roda/util.lua roda/argp.lua \ - ../{{ build_dir / 'libluv.a' }} ../{{ build_dir / 'libuv.a' }} ../{{ build_dir / 'libsystem.a' }} {{ lua_lib }} \ + {{ build_dir / 'libluv.a' }} {{ build_dir / 'libuv.a' }} {{ build_dir / 'libsystem.a' }} {{ lua_lib }} \ -I{{ lua_include }} && \ - mv spin.luastatic.c ../{{ build_dir }}/ && \ + mv spin.luastatic.c {{ build_dir }}/ && \ cd .. && \ mv lua/spin roda From 8ca9e276d2b5801bc8de53de54dca8b7d493fb87 Mon Sep 17 00:00:00 2001 From: TJ Kolleh Date: Wed, 8 Apr 2026 20:46:39 -0400 Subject: [PATCH 3/3] chore: remove AGENTS.md from local .gitignore (handled by global gitignore) --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index e9b855c..89d4287 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,3 @@ bin_spin.luastatic.c spin.luastatic.c lua/spin.luastatic.c *.luastatic.c - -# Agent documentation (user-specific) -AGENTS.md