Add instructions on how to run locally and in neovim

This commit is contained in:
Francesco Renzi
2025-11-27 15:37:14 +00:00
parent 03ffd0c44d
commit ec52bd7358
3 changed files with 114 additions and 12 deletions
+100
View File
@@ -0,0 +1,100 @@
# Using GitHub Actions Language Server in Neovim
## Prerequisites
- Node.js 18+
- Neovim 0.11+ with the new LSP config format
## Setup
### 1. Clone and build
```bash
git clone https://github.com/actions/languageservices.git
cd languageservices
npm install
npm run build --workspaces --if-present
```
### 2. Bundle the server
The server needs to be bundled into a single file to avoid ESM module resolution issues:
```bash
cd languageserver
npx esbuild src/index.ts \
--bundle \
--platform=node \
--target=node18 \
--format=cjs \
--outfile=dist/server-bundled.cjs \
--external:vscode \
--loader:.json=json
```
This creates `dist/server-bundled.cjs` (~5.6MB) that contains the entire server.
### 3. Configure Neovim
Create `~/.config/nvim/lsp/actionsls.lua`:
```lua
return {
cmd = {
"/absolute/path/to/languageservices/languageserver/bin/actions-languageserver",
},
filetypes = { "yaml" },
root_markers = { ".git" },
init_options = {
sessionToken = os.getenv("GITHUB_SESSION_TOKEN") or "",
logLevel = "info",
},
}
```
**Important:** Replace `/absolute/path/to/languageservices` with your actual clone path.
### 4. Enable the LSP in your init.lua
Add to your Neovim configuration:
```lua
vim.lsp.enable('actionsls')
```
### 5. Restart Neovim
Open any `.github/workflows/*.yml` file and the language server should attach automatically.
## Files Created
- `languageserver/dist/server-bundled.cjs` - Bundled server (~5.6MB)
- `languageserver/bin/actions-languageserver` - Shell wrapper script
The `dist/` directory is gitignored; you'll need to rebuild after pulling updates.
## Troubleshooting
Check if the server is running:
```vim
:lua =vim.lsp.get_clients()
```
View LSP logs:
```bash
tail -f ~/.local/state/nvim/lsp.log
```
Manually start the server to test:
```vim
:lua vim.lsp.start({name='actionsls', cmd={'/path/to/bin/actions-languageserver'}, root_dir=vim.fn.getcwd(), init_options={sessionToken='', logLevel='info'}})
```
## Notes
- The main code change is in `languageserver/src/index.ts` to use dynamic imports, avoiding loading browser modules in Node.js
- The bundling step is necessary because TypeScript outputs ESM with bare imports that Node.js can't resolve
- Only workflow files in git repositories will activate the LSP (due to `root_markers = { ".git" }`)
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
# Wrapper script to start the Actions language server
DIR="$(cd "$(dirname "$0")" && pwd)"
exec node "$DIR/../dist/server-bundled.cjs" --stdio "$@"
+8 -12
View File
@@ -1,26 +1,22 @@
import {Connection} from "vscode-languageserver";
import {
BrowserMessageReader,
BrowserMessageWriter,
createConnection as createBrowserConnection
} from "vscode-languageserver/browser";
import {createConnection as createNodeConnection} from "vscode-languageserver/node";
import { Connection } from "vscode-languageserver";
import {initConnection} from "./connection";
import { initConnection } from "./connection.js";
/** Helper function determining whether we are executing with node runtime */
function isNode(): boolean {
return typeof process !== "undefined" && process.versions?.node != null;
}
function getConnection(): Connection {
async function getConnection(): Promise<Connection> {
if (isNode()) {
return createNodeConnection();
const { createConnection } = await import("vscode-languageserver/node.js");
return createConnection();
} else {
const { BrowserMessageReader, BrowserMessageWriter, createConnection } = await import("vscode-languageserver/browser.js");
const messageReader = new BrowserMessageReader(self);
const messageWriter = new BrowserMessageWriter(self);
return createBrowserConnection(messageReader, messageWriter);
return createConnection(messageReader, messageWriter);
}
}
initConnection(getConnection());
getConnection().then(initConnection);