fix(repo): commit page fails to render unsigned commits with a different committer (#39381)

Since #39229 the commit page header dereferences
`.Verification.CommittingUser` when the committer is not the author.
`Verification` is `nil` for unsigned commits (see `repo.Diff`), so
opening such a commit — a rebased or cherry-picked one, for example —
logs a template error and the page comes out truncated:

```
Render failed: failed to render template: repo/commit_page, error: template error: builtin(bindata):repo/commit_page:138:22 : executing "repo/commit_page" at <.Verification.CommittingUser>: nil pointer evaluating interface {}.CommittingUser
```

This guards the access and adds an integration test that creates a
commit with distinct author and committer identities and checks the page
renders completely (the status stays 200 on a mid-render failure, so the
test looks at the body).

_The fix was worked out with help from an AI assistant; I reviewed and
tested it myself._

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Sean Yang
2026-09-23 14:34:19 +00:00
committed by GitHub
co-authored by wxiaoguang
parent 08149f9bec
commit 191287d8be
10 changed files with 73 additions and 17 deletions
+3 -2
View File
@@ -12,6 +12,7 @@ import (
issues_model "gitea.dev/models/issues"
"gitea.dev/models/unittest"
"gitea.dev/modules/templates"
"gitea.dev/routers/common"
"gitea.dev/services/context"
"gitea.dev/services/contexttest"
"gitea.dev/services/pull"
@@ -78,7 +79,7 @@ func TestRenderConversation(t *testing.T) {
ctx.Data["ShowOutdatedComments"] = true
renderConversation(ctx, preparedComment, "diff")
assert.Equal(t, http.StatusOK, resp.Code)
assert.NotContains(t, resp.Body.String(), `status-page-500`)
assert.NotContains(t, resp.Body.String(), common.PageInternalServerErrorMark)
})
run("timeline non-existing review", func(t *testing.T, ctx *context.Context, resp *httptest.ResponseRecorder) {
err := db.TruncateBeans(t.Context(), &issues_model.Review{})
@@ -86,6 +87,6 @@ func TestRenderConversation(t *testing.T) {
ctx.Data["ShowOutdatedComments"] = true
renderConversation(ctx, preparedComment, "timeline")
assert.Equal(t, http.StatusOK, resp.Code)
assert.NotContains(t, resp.Body.String(), `status-page-500`)
assert.NotContains(t, resp.Body.String(), common.PageInternalServerErrorMark)
})
}