Add instructions on how to run locally and in neovim
This commit is contained in:
+100
@@ -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" }`)
|
||||
Executable
+6
@@ -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 "$@"
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user