style(brew): update brewfiles via breww #495
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: 🔍 Validate Dotfiles | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| validate: | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| - name: Prepare CI skill stubs | |
| run: | | |
| mkdir -p .agents/skills | |
| if [[ -d dot_aictx/skills/find-skills ]]; then | |
| rm -rf .agents/skills/find-skills | |
| cp -R dot_aictx/skills/find-skills .agents/skills/ | |
| fi | |
| - name: Install chezmoi | |
| run: sh -c "$(curl -fsLS get.chezmoi.io)" -- -b /usr/local/bin | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Whitespace check | |
| run: git diff --check | |
| - name: Validate templates | |
| run: | | |
| # Verify all templates parse without errors | |
| if ! chezmoi init --source="$(pwd)" --destination=/tmp/chezmoi-test --no-tty 2>&1; then | |
| echo "ERROR: Template parsing failed" | |
| exit 1 | |
| fi | |
| echo "Template parsing: OK" | |
| - name: Template lint (execute-template) | |
| run: | | |
| # Create a mock chezmoi config so execute-template can resolve all data variables | |
| mkdir -p ~/.config/chezmoi | |
| cat > ~/.config/chezmoi/chezmoi.toml << 'EOF' | |
| [data] | |
| github_user = "test" | |
| name = "Test User" | |
| email = "test@test.com" | |
| work_email = "test@work.com" | |
| xdgCacheDir = "/home/test/.cache" | |
| xdgConfigDir = "/home/test/.config" | |
| xdgDataDir = "/home/test/.local/share" | |
| xdgStateDir = "/home/test/.local/state" | |
| machine_profile = "ubuntu-server" | |
| install_ocx = false | |
| install_mas = false | |
| [data.omarchy] | |
| override_shell = false | |
| override_nvim = false | |
| override_tmux = false | |
| override_git = false | |
| override_wm = false | |
| EOF | |
| ERRORS=0 | |
| while IFS= read -r f; do | |
| if ! OUTPUT=$(chezmoi execute-template --source="$(pwd)" < "$f" 2>&1 > /dev/null); then | |
| echo " FAIL: $f" | |
| echo "$OUTPUT" | |
| ERRORS=$(( ERRORS + 1 )) | |
| fi | |
| done < <(find . -name '*.tmpl' -not -path './.git/*' -not -path './dot_aictx/*' -not -name '.chezmoi.toml.tmpl' -not -name '.commit_message.tmpl') | |
| echo "Template lint: $ERRORS errors" | |
| if [[ "$ERRORS" -gt 0 ]]; then | |
| exit 1 | |
| fi | |
| - name: Chezmoi script render checks | |
| run: | | |
| mkdir -p /tmp/chezmoi-dest | |
| CHEZMOI_SOURCE_PATH="$(pwd)" CHEZMOI_DESTINATION_PATH=/tmp/chezmoi-dest bash dot_local/bin/executable_chezmoi-test-scripts | |
| - name: Validate Zellij plugin updater | |
| run: | | |
| python3 -m json.tool dot_config/zellij/plugins/plugins.lock.json >/dev/null | |
| python3 -m py_compile dot_local/bin/executable_update-zellij-plugins | |
| python3 dot_local/bin/executable_update-zellij-plugins | |
| - name: Validate Claude vendor metadata | |
| run: | | |
| python3 -m json.tool docs/CLAUDE_UPSTREAM.json >/dev/null | |
| python3 -m py_compile dot_local/bin/executable_update-claude-upstream dot_local/bin/executable_verify-claude-vendor | |
| python3 dot_local/bin/executable_verify-claude-vendor | |
| - name: Check for secrets | |
| run: | | |
| PATTERNS="sk-[a-zA-Z0-9]{20,}|ghp_[a-zA-Z0-9]{36}|xoxb-[0-9]{10,}|AKIA[0-9A-Z]{16}" | |
| FOUND=$(grep -rPl "$PATTERNS" --include='*.zsh' --include='*.bash' --include='*.toml' --include='*.json' --include='*.tmpl' . 2>/dev/null \ | |
| | grep -v '.git/' | grep -v 'README' | grep -v 'SKILL.md' | grep -v 'pre-commit' | grep -v 'dot_aictx/skills/' || true) | |
| if [[ -n "$FOUND" ]]; then | |
| echo "ERROR: Potential secrets found in:" | |
| echo "$FOUND" | |
| exit 1 | |
| fi | |
| echo "Secret scan: PASS" | |
| - name: Validate JSON files | |
| run: | | |
| ERRORS=0 | |
| while IFS= read -r f; do | |
| if python3 -m json.tool "$f" > /dev/null 2>&1; then | |
| echo " OK: $f" | |
| else | |
| echo " FAIL: $f" | |
| ERRORS=$(( ERRORS + 1 )) | |
| fi | |
| done < <(find . -name '*.json' -not -path './.git/*' -not -path './dot_aictx/skills/*') | |
| if [[ "$ERRORS" -gt 0 ]]; then | |
| echo "JSON validation: FAIL ($ERRORS errors)" | |
| exit 1 | |
| fi | |
| echo "JSON validation: PASS" | |
| - name: Check file naming conventions | |
| run: | | |
| ERRORS=0 | |
| for f in $(find . -maxdepth 1 -name '.*' -not -name '.git*' -not -name '.chezmoi*' -not -name '.commit_message*' -not -name '.claude' -not -name '.github' -not -name '.DS_Store' -not -name '.editorconfig'); do | |
| echo "WARNING: Unexpected dotfile at root: $f" | |
| ERRORS=$(( ERRORS + 1 )) | |
| done | |
| if [[ "$ERRORS" -gt 0 ]]; then | |
| echo "Naming conventions: $ERRORS warnings" | |
| else | |
| echo "Naming conventions: PASS" | |
| fi | |
| - name: Validate TOML files | |
| run: | | |
| ERRORS=0 | |
| while IFS= read -r f; do | |
| if python3 -c "import tomllib; tomllib.load(open('$f','rb'))" 2>/dev/null; then | |
| echo " OK: $f" | |
| else | |
| echo " FAIL: $f" | |
| ERRORS=$(( ERRORS + 1 )) | |
| fi | |
| done < <(find . -name '*.toml' -not -path './.git/*' -not -name '*.tmpl') | |
| if [[ "$ERRORS" -gt 0 ]]; then | |
| echo "TOML validation: FAIL ($ERRORS errors)" | |
| exit 1 | |
| fi | |
| echo "TOML validation: PASS" | |
| - name: Validate Aptfile/Dnffile/Pacfile format | |
| run: | | |
| ERRORS=0 | |
| while IFS= read -r f; do | |
| while IFS= read -r line || [[ -n "$line" ]]; do | |
| [[ -z "${line// }" || "$line" =~ ^[[:space:]]*# ]] && continue | |
| if ! [[ "$line" =~ ^[a-zA-Z0-9][a-zA-Z0-9.+\-_]*$ ]]; then | |
| echo " FAIL: invalid package name '${line}' in ${f}" | |
| ERRORS=$(( ERRORS + 1 )) | |
| fi | |
| done < "$f" | |
| done < <(find dot_private -name 'Aptfile_*' -o -name 'Dnffile_*' -o -name 'Pacfile_*' -o -name 'Rpmfile_*' -o -name 'Snapfile_*' 2>/dev/null) | |
| if [[ "$ERRORS" -gt 0 ]]; then | |
| echo "Manifest format: FAIL ($ERRORS errors)" | |
| exit 1 | |
| fi | |
| echo "Manifest format: PASS" | |
| - name: Validate Scoopfile.json schema | |
| run: | | |
| if [[ -f dot_private/Scoopfile.json ]]; then | |
| python3 -c " | |
| import json, sys | |
| with open('dot_private/Scoopfile.json') as f: | |
| d = json.load(f) | |
| assert 'apps' in d, 'missing apps key' | |
| assert 'buckets' in d, 'missing buckets key' | |
| print(' Scoopfile.json: OK') | |
| " | |
| echo "Scoopfile schema: PASS" | |
| else | |
| echo "Scoopfile schema: SKIP (no Scoopfile.json)" | |
| fi | |
| - name: aictx tests | |
| working-directory: tools/aictx | |
| run: | | |
| cargo fmt --check | |
| cargo check | |
| cargo test | |
| - name: ShellCheck | |
| run: | | |
| sudo apt-get install -y shellcheck | |
| ERRORS=0 | |
| while IFS= read -r f; do | |
| if ! shellcheck --severity=error "$f"; then | |
| ERRORS=$(( ERRORS + 1 )) | |
| fi | |
| done < <( | |
| find . \( -name '*.sh' -o -name '*.bash' \) \ | |
| -not -path './.git/*' -not -path './dot_claude/*' -not -path './dot_aictx/skills/*' -not -path './dot_aictx/agents/*' 2>/dev/null | |
| grep -rl '#!/.*bash' dot_local/bin/ 2>/dev/null || true | |
| ) | |
| if [[ "$ERRORS" -gt 0 ]]; then | |
| echo "ShellCheck: FAIL ($ERRORS files with issues)" | |
| exit 1 | |
| fi | |
| echo "ShellCheck: PASS" |