Replace broken JavaScript onclick toggle with native HTML
<details>/<summary> element. Works without JS, accessible,
and styled as a Fomantic UI button.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Delete button only visible to site admins (super admins)
- Delete handler checks ctx.IsUserSiteAdmin() and returns 404 otherwise
- Repo admins can still create, edit, revoke — but not delete
- IsSiteAdmin set in both repo and org context data
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add edit and delete actions for license packages:
- Edit button (pencil icon) opens edit form with all package fields
- Delete button (trash icon) with confirmation dialog
- Edit form includes active/inactive toggle
- Routes: GET/POST /licenses/packages/{id}/edit, POST /licenses/packages/{id}/delete
Ref #239
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use .Repository.HTMLURL instead of AppSubUrl+RepoLink so the
copyable update feed URLs include the full domain name.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Major licensing UI improvements:
- Org-level Licenses tab in org menu (visible to org members)
- Org-level Licenses page with full CRUD (packages, keys, revoke)
- Auto-created master key: when admin first visits Licenses page,
a Master (Internal) package + key is auto-generated
- Master keys marked with orange "Master" badge in key list
- Revoking a master key auto-creates a new one on next visit
- Fixed "New Package" button toggle (was using tw-hidden class
that didn't work, now uses style.display)
- IsRepoAdmin set as context data for template access
- Master keys have IsInternal=true, lifetime, all channels
Ref #239
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When an admin first visits the Licenses page, a master license package
and key are automatically created:
- Master package: lifetime, unlimited, all channels, all repos
- Master key: IsInternal=true, never expires
- Raw key shown once with copy instructions
- If master key is revoked, a new one is created on next visit
The master key is always present — revoking it and revisiting the page
generates a fresh one.
Ref #239
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The template couldn't call .Permission.IsAdmin() directly. Set
IsRepoAdmin as a context data variable so the template can use it.
Licenses tab now shows for repo admins even without packages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Licenses tab was hidden when no packages existed, making it
impossible for admins to find the page to create their first package.
Now shows for repo admins always, and for everyone when packages exist.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add full license management web forms to the Licenses page:
- "New Package" form: name, description, duration, max sites, channels
- "Generate Key" button per package: creates key with auto-expiry
- "Revoke" button per key: deactivates the key
- New key display: shows raw key once with copy instructions
- Update Feed URLs section: copyable Joomla/Dolibarr endpoint URLs
- Admin-only controls: forms only visible to repo admins
Ref #239
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The licenses page was using reqSignIn which blocks API token access
and redirects to login. Use optSignIn so the page is accessible.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix template error: function "DateTime" not defined. Use
DateUtils.TimeSince which is the correct template function.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a Licenses tab in the repo header that shows when license packages
exist for the repo's owner. The tab displays:
- License packages with name, duration, allowed channels, key count
- Issued keys with prefix, licensee, expiry, and status
Also includes:
- Org-level default update streams with per-repo override (#265)
- Full Joomla channel names in update feeds
- Update Feed button on releases page
- DB migration v336 for update_stream_config table
The Licenses tab appears after Packages in the repo header, gated by
whether any license packages exist for the owner.
Ref #239, #265
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use the full Joomla convention for update stream tag names:
- dev → development
- rc → release-candidate
- alpha, beta, stable unchanged
Add NormalizeChannel() helper that maps shorthand names (dev, rc)
to full names so license key allowed_channels work with either
format. Applied in XML generation, JSON generation, and key
validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add an "Update Feed" button next to the RSS link on the releases page
that links to the repo's updates.xml endpoint. Only shown on the
releases view (not tags).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Same bug as keys — packages were created with is_active=false
causing all key validation to reject even valid keys.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Keys were created with is_active=false (DB default) because the API
handler didn't explicitly set IsActive. This caused all key validation
to fail.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Clarify that update feeds (updates.xml, dolibarr.json) are always
accessible regardless of the releases visibility setting. The
visibility dropdown controls whether the releases page is browsable
by anonymous visitors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add the same inline visibility control (Private / Public) to the
issues section on the repo settings page. Now wiki, releases, and
issues all have visibility dropdowns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add per-unit visibility dropdown (Private / Public) directly on the
repo settings page next to each unit's enable checkbox. This replaces
the need to navigate to a separate Public Access settings page.
Supported units: Code, Wiki, Issues, Releases. Each gets a dropdown
that controls AnonymousAccessMode — when set to Public, the unit is
readable by anonymous visitors even on private repos.
Closes#238
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix two compilation errors in license key API routes:
- reqRepoAdmin() does not exist, use reqAdmin() instead
- m.Delete(handler) needs route pattern: m.Delete("", handler)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix reqRepoAdmin() -> reqAdmin() and m.Delete(handler) -> m.Delete("", handler)
to match the Gitea API route registration patterns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace ctx.Bind/ctx.APIErrorValidation (which don't exist on
APIContext) with web.GetForm() pattern used by all other API handlers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add REST API for managing license packages and keys:
- GET/POST /api/v1/repos/{owner}/{repo}/license-packages
- GET/POST /api/v1/repos/{owner}/{repo}/license-keys
- DELETE /api/v1/repos/{owner}/{repo}/license-keys/{id}
- GET /api/v1/repos/{owner}/{repo}/license-keys/{id}/usage
API structs for create/edit/response, with raw key only returned on
creation. Requires repo admin permissions.
Ref #239
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The WithFileConfig for LandingPage tried to parse the app.ini
LANDING_PAGE string value (e.g. "home") as JSON into a struct,
causing a startup hang. The landing page setting should only be
managed through the dynamic config system (admin UI).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add license key data model and Dolibarr update feed endpoint:
License key system:
- license_package table: subscription tiers with duration, max sites,
repo scope (org-wide or specific repos), and allowed update channels
- license_key table: individual keys with SHA-256 hashed storage,
domain restriction, custom start/end dates, internal/master key flag
- license_key_usage table: tracks update check activity per key
- DB migration v335 creates all three tables
Update server enhancements:
- Dolibarr JSON endpoint at /{owner}/{repo}/updates/dolibarr.json
- License key validation on update endpoints via ?key=MOKO-XXXX param
- Channel filtering: packages restrict which update streams keys access
- Invalid keys get empty XML response (Joomla-compatible "no updates")
- Usage tracking records domain, IP, user agent, version on each check
Key design decisions:
- Org-level master keys: IsInternal=true, package RepoScope="all"
- Keys stored as SHA-256 hashes, raw key only shown at creation
- Packages define allowed channels (e.g. ["stable","rc"] for Pro tier)
- MOKO-XXXX-XXXX-XXXX-XXXX format for license keys
Ref #239
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add GET /{owner}/{repo}/updates.xml that dynamically generates a
Joomla-compatible updates.xml from the repository's releases.
Features:
- Automatically maps release tags to channels (stable/rc/beta/alpha/dev)
- Finds .zip attachments for download URLs, falls back to archive URL
- Emits one entry per channel (latest release wins)
- Extracts version from tag names, strips common prefixes
- Publicly accessible (no auth required) for Joomla update clients
This is Phase 1 of #239 — the core dynamic update feed generation.
Future phases will add license key gating, Dolibarr support, and
repo settings UI.
Ref #239
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix three gaps that prevented per-unit public access from working on
private repositories:
1. Git HTTP handler (githttp.go): allow anonymous git pull for private
repos when the target unit (code or wiki) has AnonymousAccessMode
set to read. Previously only checked repo.IsPrivate.
2. Permission engine (repo_permission.go): call
finalProcessRepoUnitPermission for anonymous users on private repos
so that unit-level anonymous access modes are populated. Previously
returned early with AccessModeNone, skipping anonymous mode setup.
3. Search/explore (repo_list.go): include private repos that have at
least one unit with anonymous_access_mode > 0 in search results,
so anonymous users can discover repos with public sections.
The existing settings UI at /settings/public_access already allows
configuring per-unit visibility. The home page redirect to the first
readable unit (e.g. wiki) also already works via checkHomeCodeViewable.
Closes#238
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a dynamic config option to set the default landing page for
unauthenticated visitors from Site Administration > Settings. Options:
- Home (default explore page)
- Explore (repository explore)
- Organizations (org explore)
- Login (redirect to login)
- Custom path (any internal URL like /MokoConsulting)
The setting takes effect immediately without restart, using the same
dynamic config system as maintenance mode and web banner. Falls back
to the static LANDING_PAGE setting from app.ini if not configured.
Closes#240
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add push trigger on main branch to deploy-mokogitea.yml so merges
to main automatically deploy to production. When triggered by push,
the version is derived from git describe and environment defaults to
production. Manual workflow_dispatch still works for explicit version
deployments and dev environment targeting.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rebrand the built-in actions bot user from upstream Gitea naming to
MokoGitea branding:
- Name: gitea-actions → mokogitea-actions
- FullName: Gitea Actions → MokoGitea Actions
- Email: teabot@gitea.io → mokogitea-actions[bot]@mokoconsulting.tech
Add backward-compatible name recognition so all three bot name variants
(mokogitea-actions, gitea-actions, github-actions) with optional [bot]
suffix resolve to the same system user.
Add WhitelistActionsUser, MergeWhitelistActionsUser, and
ForcePushAllowlistActionsUser toggles to branch protection rules,
allowing CI/CD workflows to push to protected branches when explicitly
enabled. Previously the actions bot (virtual user ID -2) could never be
added to whitelist because updateUserWhitelist() only validates real
database users.
Closes#233
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Step 12 to auto-release pipeline that recreates the version branch
from main after each stable release. Also mirrors the version branch
to GitHub alongside main.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add runtime ${APP_NAME} placeholder substitution in locale strings so
all user-facing text reflects the configured APP_NAME from app.ini.
Replace 52 hardcoded locale strings, template literals, HTTP auth
realm headers, and Swagger API titles/descriptions with the
configurable value.
Closes#1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
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>
Allow C++, .NET, version numbers (2.0.1) in wiki filenames.
Clean up isolated plus signs that appear between hyphens.
Examples:
- C++ vs C# -> C++-vs-C.md
- .NET Guide -> .NET-Guide.md
- version 2.0.1 -> version-2.0.1-release.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New wiki page titles are now sanitized before creating the git file:
- Spaces and special characters replaced with hyphens
- Consecutive hyphens collapsed to single hyphen
- Leading/trailing hyphens trimmed
Examples:
- "My Page Name" -> "My-Page-Name"
- "API & Docs (v2)" -> "API-Docs-v2"
- "100% Complete!!" -> "100-Complete"
Only affects NEW pages. Existing wiki pages with legacy filenames
(spaces, URL encoding) continue to work — the read path is unchanged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a Require2FA toggle to organization settings. When enabled,
org members without 2FA are redirected to the security settings
page with a warning flash message.
Changes:
- New Require2FA field on User model (migration v333)
- Org settings UI checkbox with shield-lock icon
- Check2FARequirement middleware on member-required org routes
- UpdateOptions extended with Require2FA field
Closes#208
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a user signs in, sends notifications with username, IP address,
user agent, and timestamp. Notifications go through:
- Email to the user's registered address
- ntfy push to the configured topic
Enabled by default, configurable via app.ini:
[login_notification]
ENABLED = true
The notification fires asynchronously (goroutine) so it doesn't
block the login redirect. Hooks into handleSignInFull which is the
single choke point for all auth methods (password, 2FA, OAuth).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Help link added to footer right-links (next to API and Licenses)
- Login logo (login-logo.png) now shown on the signin page, not just
the home page. Hidden via onerror when not uploaded.
- Landing page is set to 'login' so home.tmpl never renders — the
logo needed to be on signin_inner.tmpl instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The help link was wrapped in {{if not .IsSigned}} which hid it for
logged-in users. Removed the condition so it's always visible.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
octicon-dashboard doesn't exist in Gitea's SVG set, causing the
icon to render as raw text. octicon-meter is the equivalent gauge icon.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Changed details.toggleable-item summary from justify-content:
space-between to gap + margin-left: auto on the chevron. Added
.flex-container-nav .item rule to force left alignment on all
menu items including standalone links.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The compiled CSS bundle doesn't pick up the flexcontainer.css change.
Use inline style with !important on the menu container to override
Fomantic UI's default center alignment.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fomantic UI's vertical menu centers text by default. Added
text-align: left to .flex-container-nav menu items so all
admin sidebar entries align consistently.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each release attachment now gets its own .sha256 checksum file
(e.g. asset.zip.sha256) instead of a single checksums.sha256 manifest.
Old .sha256 files are cleaned up before regenerating.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Each branding image row now has a Reset button when custom image exists
- Reset removes the custom file, reverting to built-in default
- All admin sidebar menu items now have octicon icons
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Help URL: knowledge base / documentation link
- Support URL: ticket system / email for user support
Both saved to app.ini and applied in-memory immediately.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace built-in logo.png, favicon.png, logo-small.png with Moko
Consulting branding images
- Remove SVG overrides so PNG takes priority
- Set apple-touch-icon.png to favicon for iOS home screen
- Update site manifest to include favicon.png as 256x256 PWA icon
so installed apps show the square brand icon
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Locale changes:
- Renamed "Gitea" -> "MokoGitea" in all user-facing strings across
28 language files (928 references)
- Preserved upstream feature names: "Gitea Actions", "Gitea API",
"gitea.com", "Gitea instances"
Branding page:
- Changed from three-card layout to single-column stacked segments
- Each image type shown inline with preview, label, and upload form
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The org home page template expects .Members, .NumMembers, .Teams,
.IsOrganizationMember, .IsOrganizationOwner, and .IsPublicMember
but the handler only set OrgOverviewMembers and OrgOverviewTeams
(different key names). The sidebar rendered empty because the
template variables were undefined.
Fixed by adding all required data bindings and capturing the
membersIsPublic map (previously discarded) as a callable function.
Closes#183
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a Branding section to Site Administration where admins can upload
custom images for three separate slots:
- Nav icon (logo-small.png) — top-left corner, 30x30px
- Login logo (logo.png) — login page and homepage
- Favicon (favicon.png) — browser tab icon
Changes:
- New admin route: /-/admin/branding with upload forms
- Templates use AssetUrlPrefix instead of hardcoded external URLs
- Nav bar uses logo-small.png with fallback to logo.png
- Uploads save to custom/public/assets/img/ (persists across restarts)
- SVG overrides auto-removed when PNG is uploaded
- Added logo-small.png as default built-in asset
Closes#181
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous regex matched across channel boundaries because <version>
appears before <tags> in the XML. Fixed by matching the entire <update>
block containing the target channel tag, then replacing fields within
that block only.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
After a successful production deployment, the deploy workflow now
automatically updates updates.xml on main with the new version,
release URL, and docker image tag for the stable channel.
Dev deployments skip this step — only production releases update
the stable channel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The deploy workflow now:
1. Enables maintenance mode before building (users see maintenance page)
2. Builds, pushes, and restarts the container
3. Disables maintenance mode after health check passes (if: always)
Uses Gitea's built-in maintenance mode via admin config API.
If the instance is already down, the enable step gracefully warns
instead of failing. The disable step runs even if deploy fails
to avoid leaving the instance in maintenance mode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The API endpoint POST /releases/{id}/assets bypasses CreateRelease
and UpdateRelease, so checksums were not generated for API uploads.
Added GenerateReleaseChecksums call after successful asset upload.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a release is created or updated with attachments, automatically
compute SHA256 checksums for every file and attach a checksums.sha256
manifest file. The manifest follows the standard sha256sum format:
<hash> <filename>
Existing checksums.sha256 files are replaced when attachments change.
Checksums are generated for both CreateRelease and UpdateRelease flows.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The update checker now emails the first admin user when a new version
is found on the configured channel. Notifications are deduplicated —
only sent once per new version, not on every cron tick.
- Added NotifyFunc callback in updatechecker module
- Wired to mailer in cron task registration
- Created mail_update.go with plain-text email including version,
channel, release URL, and docker pull command
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a dropdown on the admin dashboard to switch between update streams
(stable, rc, beta, alpha, development) matching the Joomla pattern.
Changes:
- Admin dashboard shows channel selector with descriptions
- POST handler validates and applies channel change in-memory
- Triggers immediate re-check against updates.xml after switch
- updates.xml has all 5 standard channels with descriptions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Matches the Joomla update server pattern used across all Moko repos.
Removed the non-standard 'security' channel. All five standard
channels now present in updates.xml.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename the Go module path from code.gitea.io/gitea to
git.mokoconsulting.tech/MokoConsulting/MokoGitea across the entire
codebase.
Scope:
- go.mod module declaration
- 2,235 Go source files (import paths)
- Dockerfile WORKDIR and COPY paths
- Swagger API templates
- golangci.yml linter config
External dependencies (code.gitea.io/gitea-vet, code.gitea.io/sdk/gitea,
gitea.com/gitea/act, etc.) are intentionally NOT renamed — they are
separate upstream modules.
Closes#132
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Python heredoc couldn't access shell-local API variable.
Move it to step-level env so os.environ sees it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous workflow had raw XML in bash heredocs that broke the
YAML parser during workflow discovery, causing Gitea to silently
skip the entire workflow.
Fix: all XML generation and API calls now use Python heredocs
(<<'PYEOF') which don't contain characters that confuse the YAML
parser. All github context values passed via env vars instead of
inline expressions in run blocks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gitea Actions doesn't reliably evaluate the branches: filter on
pull_request events, causing the workflow to never trigger. Replaced
with a step-level guard that checks github.base_ref at runtime.
Also fixed:
- XML insertion using sed 'e' command instead of shell interpolation
- RC entry removal using Python regex for reliability
- Simplified API URL construction
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gitea Actions may not evaluate github.event.pull_request.draft
correctly, preventing the workflow from triggering entirely.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gitea Actions may not evaluate github.event.pull_request.draft
correctly, preventing the workflow from triggering entirely.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix missing https:// protocol in pr-rc-release.yml API URL
- Update comment to remove stale fan-out reference
- Add comprehensive CHANGELOG entry for v1.26.1-moko.04.00.00 release
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a PR is opened or updated against main:
- Determines RC version from updates.xml base + PR number
- Creates/updates a prerelease on Gitea tagged as v1.26.1-moko.{version}-rc.{PR#}
- Updates updates.xml with RC channel entry pointing to the PR
Admins on the RC update channel will see the PR build as an available
update, matching the Joomla update server pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace JSON API-based update checking with Joomla-style updates.xml
that supports multiple update streams (stable, dev, security).
Changes:
- Add updates.xml at repo root with stable/dev/security channels
following the same XML structure as MokoOnyx and other Joomla repos
- Rewrite updatechecker module to parse XML with channel filtering
- Add CHANNEL setting to [update_checker] config (default: stable)
- Show channel name and docker pull command in admin dashboard banner
Config example:
[update_checker]
ENABLED = true
CHANNEL = stable
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The upstream reading permission fix (#37781) refactored Repository
to have direct IsAdmin/CanWrite/CanRead methods, but our fork's
Repository struct still uses the Permission field for these.
Keep the new CheckTokenScopes function but use ctx.Repo.Permission.*
for the middleware functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update deploy workflow description to reflect new versioning scheme:
v{upstream}-moko.{major}.{minor}.{patch} (e.g. v1.26.1-moko.04.00.00)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove .mod -> AMPL mapping from conflictingExtLangMap (AMPL lexer
doesn't exist in chroma v2.23.1, causing a panic when viewing .mod
files). Upstream doesn't have this mapping either.
- Update 500 error page issue link to MokoGitea repo
- Update home page install/license links to MokoGitea repo
- Update theme settings link to MokoGitea repo
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This PR hardens artifact URL signing by encoding signature inputs in an
unambiguous binary payload before computing the HMAC.
What it changes:
- replace direct concatenation-style signing inputs with explicit
payload builders
- encode string fields with a length prefix before appending their bytes
- encode integer fields as fixed-width binary values instead of decimal
text
- apply the same hardening to both:
- Actions Artifact V4 signing in `routers/api/actions/artifactsv4.go`
- artifact download signing in `routers/api/v1/repo/action.go`
- add regression tests that verify distinct field combinations produce
distinct payloads and signatures
Why:
The previous signing logic built HMAC inputs by appending multiple
fields without a strongly structured representation. That kind of
construction can create ambiguity at field boundaries, where different
parameter combinations may serialize into the same byte stream for
signing.
This change removes that ambiguity by constructing a deterministic
payload format with explicit boundaries between fields.
Backport #37707
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
backport #37118
This PR closes remaining `public-only` token gaps in the API by making
the restriction apply consistently across repository, organization,
activity, notification, and authenticated `/api/v1/user/...` routes.
Previously, `public-only` tokens were still able to:
- receive private results from some list/search/self endpoints,
- access repository data through ID-based lookups,
- and reach several authenticated self routes that should remain
unavailable for public-only access.
This change treats `public-only` as a cross-cutting visibility boundary:
- list/search endpoints now filter private resources consistently,
- repository lookups enforce the same restriction even when addressed
indirectly,
- and self routes that inherently expose or mutate private account state
now reject `public-only` tokens.
---
Generated by a coding agent with Codex 5.2
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: Nicolas <bircni@icloud.com>
Backport #37704
This PR hardens OAuth token exchange validation by binding exchanged
credentials to the client and redirect URI that originally obtained
them.
What it changes:
- reject refresh token exchanges when the refresh token belongs to a
different OAuth application
- reject authorization code exchanges when the `redirect_uri` in the
token request differs from the `redirect_uri` stored with the
authorization code
- add integration coverage for:
- authorization code exchange with a mismatched redirect URI
- refresh token reuse across two different dynamically created OAuth
applications
Why:
OAuth authorization codes and refresh tokens must remain bound to the
client context that originally received them. Without those checks:
- a valid authorization code can be redeemed against a different
registered redirect URI of the same client
- a refresh token can be replayed by a different OAuth client
---------
Co-authored-by: Nicolas <bircni@icloud.com>
Backport #37706
This PR tightens several OAuth validation paths related to PKCE
handling, redirect URI normalization, and refresh-token replay safety.
What it changes:
- switch redirect URI comparison to ASCII-only normalization for
exact-match checks, avoiding Unicode case-folding surprises
- harden PKCE verification by:
- allowing PKCE omission only when no challenge data was stored
- rejecting exchanges with a missing verifier when PKCE was used
- rejecting malformed challenge state where a challenge exists without a
valid method
- comparing derived challenges with constant-time string matching
- make refresh-token invalidation counter updates conditional on the
previously observed counter value, so stale refresh state cannot be
accepted after the grant changes
Why:
These checks close gaps where:
- redirect URI comparisons could rely on broader Unicode normalization
than intended
- malformed or incomplete PKCE state could be treated too permissively
- concurrent or stale refresh-token use could advance the same grant
more than once
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: Nicolas <bircni@icloud.com>
Backport #37695 by @lunny
This PR fixes two permission-checking gaps in Git and LFS request
handling.
## What it changes
- keep wiki Git HTTP pushes on the normal write-permission path, even
when proc-receive support is enabled
- revalidate LFS bearer token requests against the current user state
and current repository permissions before allowing access
- add regression coverage for unauthorized wiki HTTP pushes
- add LFS tests for blocked users, revoked repository access, read-only
upload attempts, and valid write access
## Why
- wiki repositories should not inherit the relaxed refs/for handling
used for normal code repositories
- LFS authorization tokens should not remain usable after a user is
disabled or loses repository access
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Backport of #37662.
---
This PR was written with the help of Claude Opus 4.7
---------
Co-authored-by: Giteabot <teabot@gitea.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Adds a scheduled workflow that runs daily at 08:00 UTC to automatically
detect new bug fixes merged into upstream Gitea's release/v1.26 branch
and create corresponding issues in the MokoGitea tracker.
The workflow:
- Queries GitHub Search API for recently merged fix/security PRs
- Cross-references against existing MokoGitea issues to avoid duplicates
- Creates labeled issues (type: bug, upstream, priority, security)
- Supports manual dispatch with configurable lookback period
Requires secrets: GH_TOKEN (GitHub), GITEA_TOKEN (MokoGitea)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The runs_list.tmpl used old class names (flex-list, flex-item,
flex-item-leading, flex-item-main, flex-item-trailing, flex-item-title,
flex-item-body) that no longer exist in the CSS. The shared flex-list
stylesheet was refactored to use flex-divided-list, items-with-main,
item, item-leading, item-main, item-trailing, item-title, item-body.
Without matching CSS, the Actions runs list lost all flex layout — items
were not displayed as proper rows.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
InsertRun passed nil for the attempt parameter to
EvaluateRunConcurrencyFillModel, which then dereferenced the nil
pointer at concurrency.go:39 when writing ConcurrencyGroup and
ConcurrencyCancel fields. This caused a server panic whenever a PR was
created via the API on a repo with workflow-level concurrency
configured.
The fix:
- Creates an ActionRunAttempt struct in InsertRun before calling
EvaluateRunConcurrencyFillModel, and reuses it for
PrepareToStartRunWithConcurrency
- Updates EvaluateRunConcurrencyFillModel to write concurrency fields
to both the run (for DB persistence) and the attempt (for in-memory
concurrency checks), with a nil guard on the attempt
- Fixes TestEvaluateRunConcurrency_RunIDFallback which had the wrong
argument count and was not testing the attempt path
Closes#136
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes nil pointer dereference in BulkSetIssueAssignees — the issue's
Repo field must be loaded before UpdateAssignees calls CanAssignTo.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add four new API endpoints under /repos/{owner}/{repo}/issues/bulk/ for
performing batch operations across multiple issues in a single request.
Each endpoint returns a partial-failure result with per-issue success/failure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restore original modules/badge/badge.go (upstream) and adapt our
presets to use GenerateBadge() and the existing Badge type.
- Rename Generate → GenerateRepoBadge to avoid conflict
- Add FormatRepoBadgeSVG for SVG rendering
- Add RenderFlat/RenderFlatSquare methods on Badge
- Fix API handler to use new function names
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- GetLatestCommitStatus takes db.ListOptions not int
- Use GetRepoLicenses() instead of non-existent repo.License field
- Use repo.Topics instead of repo.HasWiki() (not a method)
- licenseBadge now takes ctx parameter
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add test workflow and issue template under .mokogitea/ to verify
the dot-folder feature works end-to-end on the live server.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extend the existing /metrics endpoint with 3 new application metrics:
- gitea_active_users_30d: users active in last 30 days
- gitea_actions_queue_length: pending action jobs
- gitea_actions_running_jobs: currently running jobs
No new dependencies — extends existing collector and statistic model.
Closes#42
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-19 21:44:37 -05:00
2379 changed files with 21564 additions and 19296 deletions
This document explains how to contribute changes to the Gitea project. Topic-specific guides live in separate files so the essentials are easier to find.
Thank you for your interest in contributing. All Moko Consulting repositories follow this universal workflow and version policy.
| Topic | Document |
## Branching Workflow
| :---- | :------- |
| Backend (Go modules, API v1) | [docs/guideline-backend.md](docs/guideline-backend.md) |
- [Discuss your design before the implementation](#discuss-your-design-before-the-implementation)
- [Issue locking](#issue-locking)
- [Building Gitea](#building-gitea)
- [Styleguide](#styleguide)
- [Copyright](#copyright)
- [Testing](#testing)
- [Translation](#translation)
- [Code review](#code-review)
- [Pull request format](#pull-request-format)
- [PR title and summary](#pr-title-and-summary)
- [Breaking PRs](#breaking-prs)
- [What is a breaking PR?](#what-is-a-breaking-pr)
- [How to handle breaking PRs?](#how-to-handle-breaking-prs)
- [Maintaining open PRs](#maintaining-open-prs)
- [Reviewing PRs](#reviewing-prs)
- [For PR authors](#for-pr-authors)
- [Documentation](#documentation)
- [Developer Certificate of Origin (DCO)](#developer-certificate-of-origin-dco)
</details>
## Introduction
It assumes you have followed the [installation instructions](https://docs.gitea.com/category/installation). \
Sensitive security-related issues should be reported to [security@gitea.io](mailto:security@gitea.io).
For configuring IDEs for Gitea development, see the [contributed IDE configurations](contrib/ide/).
## AI Contribution Policy
Contributions made with the assistance of AI tools are welcome, but contributors must use them responsibly and disclose that use clearly.
1. Review AI-generated code closely before marking a pull request ready for review.
2. Manually test the changes and add appropriate automated tests where feasible.
3. Only use AI to assist in contributions that you understand well enough to explain, defend, and revise yourself during review.
4. Disclose AI-assisted content clearly.
5. Do not use AI to reply to questions about your issue or pull request. The questions are for you, not an AI model.
6. AI may be used to help draft issues and pull requests, but contributors remain responsible for the accuracy, completeness, and intent of what they submit.
Maintainers reserve the right to close pull requests and issues that do not disclose AI assistance, that appear to be low-quality AI-generated content, or where the contributor cannot explain or defend the proposed changes themselves.
We welcome new contributors, but cannot sustain the effort of supporting contributors who primarily defer to AI rather than engaging substantively with the review process.
## Issues
### How to report issues
Please search the issues on the issue tracker with a variety of related keywords to ensure that your issue has not already been reported.
If your issue has not been reported yet, [open an issue](https://github.com/go-gitea/gitea/issues/new)
and answer the questions so we can understand and reproduce the problematic behavior. \
Please write clear and concise instructions so that we can reproduce the behavior — even if it seems obvious. \
The more detailed and specific you are, the faster we can fix the issue. \
It is really helpful if you can reproduce your problem on a site running on the latest commits, i.e. <https://demo.gitea.com>, as perhaps your problem has already been fixed on a current version. \
Please follow the guidelines described in [How to Report Bugs Effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html) for your report.
Please be kind—remember that Gitea comes at no cost to you, and you're getting free help.
### Types of issues
Typically, issues fall in one of the following categories:
-`bug`: Something in the frontend or backend behaves unexpectedly
-`security issue`: bug that has serious implications such as leaking another users data. Please do not file such issues on the public tracker and send a mail to security@gitea.io instead
-`feature`: Completely new functionality. You should describe this feature in enough detail that anyone who reads the issue can understand how it is supposed to be implemented
-`enhancement`: An existing feature should get an upgrade
-`refactoring`: Parts of the code base don't conform with other parts and should be changed to improve Gitea's maintainability
### Discuss your design before the implementation
We welcome submissions. \
If you want to change or add something, please let everyone know what you're working on — [file an issue](https://github.com/go-gitea/gitea/issues/new) or comment on an existing one before starting your work!
Significant changes such as new features must go through the change proposal process before they can be accepted. \
This is mainly to save yourself the trouble of implementing it, only to find out that your proposed implementation has some potential problems. \
Furthermore, this process gives everyone a chance to validate the design, helps prevent duplication of effort, and ensures that the idea fits inside
the goals for the project and tools.
Pull requests should not be the place for architecture discussions.
### Issue locking
Commenting on closed or merged issues/PRs is strongly discouraged.
Such comments will likely be overlooked as some maintainers may not view notifications on closed issues, thinking that the item is resolved.
As such, commenting on closed/merged issues/PRs may be disabled prior to the scheduled auto-locking if a discussion starts or if unrelated comments are posted.
If further discussion is needed, we encourage you to open a new issue instead and we recommend linking to the issue/PR in question for context.
## Building Gitea
See the [development setup instructions](https://docs.gitea.com/development/hacking-on-gitea).
## Styleguide
You should always run `make fmt` before committing to conform to Gitea's styleguide.
## Copyright
New code files that you contribute should use the standard copyright header:
```
```
// Copyright <current year> The Gitea Authors. All rights reserved.
feature/* ──PR──> dev ──draft PR──> (renamed to rc) ──merge──> main
// SPDX-License-Identifier: MIT
```
```
Afterwards, copyright should only be modified when the copyright author changes.
### Step by step
## Testing
1.**Create a feature branch** from `dev`:
```bash
git checkout dev && git pull
git checkout -b feature/my-change
```
Before submitting a pull request, run all tests to make sure your changes don't cause a regression elsewhere.
2. **Work and commit** on your feature branch. Push to origin.
Here's how to run the test suite:
3. **Open a PR**: `feature/my-change` → `dev`. After review and checks, merge it.
- code lint
4. **When ready for release**, open a **draft PR**: `dev` → `main`.
- This automatically renames the source branch to `rc` (release candidate)
- An RC pre-release is built and uploaded
| | |
5. **Alpha and beta branches** are created by manually renaming the branch before the RC stage:
| `rc` | Release candidate | Auto-renamed on draft PR to main |
| `main` | Stable releases | Protected, merge only |
| `version/XX.YY.ZZ` | Archived release snapshots | Auto-created by CI |
## Translation
### Protected branches
All translation work happens on [Crowdin](https://translate.gitea.com).
| Branch | Direct push | Merge via |
The only translation that is maintained in this repository is [the English translation](https://github.com/go-gitea/gitea/blob/main/options/locale/locale_en-US.json).
Once a language has reached a **satisfactory percentage** of translated keys (~25%), it will be synced back into this repo and included in the next released version.
For that, please read the [*Best Practices for Faster Reviews*](https://github.com/kubernetes/community/blob/261cb0fd089b64002c91e8eddceebf032462ccd6/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) guide. \
It has lots of useful tips for any project you may want to contribute to. \
Some of the key points:
- Make small pull requests. \
### Stability suffixes
The smaller, the faster to review and the more likely it will be merged soon.
- Don't make changes unrelated to your PR. \
Maybe there are typos on some comments, maybe refactoring would be welcome on a function... \
but if that is not related to your PR, please make *another* PR for that.
- Split big pull requests into multiple small ones. \
An incremental change will be faster to review than a huge PR.
- Allow edits by maintainers. This way, the maintainers will take care of merging the PR later on instead of you.
### PR title and summary
Each branch appends a suffix to indicate stability:
In the PR title, describe the problem you are fixing, not how you are fixing it. \
| Branch | Suffix | Example |
Use the first comment as a summary of your PR. \
|--------|--------|---------|
In the PR summary, you can describe exactly how you are fixing this problem.
| `main` | (none) | `02.09.00` |
| `dev` | `-dev` | `02.09.01-dev` |
| `feature/*` | `-dev` | `02.09.01-dev` |
| `alpha` | `-alpha` | `02.09.01-alpha` |
| `beta` | `-beta` | `02.09.01-beta` |
| `rc` | `-rc` | `02.09.01-rc` |
PR titles must follow the [Conventional Commits](https://www.conventionalcommits.org/) format, because PRs are squash-merged and the PR title becomes the resulting commit message:
### Auto version bump
```text
On every push to `dev`, `feature/*`, or `patch/*`:
type(scope)!: subject
```
The allowed types are `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, and `test`. The generic `chore` type is intentionally not accepted; pick a more descriptive type instead.
1. Patch version incremented
2. Stability suffix `-dev` applied
3. All version-bearing files updated (manifests, CHANGELOG, PHP headers, etc.)
4. Commit created with `[skip ci]` to avoid loops
Examples:
### Release version flow
```text
Version bumps happen at specific release events:
fix(web): prevent avatar upload crash on empty file
feat(api): add pagination to repo hooks list
ci(workflows): lint PR titles with commitlint
```
Keep this summary up-to-date as the PR evolves. \
| Event | Bump | Example |
If your PR changes the UI, you must add **after** screenshots in the PR summary. \
|-------|------|---------|
If you are not implementing a new feature, you should also post **before** screenshots for comparison.
| Feature merged to dev | Patch bump after dev release | `02.09.01-dev` → release → `02.09.02-dev` |
| Dev promoted to RC | Minor bump | `02.09.02-dev` → `02.10.00-rc` |
| RC merged to main | Minor bump | `02.10.00-rc` → `02.11.00` (stable) |
| Dev recreated from main | Patch bump | `02.11.00` → `02.11.01-dev` |
If you are implementing a new feature, your PR will only be merged if your screenshots are up to date.\
### Release stream copies
Furthermore, feature PRs will only be merged if their summary contains a clear usage description (understandable for users) and testing description (understandable for reviewers).
You should strive to combine both into a single description.
Another requirement for merging PRs is that the PR is labeled correctly.\
When a higher-stability release is published, copies are created for all lesser streams with the same base version:
However, this is not your job as a contributor, but the job of the person merging your PR.\
If you think that your PR was labeled incorrectly, or notice that it was merged without labels, please let us know.
If your PR closes some issues, you must note that in a way that both GitHub and Gitea understand, i.e. by appending a paragraph like
- **RC `02.10.00-rc`** also creates: `02.10.00-dev`, `02.10.00-alpha`, `02.10.00-beta`
- **Stable `02.11.00`** also creates: `02.11.00-dev`, `02.11.00-alpha`, `02.11.00-beta`, `02.11.00-rc`
```text
This ensures Joomla sites on ANY stability channel see the update (Joomla only shows versions higher than what's installed).
Fixes/Closes/Resolves #<ISSUE_NR_X>.
Fixes/Closes/Resolves #<ISSUE_NR_Y>.
```
to your summary. \
### Version files
Each issue that will be closed must stand on a separate line.
### Breaking PRs
The version tools update all files containing version stamps:
A PR is breaking if it meets one of the following criteria:
Files synced from other repos (with a `# REPO:` header) are not touched.
- It changes API output in an incompatible way for existing users
## Code Standards
- It removes a setting that an admin could previously set (i.e. via `app.ini`)
- An admin must do something manually to restore the old behavior
In particular, this means that adding new settings is not breaking.\
- **PHP**: PSR-12, tabs for indentation
Changing the default value of a setting or replacing the setting with another one is breaking, however.
- **Copyright**: all files must include the Moko Consulting copyright header
- **License**: SPDX identifier `GPL-3.0-or-later` (or as specified per repo)
- **Attribution**: use `Authored-by: Moko Consulting` in commits, not individual names
#### How to handle breaking PRs?
## Commit Messages
If your PR has a breaking change, you must add two things to the summary of your PR:
Use conventional commit format:
1. A reasoning why this breaking change is necessary
2. A `BREAKING` section explaining in simple terms (understandable for a typical user) how this PR affects users and how to mitigate these changes. This section can look for example like
```md
## :warning: BREAKING :warning:
```
Breaking PRs will not be merged as long as not both of these requirements are met.
### Maintaining open PRs
Code review starts when you open a non-draft PR or move a draft out of draft state. After that, do not rebase or squash your branch; it makes new changes harder to review.
Merge the base branch into yours only when you need to, for example because of conflicting changes elsewhere. That limits unnecessary CI runs.
Every PR is squash-merged, so merge commits on your branch do not matter for final history. The squash produces a single commit; mergers follow the [commit message format](docs/community-governance.md#commit-messages) in the governance guide.
### Reviewing PRs
Maintainers are encouraged to review pull requests in areas where they have expertise or particular interest.
#### For PR authors
- **Response**: When answering reviewer questions, use real-world cases or examples and avoid speculation.
- **Discussion**: A discussion is always welcome and should be used to clarify the changes and the intent of the PR.
- **Help**: If you need help with the PR or comments are unclear, ask for clarification.
Guidance for reviewers, the merge queue, and the squash commit message format is in [docs/community-governance.md](docs/community-governance.md).
## Documentation
If you add a new feature or change an existing aspect of Gitea, the documentation for that feature must be created or updated in another PR at [https://gitea.com/gitea/docs](https://gitea.com/gitea/docs).
**The docs directory on main repository will be removed at some time. We will have a yaml file to store configuration file's meta data. After that completed, configuration documentation should be in the main repository.**
## Developer Certificate of Origin (DCO)
We consider the act of contributing to the code by submitting a Pull Request as the "Sign off" or agreement to the certifications and terms of the [DCO](DCO) and [MIT license](LICENSE). \
No further action is required. \
You can also decide to sign off your commits by adding the following line at the end of your commit messages:
```
```
Signed-off-by: Joe Smith <joe.smith@email.com>
type(scope): short description
Optional body with context.
Authored-by: Moko Consulting
```
```
If you set the `user.name` and `user.email` Git config options, you can add the line to the end of your commits automatically with `git commit -s`.
This document describes maintainer expectations, project governance, and the detailed pull request review workflow (labels, merge queue, commit message format for mergers). For what contributors should do when opening and updating a PR, see [CONTRIBUTING.md](../CONTRIBUTING.md).
## Code review
### Milestone
A PR should only be assigned to a milestone if it will likely be merged into the given version. \
PRs without a milestone may not be merged.
### Labels
Almost all labels used inside Gitea can be classified as one of the following:
-`modifies/…`: Determines which parts of the codebase are affected. These labels will be set through the CI.
-`topic/…`: Determines the conceptual component of Gitea that is affected, i.e. issues, projects, or authentication. At best, PRs should only target one component but there might be overlap. Must be set manually.
-`type/…`: Determines the type of an issue or PR (feature, refactoring, docs, bug, …). If GitHub supported scoped labels, these labels would be exclusive, so you should set **exactly** one, not more or less (every PR should fall into one of the provided categories, and only one).
-`issue/…` / `lgtm/…`: Labels that are specific to issues or PRs respectively and that are only necessary in a given context, i.e. `issue/not-a-bug` or `lgtm/need 2`
Every PR should be labeled correctly with every label that applies.
There are also some labels that will be managed automatically.\
In particular, these are
- the amount of pending required approvals
- has all `backport`s or needs a manual backport
### Reviewing PRs
Maintainers are encouraged to review pull requests in areas where they have expertise or particular interest.
#### For reviewers
- **Verification**: Verify that the PR accurately reflects the changes, and verify that the tests and documentation are complete and aligned with the implementation.
- **Actionable feedback**: Say what should change and why, and distinguish required changes from optional suggestions.
- **Feedback**: Focus feedback on the issue itself and avoid comments about the contributor's abilities.
- **Request changes**: If you request changes (i.e., block a PR), give a clear rationale and, whenever possible, a concrete path to resolution.
- **Approval**: Only approve a PR when you are fully satisfied with its current state - "rubber-stamp" approvals need to be highlighted as such.
### Getting PRs merged
Changes to Gitea must be reviewed before they are accepted, including changes from owners and maintainers. The exception is critical bugs that prevent Gitea from compiling or starting.
We require two maintainer approvals for every PR. When that is satisfied, your PR gets the `lgtm/done` label. After that, you mainly fix merge conflicts and respond to or implement maintainer requests; maintainers drive getting the PR merged.
If a PR has `lgtm/done`, no open discussions, and no merge conflicts, any maintainer may add `reviewed/wait-merge`. That puts the PR in the merge queue. PRs are merged from the queue in the order of this list:
Gitea uses its own tool, <https://github.com/GiteaBot/gitea-backporter>, to automate parts of the review process. The backporter:
- Creates a backport PR when needed after the initial PR merges.
- Removes the PR from the merge queue after it merges.
- Keeps the oldest branch in the merge queue up to date with merges.
### Final call
If a PR has been ignored for more than 7 days with no comments or reviews, and the author or any maintainer believes it will not survive a long wait (such as a refactoring PR), they can send "final call" to the TOC by mentioning them in a comment.
After another 7 days, if there is still zero approval, this is considered a polite refusal, and the PR will be closed to avoid wasting further time. Therefore, the "final call" has a cost, and should be used cautiously.
However, if there are no objections from maintainers, the PR can be merged with only one approval from the TOC (not the author).
### Commit messages
Mergers are required to rewrite the PR title and the first comment (the summary) when necessary so the squash commit message is clear.
The final commit message should not hedge: replace phrases like `hopefully, <x> won't happen anymore` with definite wording.
#### PR Co-authors
A person counts as a PR co-author once they (co-)authored a commit that is not simply a `Merge base branch into branch` commit. Mergers must remove such false-positive co-authors when writing the squash message. Every true co-author must remain in the commit message.
#### PRs targeting `main`
The commit message of PRs targeting `main` is always
```bash
$PR_TITLE($PR_INDEX)
$REWRITTEN_PR_SUMMARY
```
#### Backport PRs
The commit message of backport PRs is always
```bash
$PR_TITLE($INITIAL_PR_INDEX)($BACKPORT_PR_INDEX)
$REWRITTEN_PR_SUMMARY
```
## Maintainers
We list [maintainers](../MAINTAINERS) so every PR gets proper review.
#### Review expectations
Every PR **must** be reviewed by at least two maintainers (or owners) before merge. **Exception:** after one week, refactoring PRs and documentation-only PRs need only one maintainer approval.
Maintainers are expected to spend time on code reviews.
#### Becoming a maintainer
A maintainer should already be a Gitea contributor with at least four merged PRs. To apply, use the [Discord](https://discord.gg/Gitea) `#develop` channel. Maintainer teams may also invite contributors.
#### Stepping down, advisors, and inactivity
If you cannot keep reviewing, apply to leave the maintainers team. You can join the [advisors team](https://github.com/orgs/go-gitea/teams/advisors); advisors who want to review again are welcome back as maintainers.
If a maintainer is inactive for more than three months and has not left the team, owners may move them to the advisors team.
#### Account security
For security, maintainers should enable 2FA and sign commits with GPG when possible:
- [Signing commits with GPG](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits)
Any account with write access (including bots and TOC members) **must** use [2FA](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication).
## Technical Oversight Committee (TOC)
At the start of 2023, the `Owners` team was dissolved. Instead, the governance charter proposed a technical oversight committee (TOC) which expands the ownership team of the Gitea project from three elected positions to six positions. Three positions are elected as it has been over the past years, and the other three consist of appointed members from the Gitea company.
https://blog.gitea.com/quarterly-23q1/
### TOC election process
Any maintainer is eligible to be part of the community TOC if they are not associated with the Gitea company.
A maintainer can either nominate themselves, or can be nominated by other maintainers to be a candidate for the TOC election.
If you are nominated by someone else, you must first accept your nomination before the vote starts to be a candidate.
The TOC is elected for one year, the TOC election happens yearly.
After the announcement of the results of the TOC election, elected members have two weeks time to confirm or refuse the seat.
If an elected member does not answer within this timeframe, they are automatically assumed to refuse the seat.
Refusals result in the person with the next highest vote getting the same choice.
As long as seats are empty in the TOC, members of the previous TOC can fill them until an elected member accepts the seat.
If an elected member that accepts the seat does not have 2FA configured yet, they will be temporarily counted as `answer pending` until they manage to configure 2FA, thus leaving their seat empty for this duration.
Each member of the community elected TOC will be granted $500 each month as compensation for their work.
Furthermore, any community release manager for a specific release or LTS will be compensated $500 for the delivery of said release.
These funds will come from community sources like the OpenCollective rather than directly from the company.
Only non-company members are eligible for this compensation, and if a member of the community TOC takes the responsibility of release manager, they would only be compensated for their TOC duties.
Gitea Ltd employees are not eligible to receive any funds from the OpenCollective unless it is reimbursement for a purchase made for the Gitea project itself.
## TOC & Working groups
With Gitea covering many projects outside of the main repository, several groups will be created to help focus on specific areas instead of requiring maintainers to be a jack-of-all-trades. Maintainers are of course more than welcome to be part of multiple groups should they wish to contribute in multiple places.
The currently proposed groups are:
- **Core Group**: maintain the primary Gitea repository
- **Integration Group**: maintain the Gitea ecosystem's related tools, including go-sdk/tea/changelog/bots etc.
- **Documentation Group**: maintain related documents and repositories
- **Translation Group**: coordinate with translators and maintain translations
- **Security Group**: managed by TOC directly, members are decided by TOC, maintains security patches/responsible for security items
## Roadmap
Each year a roadmap will be discussed with the entire Gitea maintainers team, and feedback will be solicited from various stakeholders.
TOC members need to review the roadmap every year and work together on the direction of the project.
When a vote is required for a proposal or other change, the vote of community elected TOC members count slightly more than the vote of company elected TOC members. With this approach, we both avoid ties and ensure that changes align with the mission statement and community opinion.
This document covers backend-specific contribution expectations. For general contribution workflow, see [CONTRIBUTING.md](../CONTRIBUTING.md).
For coding style and architecture, see also the [backend development guideline](https://docs.gitea.com/contributing/guidelines-backend) on the documentation site.
## Dependencies
Go dependencies are managed using [Go Modules](https://go.dev/cmd/go/#hdr-Module_maintenance). \
You can find more details in the [go mod documentation](https://go.dev/ref/mod) and the [Go Modules Wiki](https://github.com/golang/go/wiki/Modules).
Pull requests should only modify `go.mod` and `go.sum` where it is related to your change, be it a bugfix or a new feature. \
Apart from that, these files should only be modified by Pull Requests whose only purpose is to update dependencies.
The `go.mod`, `go.sum` update needs to be justified as part of the PR description,
and must be verified by the reviewers and/or merger to always reference
an existing upstream commit.
## API v1
The API is documented by [swagger](https://gitea.com/api/swagger) and is based on [the GitHub API](https://docs.github.com/en/rest).
### GitHub API compatibility
Gitea's API should use the same endpoints and fields as the GitHub API as far as possible, unless there are good reasons to deviate. \
If Gitea provides functionality that GitHub does not, a new endpoint can be created. \
If information is provided by Gitea that is not provided by the GitHub API, a new field can be used that doesn't collide with any GitHub fields. \
Updating an existing API should not remove existing fields unless there is a really good reason to do so. \
The same applies to status responses. If you notice a problem, feel free to leave a comment in the code for future refactoring to API v2 (which is currently not planned).
### Adding/Maintaining API routes
All expected results (errors, success, fail messages) must be documented ([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L319-L327)). \
All JSON input types must be defined as a struct in [modules/structs/](modules/structs/) ([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/modules/structs/issue.go#L76-L91)) \
and referenced in [routers/api/v1/swagger/options.go](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/options.go). \
They can then be used like [this example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L318). \
All JSON responses must be defined as a struct in [modules/structs/](modules/structs/) ([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/modules/structs/issue.go#L36-L68)) \
and referenced in its category in [routers/api/v1/swagger/](routers/api/v1/swagger/) ([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/issue.go#L11-L16)) \
They can be used like [this example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L277-L279).
### When to use what HTTP method
In general, HTTP methods are chosen as follows:
- **GET** endpoints return the requested object(s) and status **OK (200)**
- **DELETE** endpoints return the status **No Content (204)** and no content either
- **POST** endpoints are used to **create** new objects (e.g. a User) and return the status **Created (201)** and the created object
- **PUT** endpoints are used to **add/assign** existing Objects (e.g. a user to a team) and return the status **No Content (204)** and no content either
- **PATCH** endpoints are used to **edit/change** an existing object and return the changed object and the status **OK (200)**
### Requirements for API routes
All parameters of endpoints changing/editing an object must be optional (except the ones to identify the object, which are required).
Endpoints returning lists must
- support pagination (`page` & `limit` options in query)
- set `X-Total-Count` header via **SetTotalCountHeader** ([example](https://github.com/go-gitea/gitea/blob/7aae98cc5d4113f1e9918b7ee7dd09f67c189e3e/routers/api/v1/repo/issue.go#L444))
This document covers frontend-specific contribution expectations. For general contribution workflow, see [CONTRIBUTING.md](../CONTRIBUTING.md).
## Dependencies
For the frontend, we use [npm](https://www.npmjs.com/).
The same restrictions apply for frontend dependencies as for [backend dependencies](guideline-backend.md#dependencies), with the exceptions that the files for it are `package.json` and `package-lock.json`, and that new versions must always reference an existing version.
## Design guideline
Depending on your change, please read the
- [backend development guideline](https://docs.gitea.com/contributing/guidelines-backend)
- [frontend development guideline](https://docs.gitea.com/contributing/guidelines-frontend)
This document describes the release cycle, backports, versioning, and the release manager checklist. For everyday contribution workflow, see [CONTRIBUTING.md](../CONTRIBUTING.md).
## Backports and Frontports
### What is backported?
We backport PRs given the following circumstances:
1. Feature freeze is active, but `<version>-rc0` has not been released yet. Here, we backport as much as possible. <!-- TODO: Is that our definition with the new backport bot? -->
2.`rc0` has been released. Here, we only backport bug- and security-fixes, and small enhancements. Large PRs such as refactors are not backported anymore. <!-- TODO: Is that our definition with the new backport bot? -->
3. We never backport new features.
4. We never backport breaking changes except when
1. The breaking change has no effect on the vast majority of users
2. The component triggering the breaking change is marked as experimental
### How to backport?
In the past, it was necessary to manually backport your PRs. \
Now, that's not a requirement anymore as our [backport bot](https://github.com/GiteaBot) tries to create backports automatically once the PR is merged when the PR
- does not have the label `backport/manual`
- has the label `backport/<version>`
The `backport/manual` label signifies either that you want to backport the change yourself, or that there were conflicts when backporting, thus you **must** do it yourself.
### Format of backport PRs
The title of backport PRs should be
```
<original PR title> (#<original pr number>)
```
The first two lines of the summary of the backporting PR should be
```
Backport #<original pr number>
```
with the rest of the summary and labels matching the original PR.
### Frontports
Frontports behave exactly as described above for backports.
## Release Cycle
We use a release schedule so work, stabilization, and releases stay predictable.
### Cadence
- Aim for a major release about every three or four months.
- Roughly two or three months of general development, then about one month of testing and polish called the **release freeze**.
- *Starting with v1.26 the release cycle will be more predictable and follow a more regular schedule.*
### Release schedule
We will try to publish a new major version every three months:
- v1.26.0 in April 2026
- v1.27.0 in June 2026
- v1.28.0 in September 2026
- v1.29.0 in December 2026
#### How is the release handled?
- The release manager will tag the release candidate (e.g. `v1.26.0-rc0`) and publish it for testing in the **first week of the release month**.
- If there are no major issues, the release manager will check with the other maintainers and then tag the final release (e.g. `v1.26.0`) in the **one or two weeks following the release candidate**.
### Feature freeze
- Merge feature PRs before the freeze when you can.
- Feature PRs still open at the freeze move to the next milestone. Watch Discord for the freeze announcement.
- During the freeze, a **release branch** takes fixes backported from `main`. Release candidates ship for testing; the final release for that line is maintained from that branch.
### Patch releases
During a cycle we may ship patch releases for an older line. For example, if the latest release is v1.2, we can still publish v1.1.1 after v1.1.0.
### End of life (EOL)
We support per standard the last major release. For example, if the latest release is v1.26, we support v1.26 and v1.25, but not v1.24 anymore. We will only publish security fixes for the last major release, so if you are using an older release, please upgrade to a supported release as soon as possible.
Also we always try to support the latest on main branch, so if you are using the latest on main, you should be fine.
## Versions
Gitea has the `main` branch as a tip branch and has version branches
such as `release/v1.19`. `release/v1.19` is a release branch and we will
tag `v1.19.0` for binary download. If `v1.19.0` has bugs, we will accept
pull requests on the `release/v1.19` branch and publish a `v1.19.1` tag,
after bringing the bug fix also to the main branch.
Since the `main` branch is a tip version, if you wish to use Gitea
in production, please download the latest release tag version. All the
branches will be protected via GitHub, all the PRs to every branch must
be reviewed by two maintainers and must pass the automatic tests.
## Releasing Gitea
- Let MAJOR, MINOR and PATCH be Major, Minor and Patch version numbers, PATCH should be rc1, rc2, 0, 1, ...... MAJOR.MINOR will be kept the same as milestones on github or gitea in future.
- Before releasing, confirm all the version's milestone issues or PRs has been resolved. Then discuss the release on Discord channel #maintainers and get agreed with almost all the owners and mergers. Or you can declare the version and if nobody is against it in about several hours.
- If this is a big version first you have to create PR for changelog on branch `main` with PRs with label `changelog` and after it has been merged do following steps:
- Create `-dev` tag as `git tag -s -F release.notes vMAJOR.MINOR.0-dev` and push the tag as `git push origin vMAJOR.MINOR.0-dev`.
- When CI has finished building tag then you have to create a new branch named `release/vMAJOR.MINOR`
- If it is bugfix version create PR for changelog on branch `release/vMAJOR.MINOR` and wait till it is reviewed and merged.
- Add a tag as `git tag -s -F release.notes vMAJOR.MINOR.PATCH`, release.notes file could be a temporary file to only include the changelog this version which you added to `CHANGELOG.md`.
- And then push the tag as `git push origin vMAJOR.MINOR.$`. CI will automatically create a release and upload all the compiled binary. (But currently it doesn't add the release notes automatically. Maybe we should fix that.)
- If needed send a frontport PR for the changelog to branch `main` and update the version in `docs/config.yaml` to refer to the new version.
- Send PR to [blog repository](https://gitea.com/gitea/blog) announcing the release.
- Verify all release assets were correctly published through CI on dl.gitea.com and GitHub releases. Once ACKed:
- bump the version of https://dl.gitea.com/gitea/version.json
- merge the blog post PR
- announce the release in discord `#announcements`
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.