Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions .ansible-lint
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
# enforce more style. Use yamllint (.yamllint) for YAML formatting concerns.
profile: min

enable_list:
- use-include-tasks

rulesdir:
- .ansible-rules/

exclude_paths:
- roles/nvim/files/ # deployed nvim config (lua/yaml), not Ansible content
- .github/
Expand All @@ -12,12 +18,11 @@ exclude_paths:
skip_list:
- yaml

# Modules the lint env can't resolve: `yay` is this repo's custom module
# (library/yay); the rest live in the community.general collection, which we
# don't install just to lint. Mock them so syntax-check passes.
# Modules the lint env can't resolve; we mock them so syntax-check passes.
mock_modules:
- yay
- kewlfft.aur.aur
- snap
- community.general.snap
- community.general.npm
- community.general.pacman
- community.general.flatpak
25 changes: 25 additions & 0 deletions .ansible-rules/use_include_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from ansiblelint.rules import AnsibleLintRule

if TYPE_CHECKING:
from ansiblelint.file_utils import Lintable
from ansiblelint.utils import Task

class UseIncludeTasksRule(AnsibleLintRule):
"""Avoid using import_tasks, use include_tasks instead to prevent static module parsing issues on platforms without dependency collections."""
id = "use-include-tasks"
description = "Use include_tasks instead of import_tasks to allow dynamic evaluation and skip loading platform-specific files on incompatible hosts."
severity = "MEDIUM"
tags = ["custom", "task"]
version_added = "1.0.0"
version_changed = "1.0.0"

def matchtask(self, task: Task, file: Lintable | None = None) -> bool | str:
# task is an instance of ansiblelint.utils.Task
normalized_task = getattr(task, "normalized_task", {})
action = normalized_task.get("action", {})
module = action.get("__ansible_module__")
if module in ["import_tasks", "ansible.builtin.import_tasks"]:
return "Avoid using import_tasks, use include_tasks instead to prevent static module parsing issues on platforms without dependency collections."
return False
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ tmp/
.stack-work
*.lock
roles/nvim/files/plugin/packer_compiled.lua
*.pyc

# ansible-lint writes mocked modules here (mock_modules in .ansible-lint), and
# ansible uses it for local galaxy installs / tmp — all generated, not source.
Expand Down
9 changes: 9 additions & 0 deletions bin/dot-bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,18 @@ install_collections() {
echo "Installing community.general collection..."
ansible-galaxy collection install community.general --ignore-certs
fi

if ! ansible-galaxy collection list kewlfft.aur >/dev/null 2>&1; then
echo "Installing kewlfft.aur collection..."
ansible-galaxy collection install kewlfft.aur --ignore-certs
fi
}

run_playbook() {
if [[ "$1" == "--no-playbook" ]] || [[ "$1" == "--only-prereqs" ]]; then
echo "Skipping playbook execution."
return 0
fi
if [[ "$1" == "--check" ]] || [[ "$1" == "dry-run" ]]; then
echo "Running dry-run..."
shift
Expand Down
4 changes: 4 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

mod nvim 'roles/nvim/files'

# Install bootstrap prerequisites and Ansible Galaxy collections without running the playbook
bootstrap:
bin/dot-bootstrap --no-playbook

# Auto-format in place. Pass a hook id to run just that one, e.g. `just fmt stylua-github`.
fmt HOOK="":
prek run --hook-stage manual {{ HOOK }} --all-files
Expand Down
2 changes: 1 addition & 1 deletion roles/fzf/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- import_tasks: debian.yml
- include_tasks: debian.yml
when: ansible_os_family == "Debian"

- name: Update fzf
Expand Down
2 changes: 1 addition & 1 deletion roles/git/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- import_tasks: debian.yml
- include_tasks: debian.yml
when: ansible_os_family == "Debian"

- name: Check if gitconfig exists
Expand Down
2 changes: 1 addition & 1 deletion roles/haskell/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- import_tasks: debian.yml
- include_tasks: debian.yml
when: ansible_os_family == "Debian"

- name: create stack directory
Expand Down
1 change: 1 addition & 0 deletions roles/nvim/files/lazy-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"HowMuch": { "branch": "master", "commit": "787ead49e6311dc77b8e07a3aca79cbd6feab34c" },
"LuaSnip": { "branch": "master", "commit": "642b0c595e11608b4c18219e93b88d7637af27bc" },
"actions-preview.nvim": { "branch": "master", "commit": "0ac9c2aa3cfc8c885321c0862b50b6b1c3392405" },
"ansi.nvim": { "branch": "main", "commit": "95de464c315ecbe9d7ca3d9a203ef85def0cf6aa" },
"baleia.nvim": { "branch": "main", "commit": "710537ff5cd669c5a76c5f5b6a9169fd9b913d18" },
"black-nvim": { "branch": "master", "commit": "8fb3efc562b67269e6f31f8653297f826534fa4b" },
"blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" },
Expand Down
10 changes: 10 additions & 0 deletions roles/nvim/files/lua/plugins/spec/misc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,14 @@ return {
})
end,
},
{
"0xferrous/ansi.nvim",
config = function()
require("ansi").setup({
auto_enable = false, -- Auto-enable for configured filetypes
auto_enable_stdin = true, -- Auto-enable for piped stdin content
filetypes = { "log", "ansi" },
})
end,
},
}
108 changes: 108 additions & 0 deletions roles/nvim/files/tests/spec/copilot_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
-- tests/spec/copilot_spec.lua

describe("Copilot Tab completion integration", function()
-- Load blink.cmp so its configuration is loaded
require("lazy").load({ plugins = { "blink.cmp" } })

it("should retrieve the Tab action from blink configuration", function()
local keymap = require("blink.cmp.config").keymap
assert.is_not_nil(keymap)
assert.is_not_nil(keymap["<Tab>"])
assert.is_table(keymap["<Tab>"])
assert.is_function(keymap["<Tab>"][1])
end)

it("should prioritize blink menu acceptance when blink menu is visible", function()
local keymap = require("blink.cmp.config").keymap
local tab_action = keymap["<Tab>"][1]

-- Case 1: blink menu visible, snippet active
local accept_called = false
local select_and_accept_called = false
local mock_cmp = {
is_visible = function()
return true
end,
snippet_active = function()
return true
end,
accept = function()
accept_called = true
return true
end,
select_and_accept = function()
select_and_accept_called = true
return true
end,
}

local res = tab_action(mock_cmp)
assert.is_true(res)
assert.is_true(accept_called)
assert.is_false(select_and_accept_called)

-- Case 2: blink menu visible, snippet not active
accept_called = false
mock_cmp.snippet_active = function()
return false
end
res = tab_action(mock_cmp)
assert.is_true(res)
assert.is_false(accept_called)
assert.is_true(select_and_accept_called)
end)

it("should accept Copilot suggestion when blink menu is closed but Copilot is visible", function()
local keymap = require("blink.cmp.config").keymap
local tab_action = keymap["<Tab>"][1]

local mock_cmp = {
is_visible = function()
return false
end,
}

-- Stub require("copilot.suggestion")
local copilot_suggestion_accept_called = false
package.loaded["copilot.suggestion"] = {
is_visible = function()
return true
end,
accept = function()
copilot_suggestion_accept_called = true
return true
end,
}

local res = tab_action(mock_cmp)
assert.is_true(res)
assert.is_true(copilot_suggestion_accept_called)

-- Cleanup package.loaded stub
package.loaded["copilot.suggestion"] = nil
end)

it("should fall back when both blink menu and Copilot suggestion are not visible", function()
local keymap = require("blink.cmp.config").keymap
local tab_action = keymap["<Tab>"][1]

local mock_cmp = {
is_visible = function()
return false
end,
}

-- Stub require("copilot.suggestion") to return not visible
package.loaded["copilot.suggestion"] = {
is_visible = function()
return false
end,
}

local res = tab_action(mock_cmp)
assert.is_false(res)

-- Cleanup package.loaded stub
package.loaded["copilot.suggestion"] = nil
end)
end)
2 changes: 1 addition & 1 deletion roles/nvim/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- import_tasks: debian.yml
- include_tasks: debian.yml
when: ansible_os_family == "Debian"

- name: Install bob-nvim with cargo-binstall
Expand Down
4 changes: 1 addition & 3 deletions roles/packages/tasks/arch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@
become_method: sudo

- name: Install 1Password and CLI with yay
yay:
kewlfft.aur.aur:
name:
- 1password
- 1password-cli
state: present
become: true
become_method: sudo
12 changes: 9 additions & 3 deletions roles/packages/tasks/debian.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,23 @@
set_fact:
missing_apt_packages: "{{ packages_debian_list | difference((dpkg_check.stdout_lines | default([])) | map('regex_replace', ' installed$', '') | list) }}"

- name: Check if snap is installed
stat:
path: /usr/bin/snap
register: snap_bin

- name: Check which snap packages are missing
command: "snap list {{ packages_snap_list | join(' ') }}"
register: snap_check
ignore_errors: true
changed_when: false
become: false
check_mode: no
when: snap_bin.stat.exists

- name: Set missing snap packages fact
set_fact:
missing_snap_packages: "{{ packages_snap_list | difference(snap_check.stdout_lines | default([]) | map('regex_replace', '^(\\S+)\\s+.*$', '\\1') | list) }}"
missing_snap_packages: "{{ (packages_snap_list | difference(snap_check.stdout_lines | default([]) | map('regex_replace', '^(\\S+)\\s+.*$', '\\1') | list)) if snap_bin.stat.exists else [] }}"

- name: Report package differences (Check Mode Only)
debug:
Expand All @@ -73,13 +79,13 @@
when: not ansible_check_mode and missing_apt_packages | length > 0

- name: Install snap packages (classic confinement)
snap:
community.general.snap:
name: "{{ missing_snap_packages }}"
state: present
classic: true
become: true
become_method: sudo
when: not ansible_check_mode and missing_snap_packages | length > 0
when: not ansible_check_mode and snap_bin.stat.exists and missing_snap_packages | length > 0

- name: Install Prism Launcher via Flatpak
community.general.flatpak:
Expand Down
4 changes: 2 additions & 2 deletions roles/packages/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
- import_tasks: debian.yml
- include_tasks: debian.yml
when: ansible_os_family == "Debian"
- import_tasks: arch.yml
- include_tasks: arch.yml
when: ansible_os_family == "Archlinux"

- name: Install global npm packages to user local bin
Expand Down
2 changes: 1 addition & 1 deletion roles/penrose/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- import_tasks: debian.yml
- include_tasks: debian.yml
when: ansible_os_family == "Debian"

- name: Fetch penrose (favilrose) git repo
Expand Down
12 changes: 9 additions & 3 deletions roles/programming/tasks/debian.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,23 @@
vars:
comp_packages: *comp_pkgs

- name: Check if snap is installed
stat:
path: /usr/bin/snap
register: snap_bin

- name: Check if go snap is missing
command: "snap list go"
register: go_snap_check
ignore_errors: true
changed_when: false
become: false
check_mode: no
when: snap_bin.stat.exists

- name: Set missing go snap fact
set_fact:
go_snap_missing: "{{ go_snap_check.rc is defined and go_snap_check.rc != 0 }}"
go_snap_missing: "{{ (go_snap_check.rc is defined and go_snap_check.rc != 0) if snap_bin.stat.exists else false }}"

- name: Report missing programming components (Check Mode Only)
debug:
Expand All @@ -51,11 +57,11 @@
when: not ansible_check_mode and missing_comp_packages | length > 0

- name: Install go
snap:
community.general.snap:
name:
- go
state: present
classic: true
become: true
become_method: sudo
when: not ansible_check_mode and go_snap_missing
when: not ansible_check_mode and snap_bin.stat.exists and go_snap_missing
Loading
Loading