A modern PHP library to automatically update WordPress plugins from public or private GitHub repositories.
- 🔒 Secure: Multiple token sources support (wp-config, environment variables, WP options)
- 🏷️ Flexible: Support for tags with or without
vprefix (v1.0.0 or 1.0.0) - 🎯 Modern: Strict PHP 8 typing, complete PHPDoc, fully tested
- ✅ Tested: Complete PHPUnit test suite with 15 tests
- 📦 Zero config: Works directly with public repositories, no token needed
- 🔐 Private repos: Full support with GitHub authentication
- 🌐 URL parsing: Accepts multiple GitHub URL formats (HTTPS, Git, SSH)
- 🔄 Smart caching: Respects WordPress transients to avoid API rate limits
- 🛡️ Error handling: Graceful degradation if GitHub API is unavailable
- 📝 Standards compliant: Follows WordPress Coding Standards and PSR-12
- PHP 7.4 or higher
- WordPress 6.0 or higher
- Composer
composer require honemo/wp-github-updater<?php
use honemo\updater\Updater;
if ( is_admin() ) {
require_once plugin_dir_path( __FILE__ ) . 'vendor/autoload.php';
$updater = new Updater(
__FILE__, // Main plugin file
'https://github.com/Honemo/wp-github-updater' // Repository URL
);
$updater->init();
}// In wp-config.php (BEFORE require_once(ABSPATH . 'wp-settings.php'))
define( 'GITHUB_UPDATER_TOKEN', 'ghp_your_secret_token' );// In your plugin - NO TOKEN in clear text!
use honemo\updater\Updater;
if ( is_admin() ) {
$updater = new Updater(
__FILE__,
'https://github.com/Honemo/my-private-plugin'
// Token is automatically retrieved from wp-config.php
);
$updater->init();
}The updater accepts various GitHub URL formats:
// Standard HTTPS URL
'https://github.com/username/repository'
// With .git extension
'https://github.com/username/repository.git'
// With trailing slash
'https://github.com/username/repository/'
// Without https://
'github.com/username/repository'
// Git SSH format (converted automatically)
'git@github.com:username/repository.git'# In .env (never versioned)
GITHUB_UPDATER_TOKEN=ghp_your_secret_tokenThe code remains the same - the updater automatically searches in environment variables.
// Via WordPress admin or in functions.php
update_option( 'github_updater_token', 'ghp_your_secret_token' );The updater searches for the token in this order:
- Parameter passed to constructor
GITHUB_UPDATER_TOKENconstant (wp-config.php)GITHUB_UPDATER_TOKENenvironment variablegithub_updater_tokenWordPress option
new Updater( string $file, string $repository_url, string $github_token = '' )Parameters:
$file(string, required): Absolute path to your main plugin file (typically__FILE__)$repository_url(string, required): GitHub repository URL. Accepts multiple formats:https://github.com/username/repositoryhttps://github.com/username/repository.gitgithub.com/username/repositorygit@github.com:username/repository.git
$github_token(string, optional): GitHub personal access token. If not provided, the updater will attempt to retrieve it from:GITHUB_UPDATER_TOKENconstantGITHUB_UPDATER_TOKENenvironment variablegithub_updater_tokenWordPress option
Example:
$updater = new \honemo\updater\Updater(
__FILE__,
'https://github.com/tcacamou-ops/all-in-one-download'
);
$updater->init();Initialize the updater by hooking into WordPress filters. Must be called after instantiation.
$updater->init();- Go to GitHub → Settings → Developer Settings → Personal access tokens
- Generate new token (classic)
- Minimum required permissions:
- ✅
repo(for private repositories) - ✅
public_repo(for public repositories only)
- ✅
- Copy the token and store it securely
A GitHub Actions workflow is included to automatically create releases when you push a tag:
Step 1: Update the version in your plugin file
/**
* Version: 1.2.0
*/Step 2: Commit your changes
git add .
git commit -m "Release version 1.2.0"Step 3: Create and push a tag
git tag v1.2.0 # or simply 1.2.0
git push origin main
git push origin v1.2.0That's it! The workflow will automatically:
- ✅ Build a distribution package (without dev dependencies)
- ✅ Generate a changelog from git commits
- ✅ Create a GitHub release with the package attached
- ✅ Upload the distributable ZIP file
The workflow supports both formats:
- Tags with prefix:
v1.0.0,v2.3.4 - Tags without prefix:
1.0.0,2.3.4
If you prefer to create releases manually:
-
Create a version tag:
git tag v1.0.0 # or simply 1.0.0 git push origin v1.0.0 -
Create a release on GitHub:
- Go to "Releases" → "Create a new release"
- Select the tag
- Add release notes
- Publish the release
-
The version in your main file must match:
/** * Version: 1.0.0 */
The .distignore file controls what's excluded from releases:
- ❌ Development dependencies (
/vendor/dev packages,/tests/) - ❌ Configuration files (
phpcs.xml,phpstan.neon) - ❌ Git files (
.git,.github,.gitignore) - ✅ Production code (
/src/) - ✅ Composer autoloader
- ✅ README.md and LICENSE
<?php
/**
* Plugin Name: My Awesome Plugin
* Version: 1.0.0
* Plugin URI: https://github.com/Honemo/my-plugin
* Description: An awesome plugin with auto-update from GitHub
* Author: Honemo
* Author URI: https://github.com/Honemo
*/
// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Composer autoloader
require_once plugin_dir_path( __FILE__ ) . 'vendor/autoload.php';
// Initialize updater (admin only)
if ( is_admin() ) {
$updater = new \honemo\updater\Updater(
__FILE__,
'https://github.com/Honemo/my-plugin'
);
$updater->init();
}
// Rest of your code...Check these points:
-
Version mismatch: Ensure the version in your plugin header matches exactly with the GitHub release tag (without
vprefix)// Plugin header Version: 1.0.0 // GitHub tag should be: v1.0.0 or 1.0.0
-
Release published: Make sure you've created and published a release on GitHub, not just a tag
-
Token authentication: For private repositories, verify your token has the correct permissions:
reposcope for private repositoriespublic_reposcope for public repositories
-
Clear transients: WordPress caches update information. Clear it with:
delete_site_transient( 'update_plugins' );
If you get an InvalidArgumentException, ensure your URL:
- Points to
github.com(not GitLab, Bitbucket, etc.) - Contains both username and repository name
- Follows one of the supported formats
Valid formats:
'https://github.com/username/repository'
'github.com/username/repository'
'git@github.com:username/repository.git'Invalid formats:
'https://gitlab.com/username/repository' // ❌ Not GitHub
'https://github.com/username' // ❌ Missing repository
'username/repository' // ❌ Missing domainVerify the token is accessible:
// Add this temporarily to debug
if ( defined( 'GITHUB_UPDATER_TOKEN' ) ) {
error_log( 'Token is defined in wp-config.php' );
}Make sure the constant is defined before wp-settings.php is loaded in wp-config.php.
# Clone repository
git clone https://github.com/Honemo/wp-github-updater.git
cd wp-github-updater
# Install dependencies
composer install
# Run tests
composer test
# Check code quality
composer check:allGPL-3.0 License. See LICENSE for more details.
Contributions are welcome! Feel free to:
- Open an issue to report a bug
- Submit a pull request to improve the code
- Suggest new features