From c7a2c793dca8509f9792e9d35d377de016c88a5b Mon Sep 17 00:00:00 2001 From: Marco Kellershoff <1384938+gorillamoe@users.noreply.github.com> Date: Mon, 14 Oct 2024 03:08:53 +0200 Subject: [PATCH] fix(tmp): use `stdpath('cache')` for tmp files (#284) * fix(tmp): use `stdpath('cache')` for tmp files This should fix: #282 * Add windows testrunner dockerfile * fix(ci): workflow file * refactor(ci): add optional windows test pipeline * feat(ci): windows * fix(fs): join_paths on windows * fix(ci): windows cache * fix(fs): gsub returns two params * debug(ci): windows caching * feat(tests): windows fs.join_paths * refactor(ci): tests --- .github/workflows/conform-code.yml | 43 ------------ .github/workflows/tests.yml | 68 +++++++++++++++++++ .../scripts/engines/javascript/init.lua | 16 ++--- lua/kulala/tmp/.gitignore | 2 - lua/kulala/tmp/scripts/requests/.gitignore | 1 - lua/kulala/utils/fs.lua | 41 ++++++++--- scripts/install-ci-test-requirements.ps1 | 44 ++++++++++++ scripts/tests.ps1 | 2 + tests/_dockerfiles/windows/Dockerfile | 46 ++++++++++++- tests/util/fs_spec.lua | 55 +++++++++++++++ 10 files changed, 252 insertions(+), 66 deletions(-) delete mode 100644 .github/workflows/conform-code.yml create mode 100644 .github/workflows/tests.yml delete mode 100644 lua/kulala/tmp/.gitignore delete mode 100644 lua/kulala/tmp/scripts/requests/.gitignore create mode 100644 scripts/install-ci-test-requirements.ps1 create mode 100644 scripts/tests.ps1 create mode 100644 tests/util/fs_spec.lua diff --git a/.github/workflows/conform-code.yml b/.github/workflows/conform-code.yml deleted file mode 100644 index 99acc24..0000000 --- a/.github/workflows/conform-code.yml +++ /dev/null @@ -1,43 +0,0 @@ ---- -name: Conform Code - -on: - pull_request: - paths: - - '**/*.lua' - branches: - - main - -jobs: - tests: - name: Tests - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - container-image: ghcr.io/mistweaverco/kulala-nvim-testrunner:latest - container: - image: ${{ matrix.container-image }} - steps: - - uses: actions/checkout@v4 - - name: Restore cache - uses: actions/cache@v4 - with: - path: | - .tests - key: ${{ runner.os }}-${{ matrix.container-image }} - - - name: Run tests - run: ./scripts/tests.sh run - lint: - name: Lint Code - runs-on: ubuntu-latest - container: - image: ghcr.io/mistweaverco/kulala-nvim-testrunner:latest - steps: - - uses: actions/checkout@v4 - - - name: Run linter - run: ./scripts/lint.sh check-code diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..a82511e --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,68 @@ +--- +name: Tests + +on: + pull_request: + paths: + - '**/*.lua' + branches: + - main + +jobs: + test-linux: + name: Test Code on Linux + runs-on: ubuntu-latest + container: + image: ghcr.io/mistweaverco/kulala-nvim-testrunner:latest + steps: + - uses: actions/checkout@v4 + - name: Restore cache + uses: actions/cache@v4 + with: + path: | + .tests + key: ${{ runner.os }}-tests + - name: Run tests + run: ./scripts/tests.sh run + lint: + name: Lint Code + runs-on: ubuntu-latest + container: + image: ghcr.io/mistweaverco/kulala-nvim-testrunner:latest + steps: + - uses: actions/checkout@v4 + + - name: Run linter + run: ./scripts/lint.sh check-code + test-windows: + name: Test Code on Windows + runs-on: windows-latest + if: ${{ github.event.label.name == 'needs-windows-test' }} + steps: + - uses: actions/checkout@v4 + - name: Restore cache + id: cache-deps + uses: actions/cache@v4 + with: + path: | + .tests + ~\scoop + ~\AppData\Roaming\LJ4W + ~\AppData\Roaming\luarocks + key: ${{ runner.os }}-tests + - name: Check if cache hit + if: steps.cache-deps.outputs.cache-hit == 'true' + run: echo "GH_CACHE_HIT=true" >> $Env:GITHUB_ENV + - name: Install dependencies + run: ./scripts/install-ci-test-requirements.ps1 + - name: Save cache + uses: actions/cache/save@v4 + with: + path: | + .tests + ~\scoop + ~\AppData\Roaming\LJ4W + ~\AppData\Roaming\luarocks + key: ${{ runner.os }}-tests + - name: Run tests + run: ./scripts/tests.ps1 diff --git a/lua/kulala/parser/scripts/engines/javascript/init.lua b/lua/kulala/parser/scripts/engines/javascript/init.lua index cfb78d1..f55b87c 100644 --- a/lua/kulala/parser/scripts/engines/javascript/init.lua +++ b/lua/kulala/parser/scripts/engines/javascript/init.lua @@ -8,13 +8,12 @@ local NPM_EXISTS = vim.fn.executable("npm") == 1 local NODE_EXISTS = vim.fn.executable("node") == 1 local SCRIPTS_DIR = FS.get_scripts_dir() local REQUEST_SCRIPTS_DIR = FS.get_request_scripts_dir() +local SCRIPTS_BUILD_DIR = FS.get_tmp_scripts_build_dir() local BASE_DIR = FS.join_paths(SCRIPTS_DIR, "engines", "javascript", "lib") -local BASE_FILE_PRE_CLIENT_ONLY = - FS.join_paths(SCRIPTS_DIR, "engines", "javascript", "lib", "dist", "pre_request_client_only.js") -local BASE_FILE_PRE = FS.join_paths(SCRIPTS_DIR, "engines", "javascript", "lib", "dist", "pre_request.js") -local BASE_FILE_POST_CLIENT_ONLY = - FS.join_paths(SCRIPTS_DIR, "engines", "javascript", "lib", "dist", "post_request_client_only.js") -local BASE_FILE_POST = FS.join_paths(SCRIPTS_DIR, "engines", "javascript", "lib", "dist", "post_request.js") +local BASE_FILE_PRE_CLIENT_ONLY = FS.join_paths(SCRIPTS_BUILD_DIR, "dist", "pre_request_client_only.js") +local BASE_FILE_PRE = FS.join_paths(SCRIPTS_BUILD_DIR, "dist", "pre_request.js") +local BASE_FILE_POST_CLIENT_ONLY = FS.join_paths(SCRIPTS_BUILD_DIR, "dist", "post_request_client_only.js") +local BASE_FILE_POST = FS.join_paths(SCRIPTS_BUILD_DIR, "dist", "post_request.js") local FILE_MAPPING = { pre_request_client_only = BASE_FILE_PRE_CLIENT_ONLY, pre_request = BASE_FILE_PRE, @@ -23,8 +22,9 @@ local FILE_MAPPING = { } M.install = function() - vim.system({ "npm", "install", "--prefix", BASE_DIR }):wait() - vim.system({ "npm", "run", "build", "--prefix", BASE_DIR }):wait() + FS.copy_dir(BASE_DIR, SCRIPTS_BUILD_DIR) + vim.system({ "npm", "install", "--prefix", SCRIPTS_BUILD_DIR }):wait() + vim.system({ "npm", "run", "build", "--prefix", SCRIPTS_BUILD_DIR }):wait() end ---@class Scripts diff --git a/lua/kulala/tmp/.gitignore b/lua/kulala/tmp/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/lua/kulala/tmp/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/lua/kulala/tmp/scripts/requests/.gitignore b/lua/kulala/tmp/scripts/requests/.gitignore deleted file mode 100644 index 8b13789..0000000 --- a/lua/kulala/tmp/scripts/requests/.gitignore +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lua/kulala/utils/fs.lua b/lua/kulala/utils/fs.lua index 7a41191..acecb7a 100644 --- a/lua/kulala/utils/fs.lua +++ b/lua/kulala/utils/fs.lua @@ -37,7 +37,19 @@ M.ps = M.get_path_separator() ---@vararg string ---@return string M.join_paths = function(...) - if M.get_os() == "windows" then + if M.os == "windows" then + for _, v in ipairs({ ... }) do + -- if the path contains at least one forward slash, + -- then it needs to be converted to backslashes + if v:match("/") then + local parts = {} + for _, p in ipairs({ ... }) do + p = p:gsub("/", "\\") + table.insert(parts, p) + end + return table.concat(parts, M.ps) + end + end return table.concat({ ... }, M.ps) end return table.concat({ ... }, M.ps) @@ -167,6 +179,14 @@ M.file_exists = function(filename) return vim.fn.filereadable(filename) == 1 end +M.copy_dir = function(source, destination) + if M.os == "unix" or M.os == "mac" then + vim.system({ "cp", "-r", source .. M.ps .. ".", destination }):wait() + elseif M.os == "windows" then + vim.system({ "xcopy", "/H", "/E", "/I", source .. M.ps .. "*", destination }):wait() + end +end + M.ensure_dir_exists = function(dir) if vim.fn.isdirectory(dir) == 0 then vim.fn.mkdir(dir, "p") @@ -177,7 +197,9 @@ end --- @return string --- @usage local p = fs.get_plugin_tmp_dir() M.get_plugin_tmp_dir = function() - local dir = M.join_paths(M.get_plugin_root_dir(), "tmp") + local cache = vim.fn.stdpath("cache") + ---@cast cache string + local dir = M.join_paths(cache, "kulala") M.ensure_dir_exists(dir) return dir end @@ -187,6 +209,12 @@ M.get_scripts_dir = function() return dir end +M.get_tmp_scripts_build_dir = function() + local dir = M.join_paths(M.get_plugin_tmp_dir(), "scripts", "build") + M.ensure_dir_exists(dir) + return dir +end + M.get_tmp_scripts_dir = function() local dir = M.join_paths(M.get_plugin_tmp_dir(), "scripts") M.ensure_dir_exists(dir) @@ -346,14 +374,7 @@ end ---Clears all cached files M.clear_cached_files = function() local tmp_dir = M.get_plugin_tmp_dir() - local scripts_dir = M.get_tmp_scripts_dir() - local request_scripts_dir = M.get_request_scripts_dir() - local compiled_pre_request_scripts = M.join_paths(M.get_scripts_dir(), "engines", "javascript", "lib", "dist") - local deleted_files = {} - deleted_files = vim.tbl_extend("force", deleted_files, M.delete_files_in_directory(tmp_dir)) - deleted_files = vim.tbl_extend("force", deleted_files, M.delete_files_in_directory(scripts_dir)) - deleted_files = vim.tbl_extend("force", deleted_files, M.delete_files_in_directory(request_scripts_dir)) - deleted_files = vim.tbl_extend("force", deleted_files, M.delete_files_in_directory(compiled_pre_request_scripts)) + local deleted_files = M.delete_files_in_directory(tmp_dir) local string_list = vim.fn.join( vim.tbl_map(function(file) return "- " .. file diff --git a/scripts/install-ci-test-requirements.ps1 b/scripts/install-ci-test-requirements.ps1 new file mode 100644 index 0000000..82f6783 --- /dev/null +++ b/scripts/install-ci-test-requirements.ps1 @@ -0,0 +1,44 @@ +$Env:KULALA_ROOT_DIR = (Get-Location).Path + +if ($Env:GH_CACHE_HIT -eq $null) { + mkdir .tests +} + +cd .tests + +Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +if ($Env:GH_CACHE_HIT -eq $null) { + Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression + scoop install main/git + scoop install main/neovim@0.10.2 +} else { + $Env:PATH = "$Env:USERPROFILE\scoop\shims;$Env:USERPROFILE\scoop\apps\git\current\cmd;$Env:USERPROFILE\scoop\apps\neovim\current\bin;$Env:PATH" +} + +if ($Env:GH_CACHE_HIT -eq $null) { + Invoke-RestMethod -Uri https://github.com/mistweaverco/luajit-for-win64/archive/refs/tags/v0.0.2.zip -outfile luajit.zip + 7z x luajit.zip + RM luajit.zip + cd luajit-for-win64-0.0.2 + .\luajit-for-win64.cmd +} else { + cd luajit-for-win64-0.0.2 +} + +$Env:KULALA_LUA_DIR = (Get-Location).Path + +$Env:PATH = "$Env:KULALA_LUA_DIR\tools\cmd;$Env:KULALA_LUA_DIR\tools\PortableGit\mingw64\bin;$Env:KULALA_LUA_DIR\tools\PortableGit\usr\bin;$Env:KULALA_LUA_DIR\tools\mingw\bin;$Env:KULALA_LUA_DIR\lib;$Env:KULALA_LUA_DIR\bin;$Env:APPDATA\LJ4W\LuaRocks\bin;$Env:PATH" +$Env:LUA_PATH = "$Env:KULALA_LUA_DIR\lua\?.lua;$Env:KULALA_LUA_DIR\lua\?\init.lua;$Env:APPDATA\luarocks\share\lua\5.1\?.lua;$Env:APPDATA\luarocks\share\lua\5.1\?\init.lua;$Env:LUA_PATH" +$Env:LUA_CPATH = "$Env:APPDATA\luarocks;$Env:APPDATA\luarocks\lib\lua\5.1\?.dll;$Env:LUA_CPATH" + +if ($Env:GH_CACHE_HIT -eq $null) { + luarocks install --lua-version 5.1 busted +} + +# Persist the Environment Variables +"PATH=$Env:Path" >> $Env:GITHUB_ENV +"LUA_PATH=$Env:LUA_PATH" >> $Env:GITHUB_ENV +"LUA_CPATH=$Env:LUA_CPATH" >> $Env:GITHUB_ENV + +cd $Env:KULALA_ROOT_DIR diff --git a/scripts/tests.ps1 b/scripts/tests.ps1 new file mode 100644 index 0000000..d4774d8 --- /dev/null +++ b/scripts/tests.ps1 @@ -0,0 +1,2 @@ +nvim --version +nvim -l tests/minit.lua tests diff --git a/tests/_dockerfiles/windows/Dockerfile b/tests/_dockerfiles/windows/Dockerfile index 064b502..0f027c9 100644 --- a/tests/_dockerfiles/windows/Dockerfile +++ b/tests/_dockerfiles/windows/Dockerfile @@ -1,4 +1,46 @@ -FROM mcr.microsoft.com/windows/nanoserver:ltsc2022 +# FROM mcr.microsoft.com/windows/nanoserver:20H2-amd64 +FROM mcr.microsoft.com/powershell:lts-windowsservercore-1809 + +SHELL ["pwsh", "-Command"] USER ContainerAdministrator -WORKDIR C:\\Users\\ContainerAdministrator\\AppData\\Local\\nvim + +WORKDIR "C:\\kulala.nvim" + +RUN Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser +RUN Invoke-RestMethod -Uri https://get.scoop.sh -outfile 'install.ps1' +RUN .\install.ps1 -RunAsAdmin + +# required before add extras +RUN scoop install main/git + +# add for extras suggested by neovim +RUN scoop bucket add extras + +RUN scoop install extras/vcredist2022 +RUN scoop install main/neovim@0.10.2 + +WORKDIR "C:\\luajjt" + +RUN Invoke-RestMethod -Uri https://github.com/mistweaverco/luajit-for-win64/archive/refs/tags/v0.0.2.zip -outfile luajit.zip +RUN 7z x luajit.zip + +WORKDIR "C:\\luajjt\luajit-for-win64-0.0.2" + +RUN .\luajit-for-win64.cmd + +RUN setx /M KULALA_LUA_DIR \"C:\luajjt\luajit-for-win64-0.0.2\" + +RUN setx /M PATH \"$Env:KULALA_LUA_DIR\tools\cmd;$Env:KULALA_LUA_DIR\tools\PortableGit\mingw64\bin;$Env:KULALA_LUA_DIR\tools\PortableGit\usr\bin;$Env:KULALA_LUA_DIR\tools\mingw\bin;$Env:KULALA_LUA_DIR\lib;$Env:KULALA_LUA_DIR\bin;$Env:APPDATA\LJ4W\LuaRocks\bin;$Env:path\" + +RUN setx /M LUA_PATH \"$Env:KULALA_LUA_DIR\lua\?.lua;$Env:KULALA_LUA_DIR\lua\?\init.lua;$Env:APPDATA\luarocks\share\lua\5.1\?.lua;$Env:APPDATA\luarocks\share\lua\5.1\?\init.lua;$Env:LUA_PATH\" +RUN setx /M LUA_CPATH \"$Env:APPDATA\luarocks;$Env:APPDATA\luarocks\lib\lua\5.1\?.dll;$Env:LUA_CPATH\" + +RUN luarocks install --lua-version 5.1 busted + +WORKDIR "C:\\kulala.nvim" + +RUN git config --global safe.directory '*' +RUN git config --global core.autocrlf true + +ENTRYPOINT ["pwsh"] diff --git a/tests/util/fs_spec.lua b/tests/util/fs_spec.lua new file mode 100644 index 0000000..f68dcde --- /dev/null +++ b/tests/util/fs_spec.lua @@ -0,0 +1,55 @@ +local Fs = require("kulala.utils.fs") + +local assert = require("luassert") + +describe("kulala.utils.fs", function() + -- restore all changed done by luassert before each test run + local snapshot + + before_each(function() + snapshot = assert:snapshot() + end) + + after_each(function() + snapshot:revert() + end) + + describe("join_paths on windows", function() + Fs.os = "windows" + Fs.ps = "\\" + it("joins mixed on windows", function() + local expected = "C:\\a\\b\\c" + local actual = Fs.join_paths("C:\\a", "b", "c") + assert.are.same(expected, actual) + end) + it("joins no-mixed on windows", function() + local expected = "C:\\a\\b\\c" + local actual = Fs.join_paths("C:\\a", "b", "c") + assert.are.same(expected, actual) + end) + it("fixes ps on windows", function() + local expected = "C:\\a\\user\\bin\\blah\\blubb" + local actual = Fs.join_paths("C:\\a", "user/bin", "blah/blubb") + assert.are.same(expected, actual) + end) + end) + describe("join_paths on linux", function() + Fs.os = "unix" + Fs.ps = "/" + it("joins mixed on unix", function() + local expected = "/a/b/c" + local actual = Fs.join_paths("/a", "b", "c") + assert.are.same(expected, actual) + end) + it("joins no-mixed on unix", function() + local expected = "/a/b/c" + local actual = Fs.join_paths("/a", "b", "c") + assert.are.same(expected, actual) + end) + it("joins more mixed on unix", function() + local expected = "/a/user/bin/blah/blubb" + local actual = Fs.join_paths("/a", "user/bin", "blah/blubb") + assert.are.same(expected, actual) + end) + end) +end)