Skip to content

Commit 01ff1b4

Browse files
committed
feat(ci): add ci-test
1 parent 540caec commit 01ff1b4

1 file changed

Lines changed: 303 additions & 0 deletions

File tree

.github/workflows/test.yml

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
name: Test Dotfiles
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
changes:
15+
name: Detect Changes
16+
runs-on: ubuntu-latest
17+
outputs:
18+
shell: ${{ steps.filter.outputs.shell }}
19+
lua: ${{ steps.filter.outputs.lua }}
20+
nvim: ${{ steps.filter.outputs.nvim }}
21+
devbox: ${{ steps.filter.outputs.devbox }}
22+
chezmoi: ${{ steps.filter.outputs.chezmoi }}
23+
steps:
24+
- uses: actions/checkout@v4
25+
- uses: dorny/paths-filter@v3
26+
id: filter
27+
with:
28+
filters: |
29+
shell:
30+
- 'dot_zshrc.tmpl'
31+
- 'dot_zshenv.tmpl'
32+
- 'install.sh'
33+
- '.chezmoiscripts/**'
34+
- '.github/workflows/**'
35+
lua:
36+
- 'dot_config/nvim/**/*.lua'
37+
- '.github/workflows/**'
38+
nvim:
39+
- 'dot_config/nvim/**'
40+
- '.github/workflows/**'
41+
devbox:
42+
- 'dot_local/share/devbox/global/default/devbox.json'
43+
- '.github/workflows/**'
44+
chezmoi:
45+
- '**/*.tmpl'
46+
- '.chezmoi*'
47+
- 'dot_config/**'
48+
- 'private_dot_ssh/**'
49+
- '.github/workflows/**'
50+
51+
format:
52+
name: Format Check
53+
needs: changes
54+
if: needs.changes.outputs.shell == 'true' || needs.changes.outputs.lua == 'true' || needs.changes.outputs.devbox == 'true'
55+
runs-on: ubuntu-latest
56+
steps:
57+
- uses: actions/checkout@v4
58+
59+
- name: Install formatters
60+
run: |
61+
# shfmt (shell formatter)
62+
curl -sS https://webinstall.dev/shfmt | bash
63+
export PATH="$HOME/.local/bin:$PATH"
64+
65+
# stylua (lua formatter)
66+
curl -sL https://github.com/JohnnyMorganz/StyLua/releases/latest/download/stylua-linux-x86_64.zip -o stylua.zip
67+
unzip stylua.zip -d /usr/local/bin
68+
chmod +x /usr/local/bin/stylua
69+
70+
- name: Check shell format (shfmt)
71+
run: |
72+
export PATH="$HOME/.local/bin:$PATH"
73+
echo "Checking shell format..."
74+
75+
# Check zsh files (remove template syntax first)
76+
for file in dot_zshrc.tmpl dot_zshenv.tmpl; do
77+
if [[ -f "$file" ]]; then
78+
sed 's/{{[^}]*}}//g' "$file" > /tmp/check.sh
79+
shfmt -d -i 2 -ci /tmp/check.sh || echo "::warning::$file needs formatting"
80+
fi
81+
done
82+
83+
- name: Check lua format (stylua)
84+
run: |
85+
echo "Checking lua format..."
86+
stylua --check dot_config/nvim/ || echo "::warning::Lua files need formatting"
87+
88+
- name: Check JSON format
89+
run: |
90+
echo "Checking JSON format..."
91+
python3 -c "
92+
import json
93+
import sys
94+
95+
files = ['dot_local/share/devbox/global/default/devbox.json']
96+
for f in files:
97+
with open(f) as fp:
98+
data = json.load(fp)
99+
formatted = json.dumps(data, indent=2)
100+
with open(f) as fp:
101+
original = fp.read().strip()
102+
if formatted != original:
103+
print(f'::warning::{f} needs formatting')
104+
"
105+
106+
lint:
107+
name: Lint
108+
needs: changes
109+
if: needs.changes.outputs.shell == 'true' || needs.changes.outputs.lua == 'true'
110+
runs-on: ubuntu-latest
111+
steps:
112+
- uses: actions/checkout@v4
113+
114+
- name: Install zsh
115+
run: sudo apt-get update && sudo apt-get install -y zsh
116+
117+
- name: Check zsh syntax
118+
run: |
119+
echo "Checking zsh syntax..."
120+
for file in dot_zshrc.tmpl dot_zshenv.tmpl; do
121+
if [[ -f "$file" ]]; then
122+
# Remove chezmoi template syntax for syntax check
123+
sed 's/{{[^}]*}}//g' "$file" > /tmp/check.zsh
124+
zsh -n /tmp/check.zsh && echo "✓ $file" || exit 1
125+
fi
126+
done
127+
128+
- name: ShellCheck
129+
run: |
130+
echo "Running ShellCheck..."
131+
# Install shellcheck if not present (ubuntu-latest usually has it)
132+
if ! command -v shellcheck &> /dev/null; then
133+
sudo apt-get update && sudo apt-get install -y shellcheck
134+
fi
135+
136+
# Check install.sh and scripts in .chezmoiscripts
137+
find . -type f \( -name "install.sh" -o -path "./.chezmoiscripts/*.sh" \) -print0 | xargs -0 shellcheck
138+
139+
- name: Check lua syntax
140+
run: |
141+
echo "Checking lua syntax..."
142+
sudo apt-get install -y lua5.4
143+
find dot_config/nvim -name "*.lua" -exec lua5.4 -p {} \; -print
144+
145+
chezmoi-linux:
146+
name: Chezmoi (Linux, ${{ matrix.env_name }})
147+
needs: changes
148+
if: needs.changes.outputs.chezmoi == 'true'
149+
runs-on: ubuntu-latest
150+
strategy:
151+
matrix:
152+
include:
153+
- business_use: ""
154+
env_name: personal
155+
- business_use: "1"
156+
env_name: business
157+
steps:
158+
- uses: actions/checkout@v4
159+
160+
- name: Install chezmoi
161+
run: sh -c "$(curl -fsLS get.chezmoi.io)" -- -b /usr/local/bin
162+
163+
- name: Setup test config (provide prompted values)
164+
run: |
165+
mkdir -p ~/.config/chezmoi
166+
cat > ~/.config/chezmoi/chezmoi.yaml << 'EOF'
167+
data:
168+
name: "Test User"
169+
email: "test@example.com"
170+
work_email: "test@work.example.com"
171+
EOF
172+
173+
- name: Test chezmoi init (dry-run)
174+
env:
175+
BUSINESS_USE: ${{ matrix.business_use }}
176+
run: |
177+
echo "Testing chezmoi template expansion..."
178+
chezmoi init --source="${PWD}" --dry-run --verbose
179+
180+
- name: Verify template expansion
181+
env:
182+
BUSINESS_USE: ${{ matrix.business_use }}
183+
run: |
184+
chezmoi init --source="${PWD}"
185+
chezmoi managed | head -20
186+
chezmoi cat ~/.config/git/config || true
187+
188+
chezmoi-macos:
189+
name: Chezmoi (macOS, ${{ matrix.env_name }})
190+
needs: changes
191+
if: needs.changes.outputs.chezmoi == 'true'
192+
runs-on: macos-latest
193+
strategy:
194+
matrix:
195+
include:
196+
- business_use: ""
197+
env_name: personal
198+
- business_use: "1"
199+
env_name: business
200+
steps:
201+
- uses: actions/checkout@v4
202+
203+
- name: Install chezmoi
204+
run: brew install chezmoi
205+
206+
- name: Setup test config (provide prompted values)
207+
run: |
208+
mkdir -p ~/.config/chezmoi
209+
cat > ~/.config/chezmoi/chezmoi.yaml << 'EOF'
210+
data:
211+
name: "Test User"
212+
email: "test@example.com"
213+
work_email: "test@work.example.com"
214+
EOF
215+
216+
- name: Test chezmoi init (dry-run)
217+
env:
218+
BUSINESS_USE: ${{ matrix.business_use }}
219+
run: |
220+
echo "Testing chezmoi template expansion..."
221+
chezmoi init --source="${PWD}" --dry-run --verbose
222+
223+
- name: Verify template expansion
224+
env:
225+
BUSINESS_USE: ${{ matrix.business_use }}
226+
run: |
227+
chezmoi init --source="${PWD}"
228+
chezmoi managed | head -20
229+
230+
devbox:
231+
name: Devbox Validation
232+
needs: changes
233+
if: needs.changes.outputs.devbox == 'true'
234+
runs-on: ubuntu-latest
235+
steps:
236+
- uses: actions/checkout@v4
237+
238+
- name: Validate devbox.json
239+
run: |
240+
echo "Validating devbox.json..."
241+
python3 -c "import json; json.load(open('dot_local/share/devbox/global/default/devbox.json'))"
242+
echo "✓ Valid JSON"
243+
244+
- name: Install devbox
245+
uses: jetify-com/devbox-install-action@v0.11.0
246+
with:
247+
enable-cache: true
248+
project-path: dot_local/share/devbox/global/default
249+
250+
- name: Test devbox packages
251+
run: |
252+
echo "Testing devbox package resolution..."
253+
devbox install --config dot_local/share/devbox/global/default/devbox.json
254+
255+
neovim:
256+
name: Neovim Config
257+
needs: changes
258+
if: needs.changes.outputs.nvim == 'true'
259+
runs-on: ubuntu-latest
260+
steps:
261+
- uses: actions/checkout@v4
262+
263+
- name: Install Neovim
264+
run: |
265+
sudo apt-get update
266+
sudo apt-get install -y neovim
267+
268+
- name: Setup Neovim config
269+
run: |
270+
mkdir -p ~/.config
271+
cp -r dot_config/nvim ~/.config/nvim
272+
273+
- name: Test Neovim startup
274+
run: |
275+
echo "Testing Neovim startup..."
276+
timeout 60 nvim --headless -c 'qall' 2>&1 || true
277+
echo "✓ Neovim config loaded"
278+
279+
- name: Validate init.lua
280+
run: nvim --headless -c 'lua print("init.lua OK")' -c 'qall' 2>&1
281+
282+
# Aggregator job for branch protection
283+
# This job always runs and reports success only if all required jobs passed or were skipped
284+
ci-complete:
285+
name: CI Complete
286+
needs: [format, lint, chezmoi-linux, chezmoi-macos, devbox, neovim]
287+
if: always()
288+
runs-on: ubuntu-latest
289+
steps:
290+
- name: Check job results
291+
env:
292+
RESULTS: ${{ join(needs.*.result, ' ') }}
293+
run: |
294+
echo "Job results: $RESULTS"
295+
296+
for result in $RESULTS; do
297+
if [[ "$result" == "failure" || "$result" == "cancelled" ]]; then
298+
echo "❌ CI failed: found $result"
299+
exit 1
300+
fi
301+
done
302+
303+
echo "✅ CI complete: all jobs passed or were skipped"

0 commit comments

Comments
 (0)