Skip to content

Add mini.test suite, Nix dev shells, and CI - #84

Merged
petertriho merged 17 commits into
mainfrom
ci/tests-and-nix
Oct 22, 2026
Merged

petertriho merged 17 commits into
mainfrom
ci/tests-and-nix

Conversation

@petertriho

@petertriho petertriho commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

Adds a mini.test suite, Nix dev shells, a GitHub Actions workflow, Dependabot, and a contributing guide. This PR adds no release automation.

Changes

  • Nix flake: three dev shells: default (locked nixpkgs Neovim, 0.12.6 today), nvim-0_12_0 (nixpkgs-multiverse fast path), and nightly (neovim-nightly-overlay). Each shell has StyLua, Selene, LuaLS, make, and git. .envrc runs use flake.
  • mini.test: the 52 tests from tests/run.lua now live in one file for each module. The suite has 101 cases. The Makefile clones mini.nvim v0.18.0 into deps/. tests/helpers.lua isolates each case:
    • It captures vim.notify, so the run prints no log lines.
    • It unsets the token variables.
    • It isolates git from the user and system config.
    • It restores the cwd, the buffers, and the stubs.
  • New coverage: utils, sort, format, both adapters (gh/glab versus curl, enterprise URLs, tokens, no-color env, state, limit, and filter args, mention preflight and pagination), and repository detection against temporary git repos.
  • Strict lint: the unused trigger_char parameters are now _trigger_char. make lint no longer passes --allow-warnings.
  • Type check gate: .luarc.json and make typecheck use LuaLS with $VIMRUNTIME/lua. All 151 warnings are fixed. The lua/ changes in this commit are annotations and inline casts only.
  • CI: Quality, Neovim stable, Neovim 0.12.0, and Nightly cache block. Neovim nightly uses the newest overlay commit that is in the cache and does not block. A weekly schedule runs only the nightly job. The actions are pinned by SHA.
  • Nightly cache: the overlay CI pushes only checks.<system>.neovim to nix-community.cachix.org. It uses the older nixpkgs of the overlay's dev partition (GCC 15.2.0, not 16.2.0), so packages.<system>.default was never in the cache, and the nightly shell built Neovim from source.
    • d2f8677: the nightly shell uses checks.<system>.neovim.
    • 6be4304: scripts/nightly-cache.sh latest finds the newest of the last 10 overlay commits whose build is in the cache, and the nightly job uses that commit. The overlay updates at 00:00 UTC, and the build arrives in the cache later.
    • eeb5cb2: the Nightly cache job runs scripts/nightly-cache.sh check. It fails when the cache has no build of the locked overlay for a system of the flake, for example on a Dependabot nix PR that locks a commit before its build is in the cache. CONTRIBUTING.md describes what to do then.
    • Both modes read the store path from the nightly shell (passthru.neovim), so they check the same build that nix develop uses.
  • Dependabot: monthly grouped updates for github-actions and nix.

Bug fixes found by the new tests

Each fix is a separate commit with regression tests.

  • 17c929f fix: keep filter_fn out of the default formats: config.normalize shared the nested default tables, so apply_filter_fn wrote a user's filter_fn into the module-level formats. Every later config, such as a second source, then used that filter. A regression test is in test_config.lua.
  • 098f690 fix: detect the repository from inside the .git directory: d9efd00 (async commands) read only the first line of git rev-parse --is-inside-work-tree --is-inside-git-dir. That brought Bug: not completing at all & two cmp-git sources listed #47 back. is_git_repo_inside_git_dir covers it.
  • 0345598 fix: pass provider tokens to gh and glab only when they are set: when GITLAB_TOKEN was unset, glab got GITLAB_TOKEN=vim.NIL, because vim.fn.getenv returns vim.NIL and the command passed it as a string. glab prefers this variable over the credentials from glab auth login, so it sent an invalid token. GITHUB_API_TOKEN had the same problem, but gh does not read it. The adapters now use vim.env. The adapter tests run a real process with the adapter env and check that the variable is unset.
  • f050252 fix: request GitHub mentions from the repos API path with curl: the curl fallback requested https://api.github.com/<owner>/<repo>/<members> without repos/, so it got a 404 and no mentions. The test asserts the full URL for github.com and for an enterprise host.
  • f5f2a70 fix: send the GitHub Accept header without literal quotes: curl runs without a shell, so it sent a header named 'Accept, and GitHub ignored it. The quotes were there since the first version.
  • 9dd025a fix: parse GitHub and GitLab dates as UTC timestamps:
    • os.time read the UTC fields as local time, so every age was off by the local UTC offset. West of UTC, items updated in the last few hours got negative ages and sorted in reverse order.
    • parse_gitlab_date added the offset for both + and -.
    • A missing or unknown date raised an error in the sort function, because 54d3fb6 removed the or 0 defaults from 20b7b8e. Such a date now gives 0, so the item sorts last.
    • The tests cover Z, +05:30, -05:30, milliseconds, a leap day, a non-UTC TZ, and missing dates.

Plan deviations

  • Five ported tests moved to the file of the module they exercise: git_commit_edit_range_is_preserved to test_core.lua, custom_trigger_actions_remove_trailers and invalid_trigger_action_pattern_is_skipped to test_core.lua, and trailer_gating and trailer_capabilities_with_git to test_trailers.lua.
  • The quality job runs format-check, lint, and typecheck as three steps, so the failing step is clear.
  • The jobs have timeout-minutes. The Dependabot commit messages use the ci and build prefixes.

Validation (local)

  • make ci exits 0 in default, nvim-0_12_0, and nightly.
  • make test passes on every commit from test: switch to mini.test onward.
  • A broken expectation in the remote URL test makes make test exit 2.
  • An unused local makes make lint exit 2. A type error makes make typecheck exit 2.
  • make test prints no stray log lines.
  • A hostile global git config (an insteadOf rule) fails a repository test when isolation is off. It passes when isolation is on.
  • GITHUB_API_TOKEN and GITLAB_TOKEN in the environment do not change the results.
  • scripts/nightly-cache.sh check fails for all three systems when the shell uses packages.<system>.default. Both modes fail with a clear message when a build is missing, and when the cache cannot be reached. shellcheck passes.
  • make test passes with TZ=XYZ+05 and with TZ=XYZ-11.
  • actionlint and the Dependabot schema check pass. nix flake show --all-systems evaluates.

Validation (CI, before merge)

  • Quality, Neovim stable, Neovim 0.12.0, and Nightly cache pass on eeb5cb2 (29s, 24s, 28s, and 53s, run 39748376784).
  • The Neovim nightly log shows that Neovim comes from nix-community.cachix.org and is not built from source. On eeb5cb2, the job picked overlay 620aaa5 and copied 2lr6d3w…-neovim-unwrapped-1cfebe9 from the cache. The job took 54s. Before the fix, it took 7m18s.
  • A workflow_dispatch run from the branch passes (run 39742358311).

Old test name checklist (52)

  • handle_response → tests/test_response.lua
  • parse_remote_url → tests/repository/test_remote_url.lua
  • missing_executable → tests/test_command.lua
  • fallback → tests/test_command.lua
  • command_fallback_cancels_active_job → tests/test_command.lua
  • command_build_cancel_suppresses_callback → tests/test_command.lua
  • build_job → tests/test_command.lua
  • logger → tests/test_log.lua
  • trigger_action_fallback_for_hash → tests/test_source.lua
  • trigger_action_ordering_for_at → tests/test_source.lua
  • trigger_action_first_handled_wins → tests/test_source.lua
  • preferred_trigger_action_names → tests/test_source.lua
  • legacy_trigger_action_aliases → tests/test_source.lua
  • legacy_trigger_action_arguments → tests/test_source.lua
  • config_normalize_fills_defaults_and_hosts → tests/test_config.lua
  • config_normalize_nested_filter_and_sort_overrides → tests/test_config.lua
  • config_normalize_provider_filter_alias → tests/test_config.lua
  • config_normalize_provider_filter_alias_overrides_nested_filter → tests/test_config.lua
  • config_normalize_does_not_leak_hosts_between_instances → tests/test_config.lua
  • source_new_uses_normalized_config → tests/test_source.lua
  • issue_capability_uses_cache_and_runner → tests/provider/capabilities/test_issues.lua
  • mention_capability_preflight_and_pagination → tests/provider/capabilities/test_mentions.lua
  • change_request_capability_returns_job → tests/provider/capabilities/test_change_requests.lua
  • commit_capability_parse_nul_records → tests/provider/capabilities/test_commits.lua
  • commit_capability_parse_marker_collision_and_malformed_records → tests/provider/capabilities/test_commits.lua
  • commit_capability_maps_items_without_cmp_params → tests/provider/capabilities/test_commits.lua
  • commit_capability_uses_parsed_cache_and_runner → tests/provider/capabilities/test_commits.lua
  • git_commit_edit_range_is_preserved → tests/test_core.lua
  • core_text_edit_ranges_for_all_triggers → tests/test_core.lua
  • blink_adapter_api_and_cancellation → tests/test_blink.lua
  • blink_adapter_suppresses_stale_callbacks_after_cancel → tests/test_blink.lua
  • github_instance_state_isolation → tests/sources/test_github.lua
  • gitlab_instance_state_isolation → tests/sources/test_gitlab.lua
  • git_instance_state_isolation → tests/sources/test_git.lua
  • config_trailer_defaults → tests/test_config.lua
  • custom_trigger_actions_remove_trailers → tests/test_core.lua
  • invalid_trigger_action_pattern_is_skipped → tests/test_core.lua
  • config_git_filter_alias_skips_trailers → tests/test_config.lua
  • core_keyword_pattern_offsets → tests/test_core.lua
  • trailer_routing → tests/test_core.lua
  • trailer_gating → tests/provider/capabilities/test_trailers.lua
  • core_pre_route_skips_repository → tests/test_core.lua
  • trailer_text_edits → tests/test_core.lua
  • trailer_keys_parse_and_sort → tests/provider/capabilities/test_trailers.lua
  • trailer_identities_request → tests/provider/capabilities/test_trailers.lua
  • trailer_identities_parse → tests/provider/capabilities/test_trailers.lua
  • trailer_capabilities_use_cache_and_runner → tests/provider/capabilities/test_trailers.lua
  • trailer_identities_job_cancel → tests/provider/capabilities/test_trailers.lua
  • blink_adapter_matches_text_before_cursor → tests/test_blink.lua
  • trailer_capabilities_with_git → tests/provider/capabilities/test_trailers.lua
  • trailer_values_request_and_parse → tests/provider/capabilities/test_trailers.lua
  • trailer_values_cache_and_fall_through → tests/provider/capabilities/test_trailers.lua

config.normalize shared the nested default tables with the result, so
apply_filter_fn wrote the filter_fn into the module-level formats. Every
later config, such as a second source instance, then used that filter.
The async rewrite in d9efd00 checked only the first line of
`git rev-parse --is-inside-work-tree --is-inside-git-dir`. Inside .git,
only the second line is true, so completion stopped there again (#47).
vim.fn.getenv returns vim.NIL for an unset variable, and the command
passed it as the string "vim.NIL". glab prefers GITLAB_TOKEN over the
credentials from `glab auth login`, so it sent an invalid token.
The curl fallback requested <owner>/<repo>/<members> without the repos/
prefix, so it got a 404 and no mentions.
The header has had literal quotes since the first version, but curl runs
without a shell. curl sent a header named "'Accept", so GitHub ignored it.
os.time read the UTC fields as local time, so every age was off by the
local UTC offset. West of UTC, items updated in the last few hours got
negative ages and sorted in reverse order.

parse_gitlab_date also added the UTC offset for both signs, and a
missing or unknown date raised an error in the sort function, for
example with GitHub fields that leave out updatedAt. Such a date now
gives 0, so the item sorts last.
The overlay CI builds checks.<system>.neovim and pushes only that
output to nix-community.cachix.org. It uses the nixpkgs of the overlay's
dev partition, so packages.<system>.default is a different build, and
the nightly shell built Neovim from source.
The overlay updates each day at 00:00 UTC, and its CI pushes the build
to nix-community.cachix.org later. The job used the overlay HEAD, so a
run before that build finished built Neovim from source.

scripts/nightly-cache.sh latest finds the newest of the last 10 overlay
commits whose build is in the cache. It reads the store path from the
nightly shell, so it checks the same build that nix develop uses.
Dependabot and nix flake update can lock an overlay commit whose build
is not in nix-community.cachix.org yet. Then nix develop .#nightly
builds Neovim from source.

The Nightly cache job runs scripts/nightly-cache.sh check, which fails
when the cache has no build of the locked overlay for a system of the
flake.
@petertriho
petertriho merged commit 21efdc7 into main Oct 22, 2026
5 checks passed
@petertriho
petertriho deleted the ci/tests-and-nix branch October 22, 2026 08:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant