Based on my recent experience of both using AI tools and reviewing
AI-generated pull requests. Partially based on
https://typescript-eslint.io/contributing/ai-policy/.
---------
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
- Replace the e2e tests initialization with a simple bash script,
removing the previous Go harness.
- `make test-e2e` is the single entry point. It always starts a fully
isolated ephemeral Gitea instance with its own temp directory, SQLite
database, and config — no interference with the developer's running
instance.
- A separate `gitea-e2e` binary is built via `EXECUTABLE_E2E` using
`TEST_TAGS` (auto-includes sqlite with `CGO_ENABLED=1`), keeping the
developer's regular `gitea` binary untouched.
- No more split into database-specific e2e tests. Test timeouts are
strict, can be relaxed later if needed.
- Simplified and streamlined the playwright config and test files.
- Remove all output generation of playwright and all references to
visual testing.
- Tests run on Chrome locally, Chrome + Firefox on CI.
- Simplified CI workflow — visible separate steps for frontend, backend,
and test execution.
- All exported env vars use `GITEA_TEST_E2E_*` prefix.
- Use `GITEA_TEST_E2E_FLAGS` to pass flags to playwright, e.g.
`GITEA_TEST_E2E_FLAGS="--ui" make test-e2e` for UI mode or
`GITEA_TEST_E2E_FLAGS="--headed" make test-e2e` for headed mode.
- Use `GITEA_TEST_E2E_DEBUG=1 make test-e2e` to show Gitea server
output.
---------
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This is the result of a full-repo review to look for `style` attributes
that can be replaced with tailwind or other methods. I will manually
validate later.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Workflows triggered by pull_request_review events (approved, rejected,
comment) complete successfully but never create a commit status on the
PR. This makes them invisible in the merge checks UI, breaking any CI
gate that re-evaluates on review submission.
The commit status handler's switch statement was missing the three
review event types, so they fell through to the default case which
returned empty strings. Additionally, review events use
PullRequestPayload but IsPullRequest() returns false for them (Event()
returns "pull_request_approved" etc. instead of "pull_request"), so
GetPullRequestEventPayload() refuses to parse their payload.
Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
Co-authored-by: silverwind <me@silverwind.io>
[`colord`](https://github.com/omgovich/colord) is significantly smaller
than [`tinycolor2`](https://github.com/bgrins/TinyColor) (~4KB vs ~29KB
minified) and ships its own TypeScript types, removing the need for
`@types/tinycolor2`.
Behaviour is exactly the same for our use cases. By using `.alpha(1)` we
force the function to always output 6-digit hex format (it would output
8-digit for non-opaque colors).
---------
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Change `security-check` not break the build which is a major
inconvenience as it breaks CI on all PRs.
https://github.com/go-gitea/gitea/security/dependabot already provides a
clean overview of outstanding security issues in dependencies and I'm
using it all the time to find and update vulnerable dependencies.
This simplifies the Makefile by removing the whole-file wrapping that
creates a tempdir introduced by
https://github.com/go-gitea/gitea/pull/11126. REPO_TEST_DIR is removed
as well.
Also clean up a lot of legacy code: unnecessary XSS test, incorrect test
env init, unused "_old_uid" hack, etc
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Fixes: https://github.com/go-gitea/gitea/issues/36612
This new setting controls which workflow directories are searched. The
default value matches the previous hardcoded behaviour.
This allows users for example to exclude `.github/workflows` from being
picked up by Actions in mirrored repositories by setting `WORKFLOW_DIRS
= .gitea/workflows`.
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite `build/generate-go-licenses.go` to use `go list -m -json all`
and read license files directly from the Go module cache instead of
relying on the buggy `google/go-licenses` tool.
This removes the need for CGO, GOOS=linux, and the intermediate temp
directory, while being like 100 times faster than before:
```
$ rm assets/go-licenses.json && time make assets/go-licenses.json
go run build/generate-go-licenses.go assets/go-licenses.json
make assets/go-licenses.json 0.21s user 0.22s system 173% cpu 0.247 total
---------
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Clean up linter configs, removing redundant rules or dead disables. One
new rule enabled, no violations. Many revive rules had same or better
rules in staticcheck or govet.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Giteabot <teabot@gitea.io>
In #32562, I incorrectly assigned mismatched `repo_id` values to the
`action_run` and `action_run_job` fixtures used in
`TestActionsCollaborativeOwner`. The changes introduced in #36173 will
cause the test to fail. This PR removes the incorrect fixtures and
switches to using mock workflows to test the relevant functionality.
Steps defined with `run:` or `uses:` without an explicit `name:` now
display with a "Run <cmd>" prefix in the Actions log UI, matching GitHub
Actions behavior.
<img width="311" height="236" alt="image"
src="https://github.com/user-attachments/assets/9fde83f5-c43a-4732-ac55-0f4e1fbc1314"
/>
---------
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Fixes: https://github.com/go-gitea/gitea/issues/36543
When running `make watch`, the backend may start before webpack finishes
building CSS theme files. Since themes were loaded once via sync.Once,
they would never reload, breaking the theme selector and showing a
persistent error on the admin page.
In dev mode, themes are now reloaded from disk on each access so they
become available as soon as webpack finishes. Production behavior is
unchanged where themes are loaded once and cached via sync.Once.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Starting with v1.26, Gitea uses a JSON configuration file format instead
of the INI format used in v1.25 and earlier versions.
Because of this fundamental format change, a clean translation backport
to the v1.25 branch (or earlier release branches) is not feasible.The
recommended approach is:
- Wait until the release/v1.26 branch is created after the official
v1.26 release.
- Then introduce a new JSON-based configuration (or
migration/compatibility layer) on top of that branch.
Fixes: https://github.com/go-gitea/gitea/issues/21045
- Move heatmap data loading from synchronous server-side rendering to
async client-side fetch via dedicated JSON endpoints
- Dashboard and user profile pages no longer block on the expensive
heatmap DB query during HTML generation
- Use compact `[[timestamp,count]]` JSON format instead of
`[{"timestamp":N,"contributions":N}]` to reduce payload size
- Public API (`/api/v1/users/{username}/heatmap`) remains unchanged
- Heatmap rendering is unchanged, still shows a spinner as before, which
will now spin a litte bit longer.
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
## Summary
- Split Dockerfile and Dockerfile.rootless into a two-stage build:
frontend assets are built on the native platform (`$BUILDPLATFORM`) then
copied to the per-architecture backend build stage
- This avoids running esbuild/webpack under QEMU emulation which causes
SIGILL (Invalid machine instruction) on arm64/riscv64
- Frontend assets (JS/CSS/fonts) are platform-independent so they only
need to be built once
- The `build-env` stage no longer needs `nodejs`/`pnpm` since it only
builds the Go backend
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
Fixes: https://github.com/go-gitea/gitea/issues/34865
1. When opening a PR from a branch with multiple commits, use the first
(oldest) commit's title as the default title instead of the branch name
2. Fix autofocus on PR title input field
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Fixes: https://github.com/go-gitea/gitea/issues/36152
Enable the `nilnil` linter while adding `//nolint` comments to existing
violations. This will ensure no new issues enter the code base while we
can fix existing issues gradually.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Fixes#36630
## Problem
`StartupProblems` warnings (from `deprecatedSetting` and other
`LogStartupProblem` calls) appear twice in the admin panel at `/-/admin`
and `/-/admin/self_check`.
`LoadCommonSettings()` is called twice during web server startup:
1. Early init via `cmd/main.go` → `InitWorkPathAndCommonConfig` →
`LoadCommonSettings()`
2. Web server startup via `cmd/web.go` → `serveInstalled` →
`LoadCommonSettings()`
The second call re-initializes the config provider first
(`InitCfgProvider`), but `StartupProblems` and `configuredPaths` are
never cleared between loads, so every warning gets appended twice.
## Fix
Clear `StartupProblems` and `configuredPaths` at the start of
`LoadCommonSettings()` so only the final load's warnings are retained.
This approach was chosen over clearing in `InitCfgProvider` because:
- Warnings are produced during settings load, not provider init
- Some callers set `CfgProvider` directly without calling
`InitCfgProvider`
- It avoids coupling correctness to a specific call ordering
## Screenshots
**Result** (single warning as expected):
<img width="1429" height="195" alt="Screenshot From 2026-02-16 01-27-01"
src="https://github.com/user-attachments/assets/d45313a2-f981-480b-9ffc-cbced7e40bb8"
/>
## testing
[x] Added `TestLoadCommonSettingsClearsStartupProblems` — verifies no
duplicate messages after consecutive loads
[x] Added `TestLoadCommonSettingsClearsConfiguredPaths` — verifies path
overlap map is identical after consecutive loads
[x] All existing `modules/setting` tests pass
[x] Manually verified in admin panel with deprecated `[oauth2].ENABLE`
setting
---------
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Fixes: go-gitea/gitea#36637. `linguist-detectable` must be able to
override the config classification.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Fixes https://github.com/go-gitea/gitea/issues/24253
When a tasklist checkbox is clicked, the tasklist code [updates
`.raw-content` with latest server
data](7a8fe9eb37/web_src/js/markup/tasklist.ts (L73))
in the DOM after POSTing.
Then when "Edit" is clicked the ComboMarkdownEditor is shown with a
stale value from the previous edit session.
The fix makes it always read from `.raw-content`, no server
syncronization necessary because the value in `.raw-content` is the
latest from the server.
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
The default configuration of `failure-only` added in
https://github.com/go-gitea/gitea/pull/34982 included sending mails for
cancelled runs which is not what one would expect from a option named
like that because a cancelled run is not a failure.
This change makes it omit mails for cancelled runs:
| Run Status | `failure-only` before | `failure-only` after |
|------------|-----------------------|----------------------|
| Success | no | no |
| Failure | mail | mail |
| Cancelled | mail | no |
The first commit in this PR is the fix, and there are a few more
refactor commits afterwards.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
It appears that an older version of the Unlicensed was used (at the
least, `http` url was referenced therein over `https` which is used in
the original)
Original formatting also has been preserved.
Signed-off-by: Beda Schmid <beda@tukutoi.com>
Persist the two boolean settings in the actions log into `localStorage`
so that they are remembered across page reloads.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This implements id based hidden emails in format of
`user+id@NoReplyAddress`
resolves: https://github.com/go-gitea/gitea/issues/33471
---
The change is not breaking however it is recommended for users to move
to this newer type of no reply address
---------
Co-authored-by: Lauris B <lauris@nix.lv>
Improve BuildCaseInsensitiveLike with lowercase, users are more likely
to input lowercase letters, so lowercase letters are used.
---------
Signed-off-by: Tyrone Yeh <siryeh@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
## Problem
`GET /api/v1/repos/{owner}/{repo}/actions/runs/{runId}/jobs` was always
returning `steps: null` for each job.
## Cause
In `convert.ToActionWorkflowJob`, when the job had a `TaskID` we loaded
the task with `db.GetByID` but never loaded `task.Steps`.
`ActionTask.Steps` is not stored in the task row (`xorm:"-"`); it comes
from `action_task_step` and is only filled by `task.LoadAttributes()` /
`GetTaskStepsByTaskID()`. So the conversion loop over `task.Steps`
always saw nil and produced no steps in the API response.
## Solution
After resolving the task (by ID when the caller passes `nil`), we now
load its steps with `GetTaskStepsByTaskID(ctx, task.ID)` and set
`task.Steps` before building the API steps slice. No other behavior is
changed.
## Testing
- New integration test `TestAPIListWorkflowRunJobsReturnsSteps`: calls
the runs/{runId}/jobs endpoint, inserts a task step for a fixture job,
and asserts that the response includes non-null, non-empty `steps` with
the expected step data.
- `make test-sqlite#TestAPIListWorkflowRunJobsReturnsSteps` passes with
this fix.
---------
Co-authored-by: Manav <mdave0905@gmail.com>
1. fix a performance regression when using line-by-line highlighting
* the root cause is that chroma's `lexers.Get` is slow and a lexer cache
is missing during recent changes
2. clarify the chroma lexer detection behavior
* now we fully manage our logic to detect lexer, and handle overriding
problems, everything is fully under control
3. clarify "code analyze" behavior, now only 2 usages:
* only use file name and language to detect lexer (very fast), mainly
for "diff" page which contains a lot of files
* if no lexer is detected by file name and language, use code content to
detect again (slow), mainly for "view file" or "blame" page, which can
get best result
4. fix git diff bug, it caused "broken pipe" error for large diff files
Fix#36448
Removed unnecessary parameters from the LFS GC process and switched to
an ORDER BY id ASC strategy with a last-ID cursor to avoid missing or
duplicating meta object IDs.
---------
Signed-off-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This pull request adds milestone filtering support to both repository
and organization project boards. Users can now filter project issues by
milestone, similar to how they filter by label or assignee. The
implementation includes backend changes to fetch and filter milestones,
as well as frontend updates to display a milestone filter dropdown in
the project board UI.
**Milestone filtering support:**
* Added support for filtering project board issues by milestone in both
repository and organization contexts, including handling for "no
milestone" and "all milestones" options. (`routers/web/repo/projects.go`
[[1]](diffhunk://#diff-5cba331a1ddf1eea017178cfefaaff9ad72a4b05797fb84bf508b0939aae2972R316-R330)
[[2]](diffhunk://#diff-5cba331a1ddf1eea017178cfefaaff9ad72a4b05797fb84bf508b0939aae2972R421-R441);
`routers/web/org/projects.go`
[[3]](diffhunk://#diff-f4279417070a8e33829c338abeb42877500377f490abb1495ae6357d50b6a765R344-R357)
[[4]](diffhunk://#diff-f4279417070a8e33829c338abeb42877500377f490abb1495ae6357d50b6a765R433-R485)
* Updated the project board template to include a milestone filter
dropdown, displaying open and closed milestones and integrating with the
query string for filtering. (`templates/projects/view.tmpl`
[[1]](diffhunk://#diff-e2c7e14d247ce381c352263a8fa639b8341690ff85f6dbebfa166ee3306542feL8-R8)
[[2]](diffhunk://#diff-e2c7e14d247ce381c352263a8fa639b8341690ff85f6dbebfa166ee3306542feR19-R58)
Solves Issue #35224
---------
Signed-off-by: josetduarte <6619440+josetduarte@users.noreply.github.com>
Co-authored-by: joseduarte <joseduarte@aidhound.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Use emoji data from https://github.com/github/gemoji/pull/303 because
`github/gemoji` is unmaintained.
`assets/emoji.json` is now pretty-printed so that future diffs will
actually be readable. This causes no isses as the only place where it is
used is in frontend which imports it via `with {type: 'json'}` where
whitespace is irrelevant.
<img width="205" height="75" alt="image"
src="https://github.com/user-attachments/assets/96e335b8-acf6-4996-ace4-824c0870a7d3"
/>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>