fix: update checker — fall back to /tags when no formal Gitea Release exists (v3.3.2)

The v3.3.0 update checker only queried Gitea's /releases/latest
endpoint, which requires a formal Release object (created via the
Gitea web UI with optional notes + zip assets attached). A plain
"git tag v3.3.x && git push --tags" from the terminal does NOT
create that Release object — so the checker kept returning "No
releases tagged on the Gitea repo yet" even when tags existed.

wp_notes_fetch_latest_release() now falls back to the
/tags?limit=1 endpoint when /releases/latest returns 404 (or any
non-200). It synthesises a release-like payload from the newest
tag — tag_name, html_url pointing at the tag view, tag message as
the body, empty assets[] so the existing download-URL logic falls
through to Gitea's source-archive URL pattern (/archive/<tag>.zip).

Net effect: the "Check now" button now finds the latest version
whether David creates formal Gitea Releases OR just pushes tags
with "git push --tags". No workflow change required.

Discovered while diagnosing why "Check now" wasn't seeing today's
v3.1.0/v3.2.0/v3.3.0/v3.3.1 tags (just pushed in this session)
— the tags were there, the formal Release objects were not.

KNOWN LIMITATION (not a bug — flagged)
The Gitea repo ranger/a-wp-notes-v3 is currently private. Anonymous
API requests get a 404 (Gitea's standard behaviour for private
repos). The updater code is correct but can't actually reach the
API on a private repo without authentication. Fix: change the
repo visibility to public on Gitea — appropriate anyway for a
GPL-licensed plugin headed for the WordPress.org marketplace.

VERSION BUMP
- wp-notes.php header 3.3.1 → 3.3.2
- WP_NOTES_VERSION constant 3.3.1 → 3.3.2
- About page version-history leads with v3.3.2; v3.3.1 demoted

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 09:29:33 +01:00
parent 3667b7a154
commit 2c03dec9b7
4 changed files with 72 additions and 13 deletions
+34
View File
@@ -9,6 +9,40 @@ Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) — versi
---
## [3.3.2] — 2026-05-25
### Fixed — update checker now works with tag-only workflows
The v3.3.0 update checker only queried Gitea's `/releases/latest`
endpoint, which requires a **formal Release object** (created via
the Gitea web UI with optional notes + zip assets). A plain
`git tag v3.3.x && git push --tags` from the terminal doesn't
create that Release object — so the checker kept returning *"No
releases tagged on the Gitea repo yet"* even when tags clearly
existed.
`wp_notes_fetch_latest_release()` now falls back to the
`/tags?limit=1` endpoint when `/releases/latest` returns 404 (or
any non-200). It synthesises a release-like payload from the
newest tag — `tag_name`, an `html_url` pointing at the tag view,
the tag message as the body, and an empty `assets[]` array so the
existing download-URL logic falls through to Gitea's source-archive
URL pattern (`/archive/<tag>.zip`).
**Net effect:** the "Check now" button now finds the latest version
whether David creates formal Gitea Releases OR just pushes tags
with `git push --tags`. No workflow change required.
### Known limitation (not a bug — flagged for awareness)
The Gitea repo `ranger/a-wp-notes-v3` is currently **private**.
Anonymous API requests get a 404 (Gitea's standard behaviour to
avoid leaking the existence of private repos). The updater code is
correct, but it can't actually reach the API on a private repo
without authentication. **Fix:** change the repo visibility to
public on Gitea (Settings → Visibility) — appropriate anyway for a
GPL-licensed plugin headed for the WordPress.org marketplace.
---
## [3.3.1] — 2026-05-25
**Naming: dropped the `WP` prefix. The plugin is now just `Logbook`.**
+5 -1
View File
@@ -125,7 +125,11 @@ function wp_notes_about_page() {
<h2>Version history</h2>
<ul>
<li>
<span class="ver">v3.3.1</span> &mdash; 25 May 2026 <span class="latest">latest</span><br>
<span class="ver">v3.3.2</span> &mdash; 25 May 2026 <span class="latest">latest</span><br>
Update checker now falls back to Gitea's <code>/tags</code> endpoint when no formal Release object exists for the latest tag. Means a plain <code>git tag &amp;&amp; git push --tags</code> is enough to make the &ldquo;Check now&rdquo; button report a new version &mdash; no need to manually create a Release in the Gitea web UI.
</li>
<li>
<span class="ver">v3.3.1</span> &mdash; 25 May 2026<br>
Dropped the <code>WP</code> prefix &mdash; the plugin is now just <strong>Logbook</strong>. Cleaner name, also clears a potential WordPress.org trademark-policy hurdle if/when the plugin ever lands on the marketplace.
</li>
<li>
+31 -10
View File
@@ -48,18 +48,44 @@ function wp_notes_fetch_latest_release( $force_refresh = false ) {
if ( is_array( $cached ) ) { return $cached; }
}
$api_url = WP_NOTES_GITEA_HOST . '/api/v1/repos/' . WP_NOTES_GITEA_OWNER . '/' . WP_NOTES_GITEA_REPO . '/releases/latest';
$response = wp_remote_get( $api_url, array( 'timeout' => 8 ) );
$base_api = WP_NOTES_GITEA_HOST . '/api/v1/repos/' . WP_NOTES_GITEA_OWNER . '/' . WP_NOTES_GITEA_REPO;
// Try /releases/latest first — that's the canonical endpoint when David
// has published a formal Gitea Release via the web UI (with notes + zip
// assets attached).
$response = wp_remote_get( $base_api . '/releases/latest', array( 'timeout' => 8 ) );
if ( is_wp_error( $response ) ) {
return null;
}
$code = (int) wp_remote_retrieve_response_code( $response );
$body = ( $code === 200 ) ? json_decode( wp_remote_retrieve_body( $response ), true ) : null;
// 404 = repo has no releases yet, OR private. Cache briefly and surface
// a friendly status to the UI.
if ( $code !== 200 ) {
// Fallback: if no formal Release exists (typical for tag-only workflows
// where you `git tag v3.3.1 && git push --tags` without using the web
// UI), hit /tags instead and synthesise a release-like payload from the
// newest tag. Gitea's /tags endpoint sorts by creation order, so [0] is
// the most recent.
if ( $code !== 200 || ! is_array( $body ) || empty( $body['tag_name'] ) ) {
$tags_response = wp_remote_get( $base_api . '/tags?limit=1', array( 'timeout' => 8 ) );
if ( ! is_wp_error( $tags_response )
&& (int) wp_remote_retrieve_response_code( $tags_response ) === 200 ) {
$tags = json_decode( wp_remote_retrieve_body( $tags_response ), true );
if ( is_array( $tags ) && ! empty( $tags[0]['name'] ) ) {
$body = array(
'tag_name' => $tags[0]['name'],
'html_url' => wp_notes_gitea_repo_url() . '/src/tag/' . rawurlencode( $tags[0]['name'] ),
'body' => isset( $tags[0]['message'] ) ? $tags[0]['message'] : '',
'published_at' => isset( $tags[0]['commit']['created'] ) ? $tags[0]['commit']['created'] : null,
'assets' => array(),
);
$code = 200;
}
}
}
// Still nothing usable? Surface a friendly status and short-cache.
if ( $code !== 200 || ! is_array( $body ) || empty( $body['tag_name'] ) ) {
$info = array(
'version' => null,
'html_url' => wp_notes_gitea_releases_url(),
@@ -72,11 +98,6 @@ function wp_notes_fetch_latest_release( $force_refresh = false ) {
return $info;
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! is_array( $body ) || empty( $body['tag_name'] ) ) {
return null;
}
// "v3.3.0" → "3.3.0" so version_compare() against WP_NOTES_VERSION works cleanly.
$version = ltrim( (string) $body['tag_name'], 'vV' );
+2 -2
View File
@@ -5,7 +5,7 @@
* Plugin Name: Logbook
* Plugin URI: https://icanhelp.ie/wp-notes
* Description: A lightweight task &amp; logbook plugin for WordPress. Log your daily work, mark tasks done, and keep a tidy record inside the dashboard. Perfect for freelancers showing clients what's been delivered and students proving work to teachers.
* Version: 3.3.1
* Version: 3.3.2
* Requires at least: 5.0
* Requires PHP: 7.2
* Author: IR240474
@@ -33,7 +33,7 @@ if (!isset($wp_notes_init)) {
$wp_notes_init = true;
// Plugin Constants
if (!defined('WP_NOTES_VERSION')) define('WP_NOTES_VERSION', '3.3.1');
if (!defined('WP_NOTES_VERSION')) define('WP_NOTES_VERSION', '3.3.2');
if (!defined('WP_NOTES_FILE')) define('WP_NOTES_FILE', __FILE__);
if (!defined('WP_NOTES_PATH')) define('WP_NOTES_PATH', plugin_dir_path(__FILE__));
if (!defined('WP_NOTES_URL')) define('WP_NOTES_URL', plugin_dir_url(__FILE__));