|
1 | 1 | # WordPress Plugin GitHub Updater |
2 | 2 |
|
3 | | -A reusable WordPress plugin updater class that enables automatic updates from GitHub repositories. Built on top of the [`yahnis-elsts/plugin-update-checker`](#dependencies) library. |
| 3 | +Reusable GitHub updater helper for WordPress plugins, built on top of `yahnis-elsts/plugin-update-checker`. |
4 | 4 |
|
5 | 5 | ## Features |
6 | 6 |
|
7 | | -- ✅ **Automatic updates** from GitHub releases and branches |
8 | | -- ✅ **Release asset filtering** with regex patterns |
9 | | -- ✅ **Custom branch support** for development/staging |
10 | | -- ✅ **Simple static factory methods** for easy setup |
11 | | -- ✅ **Built-in error handling** and debug logging |
12 | | -- ✅ **Flexible configuration** options |
| 7 | +- Automatic plugin updates from GitHub. |
| 8 | +- Release-asset filtering using regex. |
| 9 | +- Branch selection (default: `main`). |
| 10 | +- Canonical static API (`GitHubUpdater::init`) plus backward-compatible wrapper (`GitHub_Plugin_Updater`). |
| 11 | +- Error handling with `WP_DEBUG` logging. |
13 | 12 |
|
14 | | -## Table of Contents |
| 13 | +## Requirements |
15 | 14 |
|
16 | | -- [Quick Start](#quick-start) |
17 | | -- [Configuration](#configuration) |
18 | | -- [GitHub Workflow Setup](#github-workflow-setup) |
19 | | -- [Usage Examples](#usage-examples) |
20 | | -- [Advanced Usage](#advanced-usage) |
21 | | -- [Dependencies](#dependencies) |
22 | | -- [License](#license) |
| 15 | +- WordPress plugin context (`ABSPATH` must be defined). |
| 16 | +- Composer dependency: `yahnis-elsts/plugin-update-checker` (v5+). |
| 17 | +- A public GitHub repository with releases or branch updates. |
23 | 18 |
|
| 19 | +Install dependency: |
24 | 20 |
|
25 | | -## Quick Start |
| 21 | +```bash |
| 22 | +composer require yahnis-elsts/plugin-update-checker |
| 23 | +``` |
26 | 24 |
|
27 | | -Copy [`class-github-plugin-updater.php`](class-github-plugin-updater.php) to your plugin directory and include it: |
| 25 | +## Quick Start (Canonical API) |
| 26 | + |
| 27 | +Copy `class-github-plugin-updater.php` into your plugin and initialize like this: |
28 | 28 |
|
29 | 29 | ```php |
30 | | -if ( ! class_exists( 'Soderlind\WordPress\GitHub_Plugin_Updater' ) ) { |
31 | | - require_once 'class-github-plugin-updater.php'; |
| 30 | +if ( ! class_exists( \Soderlind\WordPress\GitHubUpdater::class ) ) { |
| 31 | + require_once __DIR__ . '/class-github-plugin-updater.php'; |
32 | 32 | } |
33 | 33 |
|
34 | | -// Basic setup (most common) |
35 | | -$updater = \Soderlind\WordPress\GitHub_Plugin_Updater::create( |
36 | | - 'https://github.com/username/plugin-name', |
37 | | - __FILE__, |
38 | | - 'plugin-name' |
| 34 | +\Soderlind\WordPress\GitHubUpdater::init( |
| 35 | + github_url: 'https://github.com/username/plugin-name', |
| 36 | + plugin_file: __FILE__, |
| 37 | + plugin_slug: 'plugin-name', |
| 38 | + name_regex: '/plugin-name\.zip/', |
| 39 | + branch: 'main', |
39 | 40 | ); |
40 | 41 | ``` |
41 | 42 |
|
42 | | -That's it! Your plugin will now check for updates from the specified GitHub repository. |
43 | | - |
44 | | -## Configuration |
45 | | - |
46 | | -### Parameters |
47 | | - |
48 | | -| Parameter | Required | Description | Example | |
49 | | -|-----------|----------|-------------|---------| |
50 | | -| `github_url` | Yes | GitHub repository URL | `'https://github.com/username/plugin-name'` | |
51 | | -| `plugin_file` | Yes | Path to main plugin file | `__FILE__` | |
52 | | -| `plugin_slug` | Yes | Plugin slug for WordPress | `'my-awesome-plugin'` | |
53 | | -| `branch` | No | Git branch to check for updates (default: `'master'`) | `'main'`, `'develop'` | |
54 | | -| `name_regex` | No | Regex pattern for release assets | `'/plugin-name\.zip/'` | |
55 | | -| `enable_release_assets` | No | Whether to enable release assets | `true` if name_regex provided | |
56 | | - |
57 | | -> **Note**: When `branch` is set to `master`, the updater prioritizes releases and tags before falling back to the branch itself. |
58 | | -
|
59 | | -### Initialization Methods |
| 43 | +Positional equivalent: |
60 | 44 |
|
61 | | -#### 1. Basic Setup |
62 | 45 | ```php |
63 | | -$updater = \Soderlind\WordPress\GitHub_Plugin_Updater::create( |
64 | | - 'https://github.com/username/plugin-name', |
65 | | - __FILE__, |
66 | | - 'plugin-name' |
| 46 | +\Soderlind\WordPress\GitHubUpdater::init( |
| 47 | + 'https://github.com/username/plugin-name', |
| 48 | + __FILE__, |
| 49 | + 'plugin-name', |
| 50 | + '/plugin-name\.zip/', |
| 51 | + 'main' |
67 | 52 | ); |
68 | 53 | ``` |
69 | 54 |
|
70 | | -#### 2. Custom Branch |
| 55 | +## Backward Compatibility API |
| 56 | + |
| 57 | +`GitHub_Plugin_Updater` is still available for existing integrations. |
| 58 | + |
71 | 59 | ```php |
72 | | -$updater = \Soderlind\WordPress\GitHub_Plugin_Updater::create( |
73 | | - 'https://github.com/username/plugin-name', |
74 | | - __FILE__, |
75 | | - 'plugin-name', |
76 | | - 'develop' // Branch name |
| 60 | +\Soderlind\WordPress\GitHub_Plugin_Updater::create( |
| 61 | + 'https://github.com/username/plugin-name', |
| 62 | + __FILE__, |
| 63 | + 'plugin-name', |
| 64 | + 'main' |
77 | 65 | ); |
78 | | -``` |
79 | 66 |
|
80 | | -#### 3. With Release Assets |
81 | | -```php |
82 | | -$updater = \Soderlind\WordPress\GitHub_Plugin_Updater::create_with_assets( |
83 | | - 'https://github.com/username/plugin-name', |
84 | | - __FILE__, |
85 | | - 'plugin-name', |
86 | | - '/plugin-name\.zip/' // Regex pattern for zip file |
| 67 | +\Soderlind\WordPress\GitHub_Plugin_Updater::create_with_assets( |
| 68 | + 'https://github.com/username/plugin-name', |
| 69 | + __FILE__, |
| 70 | + 'plugin-name', |
| 71 | + '/plugin-name\.zip/', |
| 72 | + 'main' |
87 | 73 | ); |
88 | 74 | ``` |
89 | 75 |
|
90 | | -#### 4. Full Configuration |
91 | | -```php |
92 | | -$updater = new \Soderlind\WordPress\GitHub_Plugin_Updater([ |
93 | | - 'github_url' => 'https://github.com/username/plugin-name', |
94 | | - 'plugin_file' => __FILE__, |
95 | | - 'plugin_slug' => 'plugin-name', |
96 | | - 'branch' => 'main', |
97 | | - 'name_regex' => '/plugin-name-v[\d\.]+\.zip/', |
98 | | - 'enable_release_assets' => true, |
99 | | -]); |
100 | | -``` |
| 76 | +## Configuration |
101 | 77 |
|
102 | | -## GitHub Workflow Setup |
103 | | - |
104 | | -To automatically create release assets, add this workflow to your repository at `.github/workflows/on-release-add.zip.yml`: |
105 | | - |
106 | | -```yaml |
107 | | -name: On Release, Build release zip |
108 | | - |
109 | | -on: |
110 | | - release: |
111 | | - types: [published] |
112 | | - |
113 | | -jobs: |
114 | | - build: |
115 | | - name: Build release zip |
116 | | - runs-on: ubuntu-latest |
117 | | - permissions: |
118 | | - contents: write |
119 | | - steps: |
120 | | - - name: Checkout |
121 | | - uses: actions/checkout@v4 |
122 | | - |
123 | | - - name: Build plugin |
124 | | - run: composer install --no-dev |
125 | | - |
126 | | - - name: Archive Release |
127 | | - uses: thedoctor0/zip-release@b57d897cb5d60cb78b51a507f63fa184cfe35554 |
128 | | - with: |
129 | | - type: 'zip' |
130 | | - filename: 'your-plugin-name.zip' # Change this |
131 | | - exclusions: '*.git* .editorconfig composer* *.md package.json package-lock.json' |
132 | | - |
133 | | - - name: Release |
134 | | - uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda |
135 | | - env: |
136 | | - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
137 | | - with: |
138 | | - files: your-plugin-name.zip # Change this |
139 | | - tag_name: ${{ github.event.release.tag_name }} |
140 | | -``` |
| 78 | +### `GitHubUpdater::init(...)` |
141 | 79 |
|
142 | | -### Customization Tips |
| 80 | +| Parameter | Required | Default | Description | |
| 81 | +|-----------|----------|---------|-------------| |
| 82 | +| `github_url` | Yes | - | Full repository URL (`https://github.com/owner/repo`) | |
| 83 | +| `plugin_file` | Yes | - | Absolute path to the main plugin file | |
| 84 | +| `plugin_slug` | Yes | - | Plugin slug used by WordPress | |
| 85 | +| `name_regex` | No | `''` | Regex to match release asset zip filename | |
| 86 | +| `branch` | No | `'main'` | Branch to track | |
143 | 87 |
|
144 | | -- Update `filename` and `files` to match your plugin name |
145 | | -- Modify `exclusions` to include/exclude specific files |
146 | | -- Adjust the build step for your project needs (npm, webpack, etc.) |
| 88 | +Notes: |
147 | 89 |
|
148 | | -This creates downloadable assets at URLs like: |
149 | | -``` |
150 | | -https://github.com/username/plugin-name/releases/latest/download/plugin-name.zip |
151 | | -``` |
| 90 | +- When `name_regex` is empty, release-asset filtering is disabled. |
| 91 | +- `init` registration is deferred to WordPress `init` to be safe regardless of load timing. |
152 | 92 |
|
153 | | -## Usage Examples |
| 93 | +## Recommended Integration Pattern |
154 | 94 |
|
155 | | -### Real-World Implementations |
156 | | -- [Additional JavaScript](https://github.com/soderlind/additional-javascript/blob/main/additional-javascript.php#L33-L44) |
157 | | -- [Multisite Exporter](https://github.com/soderlind/multisite-exporter/blob/main/includes/class-multisite-exporter.php#L57-L63) |
158 | | -- [Super Admin Switch to Admin](https://github.com/soderlind/super-admin-switch-to-admin/blob/main/super-admin-switch-to-admin.php#L38-L50) |
| 95 | +From your main plugin file, mirror the vmfa pattern: |
159 | 96 |
|
160 | | -### Basic Plugin Setup |
161 | 97 | ```php |
162 | | -// In your main plugin file |
163 | | -define( 'MY_PLUGIN_FILE', __FILE__ ); |
164 | | -require_once plugin_dir_path( __FILE__ ) . 'class-github-plugin-updater.php'; |
165 | | -
|
166 | | -$updater = \Soderlind\WordPress\GitHub_Plugin_Updater::create( |
167 | | - 'https://github.com/myusername/my-awesome-plugin', |
168 | | - MY_PLUGIN_FILE, |
169 | | - 'my-awesome-plugin' |
170 | | -); |
171 | | -``` |
| 98 | +if ( ! class_exists( \Soderlind\WordPress\GitHubUpdater::class ) ) { |
| 99 | + require_once __DIR__ . '/class-github-plugin-updater.php'; |
| 100 | +} |
172 | 101 |
|
173 | | -### Development Branch Updates |
174 | | -```php |
175 | | -$updater = \Soderlind\WordPress\GitHub_Plugin_Updater::create( |
176 | | - 'https://github.com/company/enterprise-plugin', |
177 | | - __FILE__, |
178 | | - 'enterprise-plugin', |
179 | | - 'develop' // Use development branch |
| 102 | +\Soderlind\WordPress\GitHubUpdater::init( |
| 103 | + github_url: 'https://github.com/owner/repo', |
| 104 | + plugin_file: MY_PLUGIN_FILE, |
| 105 | + plugin_slug: 'my-plugin', |
| 106 | + name_regex: '/my-plugin\.zip/', |
| 107 | + branch: 'main', |
180 | 108 | ); |
181 | 109 | ``` |
182 | 110 |
|
183 | | -### Release Assets with Pattern Matching |
184 | | -```php |
185 | | -$updater = \Soderlind\WordPress\GitHub_Plugin_Updater::create_with_assets( |
186 | | - 'https://github.com/company/premium-plugin', |
187 | | - __FILE__, |
188 | | - 'premium-plugin', |
189 | | - '/premium-plugin-v[\d\.]+\.zip/' // Match versioned zip files |
190 | | -); |
191 | | -``` |
192 | | -## Advanced Usage |
| 111 | +## Workflow Setup |
193 | 112 |
|
194 | | -### Custom Class Names |
195 | | -If you need to avoid naming conflicts, extend or wrap the class: |
| 113 | +This repository includes two workflow templates: |
196 | 114 |
|
197 | | -```php |
198 | | -namespace YourCompany\YourPlugin; |
| 115 | +- `on-release-add.zip.yml` (release-triggered build + upload) |
| 116 | +- `manually-build-zip.yml` (manual build/upload for a provided tag) |
199 | 117 |
|
200 | | -class Your_Plugin_Updater extends \Soderlind\WordPress\GitHub_Plugin_Updater { |
201 | | - // Inherit all functionality, customize as needed |
202 | | -} |
203 | | -``` |
| 118 | +Copy them into your plugin repository at `.github/workflows/`. |
204 | 119 |
|
205 | | -### Plugin-Specific Wrapper |
206 | | -```php |
207 | | -namespace YourCompany\YourPlugin; |
208 | | -
|
209 | | -class Your_Plugin_Updater { |
210 | | - private $updater; |
211 | | - |
212 | | - public function __construct() { |
213 | | - $this->updater = \Soderlind\WordPress\GitHub_Plugin_Updater::create( |
214 | | - 'https://github.com/yourcompany/your-plugin', |
215 | | - YOUR_PLUGIN_FILE, |
216 | | - 'your-plugin' |
217 | | - ); |
218 | | - } |
219 | | -} |
220 | | -``` |
| 120 | +### Workflow Checklist |
221 | 121 |
|
222 | | -### Best Practices |
| 122 | +1. Set `PLUGIN_ZIP` to your plugin zip file (example: `my-plugin.zip`). |
| 123 | +2. Keep `composer install --no-dev --optimize-autoloader` so the updater dependency is packaged. |
| 124 | +3. Keep the verification step that checks `vendor/yahnis-elsts/plugin-update-checker` exists in the zip. |
| 125 | +4. Ensure `name_regex` in PHP matches your zip filename convention. |
223 | 126 |
|
224 | | -- **Use constants** for plugin file paths: `define( 'MY_PLUGIN_FILE', __FILE__ )` |
225 | | -- **Prefer static factory methods** like `::create()` for simpler setup |
226 | | -- **Test thoroughly** with different branches and release patterns |
227 | | -- **Document your configuration** for future reference |
228 | | -- **Consider namespacing** to avoid conflicts with other plugins |
| 127 | +## Troubleshooting |
229 | 128 |
|
230 | | -### Error Handling |
| 129 | +### Updates do not appear |
231 | 130 |
|
232 | | -The updater includes built-in error handling: |
| 131 | +1. Confirm your plugin file, slug, repo URL, and branch are correct. |
| 132 | +2. Publish a release with an attached zip that matches `name_regex`. |
| 133 | +3. Trigger a manual update check in WordPress Admin (or wait for scheduled checks). |
233 | 134 |
|
234 | | -- **Parameter validation** on initialization |
235 | | -- **Exception graceful handling** during update checks |
236 | | -- **Debug logging** when `WP_DEBUG` is enabled |
237 | | -- **Graceful degradation** if updater setup fails |
| 135 | +### Dependency is missing in release zip |
238 | 136 |
|
239 | | -## Dependencies |
| 137 | +If `plugin-update-checker` is not in `vendor/`, updater setup fails. In `WP_DEBUG`, you will see: |
240 | 138 |
|
241 | | -This updater requires the `yahnis-elsts/plugin-update-checker` library: |
| 139 | +`GitHubUpdater (your-plugin-slug): Missing dependency yahnis-elsts/plugin-update-checker...` |
242 | 140 |
|
243 | | -```bash |
244 | | -composer require yahnis-elsts/plugin-update-checker |
245 | | -``` |
| 141 | +### GitHub API rate limits |
| 142 | + |
| 143 | +Unauthenticated GitHub requests are rate-limited. Keep failed lookup caching enabled in your updater flow and avoid frequent forced checks in production. |
| 144 | + |
| 145 | +### Private repositories |
| 146 | + |
| 147 | +This wrapper is designed for public GitHub releases. For private repositories, instantiate plugin-update-checker directly and configure authentication with that library. |
| 148 | + |
| 149 | +## Real-World Reference |
246 | 150 |
|
247 | | -Or download manually from: https://github.com/YahnisElsts/plugin-update-checker |
| 151 | +WordPress plugins at https://github.com/soderlind |
248 | 152 |
|
249 | 153 | ## License |
250 | 154 |
|
251 | | -MIT (same as the original library) |
| 155 | +GPL-2.0-or-later. |
0 commit comments