@silverassist/agents-toolkit 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +135 -0
  2. package/README.md +388 -0
  3. package/bin/cli.js +940 -0
  4. package/package.json +52 -0
  5. package/src/index.js +58 -0
  6. package/templates/agents/AGENTS.codex.md +195 -0
  7. package/templates/agents/AGENTS.md +195 -0
  8. package/templates/agents/CLAUDE.md +213 -0
  9. package/templates/agents/copilot-instructions.md +83 -0
  10. package/templates/shared/instructions/css-styling.instructions.md +142 -0
  11. package/templates/shared/instructions/documentation-language.instructions.md +216 -0
  12. package/templates/shared/instructions/github-workflow.instructions.md +245 -0
  13. package/templates/shared/instructions/php-standards.instructions.md +293 -0
  14. package/templates/shared/instructions/react-components.instructions.md +196 -0
  15. package/templates/shared/instructions/server-actions.instructions.md +429 -0
  16. package/templates/shared/instructions/testing-standards.instructions.md +264 -0
  17. package/templates/shared/instructions/tests.instructions.md +103 -0
  18. package/templates/shared/instructions/typescript.instructions.md +106 -0
  19. package/templates/shared/instructions/wordpress-plugin-architecture.instructions.md +238 -0
  20. package/templates/shared/prompts/README.md +129 -0
  21. package/templates/shared/prompts/_partials/README.md +57 -0
  22. package/templates/shared/prompts/_partials/documentation.md +203 -0
  23. package/templates/shared/prompts/_partials/git-operations.md +171 -0
  24. package/templates/shared/prompts/_partials/github-integration.md +100 -0
  25. package/templates/shared/prompts/_partials/jira-integration.md +155 -0
  26. package/templates/shared/prompts/_partials/pr-template.md +216 -0
  27. package/templates/shared/prompts/_partials/validations.md +87 -0
  28. package/templates/shared/prompts/add-tests.prompt.md +151 -0
  29. package/templates/shared/prompts/analyze-github-issue.prompt.md +73 -0
  30. package/templates/shared/prompts/analyze-ticket.prompt.md +63 -0
  31. package/templates/shared/prompts/create-plan.prompt.md +118 -0
  32. package/templates/shared/prompts/create-pr.prompt.md +139 -0
  33. package/templates/shared/prompts/finalize-pr.prompt.md +150 -0
  34. package/templates/shared/prompts/fix-issues.prompt.md +92 -0
  35. package/templates/shared/prompts/new-wp-component.prompt.md +51 -0
  36. package/templates/shared/prompts/new-wp-plugin.prompt.md +46 -0
  37. package/templates/shared/prompts/prepare-pr.prompt.md +123 -0
  38. package/templates/shared/prompts/prepare-release.prompt.md +74 -0
  39. package/templates/shared/prompts/quality-check.prompt.md +45 -0
  40. package/templates/shared/prompts/review-code.prompt.md +81 -0
  41. package/templates/shared/prompts/work-github-issue.prompt.md +96 -0
  42. package/templates/shared/prompts/work-ticket.prompt.md +98 -0
  43. package/templates/shared/skills/README.md +53 -0
  44. package/templates/shared/skills/component-architecture/SKILL.md +321 -0
  45. package/templates/shared/skills/create-component/SKILL.md +714 -0
  46. package/templates/shared/skills/domain-driven-design/SKILL.md +277 -0
  47. package/templates/shared/skills/plugin-creation/SKILL.md +1094 -0
  48. package/templates/shared/skills/quality-checks/SKILL.md +493 -0
  49. package/templates/shared/skills/release-management/SKILL.md +649 -0
  50. package/templates/shared/skills/testing/SKILL.md +682 -0
  51. package/templates/shared/skills/testing-patterns/SKILL.md +243 -0
@@ -0,0 +1,649 @@
1
+ ---
2
+ name: release-management
3
+ description: Create and manage releases for Silver Assist WordPress plugins. Covers the unified build script, GitHub Actions release workflow, version bumping, CHANGELOG updates, immutable tag rules, and the full release pipeline. Use when creating releases, setting up release infrastructure for new plugins, or troubleshooting failed releases.
4
+ ---
5
+
6
+ # Silver Assist — Plugin Release Management
7
+
8
+ This skill covers the unified release pipeline used across all Silver Assist WordPress plugins. It includes the build script, GitHub Actions workflow, version management, and release best practices.
9
+
10
+ ## When to Use
11
+
12
+ - Setting up release infrastructure for a **new** Silver Assist plugin
13
+ - Creating a new release for an existing plugin
14
+ - Bumping the version number
15
+ - Troubleshooting a failed release
16
+ - Understanding the build/release pipeline
17
+ - Adding or updating the build script or workflow
18
+
19
+ ---
20
+
21
+ ## Architecture Overview
22
+
23
+ Every Silver Assist plugin follows the same release structure:
24
+
25
+ ```
26
+ plugin-slug/
27
+ ├── scripts/
28
+ │ ├── build-release.sh # Unified build script (identical across plugins)
29
+ │ ├── update-version.sh # Version bumper (full variant)
30
+ │ └── update-version-simple.sh # Version bumper (simple variant)
31
+ ├── .github/
32
+ │ └── workflows/
33
+ │ └── release.yml # GitHub Actions release workflow
34
+ ├── build/ # Generated — .gitignored
35
+ │ ├── plugin-slug-vX.Y.Z.zip
36
+ │ ├── plugin-slug-vX.Y.Z.zip.md5
37
+ │ └── plugin-slug-vX.Y.Z.zip.sha256
38
+ ├── CHANGELOG.md
39
+ └── composer.json
40
+ ```
41
+
42
+ ### Key Principles
43
+
44
+ 1. **Unified scripts** — `build-release.sh` and `release.yml` are identical across all 6 plugins.
45
+ 2. **Selective copy** — Only runtime files go into the ZIP (no tests, docs, dev configs).
46
+ 3. **Auto-detection** — The build script finds the main plugin file, slug, and version automatically.
47
+ 4. **Checksums** — Every ZIP gets MD5 and SHA-256 checksums.
48
+ 5. **CI-aware** — The build script skips restoring dev dependencies when `$GITHUB_ACTIONS` is set.
49
+ 6. **Immutable tags** — GitHub tags and releases cannot be reused once created.
50
+
51
+ ---
52
+
53
+ ## ⚠️ CRITICAL: Immutable Tags and Releases
54
+
55
+ GitHub enforces **immutability** on tags and releases. Once a tag is pushed (even if the release workflow fails), that tag version **CANNOT be reused**.
56
+
57
+ ### NEVER Create Releases Manually
58
+
59
+ **ALWAYS let the `release.yml` workflow create the GitHub release.**
60
+
61
+ ```bash
62
+ # ❌ FORBIDDEN — causes "immutable release" errors
63
+ gh release create v1.3.5 --title "..." --notes "..."
64
+
65
+ # ✅ CORRECT — Only create and push the tag
66
+ git tag v1.3.6 -m "Release v1.3.6"
67
+ git push origin v1.3.6
68
+ ```
69
+
70
+ ### If a Release Fails
71
+
72
+ 1. **DO NOT** try to delete and recreate the same tag
73
+ 2. **DO NOT** manually create a release
74
+ 3. **INCREMENT** the version (e.g., v1.3.5 → v1.3.6)
75
+ 4. Start from Step 1 of the release workflow with the new version
76
+
77
+ ---
78
+
79
+ ## Release Workflow (Step by Step)
80
+
81
+ ### Step 1: Update All Versions
82
+
83
+ Use whichever version script the plugin has:
84
+
85
+ ```bash
86
+ # Full variant (acf-clone-fields, silver-assist-post-revalidate, silver-assist-security)
87
+ ./scripts/update-version.sh 1.2.0 --no-confirm --force
88
+
89
+ # Simple variant (contact-form-to-api, leadgen-app-form, nextjs-graphql-hooks)
90
+ ./scripts/update-version-simple.sh 1.2.0 --no-confirm --force
91
+ ```
92
+
93
+ Both scripts update:
94
+ - Main plugin file `Version:` header
95
+ - Plugin version constant (e.g., `PLUGIN_VERSION`)
96
+ - All PHP `@version` doc tags in source directories
97
+ - All CSS/JS `@version` tags in `assets/`
98
+ - Shell script `@version` tags in `scripts/`
99
+
100
+ ### Step 2: Update CHANGELOG.md
101
+
102
+ Follow [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format:
103
+
104
+ ```markdown
105
+ ## [1.2.0] - YYYY-MM-DD
106
+
107
+ ### Added
108
+ - New features...
109
+
110
+ ### Changed
111
+ - Changes to existing functionality...
112
+
113
+ ### Fixed
114
+ - Bug fixes...
115
+
116
+ ### Security
117
+ - Security improvements...
118
+ ```
119
+
120
+ Valid categories: **Added**, **Changed**, **Deprecated**, **Removed**, **Fixed**, **Security**.
121
+
122
+ ### Step 3: Verify Consistency (if available)
123
+
124
+ ```bash
125
+ ./scripts/check-versions.sh
126
+ ```
127
+
128
+ ### Step 4: Run Quality Checks
129
+
130
+ ```bash
131
+ # Auto-fix first
132
+ vendor/bin/phpcbf
133
+
134
+ # Then verify
135
+ vendor/bin/phpcs
136
+ vendor/bin/phpstan analyse --memory-limit=1G
137
+
138
+ # Or use the quality script if available
139
+ ./scripts/run-quality-checks.sh
140
+ ```
141
+
142
+ ### Step 5: Commit and Push
143
+
144
+ ```bash
145
+ git add -A
146
+ git commit -m "chore: bump version to 1.2.0 for release"
147
+ git push origin main
148
+ ```
149
+
150
+ ### Step 6: Create Tag (Triggers the Release)
151
+
152
+ ```bash
153
+ git tag v1.2.0 -m "Release v1.2.0"
154
+ git push origin v1.2.0
155
+ ```
156
+
157
+ ### Step 7: Monitor Workflow
158
+
159
+ ```bash
160
+ gh run list --workflow=release.yml --limit 3 | cat
161
+ gh run watch <run-id> --exit-status
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Unified Build Script (`scripts/build-release.sh`)
167
+
168
+ This script is **identical** across all Silver Assist plugins. When setting up a new plugin, copy it verbatim.
169
+
170
+ ### What It Does
171
+
172
+ 1. **Auto-detects** the main plugin file (searches for `Plugin Name:` header)
173
+ 2. **Copies runtime files** to `build/<plugin-slug>/`:
174
+ - Main plugin file (`.php`)
175
+ - Source directories: `includes/`, `Includes/`, `src/`, `assets/`, `languages/`, `blocks/`, `templates/`
176
+ - Documentation: `README.md`, `CHANGELOG.md`, `LICENSE`, `LICENSE.md`
177
+ 3. **Builds production vendor** via `composer install --no-dev --optimize-autoloader`
178
+ 4. **Copies only needed vendor files**:
179
+ - `vendor/autoload.php` + `vendor/composer/*.php` + `vendor/composer/*.json`
180
+ - `vendor/composer/installers/src/` (if present)
181
+ - `vendor/silverassist/*/src/` and `vendor/silverassist/*/assets/` for each package
182
+ 5. **Validates** the package (main file, autoloader, Silver Assist package assets)
183
+ 6. **Creates ZIP** with checksums (MD5 + SHA-256)
184
+ 7. **Restores dev dependencies** locally (skipped in CI)
185
+
186
+ ### Template
187
+
188
+ ```bash
189
+ #!/bin/bash
190
+
191
+ ################################################################################
192
+ # Silver Assist — Unified Build Release Script
193
+ #
194
+ # Creates a production-ready WordPress plugin ZIP package.
195
+ # Auto-detects plugin structure and copies only runtime files.
196
+ #
197
+ # Usage: ./scripts/build-release.sh [version]
198
+ #
199
+ # @package SilverAssist
200
+ # @author Silver Assist
201
+ ################################################################################
202
+
203
+ set -e
204
+
205
+ # Colors
206
+ RED='\033[0;31m'
207
+ GREEN='\033[0;32m'
208
+ YELLOW='\033[1;33m'
209
+ BLUE='\033[0;34m'
210
+ NC='\033[0m'
211
+
212
+ PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
213
+ PLUGIN_SLUG=$(basename "$PROJECT_ROOT")
214
+
215
+ echo -e "${BLUE}═══════════════════════════════════════════════════${NC}"
216
+ echo -e "${BLUE} ${PLUGIN_SLUG} — Release Builder${NC}"
217
+ echo -e "${BLUE}═══════════════════════════════════════════════════${NC}"
218
+ echo ""
219
+
220
+ # Auto-detect main plugin file
221
+ MAIN_FILE=$(find "$PROJECT_ROOT" -maxdepth 1 -name "*.php" -exec grep -l "Plugin Name:" {} \; 2>/dev/null | head -1)
222
+ if [ -z "$MAIN_FILE" ]; then
223
+ echo -e "${RED}❌ No main plugin file found${NC}"
224
+ exit 1
225
+ fi
226
+ MAIN_FILE_NAME=$(basename "$MAIN_FILE")
227
+
228
+ # Get version
229
+ if [ -n "$1" ]; then
230
+ VERSION="$1"
231
+ else
232
+ VERSION=$(grep -o "Version: [0-9]\+\.[0-9]\+\.[0-9]\+" "$MAIN_FILE" | cut -d' ' -f2)
233
+ fi
234
+
235
+ if [ -z "$VERSION" ]; then
236
+ echo -e "${RED}❌ Could not detect version${NC}"
237
+ exit 1
238
+ fi
239
+
240
+ echo -e " Plugin: ${PLUGIN_SLUG}"
241
+ echo -e " File: ${MAIN_FILE_NAME}"
242
+ echo -e " Version: ${VERSION}"
243
+ echo ""
244
+
245
+ # Setup
246
+ BUILD_DIR="${PROJECT_ROOT}/build"
247
+ PLUGIN_DIR="${BUILD_DIR}/${PLUGIN_SLUG}"
248
+ ZIP_FILE="${PLUGIN_SLUG}-v${VERSION}.zip"
249
+
250
+ rm -rf "$BUILD_DIR"
251
+ mkdir -p "$PLUGIN_DIR"
252
+
253
+ # ─── Copy plugin files ───────────────────────────────────────────────────────
254
+
255
+ echo -e "${YELLOW}📋 Copying plugin files...${NC}"
256
+
257
+ cp "$MAIN_FILE" "$PLUGIN_DIR/"
258
+ echo " ✅ ${MAIN_FILE_NAME}"
259
+
260
+ for dir in includes Includes src assets languages blocks templates; do
261
+ if [ -d "${PROJECT_ROOT}/${dir}" ]; then
262
+ cp -r "${PROJECT_ROOT}/${dir}" "$PLUGIN_DIR/"
263
+ echo " ✅ ${dir}/"
264
+ fi
265
+ done
266
+
267
+ for file in README.md CHANGELOG.md LICENSE LICENSE.md; do
268
+ if [ -f "${PROJECT_ROOT}/${file}" ]; then
269
+ cp "${PROJECT_ROOT}/${file}" "$PLUGIN_DIR/"
270
+ fi
271
+ done
272
+
273
+ # ─── Vendor dependencies ─────────────────────────────────────────────────────
274
+
275
+ echo ""
276
+ echo -e "${YELLOW}📦 Building vendor dependencies...${NC}"
277
+
278
+ cd "$PROJECT_ROOT"
279
+
280
+ if [ ! -f "composer.json" ]; then
281
+ echo -e "${RED}❌ composer.json not found${NC}"
282
+ exit 1
283
+ fi
284
+
285
+ composer install --no-dev --optimize-autoloader --no-interaction
286
+
287
+ if [ ! -f "vendor/autoload.php" ]; then
288
+ echo -e "${RED}❌ vendor/autoload.php not found${NC}"
289
+ exit 1
290
+ fi
291
+
292
+ echo -e "${YELLOW}📦 Copying production vendor files...${NC}"
293
+
294
+ mkdir -p "$PLUGIN_DIR/vendor/composer"
295
+ cp vendor/autoload.php "$PLUGIN_DIR/vendor/"
296
+ cp vendor/composer/*.php "$PLUGIN_DIR/vendor/composer/"
297
+ cp vendor/composer/*.json "$PLUGIN_DIR/vendor/composer/" 2>/dev/null || true
298
+ echo " ✅ autoloader"
299
+
300
+ if [ -d "vendor/composer/installers" ]; then
301
+ mkdir -p "$PLUGIN_DIR/vendor/composer/installers"
302
+ [ -d "vendor/composer/installers/src" ] && cp -r "vendor/composer/installers/src" "$PLUGIN_DIR/vendor/composer/installers/"
303
+ echo " ✅ composer/installers"
304
+ fi
305
+
306
+ if [ -d "vendor/silverassist" ]; then
307
+ mkdir -p "$PLUGIN_DIR/vendor/silverassist"
308
+ for package_dir in vendor/silverassist/*/; do
309
+ if [ -d "$package_dir" ]; then
310
+ package_name=$(basename "$package_dir")
311
+ dest="$PLUGIN_DIR/vendor/silverassist/$package_name"
312
+ mkdir -p "$dest"
313
+ [ -d "$package_dir/src" ] && cp -r "$package_dir/src" "$dest/"
314
+ [ -d "$package_dir/assets" ] && cp -r "$package_dir/assets" "$dest/"
315
+ echo " ✅ silverassist/${package_name}"
316
+ fi
317
+ done
318
+ fi
319
+
320
+ # Restore dev dependencies (skip in CI — environment is ephemeral)
321
+ if [ -z "$GITHUB_ACTIONS" ]; then
322
+ echo ""
323
+ echo -e "${YELLOW}📦 Restoring development dependencies...${NC}"
324
+ composer install --no-interaction > /dev/null 2>&1
325
+ echo " ✅ Dev environment restored"
326
+ fi
327
+
328
+ # ─── Validate ─────────────────────────────────────────────────────────────────
329
+
330
+ echo ""
331
+ echo -e "${YELLOW}🔍 Validating package...${NC}"
332
+
333
+ ERRORS=0
334
+
335
+ if [ ! -f "$PLUGIN_DIR/$MAIN_FILE_NAME" ]; then
336
+ echo -e "${RED} ❌ Main plugin file${NC}"
337
+ ERRORS=$((ERRORS + 1))
338
+ fi
339
+
340
+ if [ ! -f "$PLUGIN_DIR/vendor/autoload.php" ]; then
341
+ echo -e "${RED} ❌ Autoloader${NC}"
342
+ ERRORS=$((ERRORS + 1))
343
+ fi
344
+
345
+ if [ ! -f "$PLUGIN_DIR/vendor/silverassist/wp-settings-hub/assets/css/settings-hub.css" ]; then
346
+ echo -e "${RED} ❌ wp-settings-hub CSS asset${NC}"
347
+ ERRORS=$((ERRORS + 1))
348
+ else
349
+ echo " ✅ Settings Hub CSS"
350
+ fi
351
+
352
+ if [ ! -f "$PLUGIN_DIR/vendor/silverassist/wp-github-updater/assets/js/check-updates.js" ]; then
353
+ echo -e "${RED} ❌ wp-github-updater JS asset${NC}"
354
+ ERRORS=$((ERRORS + 1))
355
+ else
356
+ echo " ✅ GitHub Updater JS"
357
+ fi
358
+
359
+ if [ $ERRORS -gt 0 ]; then
360
+ echo -e "${RED}❌ Validation failed (${ERRORS} errors)${NC}"
361
+ exit 1
362
+ fi
363
+
364
+ echo -e "${GREEN} ✅ All checks passed${NC}"
365
+
366
+ # ─── Create ZIP ───────────────────────────────────────────────────────────────
367
+
368
+ echo ""
369
+ echo -e "${YELLOW}🗜️ Creating ZIP...${NC}"
370
+
371
+ cd "$BUILD_DIR"
372
+ zip -r "$ZIP_FILE" "$PLUGIN_SLUG/" -x "*.DS_Store*" > /dev/null
373
+
374
+ # Checksums
375
+ md5sum "$ZIP_FILE" > "${ZIP_FILE}.md5" 2>/dev/null || md5 -r "$ZIP_FILE" > "${ZIP_FILE}.md5"
376
+ shasum -a 256 "$ZIP_FILE" > "${ZIP_FILE}.sha256"
377
+
378
+ cd "$PROJECT_ROOT"
379
+
380
+ ZIP_SIZE=$(du -h "$BUILD_DIR/$ZIP_FILE" | cut -f1)
381
+
382
+ echo ""
383
+ echo -e "${GREEN}═══════════════════════════════════════════════════${NC}"
384
+ echo -e "${GREEN} ✅ Build complete${NC}"
385
+ echo -e "${GREEN}═══════════════════════════════════════════════════${NC}"
386
+ echo ""
387
+ echo " 📦 build/${ZIP_FILE} (${ZIP_SIZE})"
388
+ echo " 🔐 build/${ZIP_FILE}.md5"
389
+ echo " 🔐 build/${ZIP_FILE}.sha256"
390
+
391
+ # GitHub Actions output
392
+ if [ -n "$GITHUB_OUTPUT" ]; then
393
+ echo "zip_path=build/${ZIP_FILE}" >> "$GITHUB_OUTPUT"
394
+ echo "zip_name=${ZIP_FILE}" >> "$GITHUB_OUTPUT"
395
+ echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
396
+ echo "zip_size=${ZIP_SIZE}" >> "$GITHUB_OUTPUT"
397
+ fi
398
+ ```
399
+
400
+ ### Validation Checks
401
+
402
+ The build script validates these Silver Assist package assets exist in the final package:
403
+
404
+ | Asset | Path in ZIP |
405
+ |-------|------------|
406
+ | Settings Hub CSS | `vendor/silverassist/wp-settings-hub/assets/css/settings-hub.css` |
407
+ | GitHub Updater JS | `vendor/silverassist/wp-github-updater/assets/js/check-updates.js` |
408
+
409
+ If the plugin does NOT use these packages, remove the corresponding validation checks.
410
+
411
+ ---
412
+
413
+ ## GitHub Actions Release Workflow (`.github/workflows/release.yml`)
414
+
415
+ This workflow is **identical** across all Silver Assist plugins. It triggers on `v*` tags or manual dispatch.
416
+
417
+ ### Template
418
+
419
+ ```yaml
420
+ name: Release
421
+
422
+ on:
423
+ push:
424
+ tags:
425
+ - 'v*'
426
+ workflow_dispatch:
427
+ inputs:
428
+ version:
429
+ description: 'Version to release (e.g. 1.2.0). Leave empty to use plugin file version.'
430
+ required: false
431
+
432
+ permissions:
433
+ contents: write
434
+
435
+ jobs:
436
+ release:
437
+ name: Build & Release
438
+ runs-on: ubuntu-latest
439
+
440
+ steps:
441
+ - name: Checkout
442
+ uses: actions/checkout@v4
443
+
444
+ - name: Setup PHP
445
+ uses: shivammathur/setup-php@v2
446
+ with:
447
+ php-version: '8.2'
448
+ tools: composer
449
+
450
+ - name: Detect version
451
+ id: version
452
+ run: |
453
+ if [[ "${{ github.event_name }}" == "push" ]]; then
454
+ VERSION="${GITHUB_REF_NAME#v}"
455
+ elif [[ -n "${{ github.event.inputs.version }}" ]]; then
456
+ VERSION="${{ github.event.inputs.version }}"
457
+ else
458
+ VERSION=$(grep -o 'Version: [0-9]\+\.[0-9]\+\.[0-9]\+' *.php 2>/dev/null | head -1 | cut -d' ' -f2)
459
+ fi
460
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
461
+ echo "🏷️ Version: $VERSION"
462
+
463
+ - name: Install dependencies
464
+ run: composer install --no-interaction
465
+
466
+ - name: Update version
467
+ run: |
468
+ VERSION="${{ steps.version.outputs.version }}"
469
+ if [ -f "scripts/update-version.sh" ]; then
470
+ chmod +x scripts/update-version.sh
471
+ ./scripts/update-version.sh "$VERSION" --no-confirm --force
472
+ elif [ -f "scripts/update-version-simple.sh" ]; then
473
+ chmod +x scripts/update-version-simple.sh
474
+ ./scripts/update-version-simple.sh "$VERSION" --no-confirm --force
475
+ fi
476
+
477
+ - name: Code quality
478
+ run: |
479
+ HAS_CHECKS=false
480
+ if [ -f phpcs.xml ] || [ -f .phpcs.xml.dist ] || [ -f phpcs.xml.dist ]; then
481
+ echo "▶ PHPCS"
482
+ vendor/bin/phpcs
483
+ HAS_CHECKS=true
484
+ fi
485
+ if [ -f phpstan.neon ] || [ -f phpstan.neon.dist ]; then
486
+ echo "▶ PHPStan"
487
+ vendor/bin/phpstan analyse --no-progress
488
+ HAS_CHECKS=true
489
+ fi
490
+ if [ "$HAS_CHECKS" = false ]; then
491
+ echo "ℹ️ No quality tool configs found — skipping"
492
+ fi
493
+
494
+ - name: Build release
495
+ id: build
496
+ run: |
497
+ chmod +x scripts/build-release.sh
498
+ ./scripts/build-release.sh "${{ steps.version.outputs.version }}"
499
+
500
+ - name: Create GitHub Release
501
+ uses: softprops/action-gh-release@v2
502
+ with:
503
+ tag_name: v${{ steps.version.outputs.version }}
504
+ name: v${{ steps.version.outputs.version }}
505
+ files: |
506
+ build/*.zip
507
+ build/*.md5
508
+ build/*.sha256
509
+ generate_release_notes: true
510
+ env:
511
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
512
+ ```
513
+
514
+ ### Pinning Actions to SHA Hashes
515
+
516
+ For production repositories, pin actions to commit SHAs for supply chain security:
517
+
518
+ ```yaml
519
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
520
+ - uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.36.0
521
+ - uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
522
+ ```
523
+
524
+ ### Workflow Pipeline
525
+
526
+ ```
527
+ Tag push (v*) ──► Checkout ──► Setup PHP 8.2
528
+ ──► Detect version ──► Install Composer deps
529
+ ──► Update version in files ──► Code quality (PHPCS + PHPStan)
530
+ ──► Build release ZIP ──► Create GitHub Release with assets
531
+ ```
532
+
533
+ ---
534
+
535
+ ## Setting Up a New Plugin
536
+
537
+ When creating release infrastructure for a new Silver Assist plugin:
538
+
539
+ ### 1. Required Files
540
+
541
+ Create these files (copy templates from above):
542
+
543
+ - `scripts/build-release.sh` — Make executable: `chmod +x scripts/build-release.sh`
544
+ - `.github/workflows/release.yml`
545
+ - `scripts/update-version.sh` or `scripts/update-version-simple.sh`
546
+
547
+ ### 2. composer.json Requirements
548
+
549
+ The plugin must have `silverassist/wp-github-updater` and `silverassist/wp-settings-hub` as production dependencies:
550
+
551
+ ```json
552
+ {
553
+ "require": {
554
+ "php": ">=8.2",
555
+ "composer/installers": "^2.3",
556
+ "silverassist/wp-github-updater": "^1.3",
557
+ "silverassist/wp-settings-hub": "^1.2"
558
+ }
559
+ }
560
+ ```
561
+
562
+ ### 3. .gitignore Entries
563
+
564
+ Ensure these are in `.gitignore`:
565
+
566
+ ```gitignore
567
+ # Build directories
568
+ build/
569
+ dist/
570
+
571
+ # Dependencies
572
+ vendor/
573
+ node_modules/
574
+ composer.lock
575
+
576
+ # Archives
577
+ *.zip
578
+ *.tar.gz
579
+ ```
580
+
581
+ ### 4. Main Plugin File Header
582
+
583
+ The main PHP file must have a standard WordPress plugin header with `Plugin Name:` and `Version:`:
584
+
585
+ ```php
586
+ <?php
587
+ /**
588
+ * Plugin Name: My Plugin Name
589
+ * Plugin URI: https://github.com/silverassist/my-plugin
590
+ * Description: Plugin description.
591
+ * Version: 1.0.0
592
+ * Author: Silver Assist
593
+ * Author URI: https://silverassist.com
594
+ * License: PolyForm Noncommercial License 1.0.0
595
+ * Text Domain: my-plugin-slug
596
+ */
597
+ ```
598
+
599
+ ### 5. CHANGELOG.md
600
+
601
+ Initialize with:
602
+
603
+ ```markdown
604
+ # Changelog
605
+
606
+ All notable changes to Plugin Name will be documented in this file.
607
+
608
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
609
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
610
+
611
+ ## [Unreleased]
612
+
613
+ ## [1.0.0] - YYYY-MM-DD
614
+
615
+ ### Added
616
+ - Initial release
617
+ ```
618
+
619
+ ---
620
+
621
+ ## Existing Plugins Using This Pipeline
622
+
623
+ | Plugin | Slug | Main File |
624
+ |--------|------|-----------|
625
+ | ACF Clone Fields | `acf-clone-fields` | `silver-assist-acf-clone-fields.php` |
626
+ | Contact Form to API | `contact-form-to-api` | `contact-form-to-api.php` |
627
+ | LeadGen App Form | `leadgen-app-form` | `leadgen-app-form.php` |
628
+ | NextJS GraphQL Hooks | `nextjs-graphql-hooks` | `nextjs-graphql-hooks.php` |
629
+ | Post Revalidate | `silver-assist-post-revalidate` | `silver-assist-post-revalidate.php` |
630
+ | Security | `silver-assist-security` | `silver-assist-security.php` |
631
+
632
+ ---
633
+
634
+ ## Troubleshooting
635
+
636
+ ### Build fails: "No main plugin file found"
637
+ The script searches for `Plugin Name:` in root `.php` files. Ensure the header exists in the main plugin file.
638
+
639
+ ### Build fails: "wp-settings-hub CSS asset" or "wp-github-updater JS asset"
640
+ The `silverassist/*` packages must include `assets/` directories. Check that `composer.json` lists them in `require` (not `require-dev`), and run `composer install --no-dev` to verify they're included.
641
+
642
+ ### Release fails: "already_exists" error
643
+ The tag was already used. Increment the version and create a new tag — never try to reuse a tag.
644
+
645
+ ### ZIP is too large
646
+ The build script only copies `src/` and `assets/` from `vendor/silverassist/*` packages. If other vendor packages are needed at runtime, add them to the copy logic in `build-release.sh`.
647
+
648
+ ### Local build leaves dev dependencies removed
649
+ The script automatically restores dev deps after building locally. If interrupted, run `composer install` manually.