Skip to content

Commit e8de25b

Browse files
stasadevclaude
andauthored
feat(update-checker): add validation improvements, fixes #92 (#94)
Co-authored-by: Claude <[email protected]>
1 parent 680b51e commit e8de25b

File tree

2 files changed

+122
-15
lines changed

2 files changed

+122
-15
lines changed

.github/scripts/update-checker.sh

Lines changed: 121 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
set -o errexit
44
set -o nounset
5-
set -o pipefail
65

76
UPSTREAM=https://github.com/ddev/ddev-addon-template/blob/main
87

8+
# List to store info messages
9+
info_messages=()
10+
911
# List to store actions
1012
actions=()
1113

@@ -53,37 +55,106 @@ check_readme() {
5355
check_install_yaml() {
5456
local install_yaml="install.yaml"
5557

58+
# Minimum required DDEV version v1.24.10
59+
local min_ddev_major=1
60+
local min_ddev_minor=24
61+
local min_ddev_patch=10
62+
5663
if [[ -f "$install_yaml" ]]; then
57-
# Check for ddev_version_constraint
58-
if ! grep -q "^ddev_version_constraint: '>= v1\.24\.[3-9][0-9]*'" "$install_yaml" && ! grep -q "^ddev_version_constraint: '>= v1\.2[5-9]\." "$install_yaml"; then
59-
actions+=("install.yaml should contain 'ddev_version_constraint: \">= v1.24.3\"' or higher, see upstream file $UPSTREAM/$install_yaml")
64+
# Check for ddev_version_constraint >= minimum required version
65+
local has_valid_version=false
66+
if grep -q "^ddev_version_constraint:" "$install_yaml"; then
67+
# Extract the version number from the constraint (handles both single and double quotes)
68+
local version_string
69+
version_string=$(grep "^ddev_version_constraint:" "$install_yaml" | head -1 | sed "s/^ddev_version_constraint: ['\"]>= v//; s/['\"].*//" | grep -o "^[0-9.]*")
70+
71+
if [[ -n "$version_string" ]]; then
72+
# Split version into components
73+
local major minor patch
74+
IFS='.' read -r major minor patch <<< "$version_string"
75+
major=${major:-0}
76+
minor=${minor:-0}
77+
patch=${patch:-0}
78+
79+
# Check if version is >= minimum required version
80+
if (( major > min_ddev_major )) || \
81+
(( major == min_ddev_major && minor > min_ddev_minor )) || \
82+
(( major == min_ddev_major && minor == min_ddev_minor && patch >= min_ddev_patch )); then
83+
has_valid_version=true
84+
fi
85+
fi
86+
fi
87+
88+
if [[ "$has_valid_version" != "true" ]]; then
89+
actions+=("install.yaml should contain \`ddev_version_constraint: '>= v${min_ddev_major}.${min_ddev_minor}.${min_ddev_patch}'\` or higher, see upstream file $UPSTREAM/$install_yaml")
6090
fi
6191

6292
# Check for addon-template
6393
if grep -q "addon-template" "$install_yaml"; then
6494
actions+=("install.yaml should not contain 'addon-template', use your own name")
6595
fi
96+
97+
# Check for #ddev-nodisplay tag
98+
if grep -q "#ddev-nodisplay" "$install_yaml"; then
99+
actions+=("install.yaml should not contain '#ddev-nodisplay' tag, it's not used anymore, see upstream file $UPSTREAM/$install_yaml")
100+
fi
66101
else
67102
actions+=("install.yaml is missing, see upstream file $UPSTREAM/$install_yaml")
68103
fi
69104
}
70105

71-
# Check tests/test.bats for required conditions
106+
# Check tests/*.bats for required conditions
72107
check_test_bats() {
73108
local test_bats="tests/test.bats"
109+
local bats_files
74110

111+
# Find any .bats files in tests directory
112+
mapfile -t bats_files < <(find tests -maxdepth 1 -name "*.bats" -type f 2>/dev/null)
113+
114+
if [[ ${#bats_files[@]} -eq 0 ]]; then
115+
actions+=("tests/ directory should contain at least one .bats test file, see upstream file $UPSTREAM/tests/test.bats")
116+
return
117+
fi
118+
119+
# If tests/test.bats exists, check it for required content
75120
if [[ -f "$test_bats" ]]; then
76121
# Check for test_tags=release
77122
if grep -q "install from release" "$test_bats" && ! grep -q "# bats test_tags=release" "$test_bats"; then
78-
actions+=("$test_bats should contain '# bats test_tags=release', see upstream file $UPSTREAM/$test_bats")
123+
actions+=("$test_bats should contain '# bats test_tags=release', see upstream file $UPSTREAM/tests/test.bats")
79124
fi
80125

81126
# Check for ddev add-on get
82127
if ! grep -q "ddev add-on get" "$test_bats"; then
83-
actions+=("$test_bats should contain 'ddev add-on get', see upstream file $UPSTREAM/$test_bats")
128+
actions+=("$test_bats should contain 'ddev add-on get', see upstream file $UPSTREAM/tests/test.bats")
129+
fi
130+
131+
# Check for GITHUB_ENV usage
132+
if ! grep -q "GITHUB_ENV" "$test_bats"; then
133+
actions+=("$test_bats should use GITHUB_ENV in teardown() function, see upstream file $UPSTREAM/tests/test.bats")
134+
fi
135+
136+
# Check for DDEV_NONINTERACTIVE=true
137+
if ! grep -q "DDEV_NONINTERACTIVE=true" "$test_bats"; then
138+
actions+=("$test_bats should set DDEV_NONINTERACTIVE=true, see upstream file $UPSTREAM/tests/test.bats")
139+
fi
140+
141+
# Check for DDEV_NO_INSTRUMENTATION=true
142+
if ! grep -q "DDEV_NO_INSTRUMENTATION=true" "$test_bats"; then
143+
actions+=("$test_bats should set DDEV_NO_INSTRUMENTATION=true, see upstream file $UPSTREAM/tests/test.bats")
144+
fi
145+
146+
# Check for GITHUB_REPO
147+
if ! grep -q "GITHUB_REPO" "$test_bats"; then
148+
actions+=("$test_bats should define GITHUB_REPO, see upstream file $UPSTREAM/tests/test.bats")
149+
fi
150+
151+
# Check for bats_load_library
152+
if ! grep -q "bats_load_library" "$test_bats"; then
153+
actions+=("$test_bats should use bats_load_library, see upstream file $UPSTREAM/tests/test.bats")
84154
fi
85155
else
86-
actions+=("$test_bats is missing, see upstream file $UPSTREAM/$test_bats")
156+
# Warn if using non-standard test files
157+
info_messages+=("$test_bats not found, skipping detailed checks. Found test files: ${bats_files[*]}")
87158
fi
88159
}
89160

@@ -110,9 +181,11 @@ check_tests_workflow() {
110181
if ! grep -q "ddev/github-action-add-on-test@v2" "$tests_yml"; then
111182
actions+=("$tests_yml should use 'ddev/github-action-add-on-test@v2', see upstream file $UPSTREAM/$tests_yml")
112183
fi
113-
# Check for paths-ignore
114-
if ! grep -q "paths-ignore" "$tests_yml"; then
115-
actions+=("$tests_yml should have 'paths-ignore' for markdown, see upstream file $UPSTREAM/$tests_yml")
184+
# Check for at least 2 instances of paths-ignore
185+
local paths_ignore_count
186+
paths_ignore_count=$(grep -o "paths-ignore:" "$tests_yml" 2>/dev/null | wc -l)
187+
if (( paths_ignore_count < 2 )); then
188+
actions+=("$tests_yml should contain at least 2 instances of 'paths-ignore:', found $paths_ignore_count, see upstream file $UPSTREAM/$tests_yml")
116189
fi
117190
else
118191
actions+=("$tests_yml is missing, see upstream file $UPSTREAM/$tests_yml")
@@ -151,8 +224,8 @@ check_github_templates() {
151224
# Check PULL_REQUEST_TEMPLATE.md for the forbidden exact link
152225
local pr_template=".github/PULL_REQUEST_TEMPLATE.md"
153226
if [[ -f "$pr_template" ]]; then
154-
if grep -q "https://github.com/<user>/<repo>/tarball/<branch>" "$pr_template"; then
155-
actions+=("PULL_REQUEST_TEMPLATE.md should not contain 'https://github.com/<user>/<repo>/tarball/<branch>', see upstream file $UPSTREAM/$pr_template?plain=1")
227+
if ! grep -q "REPLACE_ME_WITH_THIS_PR_NUMBER" "$pr_template"; then
228+
actions+=("PULL_REQUEST_TEMPLATE.md should contain 'ddev add-on get https://github.com/<your-name>/<your-repo>/tarball/refs/pull/REPLACE_ME_WITH_THIS_PR_NUMBER/head', see upstream file $UPSTREAM/$pr_template?plain=1")
156229
fi
157230
fi
158231
}
@@ -203,6 +276,28 @@ check_gitattributes() {
203276
fi
204277
}
205278

279+
# Check for trailing newline and whitespace-only lines in all files
280+
check_file_formatting() {
281+
local file
282+
# Get all tracked files from git, excluding binary files and specific patterns
283+
while IFS= read -r -d '' file; do
284+
# Skip binary files and images
285+
if file "$file" 2>/dev/null | grep -qE "image|binary|executable|archive"; then
286+
continue
287+
fi
288+
289+
# Check if file ends with a newline
290+
if [[ -n "$(tail -c 1 "$file" 2>/dev/null)" ]]; then
291+
actions+=("$file should have an empty line at the end")
292+
fi
293+
294+
# Check for lines containing only whitespace
295+
if grep -qn '^[[:space:]]\+$' "$file" 2>/dev/null; then
296+
actions+=("$file contains lines with only spaces/tabs, remove trailing whitespace")
297+
fi
298+
done < <(git ls-files -z 2>/dev/null | grep -zv '^tests/testdata/' || find . -type f -not -path './.git/*' -not -path './tests/testdata/*' -print0 2>/dev/null)
299+
}
300+
206301
# Main function
207302
main() {
208303
if [[ ! -f "install.yaml" ]]; then
@@ -246,10 +341,22 @@ main() {
246341

247342
# Check LICENSE file
248343
check_license
249-
344+
250345
# Check .gitattributes
251346
check_gitattributes
252347

348+
# Check file formatting
349+
check_file_formatting
350+
351+
# Display info messages if any
352+
if [[ ${#info_messages[@]} -gt 0 ]]; then
353+
echo "INFO:" >&2
354+
local info
355+
for info in "${info_messages[@]}"; do
356+
echo "- $info" >&2
357+
done
358+
fi
359+
253360
# If any actions are needed, throw an error
254361
if [[ ${#actions[@]} -gt 0 ]]; then
255362
echo "ERROR: Actions needed:" >&2

install.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ global_files:
8282
# and prevent add-on from being installed if it doesn't validate.
8383
# See https://github.com/Masterminds/semver#checking-version-constraints for constraint rules.
8484
# Available with DDEV v1.23.4+, and works only for DDEV v1.23.4+ binaries
85-
ddev_version_constraint: '>= v1.24.3'
85+
ddev_version_constraint: '>= v1.24.10'
8686

8787
# List of add-on names that this add-on depends on
8888
dependencies:

0 commit comments

Comments
 (0)