A WordPress plugin for automatic updates from Forgejo. A lightweight alternative to Git Updater, with no banners and no external dependencies.
Find a file
2026-06-02 20:11:46 +02:00
includes v2.9.4: limit screenshot size, add numbered list support to readme_to_html 2026-06-02 19:51:22 +02:00
.distignore Fix phpcs:ignore echo $ok/$warn e nonce notice, aggiungi .distignore 2026-06-02 13:44:18 +02:00
.gitignore feat: sicurezza, file standard WP e miglioramenti architetturali 2026-04-05 20:15:53 +02:00
CHANGELOG.md v2.8.3: fix add_auth_header non sovrascrive Authorization già impostato dal chiamante 2026-05-27 20:37:44 +02:00
eg-forgejo-updater.php v2.9.5: update Upgrade Notice section with versions 2.9.x 2026-06-02 19:55:48 +02:00
index.php feat: sicurezza, file standard WP e miglioramenti architetturali 2026-04-05 20:15:53 +02:00
LICENSE feat: sicurezza, file standard WP e miglioramenti architetturali 2026-04-05 20:15:53 +02:00
README.it-IT.md Aggiorna README.it-IT.md 2026-06-02 20:11:46 +02:00
README.md README: split into README.md (English) and README.it-IT.md (Italian) 2026-05-30 23:12:30 +02:00
readme.txt v2.9.5: update Upgrade Notice section with versions 2.9.x 2026-06-02 19:55:48 +02:00
uninstall.php feat: sicurezza, file standard WP e miglioramenti architetturali 2026-04-05 20:15:53 +02:00

EG Forgejo Updater

🇬🇧 English · 🇮🇹 Italiano

Minimal WordPress plugin that automatically updates plugins hosted on a self-hosted Forgejo instance.

A lightweight replacement for Git Updater: no ad banners, no Redis compatibility issues, token saved in wp-config.php once and for all.


Project structure

eg-forgejo-updater/
├── eg-forgejo-updater.php            # Bootstrap, plugin header, class includes
├── uninstall.php                     # Data cleanup on uninstall
├── index.php                         # Directory listing protection
├── readme.txt                        # Standard WordPress readme
├── CHANGELOG.md                      # Changelog
├── LICENSE                           # GPL-2.0-or-later
└── includes/
    ├── class-eg-forgejo-api.php      # Forgejo REST API client
    ├── class-eg-forgejo-updater.php  # WordPress hooks for update detection and install
    ├── class-eg-forgejo-admin.php    # Admin page (Plugins submenu)
    └── index.php                     # Directory listing protection

Requirements

  • WordPress 6.0 or later
  • PHP 8.0 or later (uses typed properties and named arguments)
  • Forgejo instance reachable over HTTPS from the WordPress host
  • For each managed plugin: at least one tag or release in the corresponding Forgejo repo

Installation

  1. Upload the eg-forgejo-updater/ folder to wp-content/plugins/
  2. Add FORGEJO_ACCESS_TOKEN to wp-config.php (required for private repos)
  3. Activate the plugin from Dashboard > Plugins
  4. Plugins with a Forgejo Plugin URI or Gitea Plugin URI header are detected automatically
  5. To install additional plugins from Forgejo, use the built-in feature described below

Configuration in wp-config.php

Add these lines before the line /* That's all, stop editing! */:

// Personal access token (required for private repos)
define( 'FORGEJO_ACCESS_TOKEN', 'your_token_here' );

// Base URL of the Forgejo instance (optional since v2.0 — derived from the plugin header)
define( 'FORGEJO_BASE_URL', 'https://git.example.com' );

How to create FORGEJO_ACCESS_TOKEN

  1. Log in to your Forgejo instance with your account
  2. Go to Settings → Applications → Manage Access Tokens
  3. Create a new token with the following permissions:
    • Repository → Read (to read raw files and download ZIPs)
    • Everything else: No access
  4. Copy the generated token and paste it into wp-config.php

An administrator account is not required: the account that owns the repositories you need to manage is enough.

Notes on the FORGEJO_ACCESS_TOKEN constant

Required for private repos. The token is used in two places:

  1. In the Authorization: token xxx header of Forgejo REST API calls
  2. In the Authorization: token xxx header of the ZIP download request during the update

The token is added only to requests directed to known Forgejo URLs (from the FORGEJO_BASE_URL constant and/or from plugin headers). It is never sent to third-party domains.

Notes on the FORGEJO_BASE_URL constant

Deprecated. The Forgejo Plugin URI header should always contain the full repository URL (e.g. https://git.example.com/owner/repo) — the base URL is automatically derived from there. Defining FORGEJO_BASE_URL in wp-config.php is not needed and ties the plugin to a specific URL, hurting portability if the Forgejo instance changes.

Plugin auto-discovery

Since v2.0 the plugin automatically detects the plugins to manage by reading the header of the main PHP file. Two headers are supported, compatible with Git Updater:

/**
 * Plugin Name: My Plugin
 * Forgejo Plugin URI: https://git.example.com/owner/my-plugin
 */

or:

/**
 * Plugin Name: My Plugin
 * Gitea Plugin URI: https://git.example.com/owner/my-plugin
 */

If FORGEJO_BASE_URL is defined, the short form can also be used:

 * Forgejo Plugin URI: owner/my-plugin

Plugins detected automatically appear in the table with source "auto" and cannot be removed from the list (just remove the header to exclude them).

Why in wp-config.php and not in the database

Saving credentials in the WordPress database (even encrypted) potentially exposes them to malicious plugins or database dumps. wp-config.php lies outside the webroot in standard setups and is never served by NGINX/Apache. This approach is compatible with Redis Object Cache because it does not rely on transients for credentials.


How update detection works

Full flow

WordPress scheduler (every 12h) or manual action
  └── Filter site_transient_update_plugins
        └── For each plugin with a Forgejo/Gitea Plugin URI header:
              └── get_transient(eg_fu_release_{md5(plugin_file)})
                    ├── Cache hit  → use cached data
                    └── Cache miss → call Forgejo API (1 single call)
                          └── GET /api/v1/repos/{owner}/{repo}/raw/{file}.php?ref=main
                                └── Parse "Version:" from the remote source
                                      ├── Remote version > installed → inject into $transient->response
                                      └── Equal or lower version       → remove from $transient->response

Check frequency

The version-data cache is saved as a WordPress transient with a TTL of 12 hours (CACHE_TTL = 43200). This means:

  • The automatic check happens every 12 hours, in sync with the native WordPress cycle
  • Going to Dashboard > Updates and clicking "Check again" forces an immediate check
  • The "Check for updates now" button on the plugin page explicitly flushes all transients

Version comparison

WordPress internally uses version_compare() (PHP native). The remote version is read directly from the Version: header of the main PHP file on the repo branch.


ZIP file handling during the update

Archive download

The plugin downloads the ZIP archive of the primary branch from the Forgejo repo:

https://git.example.com/owner/repo/archive/main.zip

The folder-name problem

Forgejo generates archives with a folder name like repo-main/ that does not match the plugin slug (e.g. eg-fediverso-box/). WordPress expects the extracted folder to have the same name as the slug.

The plugin handles this via the upgrader_source_selection filter, which renames the extracted folder to the correct slug before WordPress finishes the installation.


Installing a plugin from Forgejo

EG Forgejo Updater lets you install any public plugin hosted on Forgejo directly from WordPress, without downloading ZIPs, without FTP, without manual upload.

How to do it

  1. Go to Plugins → Forgejo Updater
  2. In the "Install plugin from Forgejo" section, paste the repository URL
  3. Click "Verify and continue"
  4. The plugin runs an automatic checklist:
    • Valid URL format
    • Recognized Forgejo/Gitea instance
    • Reachable repository
    • Main PHP file found
    • Plugin Name and Version headers present
    • Forgejo Plugin URI header present (required for automatic updates)
  5. If all checks pass, a preview with name, version and author is shown
  6. Click "Install plugin" to proceed
  7. Activate the plugin from the plugin list

Once installed, the plugin is automatically detected by the auto-discovery feature and will receive updates like the others.

Adding via header (auto-discovery)

For plugins already installed with the header in the main PHP file:

 * Forgejo Plugin URI: https://git.emanuelegori.uno/emanuelegori/repotest
 * Primary Branch: main

The plugin is detected automatically when the page is loaded, with no additional configuration.


Forgejo icon in the plugin list

In Plugins > Installed Plugins, every plugin managed by this updater shows an extra link in the meta info row (below the name and description), with the Forgejo logo and a direct link to the repository.

The SVG logo is embedded inline in PHP (get_forgejo_svg()), with no separate asset files and no additional HTTP requests.


WordPress hooks used

Hook Class Purpose
plugins_loaded bootstrap Class initialization
site_transient_update_plugins Updater Inject update data into the native WP cycle
plugins_api Updater "Version details" popup in the dashboard
plugin_row_meta Updater Forgejo icon and repo link in the plugin list
http_request_args Updater Add Authorization token for private repo downloads
upgrader_source_selection Updater Fix the ZIP folder name from zipball
upgrader_process_complete Updater Cache flush after a completed update
admin_menu Admin Register submenu under Plugins
admin_post_eg_fu_preview Admin Verify repo URL and compatibility checklist
admin_post_eg_fu_install Admin Install plugin from Forgejo zip
admin_post_eg_fu_delete Admin Remove plugin from the list
admin_post_eg_fu_check Admin Force an immediate update check
admin_notices Admin Feedback notices

Redis Object Cache compatibility

Transients are saved through native WordPress set_transient() / get_transient() / delete_transient() functions. With Redis Object Cache active they are automatically stored in Redis without extra configuration. No direct SQL queries or database bypass accesses are used, eliminating the incompatibility issue that affected Git Updater.


Publishing a new version

For every new version of a managed plugin:

  1. Update Version: in the header of the plugin's main PHP file
  2. Commit and push to the primary branch

Within 12 hours (or immediately by clicking "Check for updates now") WordPress will show the available-update notice. There is no need to create releases or tags.


Updating EG Forgejo Updater itself

This plugin manages itself thanks to the Forgejo Plugin URI header in its own main file. It updates exactly like the other plugins.


License

GPL-2.0-or-later