fix(release): separate publication time from the release date (#36761)

`published_at` was an alias for `created_at`, so a release created from
an existing tag reported that tag's commit date as its publication time,
and drafts reported one despite never having been published. It is now
stored separately, set when a release is published and null for drafts.

`created_at` in turn means the date of the commit the release points at,
matching what GitHub documents it to be, and the latest release is
selected by it again. Publishing a release for an old commit no longer
takes over the latest badge, and a tag created in the web UI is dated
the same way as one pushed from the CLI.

Fixes https://github.com/go-gitea/gitea/issues/11206
Fixes https://github.com/go-gitea/gitea/issues/38714
Fixes https://github.com/go-gitea/gitea/issues/31789

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
silverwind
2026-08-22 08:59:37 +00:00
committed by GitHub
co-authored by Claude Opus 4.6
parent 6bb6ce678b
commit fa0b39a42b
22 changed files with 238 additions and 67 deletions
+13 -10
View File
@@ -46,18 +46,21 @@ func createNewRelease(t *testing.T, session *TestSession, repoURL, tag, title st
assert.NotEmpty(t, test.ParseJSONRedirect(resp.Body.Bytes()))
}
func checkLatestReleaseAndCount(t *testing.T, session *TestSession, repoURL, version, label string, count int) {
// returns the first listed title, which is not necessarily the one just created because releases are ordered by commit date
func checkLatestReleaseAndCount(t *testing.T, session *TestSession, repoURL, version, label string, count int) string {
req := NewRequest(t, "GET", repoURL+"/releases")
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
labelText := htmlDoc.doc.Find("#release-list > li .detail .label").First().Text()
assert.Equal(t, label, labelText)
titleText := htmlDoc.doc.Find("#release-list > li .detail h4 a").First().Text()
assert.Equal(t, version, titleText)
releaseList := htmlDoc.doc.Find("#release-list > li")
releaseList := NewHTMLParser(t, resp.Body).doc.Find("#release-list > li")
assert.Equal(t, count, releaseList.Length())
item := releaseList.FilterFunction(func(_ int, selection *goquery.Selection) bool {
return selection.Find(".detail h4 a").Text() == version
})
if assert.Equal(t, 1, item.Length(), "release %q is listed exactly once", version) {
assert.Equal(t, label, item.Find(".detail .label").First().Text())
}
return releaseList.Find(".detail h4 a").First().Text()
}
func TestViewReleases(t *testing.T) {
@@ -113,11 +116,11 @@ func TestCreateReleasePaging(t *testing.T) {
}
createNewRelease(t, session, "/user2/repo1", "v0.0.12", "v0.0.12", false, true)
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.12", translation.NewLocale("en-US").TrString("repo.release.draft"), 10)
assert.Equal(t, "v0.0.12", checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.12", translation.NewLocale("en-US").TrString("repo.release.draft"), 10))
// Check that user4 does not see draft and still see 10 latest releases
session2 := loginUser(t, "user4")
checkLatestReleaseAndCount(t, session2, "/user2/repo1", "v0.0.11", translation.NewLocale("en-US").TrString("repo.release.stable"), 10)
assert.Equal(t, "v0.0.11", checkLatestReleaseAndCount(t, session2, "/user2/repo1", "v0.0.11", translation.NewLocale("en-US").TrString("repo.release.stable"), 10))
}
func TestViewReleaseListNoLogin(t *testing.T) {