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
178 changes: 169 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,184 @@
name: Test Init
name: CI Tests

on: [push]
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install shellcheck
run: |
sudo apt-get update
sudo apt-get install -y shellcheck

- name: Run shellcheck on shell scripts
run: |
find . -type f -name "*.sh" -exec shellcheck {} + || true
find . -type f -name "*.zsh" -exec shellcheck --shell=bash {} + 2>/dev/null || true

- name: Check for syntax errors in zsh files
run: |
for file in $(find . -type f -name "*.zsh" -o -name ".zshrc"); do
if [[ -f "$file" ]]; then
zsh -n "$file" || echo "Syntax check failed for $file"
fi
done

runs-on: [macos-latest]
test:
name: Test - ${{ matrix.test-suite }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
continue-on-error: true
strategy:
matrix:
os: [macos-latest]
test-suite:
- configuration
- installers
- symlinks
include:
- os: macos-13
test-suite: symlinks
fail-fast: false

steps:
- uses: actions/checkout@v4

- name: Cache brew dependencies
uses: actions/cache@v4
env:
cache-name: cache-brew-dependencies
with:
path: |
~/Library/Caches/Homebrew
/usr/local/Homebrew
/opt/homebrew
key: ${{ runner.os }}-${{ matrix.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/.Brewfile') }}
restore-keys: |
${{ runner.os }}-${{ matrix.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-${{ matrix.os }}-build-
${{ runner.os }}-${{ matrix.os }}-

- name: Install Bats
run: |
if ! command -v bats &> /dev/null; then
brew install bats-core
fi

- name: Run ${{ matrix.test-suite }} tests
run: bats tests/${{ matrix.test-suite }}.bats

quick-checks:
name: Quick Checks
runs-on: macos-latest
continue-on-error: true

steps:
- uses: actions/checkout@v4

- name: Test make list
run: |
make list
# Verify that .claude is included
make list | grep "\.claude" || exit 1

- name: Test make install (dry run)
run: |
# Create a temporary HOME for testing
export TEST_HOME=$(mktemp -d)
export HOME=$TEST_HOME
make install
# Verify symlinks were created
ls -la $TEST_HOME
# Check that essential dotfiles are linked
test -L $TEST_HOME/.zshrc
test -L $TEST_HOME/.tmux.conf
test -L $TEST_HOME/.gitconfig

- name: Test installer syntax
run: |
for installer in installers/*.sh; do
echo "Checking syntax of $installer"
zsh -n "$installer"
done
for installer in settings/**/install.sh; do
echo "Checking syntax of $installer"
zsh -n "$installer"
done

- name: Verify critical files exist
run: |
test -f .Brewfile
test -f .zshrc
test -f .gitconfig
test -f .tmux.conf
test -f Makefile
test -d .zsh
test -d installers
test -d settings

integration:
name: Integration Test
runs-on: macos-latest
needs: [lint]
continue-on-error: true

steps:
- uses: actions/checkout@v4
- name: Cache brew dependencies (download)
uses: actions/cache@v4.2.2

- name: Cache brew dependencies
uses: actions/cache@v4
env:
cache-name: cache-brew-dependencies
with:
path: ~/Library/Caches/Homebrew
path: |
~/Library/Caches/Homebrew
/usr/local/Homebrew
/opt/homebrew
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/.Brewfile') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: Test make all
run: make all

- name: Full installation test
run: |
# Set up test environment
export ORIGINAL_HOME=$HOME
export TEST_HOME=$(mktemp -d)
export HOME=$TEST_HOME

# Run full installation
make all || true

# Verify installation
echo "=== Verifying installation ==="
ls -la $TEST_HOME

# Check symlinks
if [[ -L $TEST_HOME/.zshrc ]]; then
echo "✓ .zshrc symlink created"
else
echo "✗ .zshrc symlink missing"
fi

# Restore HOME
export HOME=$ORIGINAL_HOME

- name: Test idempotency
run: |
export TEST_HOME=$(mktemp -d)
export HOME=$TEST_HOME

# Run install twice to test idempotency
make install
make install

# Should complete without errors
echo "✓ Installation is idempotent"
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,14 @@ deps:
$(call print_step,Installing dependencies)
@echo 'Running dependency installers...'
$(foreach val, $(DEPS_INSTALLERS), echo " Running $(val)..." && /bin/zsh $(val);)

test:
@echo 'Running tests with Bats...'
@if command -v bats >/dev/null 2>&1; then \
bats tests/*.bats; \
else \
echo "Bats is not installed. Install with: brew install bats-core"; \
exit 1; \
fi

.PHONY: all list install deps test
119 changes: 119 additions & 0 deletions tests/configuration.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#!/usr/bin/env bats

load test_helper

@test ".Brewfile exists and is valid" {
assert_file_exists "${REPO_ROOT}/.Brewfile"

# Check basic Brewfile syntax
# Should contain brew commands
grep -q "^brew " "${REPO_ROOT}/.Brewfile"
}

@test ".Brewfile contains expected packages" {
local brewfile="${REPO_ROOT}/.Brewfile"

# Check for some essential packages
grep -q "brew 'zsh'" "${brewfile}"
grep -q "brew 'git'" "${brewfile}"
grep -q "brew 'tmux'" "${brewfile}"
}

@test ".zshrc exists and sources modular configs" {
assert_file_exists "${REPO_ROOT}/.zshrc"

# Check that .zshrc sources the modular config files
grep -q "source.*\.zsh/.*\.zsh" "${REPO_ROOT}/.zshrc" || \
grep -q "\. .*\.zsh/.*\.zsh" "${REPO_ROOT}/.zshrc" || \
grep -q "for.*\.zsh.*source" "${REPO_ROOT}/.zshrc"
}

@test "modular zsh configs exist" {
assert_dir_exists "${REPO_ROOT}/.zsh"

# Check for expected modular config files
local expected_configs=(
"alias.zsh"
"env.zsh"
"style.zsh"
"plugin.zsh"
)

for config in "${expected_configs[@]}"; do
if [[ ! -f "${REPO_ROOT}/.zsh/${config}" ]]; then
echo "Warning: Expected config ${config} not found"
# Not a failure, just a warning
fi
done
}

@test ".gitconfig exists and has valid structure" {
assert_file_exists "${REPO_ROOT}/.gitconfig"

# Check for basic git config structure
grep -q "\[user\]" "${REPO_ROOT}/.gitconfig" || \
grep -q "\[core\]" "${REPO_ROOT}/.gitconfig" || \
grep -q "\[alias\]" "${REPO_ROOT}/.gitconfig"
}

@test ".tmux.conf exists" {
assert_file_exists "${REPO_ROOT}/.tmux.conf"
}

@test "commit template exists if referenced" {
if grep -q "template.*=.*\.commit_template" "${REPO_ROOT}/.gitconfig" 2>/dev/null; then
assert_file_exists "${REPO_ROOT}/.commit_template"
fi
}

@test "zsh configs have valid syntax" {
# Test main .zshrc
run zsh -n "${REPO_ROOT}/.zshrc"
if [ "$status" -ne 0 ]; then
echo "Syntax error in .zshrc: ${output}"
false
fi

# Test modular configs if they exist
if [[ -d "${REPO_ROOT}/.zsh" ]]; then
for config in "${REPO_ROOT}"/.zsh/*.zsh; do
if [[ -f "${config}" ]]; then
run zsh -n "${config}"
if [ "$status" -ne 0 ]; then
echo "Syntax error in $(basename "${config}"): ${output}"
false
fi
fi
done
fi
}

@test "no hardcoded absolute paths in configs" {
# Check for common hardcoded paths that should be avoided
local configs=(
"${REPO_ROOT}/.zshrc"
"${REPO_ROOT}/.gitconfig"
"${REPO_ROOT}/.tmux.conf"
)

for config in "${configs[@]}"; do
if [[ -f "${config}" ]]; then
# Skip checking for /usr, /bin, /opt as these are system paths
# Check for hardcoded user home paths
if grep -q "/Users/[^/]*/" "${config}" | grep -v "^#"; then
echo "Warning: Possible hardcoded user path in $(basename "${config}")"
# Just a warning, not a failure
fi
fi
done
}

@test "CLAUDE.md exists and contains setup instructions" {
if [[ -f "${REPO_ROOT}/CLAUDE.md" ]]; then
# Check that CLAUDE.md contains key sections
grep -qi "repository overview\|overview" "${REPO_ROOT}/CLAUDE.md"
grep -qi "command\|setup\|install" "${REPO_ROOT}/CLAUDE.md"
else
echo "Warning: CLAUDE.md not found"
fi
}
Loading
Loading