fix: switch updater from packages API to releases API for version check
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 1m5s

Gitea's generic package list endpoint wasn't returning 200. Switched to
/api/v1/repos/{owner}/{repo}/releases/latest which is the standard
Gitea releases API. Download URLs still use the packages registry.
Repo is now public — no auth token needed for version checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell 2026-03-17 12:26:31 -04:00
parent 8b0289d133
commit 4af90bb80d

View File

@ -60,6 +60,11 @@ type giteaPackageVersion struct {
Version string `json:"version"`
}
// giteaRelease is the subset of the Gitea releases API response we need.
type giteaRelease struct {
TagName string `json:"tag_name"`
}
// versionJSON is the schema of the version.json file in the package.
type versionJSON struct {
Version string `json:"version"`
@ -75,9 +80,9 @@ func (u *UpdateService) CheckForUpdate() (*UpdateInfo, error) {
}
// Fetch latest package version from the Gitea API.
// Gitea package API — no /v1/ prefix
// Use Gitea releases API to find the latest release tag
apiURL := fmt.Sprintf(
"%s/api/packages/%s/generic/%s?limit=1&sort=created_at&direction=desc",
"%s/api/v1/repos/%s/%s/releases/latest",
u.baseURL, u.owner, u.pkg,
)
@ -88,42 +93,36 @@ func (u *UpdateService) CheckForUpdate() (*UpdateInfo, error) {
return nil, fmt.Errorf("build request: %w", err)
}
// Use GIT_TOKEN for private registries, if available.
if token := os.Getenv("GIT_TOKEN"); token != "" {
req.Header.Set("Authorization", "token "+token)
}
resp, err := u.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("fetch package versions: %w", err)
return nil, fmt.Errorf("fetch latest release: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("read package API response: %w", err)
return nil, fmt.Errorf("read release API response: %w", err)
}
slog.Info("package API response", "status", resp.StatusCode, "body", string(body)[:min(len(body), 500)])
slog.Info("release API response", "status", resp.StatusCode, "body", string(body)[:min(len(body), 500)])
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status %d from package API: %s", resp.StatusCode, string(body))
return nil, fmt.Errorf("unexpected status %d from releases API: %s", resp.StatusCode, string(body))
}
var versions []giteaPackageVersion
if err := json.Unmarshal(body, &versions); err != nil {
return nil, fmt.Errorf("decode package versions: %w", err)
var release giteaRelease
if err := json.Unmarshal(body, &release); err != nil {
return nil, fmt.Errorf("decode release: %w", err)
}
slog.Info("parsed versions", "count", len(versions), "currentVersion", u.currentVersion)
if len(versions) == 0 {
slog.Info("no package versions found")
if release.TagName == "" {
slog.Info("no releases found")
return info, nil
}
latestVer := strings.TrimPrefix(versions[0].Version, "v")
latestVer := strings.TrimPrefix(release.TagName, "v")
info.LatestVer = latestVer
slog.Info("latest release", "tag", release.TagName, "version", latestVer, "current", u.currentVersion)
cmp := CompareVersions(u.currentVersion, latestVer)
if cmp >= 0 {
@ -132,9 +131,10 @@ func (u *UpdateService) CheckForUpdate() (*UpdateInfo, error) {
}
// Newer version is available — fetch version.json for SHA256 + download URL.
tagVersion := release.TagName // e.g. "v0.6.0" or "0.6.0"
versionInfoURL := fmt.Sprintf(
"%s/api/packages/%s/generic/%s/%s/version.json",
u.baseURL, u.owner, u.pkg, versions[0].Version,
u.baseURL, u.owner, u.pkg, tagVersion,
)
vInfo, err := u.fetchVersionJSON(versionInfoURL)
@ -155,7 +155,7 @@ func (u *UpdateService) CheckForUpdate() (*UpdateInfo, error) {
if info.DownloadURL == "" {
info.DownloadURL = fmt.Sprintf(
"%s/api/packages/%s/generic/%s/%s/wraith-%s-setup.exe",
u.baseURL, u.owner, u.pkg, versions[0].Version, versions[0].Version,
u.baseURL, u.owner, u.pkg, tagVersion, tagVersion,
)
}