-
Notifications
You must be signed in to change notification settings - Fork 2
215 lines (193 loc) · 8.39 KB
/
Copy pathpr-validation.yml
File metadata and controls
215 lines (193 loc) · 8.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
name: Pull Request Validation
on:
pull_request:
branches: [main]
types: [opened, synchronize, reopened, ready_for_review]
permissions:
contents: read
pull-requests: write
jobs:
conventional-commits:
runs-on: ubuntu-latest
steps:
- name: Check conventional commits
uses: helpers4/action/conventional-commits@main
with:
checkout: "true"
pr-comment: "error"
version-bump-check:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Check touched features bumped their version
id: check
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
set -euo pipefail
MERGE_BASE=$(git merge-base "${BASE_SHA}" HEAD)
echo "::notice::Diff base = ${MERGE_BASE} → HEAD ($(git rev-parse HEAD))"
mapfile -t names < <(git diff --name-only "${MERGE_BASE}..HEAD" -- src/ \
| awk -F/ '{print $2}' | sort -u)
FAILED=0
for name in "${names[@]}"; do
manifest="src/${name}/devcontainer-feature.json"
[ -f "$manifest" ] || continue # feature removed on this branch
new_version=$(jq -r '.version' "$manifest")
old_version=$(git show "${MERGE_BASE}:${manifest}" 2>/dev/null | jq -r '.version' 2>/dev/null || echo "")
if [ -z "$old_version" ]; then
echo "✅ ${name}: new feature, no bump required"
elif [ "$old_version" = "$new_version" ]; then
echo "❌ ${name}: touched but version unchanged (${new_version})"
FAILED=1
else
echo "✅ ${name}: ${old_version} → ${new_version}"
fi
done
if [ "$FAILED" -eq 1 ]; then
echo ""
echo "One or more touched features didn't bump 'version' in devcontainer-feature.json."
echo "release.yml only publishes a feature whose version changed — bump it (patch by"
echo "default), once for the whole branch. See AGENTS.md 'Modifying an existing"
echo "feature — version bump'."
fi
exit "$FAILED"
test-features:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- features: essential-dev
baseImage: mcr.microsoft.com/devcontainers/base:debian
- features: essential-dev
baseImage: ubuntu:latest
- features: essential-dev
baseImage: mcr.microsoft.com/devcontainers/base:ubuntu
- features: shell-history-per-project
baseImage: mcr.microsoft.com/devcontainers/base:debian
- features: shell-history-per-project
baseImage: ubuntu:latest
- features: shell-history-per-project
baseImage: mcr.microsoft.com/devcontainers/base:ubuntu
- features: git-absorb
baseImage: mcr.microsoft.com/devcontainers/base:debian
- features: git-absorb
baseImage: ubuntu:latest
- features: git-absorb
baseImage: mcr.microsoft.com/devcontainers/base:ubuntu
- features: angular-dev
baseImage: mcr.microsoft.com/devcontainers/javascript-node:20
- features: package-auto-install
baseImage: mcr.microsoft.com/devcontainers/javascript-node:20
- features: helpers4-common
baseImage: mcr.microsoft.com/devcontainers/base:debian
- features: helpers4-common
baseImage: ubuntu:latest
- features: claude-dev
baseImage: ubuntu:latest
- features: pnpm-store
baseImage: mcr.microsoft.com/devcontainers/typescript-node:20
- features: pnpm-store
baseImage: ubuntu:latest
- features: vite-plus
baseImage: mcr.microsoft.com/devcontainers/typescript-node:20
- features: typescript-dev
baseImage: mcr.microsoft.com/devcontainers/typescript-node:20
- features: auto-header
baseImage: mcr.microsoft.com/devcontainers/base:ubuntu
- features: peon-ping
baseImage: ubuntu:latest
- features: peon-ping
baseImage: mcr.microsoft.com/devcontainers/base:ubuntu
- features: dotfiles-sync
baseImage: mcr.microsoft.com/devcontainers/base:debian
- features: dotfiles-sync
baseImage: mcr.microsoft.com/devcontainers/base:ubuntu
- features: github-dev
baseImage: mcr.microsoft.com/devcontainers/base:debian
- features: github-dev
baseImage: mcr.microsoft.com/devcontainers/base:ubuntu
- features: mistral-dev
baseImage: ubuntu:latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Install latest devcontainer CLI
run: npm install -g @devcontainers/cli
- name: Create mount sources for claude-dev
if: matrix.features == 'claude-dev'
# The bind mount source ~/.claude must exist on the host or `docker run` aborts
# before the test runs (same pattern as dotfiles-sync below).
run: mkdir -p ~/.claude
- name: Create mount sources for mistral-dev
if: matrix.features == 'mistral-dev'
# The bind mount source ~/.vibe must exist on the host or `docker run` aborts.
run: mkdir -p ~/.vibe
- name: Create mount sources for dotfiles-sync
if: matrix.features == 'dotfiles-sync'
# All bind sources declared in src/dotfiles-sync/devcontainer-feature.json
# must exist on the host or `docker run` aborts before the test runs.
run: |
mkdir -p ~/.ssh ~/.gnupg \
~/.config/git ~/.config/gh ~/.config/pnpm ~/.config/pip \
~/.cargo ~/.aws ~/.kube ~/.docker
touch ~/.gitconfig ~/.gitignore_global ~/.npmrc ~/.yarnrc.yml \
~/.config/pnpm/rc ~/.config/gh/config.yml ~/.config/gh/hosts.yml \
~/.cargo/config.toml ~/.config/pip/pip.conf \
~/.aws/config ~/.kube/config ~/.docker/config.json
- name: "Test feature '${{ matrix.features }}' against '${{ matrix.baseImage }}'"
run: devcontainer features test --features ${{ matrix.features }} --base-image ${{ matrix.baseImage }} .
shellcheck:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Run ShellCheck on install scripts
uses: ludeeus/action-shellcheck@2.0.0
with:
severity: warning
scandir: src
# Preserve the previous scope (install.sh only) — path-keys.sh, sync-files.sh,
# and gh-auth.sh have never been linted here and may have pre-existing issues.
ignore_names: "path-keys.sh sync-files.sh gh-auth.sh"
- name: Verify bootstrap copies match helpers4-common canonical
run: |
# Extract the H4_COMMON heredoc body — same delimiter used by both
# helpers4-common/install.sh (canonical) and every feature's bootstrap.
CANONICAL=$(sed -n "/<< 'H4_COMMON'/,/^H4_COMMON$/p" \
src/helpers4-common/install.sh | sed '1d;$d')
FAILED=0
for f in src/*/install.sh; do
[ "$f" = "src/helpers4-common/install.sh" ] && continue
COPY=$(sed -n "/<< 'H4_COMMON'/,/^H4_COMMON$/p" \
"$f" | sed '1d;$d')
[ -z "$COPY" ] && continue
if [ "$CANONICAL" != "$COPY" ]; then
echo "❌ Bootstrap in $f differs from src/helpers4-common/install.sh"
diff <(echo "$CANONICAL") <(echo "$COPY") || true
FAILED=1
fi
done
if [ "$FAILED" -eq 0 ]; then
echo "✅ All bootstrap copies match the canonical helpers4-common version"
fi
exit $FAILED
pr-comment:
runs-on: ubuntu-latest
needs: [conventional-commits, version-bump-check, test-features, shellcheck]
if: always()
steps:
- name: Update PR comment
uses: helpers4/action/pr-status-comment@main
with:
jobs: |
{
"🧾 Conventional Commits": "${{ needs.conventional-commits.result }}",
"🔖 Version Bump": "${{ needs.version-bump-check.result }}",
"🧪 Feature Tests": "${{ needs.test-features.result }}",
"🐚 ShellCheck": "${{ needs.shellcheck.result }}"
}