Skip to content

Commit 274529e

Browse files
stackptrclaude
andauthored
feat: path-based deploy filtering with host selection (#382)
* feat: deploy only affected hosts based on changed paths Add a changes detection job using dorny/paths-filter to build a dynamic deploy matrix. Host-specific changes (hosts/{name}/**) only deploy that host, while shared path changes (modules, home, lib, overlays, packages, flake files) deploy all hosts. workflow_dispatch deploys all hosts. Also adds GitHub Environments for per-host deployment status tracking. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add host selection input to workflow_dispatch Adds a dropdown input to the manual dispatch trigger allowing deployment of a specific host (glyph, spore, zeta) or all hosts. Defaults to all. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: add CI and deployment section to README Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c2e5167 commit 274529e

2 files changed

Lines changed: 110 additions & 12 deletions

File tree

‎.github/workflows/deploy.yml‎

Lines changed: 87 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,102 @@ on:
66
types: [completed]
77
branches: [main]
88
workflow_dispatch:
9+
inputs:
10+
hosts:
11+
description: 'Hosts to deploy'
12+
required: false
13+
default: 'all'
14+
type: choice
15+
options:
16+
- all
17+
- glyph
18+
- spore
19+
- zeta
920

1021
jobs:
11-
deploy:
22+
changes:
1223
if: >-
1324
github.event_name == 'workflow_dispatch' ||
1425
github.event.workflow_run.conclusion == 'success'
26+
runs-on: ubuntu-latest
27+
outputs:
28+
matrix: ${{ steps.set-matrix.outputs.matrix }}
29+
steps:
30+
- uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 2
33+
34+
- uses: dorny/paths-filter@v3
35+
id: filter
36+
if: github.event_name != 'workflow_dispatch'
37+
with:
38+
filters: |
39+
glyph:
40+
- 'hosts/glyph/**'
41+
spore:
42+
- 'hosts/spore/**'
43+
zeta:
44+
- 'hosts/zeta/**'
45+
shared:
46+
- 'modules/**'
47+
- 'home/**'
48+
- 'lib/**'
49+
- 'overlays/**'
50+
- 'packages/**'
51+
- 'flake.nix'
52+
- 'flake.lock'
53+
54+
- id: set-matrix
55+
run: |
56+
all='[
57+
{"host":"glyph","system":"x86_64-linux","runner":"ubuntu-latest"},
58+
{"host":"spore","system":"x86_64-linux","runner":"ubuntu-latest"},
59+
{"host":"zeta","system":"aarch64-linux","runner":"ubuntu-24.04-arm"}
60+
]'
61+
62+
# workflow_dispatch: use selected host or all
63+
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
64+
host="${{ inputs.hosts }}"
65+
if [[ "$host" == "all" ]]; then
66+
echo "matrix={\"include\":$all}" >> "$GITHUB_OUTPUT"
67+
else
68+
echo "matrix={\"include\":$(echo "$all" | jq --arg h "$host" '[.[] | select(.host == $h)]')}" >> "$GITHUB_OUTPUT"
69+
fi
70+
exit 0
71+
fi
72+
73+
# Shared path changes: deploy all hosts
74+
if [[ "${{ steps.filter.outputs.shared }}" == "true" ]]; then
75+
echo "matrix={\"include\":$all}" >> "$GITHUB_OUTPUT"
76+
exit 0
77+
fi
78+
79+
selected="[]"
80+
if [[ "${{ steps.filter.outputs.glyph }}" == "true" ]]; then
81+
selected=$(echo "$selected" | jq '. + [{"host":"glyph","system":"x86_64-linux","runner":"ubuntu-latest"}]')
82+
fi
83+
if [[ "${{ steps.filter.outputs.spore }}" == "true" ]]; then
84+
selected=$(echo "$selected" | jq '. + [{"host":"spore","system":"x86_64-linux","runner":"ubuntu-latest"}]')
85+
fi
86+
if [[ "${{ steps.filter.outputs.zeta }}" == "true" ]]; then
87+
selected=$(echo "$selected" | jq '. + [{"host":"zeta","system":"aarch64-linux","runner":"ubuntu-24.04-arm"}]')
88+
fi
89+
90+
# Fallback: deploy all if no specific hosts matched
91+
if [[ "$selected" == "[]" ]]; then
92+
echo "matrix={\"include\":$all}" >> "$GITHUB_OUTPUT"
93+
else
94+
echo "matrix={\"include\":$selected}" >> "$GITHUB_OUTPUT"
95+
fi
96+
97+
deploy:
98+
needs: changes
1599
concurrency:
16100
group: deploy-${{ matrix.host }}
17101
cancel-in-progress: false
102+
environment: ${{ matrix.host }}
18103
strategy:
19-
matrix:
20-
include:
21-
- host: glyph
22-
system: x86_64-linux
23-
runner: ubuntu-latest
24-
- host: spore
25-
system: x86_64-linux
26-
runner: ubuntu-latest
27-
- host: zeta
28-
system: aarch64-linux
29-
runner: ubuntu-24.04-arm
104+
matrix: ${{ fromJson(needs.changes.outputs.matrix) }}
30105
runs-on: ${{ matrix.runner }}
31106
steps:
32107
- uses: actions/checkout@v4

‎README.md‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,27 @@ nixos-rebuild switch --flake .#spore --target-host root@spore --build-host local
2525

2626
</details>
2727

28+
<details>
29+
30+
<summary>CI and deployments</summary>
31+
32+
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:
33+
34+
- Changes under `hosts/{name}/` deploy only that host
35+
- Changes to shared paths (`modules/`, `home/`, `lib/`, `overlays/`, `packages/`, `flake.nix`, `flake.lock`) deploy all hosts
36+
37+
Deploy all hosts manually:
38+
```shell
39+
gh workflow run Deploy
40+
```
41+
42+
Deploy a specific host:
43+
```shell
44+
gh workflow run Deploy -f hosts=glyph
45+
gh workflow run Deploy -f hosts=spore
46+
gh workflow run Deploy -f hosts=zeta
47+
```
48+
49+
</details>
50+
2851
[nix-darwin-repo]: https://github.com/nix-darwin/nix-darwin

0 commit comments

Comments
 (0)