@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.
- package/LICENSE +135 -0
- package/README.md +388 -0
- package/bin/cli.js +940 -0
- package/package.json +52 -0
- package/src/index.js +58 -0
- package/templates/agents/AGENTS.codex.md +195 -0
- package/templates/agents/AGENTS.md +195 -0
- package/templates/agents/CLAUDE.md +213 -0
- package/templates/agents/copilot-instructions.md +83 -0
- package/templates/shared/instructions/css-styling.instructions.md +142 -0
- package/templates/shared/instructions/documentation-language.instructions.md +216 -0
- package/templates/shared/instructions/github-workflow.instructions.md +245 -0
- package/templates/shared/instructions/php-standards.instructions.md +293 -0
- package/templates/shared/instructions/react-components.instructions.md +196 -0
- package/templates/shared/instructions/server-actions.instructions.md +429 -0
- package/templates/shared/instructions/testing-standards.instructions.md +264 -0
- package/templates/shared/instructions/tests.instructions.md +103 -0
- package/templates/shared/instructions/typescript.instructions.md +106 -0
- package/templates/shared/instructions/wordpress-plugin-architecture.instructions.md +238 -0
- package/templates/shared/prompts/README.md +129 -0
- package/templates/shared/prompts/_partials/README.md +57 -0
- package/templates/shared/prompts/_partials/documentation.md +203 -0
- package/templates/shared/prompts/_partials/git-operations.md +171 -0
- package/templates/shared/prompts/_partials/github-integration.md +100 -0
- package/templates/shared/prompts/_partials/jira-integration.md +155 -0
- package/templates/shared/prompts/_partials/pr-template.md +216 -0
- package/templates/shared/prompts/_partials/validations.md +87 -0
- package/templates/shared/prompts/add-tests.prompt.md +151 -0
- package/templates/shared/prompts/analyze-github-issue.prompt.md +73 -0
- package/templates/shared/prompts/analyze-ticket.prompt.md +63 -0
- package/templates/shared/prompts/create-plan.prompt.md +118 -0
- package/templates/shared/prompts/create-pr.prompt.md +139 -0
- package/templates/shared/prompts/finalize-pr.prompt.md +150 -0
- package/templates/shared/prompts/fix-issues.prompt.md +92 -0
- package/templates/shared/prompts/new-wp-component.prompt.md +51 -0
- package/templates/shared/prompts/new-wp-plugin.prompt.md +46 -0
- package/templates/shared/prompts/prepare-pr.prompt.md +123 -0
- package/templates/shared/prompts/prepare-release.prompt.md +74 -0
- package/templates/shared/prompts/quality-check.prompt.md +45 -0
- package/templates/shared/prompts/review-code.prompt.md +81 -0
- package/templates/shared/prompts/work-github-issue.prompt.md +96 -0
- package/templates/shared/prompts/work-ticket.prompt.md +98 -0
- package/templates/shared/skills/README.md +53 -0
- package/templates/shared/skills/component-architecture/SKILL.md +321 -0
- package/templates/shared/skills/create-component/SKILL.md +714 -0
- package/templates/shared/skills/domain-driven-design/SKILL.md +277 -0
- package/templates/shared/skills/plugin-creation/SKILL.md +1094 -0
- package/templates/shared/skills/quality-checks/SKILL.md +493 -0
- package/templates/shared/skills/release-management/SKILL.md +649 -0
- package/templates/shared/skills/testing/SKILL.md +682 -0
- 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.
|