rc(v05.06.00): security backports, actions deadlock fix, dep bumps #228

Merged
jmiller merged 17 commits from rc/05.06.00 into main 2026-05-26 22:37:12 +00:00
Owner

RC v05.06.00

Security Fixes

  • fix(git): Fix smart http request scope bug -- token scopes now enforced on git smart HTTP requests
  • Fix basic auth bug -- OAuth token scope properly set during basic auth
  • fix(auth): set User-Agent on avatar fetch + sync avatar on link-account register -- auth hardening
  • chore(deps): bump go-git/go-git/v5 to 5.19.0 -- security fix in go-git dependency

Bug Fixes

  • fix(actions): retry workflow insertion on database deadlock -- fixes #220, PR events silently dropped due to InnoDB deadlock in InsertRun/UpdateRepoRunsNumbers
  • fix(actions): wrong assumption that run id always >= job id -- prevents action run ordering bugs
  • fix: make clone URL respect public URL detection setting -- URL correctness

CI/CD

  • Updated auto-release, pre-release, auto-bump workflows from moko-platform
  • Added update-server.yml universal workflow

Testing

  • Dev deployed and verified at git.dev.mokoconsulting.tech
  • API-created PR triggers both workflow runs (2/2 -- deadlock fix confirmed)
  • Health check passes (DB + cache)
  • go build + go vet clean
  • IsErrDeadlock unit tests pass (6/6)

Closes #220
Ref #225

## RC v05.06.00 ### Security Fixes - **fix(git): Fix smart http request scope bug** -- token scopes now enforced on git smart HTTP requests - **Fix basic auth bug** -- OAuth token scope properly set during basic auth - **fix(auth): set User-Agent on avatar fetch + sync avatar on link-account register** -- auth hardening - **chore(deps): bump go-git/go-git/v5 to 5.19.0** -- security fix in go-git dependency ### Bug Fixes - **fix(actions): retry workflow insertion on database deadlock** -- fixes #220, PR events silently dropped due to InnoDB deadlock in InsertRun/UpdateRepoRunsNumbers - **fix(actions): wrong assumption that run id always >= job id** -- prevents action run ordering bugs - **fix: make clone URL respect public URL detection setting** -- URL correctness ### CI/CD - Updated auto-release, pre-release, auto-bump workflows from moko-platform - Added update-server.yml universal workflow ## Testing - [x] Dev deployed and verified at git.dev.mokoconsulting.tech - [x] API-created PR triggers both workflow runs (2/2 -- deadlock fix confirmed) - [x] Health check passes (DB + cache) - [x] go build + go vet clean - [x] IsErrDeadlock unit tests pass (6/6) Closes #220 Ref #225
jmiller added 16 commits 2026-05-26 22:31:43 +00:00
fix(actions): retry workflow insertion on database deadlock
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Failing after 21s
dd6fc4b69c
When multiple workflows are triggered by a single event (e.g. a
pull_request with several matching workflow files), each InsertRun
transaction acquires an X-lock on the repository row via
UpdateRepoRunsNumbers and an index lock on action_run. Two concurrent
transactions can deadlock when each holds one lock and waits for the
other. InnoDB kills the lighter transaction, but handleWorkflows only
logged the error and silently dropped the workflow run — making it
appear as though pull_request events were never fired.

This was the root cause of API-created PRs appearing to not trigger
Actions workflows: the notification pipeline was correct, but the DB
insert was lost to an unretried deadlock.

The fix wraps PrepareRunAndInsert in a retry loop (up to 3 attempts
with exponential backoff) that detects deadlock errors across MySQL,
PostgreSQL, and SQLite. On deadlock, the rolled-back run fields are
reset before the next attempt.

Also adds db.IsErrDeadlock() for cross-engine deadlock detection and
unit tests for the same.

Closes #220

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backport #37737

Fix #37734

Follow up #37008

The `jobNum >= runNum` check is useless. Removed it to support `job_id <
run_id`
Backport #37588 by @pandareen

## Summary

Fixes
[go-gitea/gitea#37564](https://github.com/go-gitea/gitea/issues/37564):
when an OIDC provider returns a `picture` claim, Gitea is supposed to
download that image as the user's avatar (if `[oauth2_client]
UPDATE_AVATAR = true`). Two latent bugs prevented this from working
consistently:

1. **Default Go User-Agent rejected by some image hosts.**
`oauth2UpdateAvatarIfNeed` used `http.Get`, which sends `User-Agent:
Go-http-client/1.1`. Hosts like `upload.wikimedia.org` reject that UA
with `403`, and every error path silently returned, so the user was left
with an identicon and **no log line** to diagnose the issue.
2. **Link-account *register* path skipped avatar sync.** First-time OIDC
sign-ins where auto-registration is disabled (or required a
username/password retype) go through `LinkAccountPostRegister`, which
created the user but never called `oauth2SignInSync`. So the avatar /
full name / SSH keys from the IdP were dropped on the floor for those
users, even though the existing-account-link path (`oauth2LinkAccount`)
and the auto-register path (`handleOAuth2SignIn`) both already did the
sync.

## Changes

- `routers/web/auth/oauth.go` — `oauth2UpdateAvatarIfNeed` now uses
`http.NewRequest` + `http.DefaultClient.Do`, sets `User-Agent: Gitea
<version>`, and logs every failure path at `Warn` (invalid URL, fetch
error, non-200, body read error, oversize body, upload error). No silent
failures.
- `routers/web/auth/linkaccount.go` — `LinkAccountPostRegister` now
calls `oauth2SignInSync` after a successful user creation, mirroring the
auto-register and link-existing-account flows.
- `tests/integration/oauth_avatar_test.go` — new
`TestOAuth2AvatarFromPicture` integration test with five sub-cases:
- `AutoRegister_FetchesAvatarFromPictureWithGiteaUA` — happy path,
asserts `use_custom_avatar=true`, an avatar hash is set, exactly one
HTTP request was made, and the request carried a `Gitea ` UA. The mock
server enforces the UA prefix to mirror real-world hosts that reject
Go's default UA.
- `AutoRegister_NonOK_DoesNotUpdateAvatar` — server returns 403; user's
avatar must remain unset.
- `AutoRegister_EmptyPicture_NoFetch` — empty `picture` claim must not
trigger any HTTP request.
- `AutoRegister_UpdateAvatarFalse_NoFetch` — `UPDATE_AVATAR=false` must
not trigger any HTTP request.
- `LinkAccountRegister_FetchesAvatarFromPicture` — guards the
`linkaccount.go` fix; without the new `oauth2SignInSync` call this
assertion fails.

## Test plan

- [x] `go test -tags 'sqlite sqlite_unlock_notify' -run
'^TestOAuth2AvatarFromPicture$' ./tests/integration/ -v` — 5/5 sub-tests
pass.
- [x] Manual: log in as a Keycloak user with `picture` claim pointing at
`https://avatars.githubusercontent.com/u/9919?v=4` — Gitea avatar is
replaced with the GitHub picture.
- [x] Manual: same flow with `https://upload.wikimedia.org/...` —
request now succeeds (or returns a clearly logged `Warn` line if
rate-limited with `429`); previously it silently 403'd.
- [x] Manual: `UPDATE_AVATAR=false` — user keeps the identicon, no
outbound request in container logs.
- [ ] Reviewer: please double-check that no other call sites of
`oauth2UpdateAvatarIfNeed` rely on the old `http.Get` behaviour.

## Related

- Upstream issue: go-gitea/gitea#37564
--------------------------------------------


AI Editor was used in this PR

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: pandareen <7270563+pandareen@users.noreply.github.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
Backport #37615 by @wxiaoguang

Fix #37614

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Backport for #37486
Backport #37583 by @lunny

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: silverwind <me@silverwind.io>
chore(deps): bump go-git/go-git/v5 to 5.19.0 (security)
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Failing after 20s
775766bc64
Addresses security fixes in the go-git library. Upstream backport of
go-gitea/gitea#37608.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(actions): retry workflow insertion on database deadlock (#221)
fix(security): backport upstream v1.26.2 security fixes (#226)
jmiller added 1 commit 2026-05-26 22:36:31 +00:00
Merge remote-tracking branch 'origin/main' into rc/05.06.00
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 22s
Universal: Build & Release / Promote Pre-Release to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 1m0s
c3eb57f124
# Conflicts:
#	.mokogitea/workflows/update-server.yml
jmiller merged commit 4c4d2ac956 into main 2026-05-26 22:37:12 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: MokoConsulting/MokoGitea#228