Skip to content

Commit dbd3aba

Browse files
Tsvetan StoychevTsvetan Stoychev
authored andcommitted
Enforce repository conventions in CI
1 parent 32e80af commit dbd3aba

9 files changed

Lines changed: 189 additions & 7 deletions

File tree

.github/workflows/ci.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@ permissions:
1212
contents: read
1313

1414
jobs:
15+
conventions:
16+
name: Repository conventions
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
22+
23+
- name: Enforce repository conventions
24+
run: make conventions
25+
1526
quality:
1627
name: Static and dependency analysis
1728
runs-on: ubuntu-latest
@@ -187,6 +198,7 @@ jobs:
187198
name: Release ZIP smoke test
188199
runs-on: ubuntu-latest
189200
needs:
201+
- conventions
190202
- quality
191203
- translations
192204
- javascript

.github/workflows/prerelease.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ jobs:
1515
steps:
1616
- name: Checkout
1717
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
18+
with:
19+
ref: ${{ github.event.release.tag_name }}
20+
21+
- name: Verify release version
22+
env:
23+
BASICRUM_RELEASE_TAG: ${{ github.event.release.tag_name }}
24+
run: make conventions
1825

1926
- name: Setup release PHP
2027
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2

.github/workflows/release.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ jobs:
1515
steps:
1616
- name: Checkout
1717
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
18+
with:
19+
ref: ${{ github.event.release.tag_name }}
20+
21+
- name: Verify release version
22+
env:
23+
BASICRUM_RELEASE_TAG: ${{ github.event.release.tag_name }}
24+
run: make conventions
1825

1926
- name: Setup release PHP
2027
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2

AGENTS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ namespace, PSR-4 Composer autoloading, PHP 7.4+, and WordPress 6.0+.
2626
- Guard PHP files with `ABSPATH`; escape output and sanitize all input.
2727
- Use ASCII hyphens (`-`); do not use typographic dashes in source, comments,
2828
documentation, or user-facing text.
29+
- Keep the plugin header Version, `BASICRUM_VERSION`, `Stable tag`, and top
30+
changelog version identical. Release tags use the `v<version>` form.
2931
- Prefix hooks with `basicrum_`; use `Assets` handle constants rather than
3032
hard-coded script handles.
3133
- Boomerang lives in `assets/js/boomr/`; standard and consent loaders live in
@@ -45,6 +47,7 @@ make lint
4547
make analyse
4648
make composer-validate
4749
make composer-audit
50+
make conventions
4851
make unit
4952
make js-test
5053
make integration-setup

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ TEST_DB_PASS = root
1313
TEST_DB_HOST = db
1414
WP_TEST_VERSION ?= latest
1515

16-
.PHONY: help build up down restart logs shell composer-install wp-install lint lint-fix lint-php analyse composer-validate composer-audit translations js-install js-test integration-setup integration test package package-verify package-smoke clean
16+
.PHONY: help build up down restart logs shell composer-install wp-install lint lint-fix lint-php analyse composer-validate composer-audit conventions translations js-install js-test integration-setup integration test package package-verify package-smoke clean
1717

1818
help:
1919
@echo "Targets:"
@@ -31,6 +31,7 @@ help:
3131
@echo " analyse Run PHPStan static analysis"
3232
@echo " composer-validate Validate Composer metadata and lock file"
3333
@echo " composer-audit Audit locked Composer dependencies"
34+
@echo " conventions Enforce ASCII hyphens and version consistency"
3435
@echo " translations Update POT, PO, and MO translation catalogs"
3536
@echo " js-install Install locked JavaScript test dependencies"
3637
@echo " js-test Run loader behavior tests in Chromium"
@@ -85,6 +86,10 @@ composer-validate:
8586
composer-audit:
8687
$(COMPOSE) run --rm -w $(PLUGIN_WORKDIR) $(PHP_SERVICE) composer audit --locked
8788

89+
conventions:
90+
sh tools/verify-ascii-hyphens.sh
91+
sh tools/verify-version-consistency.sh
92+
8893
translations:
8994
$(COMPOSE) run --rm --no-deps --user "$$(id -u):$$(id -g)" -e HOME=/tmp -w $(WPCLI_PLUGIN_WORKDIR) $(WPCLI_SERVICE) sh /tools/update-translations.sh .
9095

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ make lint
2525
make analyse
2626
make composer-validate
2727
make composer-audit
28+
make conventions
2829
make translations
2930
make js-test
3031
make package
@@ -132,6 +133,13 @@ configuration is stored in `plugins/basicrum/phpstan.neon.dist`.
132133
strict mode. `make composer-audit` checks the complete lock file against current
133134
security advisories. CI runs all three checks on every push and pull request.
134135

136+
`make conventions` rejects en dash and em dash characters in tracked text files.
137+
It also verifies that the plugin header version, `BASICRUM_VERSION`, WordPress
138+
`Stable tag`, and top changelog version match. Release workflows additionally
139+
compare the GitHub release tag to that version. Release tags must use the
140+
`v<version>` form, such as `v1.0.2`. To check a planned release locally, run
141+
`BASICRUM_RELEASE_TAG=v<version> make conventions`.
142+
135143
Dependabot checks npm, Composer dependencies, and GitHub Actions weekly. CI
136144
workflows use a read-only `GITHUB_TOKEN`; release and pre-release workflows
137145
receive only the `contents: write` permission required to attach release assets.

checklist.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,16 @@ Acceptance criteria:
145145

146146
## 8. Enforce repository conventions in CI
147147

148-
- [ ] Add an automated check that rejects en dash and em dash characters in
148+
- [x] Add an automated check that rejects en dash and em dash characters in
149149
tracked source, comments, documentation, and user-facing text.
150-
- [ ] Add a version consistency check covering the plugin header,
150+
- [x] Add a version consistency check covering the plugin header,
151151
`BASICRUM_VERSION`, `Stable tag`, changelog, and release tag.
152-
- [ ] Run both checks in pull requests and pushes to the main branch.
153-
- [ ] Document the checks in `AGENTS.md` and the contributor documentation.
152+
- [x] Run both checks in pull requests and pushes to the main branch.
153+
- [x] Document the checks in `AGENTS.md` and the contributor documentation.
154154

155155
Acceptance criteria:
156156

157-
- [ ] Repository conventions and version metadata cannot drift silently even when
157+
- [x] Repository conventions and version metadata cannot drift silently even when
158158
changes are made without an agent.
159159

160160
## Final release gate
@@ -168,4 +168,4 @@ Acceptance criteria:
168168
- [x] Composer validation and audit pass.
169169
- [ ] Generated asset checks pass.
170170
- [x] The packaged ZIP smoke test passes.
171-
- [ ] Version and repository convention checks pass.
171+
- [x] Version and repository convention checks pass.

tools/verify-ascii-hyphens.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/bin/sh
2+
3+
set -eu
4+
5+
repository_root=$( git rev-parse --show-toplevel 2>/dev/null ) || {
6+
printf '%s\n' 'ASCII hyphen check must run inside a Git worktree.' >&2
7+
exit 1
8+
}
9+
10+
cd "$repository_root"
11+
12+
# UTF-8 byte sequences keep the forbidden characters out of this source file.
13+
en_dash=$( printf '\342\200\223' )
14+
em_dash=$( printf '\342\200\224' )
15+
16+
set +e
17+
matches=$( LC_ALL=C git grep -nIF -e "$en_dash" -e "$em_dash" -- . )
18+
status=$?
19+
set -e
20+
21+
case "$status" in
22+
0)
23+
printf '%s\n' 'ASCII hyphen check failed: replace en dash and em dash characters with ASCII hyphens.' >&2
24+
printf '%s\n' "$matches" >&2
25+
exit 1
26+
;;
27+
1)
28+
printf '%s\n' 'ASCII hyphen check passed.'
29+
;;
30+
*)
31+
printf '%s\n' 'ASCII hyphen check could not search tracked text files.' >&2
32+
exit "$status"
33+
;;
34+
esac
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#!/bin/sh
2+
3+
set -eu
4+
5+
fail() {
6+
printf '%s\n' "$1" >&2
7+
exit 1
8+
}
9+
10+
require_file() {
11+
if [ ! -f "$1" ]; then
12+
fail "Required version metadata file is missing: $1"
13+
fi
14+
}
15+
16+
require_single_value() {
17+
label=$1
18+
value=$2
19+
20+
if [ -z "$value" ]; then
21+
fail "Could not find $label."
22+
fi
23+
24+
line_count=$( printf '%s\n' "$value" | awk 'END { print NR }' )
25+
26+
if [ "$line_count" -ne 1 ]; then
27+
fail "Expected exactly one $label, found $line_count."
28+
fi
29+
30+
printf '%s\n' "$value"
31+
}
32+
33+
repository_root=$( git rev-parse --show-toplevel 2>/dev/null ) || {
34+
fail 'Version consistency check must run inside a Git worktree.'
35+
}
36+
37+
cd "$repository_root"
38+
39+
plugin_file='plugins/basicrum/basicrum.php'
40+
readme_file='plugins/basicrum/readme.txt'
41+
42+
require_file "$plugin_file"
43+
require_file "$readme_file"
44+
45+
plugin_header_version=$( require_single_value 'plugin header Version value' "$(
46+
sed -n 's/^[[:space:]]*\*[[:space:]]*Version:[[:space:]]*\([^[:space:]]*\)[[:space:]]*$/\1/p' "$plugin_file"
47+
)" )
48+
49+
constant_version=$( require_single_value 'BASICRUM_VERSION value' "$(
50+
sed -n "s/^[[:space:]]*define( 'BASICRUM_VERSION', '\([^']*\)' );[[:space:]]*$/\1/p" "$plugin_file"
51+
)" )
52+
53+
stable_tag=$( require_single_value 'readme Stable tag value' "$(
54+
sed -n 's/^Stable tag:[[:space:]]*\([^[:space:]]*\)[[:space:]]*$/\1/p' "$readme_file"
55+
)" )
56+
57+
changelog_version=$( require_single_value 'top changelog version' "$(
58+
awk '
59+
$0 == "== Changelog ==" {
60+
in_changelog = 1
61+
next
62+
}
63+
64+
in_changelog && /^= .+ =$/ {
65+
version = $0
66+
sub(/^= /, "", version)
67+
sub(/ =$/, "", version)
68+
print version
69+
exit
70+
}
71+
' "$readme_file"
72+
)" )
73+
74+
if [ "$constant_version" != "$plugin_header_version" ]; then
75+
fail "BASICRUM_VERSION ($constant_version) does not match plugin header Version ($plugin_header_version)."
76+
fi
77+
78+
if [ "$stable_tag" != "$plugin_header_version" ]; then
79+
fail "Stable tag ($stable_tag) does not match plugin header Version ($plugin_header_version)."
80+
fi
81+
82+
if [ "$changelog_version" != "$plugin_header_version" ]; then
83+
fail "Top changelog version ($changelog_version) does not match plugin header Version ($plugin_header_version)."
84+
fi
85+
86+
if ! printf '%s\n' "$plugin_header_version" | grep -Eq '^[0-9]+(\.[0-9]+){2}([.-][0-9A-Za-z]+)*$'; then
87+
fail "Plugin header Version ($plugin_header_version) must use an X.Y.Z version format."
88+
fi
89+
90+
release_tag=${BASICRUM_RELEASE_TAG:-}
91+
92+
if [ "$#" -gt 1 ]; then
93+
fail 'Usage: tools/verify-version-consistency.sh [release-tag]'
94+
fi
95+
96+
if [ "$#" -eq 1 ]; then
97+
release_tag=$1
98+
fi
99+
100+
if [ -n "$release_tag" ]; then
101+
if [ "$release_tag" != "v$plugin_header_version" ]; then
102+
fail "Release tag ($release_tag) does not match plugin header Version ($plugin_header_version). Use v$plugin_header_version."
103+
fi
104+
fi
105+
106+
printf '%s\n' "Version consistency check passed: $plugin_header_version"

0 commit comments

Comments
 (0)