diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f27703b0..c448293c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -6,27 +6,102 @@ on: types: [completed] branches: [main] workflow_dispatch: + inputs: + hosts: + description: 'Hosts to deploy' + required: false + default: 'all' + type: choice + options: + - all + - glyph + - spore + - zeta jobs: - deploy: + changes: if: >- github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - uses: dorny/paths-filter@v3 + id: filter + if: github.event_name != 'workflow_dispatch' + with: + filters: | + glyph: + - 'hosts/glyph/**' + spore: + - 'hosts/spore/**' + zeta: + - 'hosts/zeta/**' + shared: + - 'modules/**' + - 'home/**' + - 'lib/**' + - 'overlays/**' + - 'packages/**' + - 'flake.nix' + - 'flake.lock' + + - id: set-matrix + run: | + all='[ + {"host":"glyph","system":"x86_64-linux","runner":"ubuntu-latest"}, + {"host":"spore","system":"x86_64-linux","runner":"ubuntu-latest"}, + {"host":"zeta","system":"aarch64-linux","runner":"ubuntu-24.04-arm"} + ]' + + # workflow_dispatch: use selected host or all + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + host="${{ inputs.hosts }}" + if [[ "$host" == "all" ]]; then + echo "matrix={\"include\":$all}" >> "$GITHUB_OUTPUT" + else + echo "matrix={\"include\":$(echo "$all" | jq --arg h "$host" '[.[] | select(.host == $h)]')}" >> "$GITHUB_OUTPUT" + fi + exit 0 + fi + + # Shared path changes: deploy all hosts + if [[ "${{ steps.filter.outputs.shared }}" == "true" ]]; then + echo "matrix={\"include\":$all}" >> "$GITHUB_OUTPUT" + exit 0 + fi + + selected="[]" + if [[ "${{ steps.filter.outputs.glyph }}" == "true" ]]; then + selected=$(echo "$selected" | jq '. + [{"host":"glyph","system":"x86_64-linux","runner":"ubuntu-latest"}]') + fi + if [[ "${{ steps.filter.outputs.spore }}" == "true" ]]; then + selected=$(echo "$selected" | jq '. + [{"host":"spore","system":"x86_64-linux","runner":"ubuntu-latest"}]') + fi + if [[ "${{ steps.filter.outputs.zeta }}" == "true" ]]; then + selected=$(echo "$selected" | jq '. + [{"host":"zeta","system":"aarch64-linux","runner":"ubuntu-24.04-arm"}]') + fi + + # Fallback: deploy all if no specific hosts matched + if [[ "$selected" == "[]" ]]; then + echo "matrix={\"include\":$all}" >> "$GITHUB_OUTPUT" + else + echo "matrix={\"include\":$selected}" >> "$GITHUB_OUTPUT" + fi + + deploy: + needs: changes concurrency: group: deploy-${{ matrix.host }} cancel-in-progress: false + environment: ${{ matrix.host }} strategy: - matrix: - include: - - host: glyph - system: x86_64-linux - runner: ubuntu-latest - - host: spore - system: x86_64-linux - runner: ubuntu-latest - - host: zeta - system: aarch64-linux - runner: ubuntu-24.04-arm + matrix: ${{ fromJson(needs.changes.outputs.matrix) }} runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v4 diff --git a/README.md b/README.md index 42d8b703..2d27cc0c 100644 --- a/README.md +++ b/README.md @@ -25,4 +25,27 @@ nixos-rebuild switch --flake .#spore --target-host root@spore --build-host local +
+ +CI and deployments + +CI builds all host configurations on every push and PR. On pushes to `main`, the deploy workflow runs automatically after CI succeeds, deploying only the hosts affected by the change: + +- Changes under `hosts/{name}/` deploy only that host +- Changes to shared paths (`modules/`, `home/`, `lib/`, `overlays/`, `packages/`, `flake.nix`, `flake.lock`) deploy all hosts + +Deploy all hosts manually: +```shell +gh workflow run Deploy +``` + +Deploy a specific host: +```shell +gh workflow run Deploy -f hosts=glyph +gh workflow run Deploy -f hosts=spore +gh workflow run Deploy -f hosts=zeta +``` + +
+ [nix-darwin-repo]: https://github.com/nix-darwin/nix-darwin