diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96f333c..ecf0100 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,3 +56,47 @@ jobs: with: scandir: "." ignore_paths: "collections .github" + + # --- macOS jobs -------------------------------------------------------- + # + # Standard GitHub-hosted macos-26 runners are Apple Silicon (M1, 3 CPU, + # 7 GB RAM, 14 GB disk) and free for public repos. These two jobs catch + # platform-specific bugs that the Ubuntu lint jobs cannot see. + + macos-check: + name: macos-check (syntax + asserts) + runs-on: macos-26 + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - name: Install Ansible via Homebrew + run: brew install ansible + - name: Install Ansible Galaxy collections + run: ansible-galaxy collection install -r requirements.yml + - name: ansible-playbook --syntax-check + run: ansible-playbook -i inventory/localhost.yml playbook.yml --syntax-check + - name: Run preflight asserts only + # --tags always pulls just the pre_tasks block (macOS / arm64 / + # Sequoia-or-later asserts). Proves the playbook can boot on a + # real Apple Silicon mac without doing any installs. + run: ansible-playbook -i inventory/localhost.yml playbook.yml --tags always + + macos-homebrew: + name: macos-homebrew (install package set) + runs-on: macos-26 + timeout-minutes: 25 + steps: + - uses: actions/checkout@v4 + - name: Install Ansible via Homebrew + run: brew install ansible + - name: Install Ansible Galaxy collections + run: ansible-galaxy collection install -r requirements.yml + - name: Run system + homebrew roles + # We stop here on purpose: the kubernetes role wants to launch + # Docker Desktop, which is not viable inside a CI runner. The + # homebrew install path is the high-leverage check for catching + # typo'd brew formulas / casks before a user hits them. + run: | + ansible-playbook -i inventory/localhost.yml playbook.yml \ + --tags 'always,system,homebrew' \ + --diff diff --git a/ansible.cfg b/ansible.cfg index 795a6ff..69b675f 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,14 +1,20 @@ [defaults] inventory = inventory/localhost.yml roles_path = roles -collections_paths = ./collections:~/.ansible/collections +collections_path = ./collections:~/.ansible/collections host_key_checking = False nocows = True -stdout_callback = yaml +# Use the in-tree default callback (community.general.yaml was +# removed in community.general v12; modern Ansible wants the +# `result_format` knob on ansible.builtin.default instead). +stdout_callback = ansible.builtin.default display_skipped_hosts = False retry_files_enabled = False interpreter_python = auto_silent +[callback_default] +result_format = yaml + [inventory] enable_plugins = yaml, ini, auto diff --git a/playbook.yml b/playbook.yml index 7f5b880..82fc018 100644 --- a/playbook.yml +++ b/playbook.yml @@ -44,21 +44,23 @@ tags: [always] roles: - # Base path -- everyone gets these in order. + # Base path -- everyone gets these in order. Each role also + # gets a tag of its own name so CI can run a subset cleanly + # (e.g. --tags system,homebrew for the macOS install test). - role: system - tags: [base] + tags: [base, system] - role: homebrew - tags: [base] + tags: [base, homebrew] - role: kubernetes - tags: [base] + tags: [base, kubernetes] - role: llmkube_core - tags: [base] + tags: [base, llmkube_core] - role: model_starter - tags: [base] + tags: [base, model_starter] - role: developer_tools - tags: [base] + tags: [base, developer_tools] - role: opencode - tags: [base] + tags: [base, opencode] # Opt-in -- only when --tags includes the matching tag. - role: carnice