This updater provides a simple, production‑ready way to update your PHP app from GitHub Releases. It creates a ZIP backup, downloads the latest release asset, extracts it to a temp directory, copies files over your app (skipping the updater and backups dir), and updates version.json
.
- Author: Fattain Naime
- GitHub: https://github.com/fattain-naime/automatic-update-via-github
- License: GPLv3 or later
- Version: 1.0.0
- PHP 7.4+ (PHP 8.x recommended)
- Extensions:
curl
,zip
- Write permissions for:
- The application root (to copy files)
- The backup directory (defaults to
backups/
next toupdate.php
) - Log file (defaults to
update.log
next toupdate.php
)
- A GitHub repository with Releases and a downloadable ZIP asset
- Optional: GitHub token (recommended in production for higher API limits/private assets)
update.php
— The updater UI and logicversion.json
— Stores current version, e.g.{ "version": "v1.2.3" }
- Copy
update.php
andversion.json
into your app (ideally in an admin‑only area). - Open
update.php
and set:GITHUB_REPO
to your repo inowner/repo
format.GITHUB_TOKEN
to your PAT (optional but recommended).- Optionally change
CURRENT_VERSION_JSON
andBACKUP_DIR
paths.
- Ensure the web user (Apache/IIS/PHP‑FPM) can write to your app directory and backup directory.
- Visit
update.php
while logged in to your app’s admin; click “Update Now”.
By default, only logged‑in users can access the updater UI.
- Constants at the top of
update.php
:ACCESS_REQUIRE_LOGIN
(default:true
)ACCESS_REQUIRE_ADMIN
(default:false
)HOME_URL
(default:..
) — where unauthenticated/unauthorized users are redirected
If your app distinguishes admins, set ACCESS_REQUIRE_ADMIN
to true
.
The default guard checks typical session keys:
$_SESSION['user_id']
or$_SESSION['logged_in']
or$_SESSION['user']
$_SESSION['is_admin']
or arole
value equal toadmin
/administrator
When access is denied (not logged in or not admin when required), the script redirects to HOME_URL
with a 302.
Customize the guard to match your app’s session/role model. For example:
// Replace the guard with your own app’s checks
if (!myAppIsLoggedIn() || !myAppIsAdmin()) {
header('Location: ..');
exit;
}
Tip: You can also place update.php
inside an existing admin route that already enforces authentication.
- Checks GitHub Releases API for the latest release.
- Selects the first ZIP asset (or falls back to the source zipball).
- Creates a ZIP backup of the current app into
backups/
. - Downloads the release ZIP using cURL.
- Extracts to a temp folder and copies files into the app directory.
- Skips the updater script and the
backups/
folder.
- Skips the updater script and the
- Writes the new version to
version.json
and resets opcache. - Logs errors to
update.log
(errors are not displayed to users in production).
Version comparison uses semantic comparison with optional v
/V
prefix stripping (e.g., v1.2.3
). The updater won’t downgrade if the remote tag is older.
GITHUB_REPO
: GitHub repo inowner/repo
format.GITHUB_TOKEN
: Personal Access Token string. For public repos, no scopes are required; for private releases, add appropriate scopes.CURRENT_VERSION_JSON
: Path to the version JSON file to update.BACKUP_DIR
: Directory for ZIP backups.ACCESS_REQUIRE_LOGIN
: Require authenticated user to access the updater page.ACCESS_REQUIRE_ADMIN
: Require admin role in addition to login.
- Keep
update.php
in an authenticated admin area. - Ensure backups and logs are not web‑accessible (or use server rules to deny direct access to
backups/
andupdate.log
). - Use a GitHub token in production to avoid rate limits and to support private assets.
- Only allow downloads from GitHub hosts (enforced by the script).
- “Could not create backup” — check write permissions and that the
zip
extension is enabled. - “Download failed” — verify network access, token (if needed), and that the asset URL is valid.
- “ZIP extraction failed” — ensure
zip
extension is enabled and disk has space. - “Up to date” but you expect an update — verify your tags are semantic and prefixed consistently (e.g.,
v1.2.3
).
If your app doesn’t already set login session flags, a very simple approach is:
// During login in your app
$_SESSION['user_id'] = $userId; // or any truthy value
$_SESSION['role'] = 'admin'; // optional, for admin‑only access
Then the updater’s default guard will allow access when logged in.
For questions or improvements, feel free to extend update.php
— it’s a single self‑contained file.