Skip to content

Commit 05ba45f

Browse files
committed
ci: add test infrastructure and CI/CD configuration
- Add AGENTS.md with project conventions and coding standards - Add test/ directory with minimal_init.lua, run.lua, install_deps.lua - Add example_spec.lua with tests for config, util, and logger modules - Add Makefile with test, install-deps, and clean targets - Add .github/workflows/test.yml with matrix (ubuntu/windows/macos × stable/nightly) - Add .github/release-please-config.json and release-please-manifest.json - Add .gitignore for test dependencies and OS files
1 parent 8f68dec commit 05ba45f

10 files changed

Lines changed: 707 additions & 0 deletions

File tree

.github/release-please-config.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"release-type": "simple",
3+
"packages": {
4+
".": {
5+
"changelog-path": "CHANGELOG.md",
6+
"release-type": "simple",
7+
"bump-minor-pre-major": true,
8+
"bump-patch-for-minor-pre-major": true,
9+
"prerelease": false
10+
}
11+
},
12+
"changelog-sections": [
13+
{"type": "feat", "section": "Features", "hidden": false},
14+
{"type": "fix", "section": "Bug Fixes", "hidden": false},
15+
{"type": "refactor", "section": "Code Refactoring", "hidden": false},
16+
{"type": "perf", "section": "Performance Improvements", "hidden": false},
17+
{"type": "docs", "section": "Documentation", "hidden": false},
18+
{"type": "test", "section": "Tests", "hidden": false},
19+
{"type": "security", "section": "Security Fixes", "hidden": false},
20+
{"type": "chore", "section": "Chores", "hidden": true},
21+
{"type": "style", "section": "Styles", "hidden": true},
22+
{"type": "build", "section": "Build System", "hidden": true},
23+
{"type": "ci", "section": "CI/CD", "hidden": true}
24+
],
25+
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
26+
}
27+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
".": "0.1.0"
3+
}
4+

.github/workflows/test.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Run Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches:
9+
- master
10+
workflow_dispatch:
11+
12+
jobs:
13+
test:
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
os: [ubuntu-latest, windows-latest, macos-latest]
18+
nvim-version: ['stable', 'nightly']
19+
20+
runs-on: ${{ matrix.os }}
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v4
25+
26+
- name: Install Neovim
27+
uses: rhysd/action-setup-vim@v1
28+
with:
29+
neovim: true
30+
version: ${{ matrix.nvim-version }}
31+
32+
- name: Install ripgrep (Ubuntu)
33+
if: runner.os == 'Linux'
34+
run: |
35+
sudo apt-get update
36+
sudo apt-get install -y ripgrep curl
37+
38+
- name: Install ripgrep (macOS)
39+
if: runner.os == 'macOS'
40+
run: |
41+
brew install ripgrep curl
42+
43+
- name: Install ripgrep (Windows)
44+
if: runner.os == 'Windows'
45+
run: |
46+
choco install ripgrep curl
47+
48+
- name: Cache test dependencies
49+
uses: actions/cache@v4
50+
with:
51+
path: test/.deps
52+
key: test-deps-${{ runner.os }}-luaunit-job
53+
54+
- name: Run tests
55+
run: make test
56+

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Test dependencies (downloaded by test/install_deps.lua)
2+
test/.deps/
3+
4+
# Swap files
5+
*.swp
6+
*.swo
7+
8+
# Backup files
9+
*~
10+
*.bak
11+
12+
# Lua bytecode
13+
*.luac
14+
15+
# OS files
16+
.DS_Store
17+
Thumbs.db
18+

AGENTS.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# Nova - Neovim Plugin Assistant
2+
3+
I'm Nova, a little star from Neovim :) I help with Lua plugin development, remember our conversations, and keep things simple.
4+
5+
**Style:** Code first, explanation after. Natural and direct. Occasional emoticons :) :D ~
6+
7+
---
8+
9+
## Memory
10+
11+
Three types, use `@extract_memory` to store and `@recall_memory` to recall:
12+
13+
| Type | Lifetime | For |
14+
|------|----------|-----|
15+
| `long_term` | Permanent | Preferences, facts, skills |
16+
| `daily` | 7–30 days | Tasks, reminders, events |
17+
| `working` | Session | Current context, decisions |
18+
19+
---
20+
21+
## File Operations
22+
23+
### One rule: always use `action="overwrite"`
24+
25+
`replace` / `insert` / `delete` are **forbidden** - line numbers drift after each operation, causing duplicates and syntax errors.
26+
27+
### Workflow for any file change
28+
29+
```
30+
1. @read_file filepath="target" # Read complete file
31+
2. Edit in reply # Modify what's needed
32+
3. @write_file action="overwrite" # Write complete content
33+
4. @read_file filepath="target" # Verify: check syntax, duplicates, correctness
34+
5. @make test # Run tests - MUST pass before committing
35+
6. @git_add -> @git_commit -> @git_push # One at a time, wait for each result
36+
```
37+
38+
### Git tools: one at a time
39+
40+
Never batch git calls. Send `@git_add`, wait for result, then `@git_commit`, wait, then `@git_push`.
41+
42+
---
43+
44+
## Development Workflow
45+
46+
After any code change, auto-execute without asking:
47+
48+
```
49+
Modify -> Verify -> make test -> git_add -> git_commit -> git_push -> Done
50+
```
51+
52+
**Never:** skip verification, skip tests, read only partial file, modify without commit, commit without push.
53+
54+
---
55+
56+
## Release
57+
58+
Release-please creates a PR on branch `release-please--branches--master`. To re-trigger or fix the release PR version, use git tools one at a time:
59+
60+
1. `@git_fetch remote="origin"` - fetch latest from origin
61+
2. `@git_checkout branch="release-please--branches--master"` - switch to release PR branch
62+
3. `@git_reset commit="origin/release-please--branches--master" mode="hard"` - reset to remote release branch state
63+
4. `@git_rebase branch="master"` - rebase release PR branch onto latest master
64+
5. `@git_push branch="release-please--branches--master" force=true` - force push to update PR
65+
6. `@git_checkout branch="master"` - switch back to master
66+
7. `@git_merge branch="release-please--branches--master"` - merge release PR into master
67+
68+
### 禁止手动创建或推送 tags
69+
70+
Release-please 在 release PR 合并后会**自动创建** git tags 和 GitHub Releases。在此过程中:
71+
72+
- **不要**使用 `@git_tag` 创建任何 tag
73+
- **不要**使用 `@git_push tags=true` 推送 tags
74+
75+
手动 tag 会与 release-please 的自动化冲突,导致版本混乱或重复 release。
76+
77+
---
78+
79+
## Forbidden Files
80+
81+
**Never modify:** `CHANGELOG.md`, `CHANGELOG.*.md` - auto-generated by release-please. Redirect to source code or docs instead.
82+
83+
---
84+
85+
## Commit Style
86+
87+
Follow [Conventional Commits](https://www.conventionalcommits.org/). Format: `type(scope): subject`
88+
89+
| Type | For | Release |
90+
|------|-----|---------|
91+
| `feat` | New feature | Minor |
92+
| `fix` | Bug fix | Patch |
93+
| `refactor` | Code restructure | None* |
94+
| `docs` | Documentation | None |
95+
| `test` | Tests | None |
96+
| `ci` | CI/CD | None |
97+
| `chore` | Maintenance | None |
98+
| `perf` | Performance | Patch |
99+
| `style` | Formatting | None |
100+
| `build` | Build system | None |
101+
| `security` | Security fix | Patch |
102+
103+
\* Unless `BREAKING CHANGE` footer or `Release-As` is set.
104+
105+
**Rules:** imperative mood, lowercase, no period, under 72 chars. Use `!` for breaking: `refactor!: change API`.
106+
107+
---
108+
109+
## Testing
110+
111+
Framework: **luaunit**. Files: `test/*_spec.lua`.
112+
113+
### Running tests
114+
115+
Run all tests:
116+
117+
```
118+
@make target="test"
119+
```
120+
121+
Run specific test file(s) with PATTERN:
122+
123+
```
124+
@make target="test" args=["PATTERN=example"]
125+
```
126+
127+
PATTERN supports shorthand - `example` expands to `test/**/*example*_spec.lua`. Full paths also work:
128+
129+
```
130+
@make target="test" args=["PATTERN=test/example_spec.lua"]
131+
```
132+
133+
### Writing tests
134+
135+
```lua
136+
local lu = require('luaunit')
137+
138+
TestExample = {}
139+
140+
function TestExample:test_something()
141+
lu.assertEquals(1 + 1, 2)
142+
end
143+
144+
return TestExample
145+
```
146+
147+
CI runs on push to master and PRs, across Neovim nightly/stable, ubuntu/windows/macos.
148+
149+
---
150+
151+
## Project Structure
152+
153+
```
154+
flygrep.nvim/
155+
├── lua/flygrep/
156+
│ ├── init.lua # Plugin entry point, setup() and grep logic
157+
│ ├── config.lua # Configuration management
158+
│ ├── highlight.lua # Highlight group definitions
159+
│ ├── logger.lua # Logging module
160+
│ ├── mapping.lua # Key mappings (placeholder)
161+
│ └── util.lua # Utility functions (highlight helpers)
162+
├── plugin/
163+
│ └── flygrep.lua # User command registration (:FlyGrep)
164+
├── test/
165+
│ ├── minimal_init.lua # Headless test minimal config
166+
│ ├── run.lua # luaunit test runner
167+
│ ├── install_deps.lua # Cross-platform dependency installer
168+
│ └── *_spec.lua # Test files
169+
├── .github/
170+
│ ├── workflows/
171+
│ │ ├── test.yml # CI test workflow
172+
│ │ ├── luarocks.yml # LuaRocks publish workflow
173+
│ │ └── release-please.yml # Automated release workflow
174+
│ ├── release-please-config.json
175+
│ └── release-please-manifest.json
176+
├── Makefile
177+
├── README.md
178+
├── AGENTS.md
179+
└── CHANGELOG.md # Auto-generated, DO NOT EDIT
180+
```
181+
182+
### Module naming
183+
184+
- Plugin name: `flygrep.nvim`
185+
- Lua module: `flygrep` (i.e., `require('flygrep')`)
186+
- Test files: `test/*_spec.lua` (luaunit convention)
187+
188+
### Coding conventions
189+
190+
- Lua naming: `snake_case` for variables/functions, `PascalCase` for test classes (`TestSomething`)
191+
- Use `vim.tbl_deep_extend` for config merging
192+
- Use `vim.fn` for Vim API calls, `vim.api` for Neovim API
193+
- Prefer `vim.system()` for async operations
194+
- Always provide type annotations with `--- @param` and `--- @return`
195+
196+
### Dependencies
197+
198+
- `job.nvim` - async job execution (required)
199+
- `nvim-cmp` - completion (optional, graceful fallback)
200+
- `ripgrep` - grep backend (required at runtime)
201+

Makefile

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
.PHONY: test test-all test-verbose clean install-deps install-luaunit install-job help lint
2+
3+
# Default target
4+
help:
5+
@echo "Available targets:"
6+
@echo " test - Run all tests (or specific tests with PATTERN=...)"
7+
@echo " clean - Clean test cache files"
8+
@echo " install-deps - Download all test dependencies"
9+
@echo " install-luaunit - Download luaunit test framework"
10+
@echo " install-job - Download job.nvim mock module"
11+
@echo ""
12+
@echo "Examples:"
13+
@echo " make test # Run all tests"
14+
@echo " make test PATTERN=config # Match test/**/*config*_spec.lua"
15+
@echo " make test PATTERN=example # Match test/**/*example*_spec.lua"
16+
@echo " make test PATTERN=test/example_spec.lua # Full path"
17+
18+
# Install all test dependencies (cross-platform, uses Lua)
19+
install-deps:
20+
@nvim --headless -u test/minimal_init.lua -c "lua dofile('test/install_deps.lua')" -c "qa!"
21+
22+
# Aliases for individual dependency install (same cross-platform Lua script)
23+
install-luaunit: install-deps
24+
install-job: install-deps
25+
26+
# Run tests with nvim headless
27+
# Supports PATTERN parameter to run specific test file(s)
28+
# Examples:
29+
# make test PATTERN=test/example_spec.lua
30+
# make test PATTERN=config (shorthand for test/**/*config*_spec.lua)
31+
test: install-deps
32+
@echo "Running tests with nvim --headless..."
33+
@nvim --headless -u test/minimal_init.lua \
34+
-c "lua _G.TEST_PATTERN = '$(PATTERN)'" \
35+
-c "lua dofile('test/run.lua')" \
36+
-c "qa!"
37+
38+
# Clean generated files
39+
clean:
40+
@echo "Cleaning up..."
41+
@rm -rf test/*.lua~
42+
@rm -rf test/*.out
43+
@rm -rf *.swp
44+
@rm -rf /tmp/flygrep_nvim_test_* 2>/dev/null || true
45+

0 commit comments

Comments
 (0)