Follow-up to #37987, addressing the unresolved review comments on the
org members search form.
And fix more trivial problems together (see the commit titles)
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Follow
https://docs.github.com/en/enterprise-server@3.20/rest/issues/assignees?apiVersion=2022-11-28Fix#33576
And it also fixed some possible dead-lock problem.
---------
Signed-off-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Nicolas <bircni@icloud.com>
Co-authored-by: Zettat123 <zettat123@gmail.com>
- Add GitHub-style Actions **job summaries** support
(`GITHUB_STEP_SUMMARY` / `workflow/SUMMARY.md`) and render them on the
run Summary view.
- Store uploaded summaries internally in the DB (not as downloadable
artifacts).
- Add runtime-token endpoint for runners to upload summaries:
- `PUT
/api/actions_pipeline/_apis/pipelines/workflows/{run_id}/jobs/{job_id}/summary`
- Advertise support to runners via `RunnerService.Declare` response
header:
- `X-Gitea-Actions-Capabilities: job-summary`
- Devtest: extend `/devtest/repo-action-view/...` to include mock
`jobSummaries` for previewing UI rendering.
## Compatibility
- New Gitea + old runner: no summary upload → UI shows nothing (no
behavior change)
- New runner + old Gitea: capability not advertised → runner skips
upload (no behavior change)
## Screenshot:
<img width="2017" height="729"
src="https://github.com/user-attachments/assets/31f8b945-50c4-40e1-9f40-382901a53013"
/>
Fixes#23721
PR on gitea-runner https://gitea.com/gitea/runner/pulls/917
---------
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
## Summary
- Redesign the Actions run summary header to follow GitHub Actions
layout: trigger info on the left, Status / Total duration / Artifacts
columns inline on the right
- Expose trigger user avatar, pull request link, and PR head branch info
from the run view API
- Update the workflow graph header to show the workflow filename (linked
to the run workflow file) and `on: <event>`, while keeping the
jobs/dependencies/success stats line
- Remove the redundant commit/workflow metadata row below the run title;
that information now lives in the summary bar
New:
<img width="1564" height="639"
src="https://github.com/user-attachments/assets/e6bc1623-c5fc-4e97-abc9-fde7f3c6aef9"
/>
Old:
<img width="2038" height="1038"
src="https://github.com/user-attachments/assets/0857f19a-8d3a-4da2-82fd-e9ebeb200062"
/>
Replaces https://github.com/go-gitea/gitea/pull/36721
---------
Co-authored-by: Giteabot <teabot@gitea.io>
Parse `Co-authored-by:` trailers from commit messages and surface
contributors as an avatar stack across the commit page, commits list, PR
commits tab, latest-commit row, blame, graph, and dashboard feed.
- Up to 10 visible 20px avatars, GitHub-style overlap (6px first stride,
4px between subsequent), `+N` chip for the rest.
- Label: 1 → name; 2 → `<a> and <b>`; 3+ → `<N> people` opens a Tippy
popup with all participants.
- Names and avatars link to the repo's commits-by-author search; fall
back to profile or `mailto:`.
- Trailer parsing uses `net/mail.ParseAddress`, scans only the trailing
paragraph, filters out the commit's own author/committer.
- Drops the non-standard `Co-committed-by:` emission on squash merge and
web edits.
Devtest: `/devtest/coauthor-avatars`.
Fixes#25521
----
<img width="353" height="277" alt="image"
src="https://github.com/user-attachments/assets/72092ceb-97ca-4b09-9557-0b72d3c5458e"
/>
<img width="533" height="328"
src="https://github.com/user-attachments/assets/11d0c8f8-8b3f-4f2e-9993-879f1c06bcc5"
/>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
Follow up #37478
## Changes
1. #37478 doesn't support absolute URL in `uses`. This PR provides
partial support for URL-style reusable workflow references. A reusable
workflow can now be referenced by an absolute URL, as long as it points
to the local Gitea instance:
```yaml
jobs:
call:
uses: https://your-gitea.example.com/OWNER/REPO/.gitea/workflows/ci.yaml@v1
```
2. Show an error message in the UI for invalid `uses`.
<img width="1600" alt="image"
src="https://github.com/user-attachments/assets/21b34e61-bf10-4af1-b9fd-4ee4e9fde049"
/>
3. Fix reusable caller cancellation issue. A reusable caller's status is
aggregated from its children, so cancellation should processes a
caller's descendants deepest-first.
---------
Signed-off-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: Giteabot <teabot@gitea.io>
- Fix workflow dependency graph overflow by making the graph container
scrollable (no more clipped DAGs; addresses #37493).
- Improve Actions job list readability by keeping durations
fixed-width/right-aligned so long times don’t squeeze job names.
- Make workflow graph layout more intuitive by vertically centering
shorter columns to reduce misleading “looks like it depends on”
alignments (addresses #37395).
### Screenshot
<img width="966" height="439"
src="https://github.com/user-attachments/assets/c180c5a2-4f56-4287-bcaa-f2735ba72949"
/>
<img width="949" height="559"
src="https://github.com/user-attachments/assets/a383511d-a962-4920-b792-69f556847eff"
/>
Fixes#37493Fixes#37395
---------
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
The OAuth2 sign-in callback unconditionally set IsActive=true on the
local user row whenever the IdP authenticated them, silently undoing an
administrator's "Disable Account" action and granting the user a fresh
session in the same response. Treat the local IsActive flag as an
authoritative admin override: inactive users get a session and are
routed through the existing activate / prohibit-login pages by
verifyAuthWithOptions, matching the local-credentials sign-in path.
Adds an integration regression test that disables a linked local user
and asserts the row stays IsActive=false after a full OIDC callback.
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
fixes defect where claims where only applies on login but not during
account linking making only the second login take them into account
fixes: https://github.com/go-gitea/gitea/issues/32566
## Summary
This fixes an OIDC sign-in edge case where a stale `external_login_user`
record can still point to an organization or a deleted user.
In that situation, Gitea may keep resolving the external login to the
wrong account during sign-in. For affected instances, this matches the
behavior reported in #36439 and #37812, where a user signing in with
OIDC/Entra ID could appear as an organization, or hit a 404 after that
organization was removed.
## What changed
- validate the user resolved from `external_login_user` during
OAuth2/OIDC login
- ignore stale links when the linked user no longer exists
- ignore stale links when the linked user is not an individual user
- remove the stale external login row so the sign-in flow can relink the
external account to the correct user
## Related
- Fixes#37812
- Related to #36439
---------
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>
## Summary
This PR improves reusable workflow support for Gitea Actions. The
parsing of the called workflow now happens on Gitea side, not on the
runner. When the caller becomes ready, Gitea fetches the called workflow
source, parses it, and inserts each child job into the database as a
`ActionRunJob` linked to the caller via `ParentCallJobID`. As a result,
every callee job is dispatched as its own task and its logs surface as
an independent job entry in the UI, rather than being inlined into the
caller's "Set up job" step.
This PR supports two kinds of `uses` :
- same-repo call: `uses: ./.gitea/workflows/foo.yaml`
- cross-repo call: `uses: OWNER/REPO/.gitea/workflows/foo.yaml@REF`
## **⚠️ BREAKING ⚠️**
External reusable workflows (`uses:
https://other-gitea-instance/OWNER/REPO/.gitea/workflows/test.yaml@REF`)
are no longer supported. To keep using them, clone the repositories to
the local instance.
## Main changes
### Execution model
- Each caller job carries `IsReusableCaller=true` and won't be fetched
by runners.
- `ParentCallJobID` can link a called job to its caller.
- Caller status is derived from its direct children.
### Workflow syntax
- `jobparser` now supports parsing `on: workflow_call` trigger with
`inputs:`, `outputs:`, and `secrets:` declarations.
- **Max nesting depth**: capped at `MaxReusableCallLevels = 9`, which
means a top-level caller may have at most 9 nested callers below it.
- **Cycle prevention**: at expansion time, `checkCallerChain` walks the
caller's ancestor chain via `ParentCallJobID` and rejects if the same
`uses:` string appears anywhere upstream (`reusable workflow call cycle
detected`). This catches both direct (`A -> A`) and indirect (`A -> B ->
A`) cycles.
### Cross-repo access
- To share reusable workflows from private repos, use `Collaborative
Owners` introduced by #32562
### Rerun semantics
- `expandRerunJobIDs` partitions the latest attempt's jobs into:
- a **rerun set**: jobs being rerun + downstream siblings within the
same scope.
- an **ancestor set**: reusable callers whose only *some* descendants
are being rerun (the caller itself is not).
- Cloning behavior for callers in `execRerunPlan`:
- **Caller is fully rerun** (caller's `AttemptJobID` in `rerunSet`):
none of its descendants are cloned. The caller is cloned with
`IsCallerExpanded=false`, and re-expansion (which reinserts the children
fresh) happens later when the resolver brings the caller to `Waiting`
again.
- **Caller is in ancestor set** (only some descendants rerun): the
caller is pass-through (`Status` will be updated by its fresh children).
Its non-rerun descendants are also pass-through clones (point
`SourceTaskID` at the original task). Their `ParentCallJobID` is
remapped to the new attempt's caller row.
### UI
- Job list in `RepoActionView.vue` is now tree-shaped: callers indent
their children. Callers default to collapsed.
- New caller detail page using `WorkflowGraph` to show direct children
only; the run summary's `WorkflowGraph` shows top-level callers and
their immediate descendants.
### Known trade-offs
- **Caller expansion runs inside the enclosing write transaction.**
`expandReusableWorkflowCaller` performs a git read of the called
workflow while holding the row locks that update the caller and insert
its children. This is intentional: the caller-row update and child-row
inserts must commit atomically. None of the call sites is hot (each
caller is expanded once per attempt), so the trade-off is acceptable.
- **A malformed `if:` expression on a job leaves it `Blocked`
silently.** `evaluateJobIf` now runs server-side as part of resolver
passes; deterministic expression errors (typos, undefined context
fields) are logged but do not surface in the UI. This is the same
behavior the resolver already had for concurrency-expression errors.
Distinguishing transient DB errors from user-authored expression errors
and writing the latter back as `StatusFailure` is a follow-up.
#### Screenshots
<img width="1600" alt="image"
src="https://github.com/user-attachments/assets/bfaa9b7a-07e9-4127-8de9-a81f86e82828"
/>
<img width="1600" alt="image"
src="https://github.com/user-attachments/assets/8af109b3-ef28-4b53-aaad-d4632b923224"
/>
## References
-
https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows
-
https://docs.github.com/en/actions/reference/workflows-and-actions/reusing-workflow-configurations
---
Replace #36388
---------
Signed-off-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Adds bulk actions on the site-admin runner list
(`/-/admin/actions/runners`). Site admins can now select multiple
runners and **Delete**, **Disable**, or **Enable** them in one go
instead of clicking through each runner's edit page.
Scope is intentionally limited to the admin page. The user, org, and
repo runner pages keep their existing per-row UX — the shared list
template gates the bulk UI behind an `AllowBulkActions` flag set only by
the admin handler.
## Screenshots
<img width="1582" height="353"
src="https://github.com/user-attachments/assets/2125661f-aac0-4168-990a-97995a26abd2"
/>
---------
Signed-off-by: Nicolas <bircni@icloud.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
### Description
Replaces all remaining direct `gopkg.in/yaml.v3` imports with
`go.yaml.in/yaml/v4` across models, modules, routers, services, and
integration tests. `gopkg.in/yaml.v3` moves from a direct to an indirect
dependency in `go.mod`.
#### API compatibility
The yaml.Node type, node.Kind/node.Content traversal style
(modules/markup/markdown/convertyaml.go), and the
UnmarshalYAML(*yaml.Node) interface signature
(modules/optional/serialization.go) are all preserved in v4 — no
call-site changes were required beyond the import path.
**Related:**
- https://github.com/go-gitea/gitea/pull/36564#issuecomment-4526536805
---------
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>
## Summary
- Add a Branch filter dropdown to the repo Actions run list web UI
- Wire `?branch=` query param through the web handler, matching the
existing REST API filter behavior
- Source the Branch dropdown from the indexed `branch` table (filtering
out deleted branches) instead of scanning `action_run.ref`, addressing
review feedback about unindexed columns
The Event filter was dropped after review: a static list of supported
events was noisy as UX, and querying distinct values from
`action_run.trigger_event` is slow because the column is not indexed.
`FindRunOptions.TriggerEvent` is kept for the REST API.
Closes#25042
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Fixes#36983
## Summary
1. Add transitional `Cancelling` status (between `Running` and
`Cancelled`); cancel flow marks active tasks `Cancelling`, runner
finalizes to `Cancelled` on terminal result.
2. Taskless jobs cancel directly (no runner to finalize).
3. Runner-protocol responses map `Cancelling` → `RESULT_CANCELLED`.
4. Run/job aggregation treats `Cancelling` as active.
5. Status mapping/aggregation tests + en-US locale added.
**Problem**
When a workflow was cancelled from the UI, jobs were marked cancelled
immediately, which could skip post-run cleanup behavior.
## Solution
Use a transitional status path:
Running → Cancelling → Cancelled
This allows runner finalization and cleanup path execution before final
terminal state.
**Testing**
> 1. go test -tags "sqlite sqlite_unlock_notify" ./models/actions -run
"TestAggregateJobStatus|TestStatusAsResult|TestStatusFromResult"
> 2. go run
github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.4 run
./models/actions/... ./routers/api/actions/runner/...
## Related
- act_runner: https://gitea.com/gitea/act_runner/pulls/825 —
independent; this PR's capability gate keeps legacy runners on the
immediate-cancel path. The new flow activates only for runners that
advertise the `cancelling` capability.
Co-authored-by: Nicolas <bircni@icloud.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>