Compare commits

...

198 Commits

Author SHA1 Message Date
petru 471cfdd161 Modified - [install] [backup] [database] [recovery] Consolidated database backup and installer recovery support.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - Add: Gitea now creates timestamped database backup bundles under `[backup].PATH`, exposes the backup schedule in the installer, and surfaces the `database_backup` cron task in admin monitoring.
- 2 - Add: installed instances now use `.gitea-installed` and `.gitea-recovery.ini` to enter email-gated recovery instead of falling back to public install mode when configuration or database access is broken.
- 3 - Mod: the installer recovery flow now covers backup-bundle restore, bundled or manual `app.ini` reuse, uploaded SQL/GZ database restores, and repository-filesystem recovery with source-specific validation, confirmations, and preserved launcher state.
- 4 - Fix: recovery now restores bundled `app.ini` snapshots when needed, discovers backup bundles from both the active backup path and persisted `.gitea-recovery.ini` path, and preserves SMTP and other rebuilt settings correctly when `app.ini` is missing or incomplete.
- 5 - Fix: recovery validation and restore handling now accept either a selected backup bundle or an uploaded SQL/GZ dump, keep sensitive secrets and existing `LFS_JWT_SECRET` when appropriate, clear SQLite restore targets before import, and complete the post-install handoff without redirect loops.
- 6 - Mod: fresh installs now default recovery email authorization to enabled with first-admin fallback, and the install/recovery UI, styling, and EN/RO wording were refined to match the final launcher behavior.

Co-Authored-By: petru @ codex (GPT-5) <codex@openai.com>
(cherry picked from commit 9879caf2292691b0cb521d12e6fee924b066bae2)
2026-06-01 03:56:03 +03:00
petru 406e6d0697 Modified - [admin] [badges] [orgs] [delete] Added direct delete actions in the admin badges and organizations tables.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - Mod: `/-/admin/badges` now shows a delete button in each row that opens the badge delete modal directly from the table.
- 2 - Mod: `/-/admin/orgs` now shows a delete button in each row that opens an organization delete modal directly from the table.
- 3 - Mod: the new table actions reuse the original delete modal layouts already used in badge edit and organization settings, and deleting an organization from `/-/admin/orgs` now returns to the admin organizations list instead of `/`.
2026-05-24 06:03:05 +03:00
petru 6ea9c8660f Modified - [migrate] [cancel] [windows] [git] [retry] Made canceled repository migrations wait for the real clone shutdown before exposing retry/delete actions, and added Windows process-tree termination for migration clones.
- 1 - Fix: canceling a repository migration no longer marks the page as failed while the Git clone is still running.
- 2 - Mod: `Retry` and `Delete This Repository` stay hidden until the migration task is fully stopped.
- 3 - Fix: canceled migrations now persist as `stopped` and no longer show the raw `clone error: context canceled ...` message.
- 4 - Fix: added an opt-in Windows process-tree kill for migration clone commands via `taskkill /T /F`, because Git helper processes could remain alive after `Cancel`, keep writing `tmp_pack_*`, and block cleanup or retry.
2026-05-24 04:11:48 +03:00
petru 70659dc6c3 Modified - [locale] [ro] Refined several Romanian UI strings for clearer wording and corrected grammar in settings, migration, repository, and admin badge messages.
- 1 - I updated `options/locale/locale_ro-RO.json` so several existing Romanian translations now use clearer and more natural phrasing, including the account deletion warning, Git migration progress text, archive action wording, workflow notification label order, and a few admin badge status messages with corrected agreement and grammar.
2026-05-24 01:28:44 +03:00
petru f293572182 Modified - [install] [reinstall] [modal] [app-ini-import] [secrets] Reworked the installer recovery flow around existing databases and imported app.ini secrets.
- 1 - Compared to the previous project state, the installer no longer mixes the existing-database reinstall warning into the main page body and instead runs that confirmation flow in a dedicated modal with the warning content grouped at the top, a `Back` exit path, and an `Install %s` action that stays disabled until all required confirmations are checked; in the same recovery-oriented flow, importing `app.ini` now comes back with `Import sensitive secrets from app.ini` enabled by default, preserves the imported secret values in the form, and keeps the derived site-name label for the install action stable during validation rerenders.
2026-05-24 01:15:41 +03:00
petru 66093c1564 Added - [org] [settings] [repository] [adopt] Added an organization-scoped pre-existing repository adoption flow under organization settings.
- 1 - I added `routers/web/org/setting_repos.go`, `templates/org/settings/repos.tmpl`, `templates/org/settings/navbar.tmpl`, and the corresponding route wiring in `routers/web/web.go`, then aligned the user and organization repository settings pages so both now separate normal adopted repositories from `Unadopted Repositories`; the final organization implementation correctly resolves adopted repos by `OwnerID`, preventing newly adopted organization repositories from lingering in the unadopted list.
2026-05-23 06:08:13 +03:00
petru 26e30f5ac2 Modified - [install] [repository] [app-ini-import] Exposed repository recovery options in the installer and auto-enabled them for imported app.ini installs without a previously used database.
- 1 - I updated `services/forms/user_form.go`, `routers/install/install.go`, `templates/install.tmpl`, `routers/install/routes_test.go`, and the EN/RO locale files so the installer now shows `ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES` and `ALLOW_DELETE_OF_UNADOPTED_REPOSITORIES` under `Repository Options` with helper descriptions, defaults both checkboxes to enabled, imports their values from `app.ini`, and forces them back to `true` during save when an imported configuration is being installed against a database that has not been used before.
- 2 - I updated `custom/conf/app.example.ini` to document both repository recovery options with the live config key names and added inline explanations that match the new installer behavior, including the imported-`app.ini` recovery auto-enable case.
2026-05-23 04:54:36 +03:00
petru efbd83def5 Fixed - [adopt] [repository] [visibility] Added an explicit Privat checkbox to the pre-existing repository adopt dialogs.
- 1 - I updated `templates/user/settings/repos.tmpl`, `templates/admin/repo/unadopted.tmpl`, `routers/web/user/setting/adopt.go`, and `routers/web/admin/repos.go` so the `Adopt pre-existing files` panels now submit a `private` checkbox: checked adopts the repository as private, unchecked adopts it as public. Repositories that already exist in the database continue to be shown as existing repos instead of appearing in the adopt flow.
2026-05-23 04:04:00 +03:00
petru b7661af8d7 Modified - [admin] [users] [table] [nowrap] Kept the username column and its role badges on a single line in the admin user list.
- 1 - I updated `templates/admin/user/list.tmpl` so the username cell on `/-/admin/users` now uses `tw-whitespace-nowrap`, preventing the username plus `Admin by ...` or `Super Admin by ...` badges from wrapping awkwardly in the table.
2026-05-22 23:46:09 +03:00
petru 03f90d9234 Updated AGENTS.md
Co-Authored-By: Petru via Codex GPT-5 <petru-codex@example.com>
2026-05-22 23:44:18 +03:00
petru 0e5e7b03ab Modified - [install] [repository-release] [ui] Added release attachment limits to the installer under "Server and Third-Party Service Settings".
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated `services/forms/user_form.go`, `routers/install/install.go`, `templates/install.tmpl`, and the EN/RO locale files so the installer now exposes `[repository.release] MAX_FILES` and `FILE_MAX_SIZE`, preloads them from the current settings or imported `app.ini`, and persists them back into the generated configuration with inline help text.
2026-05-22 22:49:34 +03:00
petru a3b699bc70 Fixed - [install] [app-ini-import] [mailer] Corrected installer app.ini import so imported mailer sender details and Site Title branding fully replace the current form state.
- 1 - I updated `routers/install/install.go`, `routers/install/routes_test.go`, and `templates/install.tmpl` so importing `app.ini` now replaces stale split mailer sender fields with the imported `FROM = site_name <email@example.com>` value and immediately refreshes the derived `Install %s` button label from the imported `APP_NAME`.
2026-05-22 21:17:07 +03:00
petru c498ee9b9c Modified - [badge] [label] [repo] [repo-explore] [visibility-badge] [admin] Refined the repo visibility badges (Public / Privat) and the small by ... labels, and kept long admin badge slugs on a single line.
- 1 - I updated `web_src/css/modules/label.css` so the repo visibility badges and the small attribution labels such as `by ...` now use a pill-style border radius with tighter horizontal padding, giving both label families a more compact visual treatment.
- 2 - I updated `templates/admin/badge/list.tmpl` to keep badge slug cells on a single line with `tw-whitespace-nowrap`, preventing awkward wrapping in the admin badge list.
2026-05-22 19:45:51 +03:00
petru a36bddc1c2 Modified - [commit] [segment] [ui] Tightened the attached segment spacing in the repository commit view.
- 1 - I updated `web_src/css/modules/segment.css` so bottom-attached segments no longer keep the extra `1rem` bottom margin, helping the stacked commit-panel blocks on `/user/repo/commit/xxxx` sit more tightly together.
2026-05-22 04:06:21 +03:00
petru c57da3e249 Modified - [locale] [ro] Adjusted the Romanian repo visibility badge labels to use concise badge-friendly wording.
- 1 - I updated `options/locale/locale_ro-RO.json` so `settings.visibility.public`, `settings.visibility.limited`, and `settings.visibility.private` now read `Public`, `Limitat`, and `Privat`, matching the compact badge style used in the repository UI.
2026-05-22 03:50:16 +03:00
petru d931966231 Modified - [commit] [diff] [ui] Refined the sticky commit and diff panel spacing on the repository commit view.
- 1 - I updated `web_src/css/repo.css` so the sticky `.repository .diff-detail-box` gets extra top padding, the sticky `#diff-file-tree` sits 1px lower under the persistent navbar offset, and the sticky second-row `.diff-file-header` is pushed further down to visually clear the adjusted top panel on `/user/repo/commit/xxxx`.
2026-05-22 03:46:22 +03:00
petru 64f260a06d Modified - [migrate] [lfs] [ui] Refined the advanced LFS migration option layout on the repository migrate form.
- 1 - I updated `templates/repo/migrate/options.tmpl` and `web_src/css/modules/form.css` so the advanced LFS endpoint block now uses dedicated `lfs` layout hooks, giving the help text and inline input row a cleaner alignment on `/repo/migrate?service_type=2&org=&mirror=`.
2026-05-22 03:15:27 +03:00
petru 7f0a7db812 Modified - [locale] [i18n] Synchronized the locale files with the current installer and sticky-layout strings.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated all translated `options/locale/locale_*.json` files so `install.install_btn_confirm` now accepts a `%s` site-name placeholder instead of hardcoding `Gitea`, matching the current installer button behavior.
- 2 - I added the missing `footer.show`, `footer.hide`, `install.smtp_from_name_placeholder`, and `install.smtp_from_address_placeholder` keys across the locale files, using the current English fallback text where no localized variant was available in this change.
2026-05-21 03:11:30 +03:00
petru b1db0705d8 Modified - [install] [mailer] Split the installer mail sender field into display name and address, auto-filled the sender name from Site Title, and reused that site name in test mails.
- 1 - I updated `services/forms/user_form.go`, `routers/install/install.go`, `templates/install.tmpl`, `options/locale/locale_en-US.json`, and `options/locale/locale_ro-RO.json` so the installer now edits `Send Email As` through separate sender-name and sender-address inputs on the same line, auto-fills the sender name from the part of `Site Title` before `:`, or from the first word when no `:` is present, and composes `[mailer] FROM = site_name <mail@address>` server-side during test mail and install submission.
- 2 - I updated `services/mailer/mail.go` so the installer test mail subject/body reuse that derived site name instead of the hardcoded `Gitea` label.
- 3 - I added targeted coverage in `routers/install/routes_test.go` and `services/mailer/mail_test.go` for the derived site-name logic and the composed installer `FROM` address.
- 4 - I updated `routers/install/install.go`, `templates/install.tmpl`, and the installer locale strings so the primary install button now renders `Install <site_name>` from the same derived site-name rule and updates live as `Site Title` changes.
2026-05-21 02:32:36 +03:00
petru 953a7c08be Modified - [footer] [sticky-ui] Fine-tuned the persistent footer lip geometry for better visual balance.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated `web_src/css/home.css` so the persistent-footer toggle lip now rises a bit higher above the footer edge and is slightly taller, giving the handle a more relaxed fit against the footer border.
2026-05-21 00:25:53 +03:00
petru f09229e739 Modified - [navbar] [sticky-ui] Fine-tuned the persistent navbar lip geometry for better visual balance.
- 1 - I updated `web_src/css/modules/navbar.css` so the persistent-navbar toggle lip now sits 2px lower and is 1px taller, giving the handle a slightly more relaxed fit against the navbar edge.
2026-05-21 00:23:30 +03:00
petru 18c3bd2a67 Modified - [repo-header] [sticky-ui] Let the secondary navigation use the full available page width and added a little extra clearance for the sticky toggle lip.
- 1 - I updated `templates/repo/header.tmpl` and `web_src/css/modules/container.css` so the two repository `secondary-nav` containers now opt into a dedicated full-width `ui container nav` layout while still respecting the shared page margins.
- 2 - I updated `web_src/css/repo/header.css` to add 2px of extra top padding on `.repository .secondary-nav`, preventing the sticky lip from crowding the existing content at the top of the repository header area.
2026-05-21 00:19:23 +03:00
petru ced65dc5cd Modified - [footer] [sticky-ui] Added a top lip show/hide toggle for the persistent footer.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated `templates/base/footer_content.tmpl`, `web_src/css/home.css`, and `web_src/js/features/common-page.ts` so pages with the persistent footer preference now render a top-edge toggle lip on desktop, remember the collapsed state in local user settings under `persistent-footer-collapsed`, measure the live footer height for smooth hide/show motion, and keep only the lip visible when the footer is collapsed.
- 2 - I added the new footer show/hide labels to `options/locale/locale_en-US.json` and `options/locale/locale_ro-RO.json`.
2026-05-20 19:27:41 +03:00
petru 78f429361d 163 - [2026-05-20 00:37:42] - v1.27.0-dev-174-gef319c5c07 - Type: Modified - [navbar] [sticky-ui] Refined the persistent navbar toggle lip to be shorter and vertically center the arrow icon.
- 1 - I updated `web_src/css/modules/navbar.css` so the bottom-right persistent-navbar toggle tab now uses a slimmer 8px lip, sits 8px below the navbar edge, and centers a smaller chevron within the lip instead of bottom-aligning it.
2026-05-20 03:07:39 +03:00
petru ef319c5c07 Fixed - [navbar] [sticky-ui] [cookies] Kept the persistent navigation bar sticky for signed-out pages by reusing the saved preference from a site cookie.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated `modules/web/middleware/cookie.go`, `routers/common/pagetmpl.go`, and `routers/web/user/setting/profile.go` to add a dedicated `gitea_persistent_navbar` cookie, synchronize it when authenticated users save or load the preference, and reuse that cookie as the anonymous-page fallback so the navbar stays sticky after logout just like the footer already does.
2026-05-20 02:37:11 +03:00
petru b66ec8c19d Modified - [scripts] [configure] [git-lfs] Added conditional Git LFS setup to configure.sh when repository LFS hooks are installed.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated `.configure.sh` so repositories that already have Git LFS hook scripts in `.git/hooks` now treat `git-lfs` as a required dependency during verification, install the `git-lfs` system package on supported package managers, and run `git lfs install --local` during non-verify setup.
2026-05-19 23:46:15 +03:00
petru 06e5bd7f46 Modified - [scripts] [smart-build] [darwin] Added macOS amd64/arm64 smart-build support, including SQLite-aware Docker-host handling for containerized workspaces.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated `smart-build.sh` so its interactive architecture menu now offers `macos-amd64`, `macos-arm64`, and includes both Darwin targets in `All Arch`, while preserving the existing `darwin` artifact naming in `dist/`.
- 2 - I added a dedicated Darwin SQLite build path in `smart-build.sh` that routes macOS `bindata sqlite sqlite_unlock_notify` builds through `make release-darwin`, and I updated `Makefile` to make `release-darwin` configurable through `DARWIN_ARCHS` so helper scripts can request only `darwin-10.12/amd64` or `darwin-10.12/arm64`.
- 3 - I hardened the Darwin SQLite flow in `smart-build.sh` for `code-server`-style containerized workspaces by distinguishing between a missing Docker CLI and an unreachable Docker daemon, by validating that the host Docker daemon can see the same mounted repository `go.mod` path as the current workspace, and by moving the temporary release output under `dist/` instead of `/tmp`.
- 4 - I added `SMART_BUILD_DARWIN_HOST_REPO_PATH` support to `smart-build.sh` so Darwin SQLite builds can be redirected to a host-visible repository mount path when the interactive workspace path inside the container differs from the real host path used by the Docker daemon.
2026-05-19 23:25:35 +03:00
petru a039c0d401 Modified - [navbar] [sticky-ui] [user-settings] Added a show/hide toggle tab for the persistent navigation bar.
- 1 - I updated `templates/base/head_navbar.tmpl`, `web_src/css/modules/navbar.css`, and `web_src/css/modules/flexcontainer.css` so pages with `Keep the navigation bar visible while scrolling` now show a small bottom-right toggle tab that collapses the sticky navbar to a minimal visible handle and restores it on demand while keeping sticky offsets aligned.
- 2 - I updated `web_src/js/features/common-page.ts` so the toggle state is applied on page load and stored in local user settings under `persistent-navbar-collapsed`, preserving the chosen shown/hidden state across navigation.
- 3 - I added the new show/hide navbar labels to `options/locale/locale_en-US.json` and `options/locale/locale_ro-RO.json`.
- 4 - I refined the navbar toggle geometry in `web_src/css/modules/navbar.css` and `web_src/css/modules/flexcontainer.css` so the handle now sits like a slim tab just below the navbar border, is pushed closer to the right edge, and leaves only the handle visible when the persistent navbar is collapsed.
2026-05-19 23:25:35 +03:00
petru 708819629a Modified - [repo-diff] [sticky-ui] [navbar] Prevented sticky diff headers from sliding under the persistent navigation bar.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated `web_src/css/repo.css` so the sticky repository diff summary bar, the sticky second-row file headers, and the diff file scroll anchor margin now all include `--persistent-navbar-offset`, keeping them visible below the navbar when `Keep the navigation bar visible while scrolling` is enabled.
- 2 - I extended the same offset handling to `#diff-file-tree` so the sticky diff file tree no longer slides under the diff summary bar after the persistent-navbar preference shifts the sticky stack downward.
2026-05-18 23:30:30 +00:00
petru 69356f6de0 Fixed - [scripts] [custom-release] [release-target] Stopped release-target sync from requiring the remote release branch when an explicit target tag/ref is configured.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated [`.maintain-custom-release.sh`](/config/workspace/gitea-dev/gitea/.maintain-custom-release.sh) so `Sync upstream release target commits` validates only the configured `UPSTREAM_RELEASE_TARGET_REF` when one is set, instead of still failing on a missing local `upstream/release/...` remote-tracking branch after successfully fetching a target tag such as `v1.26.1`.

(cherry picked from commit 244a472691)
(cherry picked from commit 63b691c29e)
2026-05-18 21:12:09 +00:00
petru 2bf2288ba8 Modified - [scripts] [smart-build] [artifacts] Renamed smart-build outputs to include the tag/ref and generated per-file SHA-256 checksums.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated [`.smart-build.sh`](/config/workspace/gitea-dev/gitea/.smart-build.sh) so each build artifact is now written as `gitea-<tag-or-ref>-<os>-<platform><-sqlite>` with the original executable extension preserved, and each output also gets its own adjacent `.sha256` file generated with `sha256sum` or `shasum -a 256`.

(cherry picked from commit c6f2b32f0b)
(cherry picked from commit bff70ba3de)
2026-05-18 21:00:09 +00:00
petru 725c21ef84 Fixed - [admin-users] [terminology] [locale] [en] [ro] Corrected the bootstrap-admin label from GOOD to GOD.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
(cherry picked from commit 1f2bb43f46)
(cherry picked from commit a1052dbf96)
2026-05-18 20:49:07 +00:00
petru 8b215d1e16 Modified - [docs] [changelog] [github-links] Converted remaining bare pull-request references in CHANGELOG.md and CHANGELOG-archived.md to explicit GitHub links.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated `CHANGELOG.md` and `CHANGELOG-archived.md` so bare changelog references of the form `#123` now use explicit Markdown links to `https://github.com/go-gitea/gitea/pull/123`, while preserving the existing local changelog edits already present in the working tree.
2026-05-18 17:41:08 +00:00
petru ee30675569 Stop tracking .frontend.hash 2026-05-18 12:01:53 +00:00
petru f4e7ba76d8 First try for Codex AI routine optimisation 2026-05-15 23:01:24 +00:00
petru 59bc832f0a Added Routing Rules for Tasks (Multi-Model Delegation) for OpenAI Codex.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-15 21:44:05 +00:00
petru ac76745362 Fix - For .maintain-custom-release.sh - Hardened recovery so rollback, restore-point, restore-snapshot, restore-stash, and restore-deletion correctly preserve or clean script-managed refs, maintenance branches, state files, backup branches, and snapshots, including rollback from the original entry branch after a bootstrap-created maintenance branch, cleanup of legacy restore-point leftovers, and removal of the correctly paired backup/maint-* Git Graph marker when a saved snapshot is deleted. 2026-05-15 21:42:43 +00:00
petru 5eae94f95a Modified - Finalized the custom-release maintenance helper workflow and recovery behavior.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I made `bootstrap` a clean branch-creation step from `BASE_TAG`, separated fetch and sync into explicit compare/release-target/custom actions, added `UPSTREAM_RELEASE_TARGET_REF`, and updated the built-in help so the recommended workflow matches the current menu structure.
- 2 - I hardened recovery so rollback, restore-point, restore-snapshot, restore-stash, and restore-deletion correctly preserve or clean script-managed refs, maintenance branches, state files, backup branches, and snapshots, including rollback from the original entry branch after a bootstrap-created maintenance branch, cleanup of legacy restore-point leftovers, and removal of the paired `backup/maint-*` Git Graph marker when a saved snapshot is deleted.
- 3 - I finalized the interactive UX by keeping a self-updating runtime copy in `/tmp`, persisting the last-used settings in `/tmp/.maintain-custom-release.env`, and reorganizing the menu into `Manual Backups >`, `Fetch upstreams >`, `Sync >`, `Rollback >`, and `Restore >` submenus, including `Delete Restore >` with numbered stash and snapshot selection, with numbered selections, `b`/`B` or `Enter` for Back, correct return-to-parent behavior from every submenu, and `0` for Exit.
2026-05-15 14:21:34 +00:00
petru 3bbe60b6b7 Modified - Finalized the custom-release maintenance helper workflow and recovery behavior.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I made `bootstrap` a clean branch-creation step from `BASE_TAG`, separated fetch and sync into explicit compare/release-target/custom actions, added `UPSTREAM_RELEASE_TARGET_REF`, and updated the built-in help so the recommended workflow matches the current menu structure.
- 2 - I hardened recovery so rollback, restore-point, restore-snapshot, and restore-stash correctly preserve or clean script-managed refs, maintenance branches, state files, backup branches, and snapshots, including rollback from the original entry branch after a bootstrap-created maintenance branch and cleanup of legacy restore-point leftovers.
- 3 - I finalized the interactive UX by keeping a self-updating runtime copy in `/tmp`, persisting the last-used settings in `/tmp/.maintain-custom-release.env`, and reorganizing the menu into `Backups >`, `Fetch upstreams >`, `Sync >`, `Rollback >`, and `Restore >` submenus with numbered selections, `b`/`B` or `Enter` for Back, and `0` for Exit.
2026-05-15 00:14:09 +00:00
petru 1d43078c0b Moved in .maintain-custom-release.sh bootstrap ahead of the explicit fetch actions in the interactive menu, kept it in the menu flow instead of exiting the script, removed automatic fetching from bootstrap and plan, and split both the fetch and sync flows into separate compare-branch and release-target actions while clarifying that custom commits are cherry-picked from oldest to newest.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-14 22:03:04 +00:00
petru f5718dd509 Updated [.maintain-custom-release.sh](/config/workspace/gitea-dev/gitea/.maintain-custom-release.sh) so bootstrap now only creates or switches to the maintenance branch from BASE_TAG, without automatically fetching or importing anything.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- Added a persistent `/tmp/.maintain-custom-release.env` settings file so the last used configuration survives script restarts.
- Moved `bootstrap` ahead of the explicit fetch actions in the interactive menu, removed automatic fetching from `bootstrap` and `plan`, and split both the fetch and sync flows into separate compare-branch and release-target actions while clarifying that custom commits are cherry-picked from oldest to newest.
2026-05-14 21:01:25 +00:00
petru f765bfdc05 Taught the .maintain-custom-release.sh script to maintain and relaunch itself from a runtime copy in /tmp, automatically creating or refreshing that copy from the repo version when needed while still falling back to the existing /tmp copy if the current checkout no longer contains the script, and I split both the fetch and sync flows into separate compare-branch and release-target actions while clarifying that custom commits are cherry-picked from oldest to newest.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-14 20:27:18 +00:00
petru 2c95b1faf4 Taught the .maintain-custom-release.sh script to maintain and relaunch itself from a runtime copy in /tmp, automatically creating or refreshing that copy from the repo version when needed while still falling back to the existing /tmp copy if the current checkout no longer contains the script, and I split the upstream sync flow into separate sync-upstream-compare and sync-upstream-target actions while clarifying that custom commits are cherry-picked from oldest to newest.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-14 20:00:01 +00:00
petru 2d37281725 Added to .maintain-custom-release.sh an explicit UPSTREAM_RELEASE_TARGET_REF setting so the upstream import can stop at a chosen tag such as v1.26.0 instead of always importing to the current head of upstream/release/v1.26, and I also made rollback clean up the original backup/maint-* branch and fetched upstream/* refs so a canceled bootstrap leaves the branch graph closer to its pre-run state.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-14 18:43:47 +00:00
petru c8bd47f0d9 Tightened in .maintain-custom-release.sh the manual restore-point management so list-restore-points now shows only valid restore points that still have their Git Graph marker branch, while delete-restore-point can still remove orphaned restore-point directories even after their associated backup branch has already been deleted manually.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-14 15:39:49 +00:00
petru aba98b9361 Fixed the script-managed ref discovery itself so restore cleanup now matches refs/remotes/upstream/... and backup/maint-... by prefix instead of a non-matching glob pattern, which was the reason upstream/release/v1.26 could still remain after a restore.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-14 01:44:26 +00:00
petru b31ce595d3 Added a legacy restore-point fallback so older restore points that predate the script-managed ref snapshot files now explicitly remove current upstream/*, maintenance-branch, backup/maint-*, state-file, and snapshot artifacts instead of leaving them behind after restore.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-14 01:22:18 +00:00
petru 8f9b67397e fixed the restore flows so manual restore points now capture and restore the script-managed refs, state file, and snapshot directories, while successful rollback, restore-snapshot, and restore-point operations automatically clean up their temporary safety backup branches and snapshots when no preserved local stash needs to be kept.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-14 01:04:02 +00:00
petru f527cf4ce3 Modified - Simplified bootstrap and tightened rollback cleanup in the custom-release maintenance helper.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-14 00:16:33 +00:00
petru 209224d0cc Fix - fixing the interactive configuration prompts so they are shown correctly during Edit configuration.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-13 21:24:14 +00:00
petru 363c86ecaf Modified - Extended the custom-release maintenance helper with manual restore points and corrected its fetch behavior.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-13 20:26:59 +00:00
petru 92c6dad4b9 Set script as .update-gitea.sh as executable.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-13 18:19:03 +00:00
petru a6a278b551 Added - Added a dedicated safe upstream import helper based on cherry-pick.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
Added - Added an interactive custom-release maintenance helper for stable patch lines.

Added - Added a dedicated safe upstream import helper based on `cherry-pick`.
Added - Added an interactive custom-release maintenance helper for stable patch lines.

Added - Added a dedicated safe upstream import helper based on cherry-pick.
Added - Added an interactive custom-release maintenance helper for stable patch lines.
2026-05-13 17:22:01 +00:00
petru 6d0a7ec238 Added - Finalized the safe upstream update helper script as .update-gitea.sh.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 5 - I improved conflict reporting so package.json conflicts show the upstream scripts block, the conflicting commit side, and the current branch working-tree side, and the final dry-run summary now includes the total conflict-step count, the local commits that conflicted, and the unique conflicted files.
2026-05-12 23:37:02 +00:00
petru cca877c06e Added - Finalized the safe upstream update helper script as .update-gitea.sh.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I renamed the updater to `.update-gitea.sh`, documented its purpose and ordered usage steps, and added an interactive menu plus direct commands for `sync`, `dry-run`, `fetch`, `backup`, `status`, `list-backups`, `rollback`, `restore-stash`, and `clean-dry-run`.
- 2 - I hardened real update actions so they verify repository state, enforce or offer safety backups before modifying the branch, stash tracked and untracked local changes, record sync state inside `.git`, and support rollback to the exact saved starting commit or to a selected backup branch while preserving recoverability of local changes.
- 3 - I implemented a reusable dry-run workspace under `.git/.update-gitea-dry-run`, added cleanup for both that workspace and legacy temporary dry-run directories, and made dry-run collect and report all detected rebase conflict steps without modifying the real repository.
- 4 - I improved conflict reporting so package.json conflicts show the upstream scripts block, the conflicting commit side, and the current branch working-tree side, and the final dry-run summary now includes the total conflict-step count, the local commits that conflicted, and the unique conflicted files.
2026-05-12 22:51:45 +00:00
petru 512e577c3f Added - Added optional sensitive-secret import for installer app.ini uploads.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I added an explicit installer checkbox for importing sensitive secrets from `app.ini` in `templates/install.tmpl`.
- 2 - I extended the installer form, submit pipeline, and final config writer so the optional import reuses `LFS_JWT_SECRET`, `INTERNAL_TOKEN`, and `oauth2.JWT_SECRET` from the uploaded `app.ini` instead of generating new values, including a submit-time fallback that re-reads the uploaded file if the checkbox was enabled after the first auto-import.
- 3 - I finalized secret resolution for both direct values and `LFS_JWT_SECRET_URI` / `INTERNAL_TOKEN_URI` / `JWT_SECRET_URI` file-based references, and added regression coverage for direct imports, URI-based imports, the real `POST /import_app_ini` flow, and the persisted `app.ini` output.
2026-05-12 20:35:52 +00:00
petru e69839ed88 Modified - Enabled shared branding assets by default in the installer.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I updated `routers/install/install.go` so `BrandingUseSharedAssets` starts as enabled on the install form, making `Use the same logo files for favicon assets` checked by default.
2026-05-12 02:36:16 +00:00
petru b907e4c38c Added - added installer locale strings in both options/locale/locale_en-US.json and options/locale/locale_ro-RO.json for the new import UI, success message, and import errors, and the success flash now auto-dismisses after 5 seconds both on initial page load and after the AJAX import injects a new flash message.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-12 02:25:00 +00:00
petru 52f3495ca0 Added - Added installer support for importing an existing app.ini.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I added an `Import Existing Configuration` section at the top of `templates/install.tmpl` with an `app.ini` upload control that imports automatically as soon as a file is selected, without a separate `Load app.ini` button.
- 2 - I kept the dedicated installer route `POST /import_app_ini` in `routers/install/routes.go`, but the page now posts to it via `fetch` and applies the imported values back into the existing form with `DOMParser`, so the browser is not visibly navigated to `/import_app_ini` and the page scripts are not re-executed.
- 3 - In `routers/install/install.go`, I factored the installer defaults into reusable helpers, added `app.ini` upload parsing with size/error handling, and mapped the imported config into the existing install form fields for database, general server paths, mailer, registration, OpenID, security, and admin policy settings.
- 4 - I added installer locale strings in both `options/locale/locale_en-US.json` and `options/locale/locale_ro-RO.json` for the new import UI, success message, and import errors, and the success flash now auto-dismisses after 5 seconds.
- 5 - I added regression coverage in `routers/install/routes_test.go` for the new upload control and the config-to-form mapping behavior.
2026-05-12 02:08:51 +00:00
petru 70479ea5a0 Added - Added the password visibility toggle to /user/settings/change_password.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I wrapped the forced-change password field in `templates/user/auth/change_passwd_inner.tmpl` with the shared `js-password-toggle-group`, reusing the existing eye-toggle logic and show/hide labels.
- 2 - I wired the confirm-password field into the existing toggle sync behavior so revealing the new password hides the confirm field and keeps it synchronized like the other password-update forms.
2026-05-12 01:06:36 +00:00
petru 9ee45b3392 Modified - Finalized Register behavior for admin-created notification accounts without altering the invitation flow.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I extended `POST /user/sign_up` in `routers/web/auth/auth.go` for existing active local accounts created by an admin when `username` and `email` match, while explicitly leaving pending admin invitations on their existing flow.
- 2 - If password is correct, the user is now authenticated into that existing account; when `MustChangePassword` is enabled, the flow redirects directly to `/user/settings/change_password`, otherwise it follows the normal post-auth redirect.
- 3 - If password is incorrect, the flow now redirects to `/user/forgot_password?email=<email>` and shows a warning to use account recovery plus check Spam/Junk.
- 4 - I added the locale key `auth.admin_notify_recover_password_spam_hint` in both `options/locale/locale_en-US.json` and `options/locale/locale_ro-RO.json`.
- 5 - I added regression tests in `routers/web/auth/auth_test.go` for normal sign-in, forced change-password redirect, wrong-password recovery redirect, and a guard that the admin-invitation flow still redirects to `/user/invitation`.
2026-05-12 00:48:37 +00:00
petru d81fdfc31f Added - Added optional custom branding uploads to the install page.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
- 1 - I finalized the installer `Branding` section with optional uploads for `logo.svg`, `logo.png`, `loading.png`, `favicon.svg`, and `favicon.png`, including clear format/size guidance plus a shared-assets checkbox for using one SVG and one PNG upload for both logo and favicon.
- 2 - I implemented backend validation and persistence for all branding uploads in `routers/install/install.go` (expected type checks, 1 MB limit, square PNG with minimum 64x64) and save accepted overrides under `custom/public/assets/img/`.
- 3 - I completed the runtime behavior so uploaded branding files override built-in assets through layered serving, `logo.svg` is mirrored to `gitea.svg` for legacy lookups, post-install progress prefers a custom `loading.png`, and the shared-assets mode hides favicon fields while relabeling logo fields to `Logo & Favicon SVG/PNG`.
- 4 - I manually updated Romanian locale wording for the final branding texts and labels.
2026-05-11 20:38:50 +00:00
petru 7dbc4726fa Added - Added the password visibility toggle and confirm-password behavior to /user/settings/account.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-10 23:28:46 +00:00
petru 3b52932acd Added - Added the password visibility toggle to the install-page database password field.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
+ Fix - some new correction Romanian wording and grammar in locale_ro-RO.json.
2026-05-10 23:08:40 +00:00
petru 4ff2054a83 Added - Added the password visibility toggle and confirm-password behavior to the install-page super-admin password fields.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
+ Fix - some new correction Romanian wording and grammar in locale_ro-RO.json.
2026-05-10 22:14:03 +00:00
petru fb34e858c1 Modified - Enabled install-page email notifications by default for fresh setups.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-10 21:29:05 +00:00
petru a59bb9753f Added - Added the password visibility toggle to the SMTP password field on the install page.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-10 21:13:27 +00:00
petru ca7092e23c Added - Added column-wide Select all controls to the organization team-units permissions table.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
+ Fix - some new correction Romanian wording and grammar in locale_ro-RO.json.
2026-05-10 20:52:49 +00:00
petru 490e119254 Fix - some new correction Romanian wording and grammar in locale_ro-RO.json.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-10 05:05:16 +00:00
petru 3b121911c1 Modified - Unified the persistent appearance toggles into a single settings group. 2026-05-10 04:49:07 +00:00
petru 354521fbd3 Modified - Some changes in .gitignore
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-10 03:44:23 +00:00
petru aaaada5129 Fix - some new correction Romanian wording and grammar in locale_ro-RO.json. 2026-05-10 03:43:31 +00:00
petru cbedf15d3b Modified - Finalized the manual-only password visibility toggle behavior for login and signup. 2026-05-10 03:41:03 +00:00
petru 1525c9c8ee Modified - Added an audio bell for interactive prompts in 'smart-build.sh'.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-09 22:10:57 +00:00
petru 75bc9606d5 Added - Added pilot partial navigation for the repository Actions sidebar. 2026-05-09 22:01:46 +00:00
petru 0f3876c0b1 Modified - Applied the shared sticky side-menu behavior to repository Actions pages.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-09 20:52:12 +00:00
petru 652d3c20da Modified - Applied the shared sticky side-menu behavior to repository settings pages.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-09 19:52:43 +00:00
petru bfb584f161 Added - Added password visibility toggles to the login and signup forms.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-09 19:33:09 +00:00
petru 01e3eb1306 Fix - some new correction Romanian wording and grammar in locale_ro-RO.json.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-09 18:35:37 +00:00
petru 827a35ce09 Modified - Applied the shared sticky side-menu behavior to organization settings pages.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-09 17:45:42 +00:00
petru 021f12509f Added - Added header-level Select all controls to the shared Actions maximum-permissions table.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-09 17:30:08 +00:00
petru ab1135d1c6 Added - Added column-wide Select all controls to the user access-token permissions table.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-09 16:39:10 +00:00
petru 8a0d319607 Modified - Highlighted the active submenu entry with the standard active background color.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-09 15:32:40 +00:00
petru 06b7bd3ca1 Modified - Finalized the sticky side-menu bottom-edge behavior by compacting menu items and increasing the viewport reserve.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-09 15:10:16 +00:00
petru bb77e80bf5 Modified - Restored the pre-122 /user/settings layout baseline while keeping the current sticky-menu behavior.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-09 11:02:31 +00:00
petru 71246d4ee1 Modified - Restored the agreed /user/settings sticky-menu item padding behavior.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-08 20:43:57 +00:00
petru 3dd2ffc195 Modified - Preserved the /user/settings left-menu scroll position without the visible reset flicker during navigation.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-08 20:22:45 +00:00
petru 5e31019b99 Modified - Made the Admin Settings menu header sticky while the admin left-menu options scroll.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-08 17:04:44 +00:00
petru cfd1c9ddbb Modified - Made the footer Licenses and API links open in a new browser tab and finalized the sticky User Settings header plus its top green scroll indicator.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-08 16:05:15 +00:00
petru a8a099edea Modified - Preserved the /user/settings left-menu scroll position across settings-page navigation
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
+ Fix - some new correction Romanian wording and grammar in `locale_ro-RO.json`.
2026-05-08 09:08:33 +00:00
petru 90735ea826 Modified - Added a persistent navigation-bar preference in /user/settings/appearance.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-08 00:33:34 +00:00
petru 351d6b0811 Modified - Added the persistent sticky side-menu preference and the finalized sidebar behavior for /user/settings and /-/admin.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-07 23:57:58 +00:00
petru 61a9e4bd06 Modified - Moved the persistent footer outside the page scroll area
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
+ some new correction Romanian wording and grammar in `locale_ro-RO.json`.
2026-05-07 09:45:13 +00:00
petru b3a7692ce9 Modified - Reverted the global fixed-footer behavior and replaced it with a persistent per-user footer preference in /user/settings/appearance.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-07 01:14:36 +00:00
petru 10495b7cd1 Modified - Made the admin-created account notification link behave like an invitation by signing the user in through /user/activate
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
+ Modified - Simplified the admin-created account notification email to show only the personalized activation link.
2026-05-07 00:15:26 +00:00
petru 2ecb570a7d Modified - Made the admin-created account notification link behave like an invitation by signing the user in through /user/activate.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-07 00:01:12 +00:00
petru 146013827c Fixed - Corrected the admin-created account password-setup email link to use the public recovery route
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
+ some new correction Romanian wording and grammar in `locale_ro-RO.json`.
2026-05-06 23:36:08 +00:00
petru 85620a4f29 Modified - Personalized the admin-created account notification email with the creator name and a direct set-password link.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-06 22:18:19 +00:00
petru 70ef46362e Fixed - Made admin-created user notification and invitation emails use the current page locale
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
+ ome new correction Romanian wording and grammar in `locale_ro-RO.json`.
2026-05-06 22:02:22 +00:00
petru fc43980a5c Fixed - Prevented the new-organization modal from inheriting unrelated global success flashes from the underlying page.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
+ Some new correction Romanian wording and grammar in `locale_ro-RO.json`.
2026-05-06 20:59:20 +00:00
petru 5f0f52d04f Modified - Reduced the resend button size on the invitation acceptance prompt.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-06 18:55:23 +00:00
petru 17814a4dda Modified - Reduced the resend button size on the invitation acceptance prompt. 2026-05-06 18:54:34 +00:00
petru 7c7357f314 Modified - Some new correction Romanian wording and grammar in locale_ro-RO.json.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-06 15:51:02 +00:00
petru f00f80bae7 Modified - Some new correction Romanian wording and grammar in locale_ro-RO.json. 2026-05-06 15:50:59 +00:00
petru d1e10b41a5 Modified - Fix align new-user check-boxes help text.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-06 15:19:57 +00:00
petru c80f065a09 Modified - Somes correction Romanian wording and grammar in locale_ro-RO.json
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-06 15:05:41 +00:00
petru 5338d5f7f6 Modified - Converted the organization creation page to a modal-style dialog and preserved the caller page for cancel.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-06 14:56:11 +00:00
petru ba0da47957 Modified - Converted the organization creation page to a modal-style dialog and preserved the caller page for cancel.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-06 01:50:23 +00:00
petru 75a9dbf7d7 Updated .codex-history.md
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-06 00:32:23 +00:00
petru cc36930cdd Modified - Another visual polish of Romanian translation for locale_ro-RO.json.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-06 00:31:03 +00:00
petru cb765b81a7 Modified - Visual polish of Romanian translation for locale_ro-RO.json.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-05 23:33:12 +00:00
petru 144bc4796f Modified - Added a first complete Romanian translation pass for locale_ro-RO.json.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-02 15:07:15 +00:00
petru 414c77278b Modified - Added official bootstrap support for the Romanian locale.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-02 13:59:49 +00:00
petru 4eaa42bccd Modified - Added an install-page language hint balloon anchored to the footer language selector.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-02 13:20:52 +00:00
petru f60b2af5a6 Modified - Aligned the admin new-user invitation help text with the install-page help layout.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-02 11:52:18 +00:00
petru f7bc24d4e8 Modified - Added a dedicated pending-invitation flow for admin-created invite accounts and pinned the install footer.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-02 04:04:22 +00:00
petru f8f988e85e Modified - Disabled forbidden email deletion actions in the admin email list.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-02 02:52:52 +00:00
petru b7e7b32caa Modified - Added default language selection to the install page initial configuration.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-02 02:36:54 +00:00
petru 4ab8063966 Modified - Unified classic email-confirmation signup with the resend-based pending validation flow.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-02 02:11:55 +00:00
petru a6695a6e73 Modified - Moved admin-created account delivery mode selection from install to the admin new-user form.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-02 01:39:34 +00:00
petru ad0ab4be60 Modified - Completed install-page admin-managed account modes and aligned locale install sections-v.1
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-01 23:45:15 +00:00
petru 19fb194db6 Modified - v.1-Added install-page Registration Management with coherent mode-driven registration settings.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-01 17:36:28 +00:00
petru 362d01abbc Type: Modified - Added install-page testing email verification using the entered SMTP settings.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-05-01 12:24:01 +00:00
petru d4a1b88385 Modified - Updated install-page administrator labels to super administrator wording.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-30 22:46:11 +00:00
petru f13470096f Modified - Updated install-page administrator labels to super administrator wording. 2026-04-30 22:45:52 +00:00
petru 1e13af4d6e Modified - Added install-time admin management policy choices with direct-grantor and inherited-grantor enforcement.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
Modified - Updated the example app.ini documentation for the new administrator management policies.
2026-04-30 21:07:08 +00:00
petru 43161732e3 Modified - Restored normal self-edit access for super admins and disabled only the admin actions that are truly forbidden.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-30 17:19:49 +00:00
petru 80497e4194 Modified - Protected GOOD-granted admin accounts and blocked deleting the direct grantor.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-30 16:46:01 +00:00
petru 0cbec16f84 Modified - Protected GOOD-granted admin accounts and blocked deleting the direct grantor. 2026-04-30 16:45:56 +00:00
petru 22a6945b9d Modified - Protected GOOD-granted admin accounts and blocked deleting the direct grantor. 2026-04-30 16:45:31 +00:00
petru 5da24d2c7b Modified - Kept super administrator Edit and Delete controls visible but disabled for regular admins.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-30 04:19:49 +00:00
petru 0fc6f30a30 Fixed - Blocked regular administrators from editing super administrator accounts.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-30 04:12:54 +00:00
petru 35b9fa65d3 Fixed - Enabled super administrator bootstrap by default.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-30 03:33:30 +00:00
petru a14158b63a Added - Added persistent super administrator protection & Enabled super administrator bootstrap by default. 2026-04-30 02:40:17 +00:00
petru cff1b46f50 Fixed - Hidde Is Administrator reason unless admin rights were revoked.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-30 01:21:34 +00:00
petru 4aacf3bd20 Modified - Added admin actor badge beside the Is Administrator option.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-29 23:48:49 +00:00
petru 3afb4e8afa Fixed - Disabled critical self-edit account state checkboxes.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-29 22:14:55 +00:00
petru 067a09c2ac Added - Added Is Administrator reason and admin-grant badges.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-29 21:48:14 +00:00
petru 396b15372d Added - Added restricted-admin badges and reason actor badges.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-29 20:31:51 +00:00
petru b3204f3db6 Fixed - Corrected admin status reason behavior and reactivation emails.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-29 19:29:14 +00:00
petru 936ccf3738 Fixed - Corrected admin status reason behavior and reactivation emails. 2026-04-29 19:23:40 +00:00
petru 210955465e Added - Added admin status-change reasons and user email notifications.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-29 14:50:35 +00:00
petru 1dcd81b420 Added - Added Disable Sign-In metadata to the admin users list.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-29 14:19:31 +00:00
petru a8d9e5e659 Modified - Defaulted admin user purge checkboxes to enabled.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-29 09:34:05 +00:00
petru c7c7af77a1 Modified - Moved account request review controls to the top of the admin user edit panel.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
Fixed - Prevented empty `by` badges in the admin users list.
2026-04-29 09:15:48 +00:00
petru a3e09bb819 Modified - Added persistent admin email tooltip to creator badges.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
Add: Activated column show a `by <admin>` badge with the stored admin email as a hover tooltip.
2026-04-29 02:34:37 +00:00
petru cd96c721e0 Fixed - Kept creator-admin badges permanently attached to invited accounts.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-29 01:56:06 +00:00
petru cfd7cfa1dc Modified - Added a user creator-admin badges to the admins users list.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-29 00:11:55 +00:00
petru 8147f7a798 Added - Notified inviting admins when admin-created invitations are accepted.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-28 23:40:52 +00:00
petru 20405fe5e7 Added - Added admin-created account invitation flow when registration is disabled.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-28 22:38:38 +00:00
petru 25a1d84c2e Modified - Added password confirmation to account recovery.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-28 17:53:09 +00:00
petru f21b6b7a3b Blocked inactive account-request users from getting a signed-in session
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-28 10:26:11 +00:00
petru 8b14814199 Added an admin user-list delete account action button
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-28 08:24:22 +00:00
petru 62164e3fd8 Added inline test email feedback, keep page scroll position & display email delivery status messages.
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-27 21:29:17 +00:00
petru 1a438e765d admin registration confirm OK
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-27 15:47:14 +00:00
petru b2b024d0b6 feat(auth): add staged account request validation and admin review workflow
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-16 20:06:58 +00:00
petru 81727dd3e9 feat(admin): improve new account request notification safeguards
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
feat(admin): enforce fallback and subscription rules for new account request notifications
2026-04-16 18:36:45 +00:00
petru 97eee0a9a8 Added administrator notifications for pending account requests-Step1
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-16 15:06:54 +00:00
petru c3b9d21472 Disable last Admin to self delete
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-16 04:45:18 +00:00
petru 5c88e0bc76 Disable admin users to downgrade
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-16 03:08:35 +00:00
petru 4b334df6d4 Added Public/Private Badges & repos Settings links
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-16 01:19:40 +00:00
petru db1e8b4021 Added menu to smart-build.sh, fixed errors in some files
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-15 22:37:27 +00:00
petru eb0b9b2dee Add some fetch & builing scripts
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-15 21:11:20 +00:00
petru 6382652b70 Revert "some commit test"
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
This reverts commit 5fda0c3d01.
2026-04-14 22:32:42 +00:00
petru 5fda0c3d01 some commit test
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
2026-04-14 19:39:52 +00:00
wxiaoguang 893df6b265 Fix UI regression (#37218)
Fix  #37213

Also fix the misaligned tags, remove unused classes, etc.
2026-04-14 23:24:44 +08:00
wxiaoguang b9961e193d Fix corrupted JSON caused by goccy library (#37214)
Fix #37211
2026-04-14 14:00:20 +00:00
wxiaoguang 699eb41e7c Add test for "fetch redirect", add CSS value validation for external render (#37207)
By the way, fix the checkAppUrl message for #37212
2026-04-14 13:11:08 +00:00
Zettat123 9327b1808e Fix incorrect concurrency check (#37205)
This bug was identified in
https://github.com/go-gitea/gitea/pull/37119/changes#diff-37655a02d5a44d5c0e3e19c75fb58adb47a8e7835cbd619345d5b556292935a7L180

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
2026-04-14 12:34:41 +00:00
Copilot 84d5c99e64 refactor: simplify ParseCatFileTreeLine and catBatchParseTreeEntries (#37210)
Simplify ParseCatFileTreeLine: it is faster without the preset buffers,
and easier to read and maintain.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: wxiaoguang <2114189+wxiaoguang@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-14 12:03:26 +00:00
Sebastian Ertz b55528b1a2 Update go js py dependencies (#37204)
| go | from | to |
| --- | --- | --- |
| github.com/go-webauthn/webauthn | `0.16.3` | `0.16.4` |
| github.com/meilisearch/meilisearch-go | `0.36.1` | `0.36.2` |
| golang.org/x/crypto | `0.49.0` | `0.50.0` |
| golang.org/x/image | `0.38.0` | `0.39.0` |
| golang.org/x/net | `0.52.0` | `0.53.0` |
| golang.org/x/text | `0.35.0` | `0.36.0` |

| js | from | to |
| --- | --- | --- |
| @primer/octicons | `19.23.1` | `19.24.0` |
| @vitejs/plugin-vue | `6.0.5` | `6.0.6` |
| rolldown-license-plugin | `2.2.0` | `2.2.5` |
| vite | `8.0.7` | `8.0.8` |
| @types/node | `25.5.2` | `25.6.0` |
| @typescript-eslint/parser | `8.58.1` | `8.58.2` |
| @vitest/eslint-plugin | `1.6.14` | `1.6.15` |
| globals | `17.4.0` | `17.5.0` |
| stylelint | `17.6.0` | `17.7.0` |
| typescript-eslint | `8.58.1` | `8.58.2` |
| updates | `17.13.5` | `17.15.3` |
| vitest | `4.1.3` | `4.1.4` |

| py | from | to |
| --- | --- | --- |
| click | `8.3.1` | `8.3.2` |
| json5 | `0.13.0` | `0.14.0` |
| regex | `2026.2.19` | `2026.4.4` |
| tomli | `2.4.0` | `2.4.1` |
2026-04-14 12:45:54 +02:00
wxiaoguang 0593b58ff7 Add comment for the design of "user activity time" (#37195) 2026-04-13 20:01:29 +00:00
Mohit Swarnkar 37396fff13 fix(api): handle missing base branch in PR commits API (#37193)
Closes #36366

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-13 19:30:41 +00:00
wxiaoguang 6bcb666a9d Refactor htmx and fetch-action related code (#37186)
This is the first step (the hardest part):

* repo file list last commit message lazy load
* admin server status monitor
* watch/unwatch (normal page, watchers page)
* star/unstar (normal page, watchers page)
* project view, delete column
* workflow dispatch, switch the branch
* commit page: load branches and tags referencing this commit

The legacy "data-redirect" attribute is removed, it only makes the page
reload (sometimes using an incorrect link).

Also did cleanup for some devtest pages.
2026-04-13 18:53:55 +00:00
Nicolas 6eae04241d Fix encoding for Matrix Webhooks (#37190)
`url.PathEscape` unnecessarily encodes ! to %21, causing Matrix
homeservers to reject the request with 401. Replace %21 back to ! after
escaping.

Fixes #36012

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-13 18:10:43 +00:00
Xing Hong fa8f7f15ef Always show owner/repo name in compare page dropdowns (#37172)
Fixes: https://github.com/go-gitea/gitea/issues/36677

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-14 01:25:58 +08:00
Mohit Swarnkar 80585adab4 fix(api): handle fork-only commits in compare API (#37185)
Fix 500 error when comparing branches across fork repositories

## Problem

The compare API returns a 500 Internal Server Error when comparing
branches where the head commit exists only in the fork repository.

## Cause

The API was using the base repository's GitRepo and repository context
when converting commits. This fails when the commit does not exist in
the base repository, resulting in a "fatal: bad object" error.

## Solution

Use the head repository and HeadGitRepo when available to ensure commits
are resolved in the correct repository context.

## Result

* Fixes "fatal: bad object" error
* Enables proper comparison between base and fork repositories
* Prevents 500 Internal Server Error

Fixes #37168

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-12 18:52:46 -07:00
Nicolas 47fdf3e284 Improve Contributing docs and set a release schedule (#37109)
This PR updates `CONTRIBUTING.md` for clarity (code review, maintainers,
PR workflow)

## Suggestion

- majors about every **three months**, with a more predictable cadence
from **v1.26** onward.
- target dates such as **v1.26.0** (April 2026), **v1.27.0** (June
2026), **v1.28.0** (September 2026), **v1.29.0** (December 2026).
- announce feature freeze **two weeks** before each release.

## Other doc changes

- Reviewing PRs: separate guidance for reviewers vs authors; small edits
to maintaining PRs, merge queue, commit messages, co-authors.
- Maintainers: clearer subsections; links to GitHub Docs for 2FA / GPG.
- Split the Contributing.md into more useful markdown files

---------

Signed-off-by: Nicolas <bircni@icloud.com>
2026-04-12 11:26:02 -07:00
github-actions[bot] 355aafd1f9 Update Nix flake (#37183) 2026-04-12 16:51:54 +00:00
wxiaoguang c2fa157731 Remove outdated RunUser logic (#37180)
That logic is from 2014~2015, it unclear why it is necessary or 
whether it is still needed (whether Windows is still special)

The comment "so just use current one if config says default" is not
right anymore: "git" isn't the "default" value of RunUser (Comment out
app.example.ini #15807). The RunUser's value is from current session's
username.
2026-04-12 02:52:12 +00:00
wxiaoguang 8fcbdf05b0 Refactor flash message and remove SanitizeHTML template func (#37179)
1. Fix the "flash message" layout problem for different cases
* I am sure most of the users should have ever seen the ugly
center-aligned error message with multiple lines.
2. Fix inconsistent "Details" flash message EOL handling, sometimes
`\n`, sometimes `<br>`
   * Now, always use "\n" and use `<pre>` to render
3. Remove SanitizeHTML template func because it is not useful and can be
easily abused.
* But it is still kept for mail templates, for example:
https://github.com/go-gitea/gitea/issues/36049
4. Clarify PostProcessCommitMessage's behavior and add FIXME comment

By the way: cleaned up some devtest pages, move embedded style block to
CSS file
2026-04-12 10:17:25 +08:00
silverwind ba9258c478 Indicate form field readonly via background (#37175)
The `Run As Username` field on the install page was a `readonly` input
that looked editable but wasn't, confusing users. Style `readonly`
inputs with a subtle background, matching other frameworks.

Fixes: #37174
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-11 14:38:56 +00:00
silverwind d913fae237 Remove dead CSS rules (#37173)
Remove CSS rules whose HTML classes/IDs are no longer referenced in any
template, Go source, or JavaScript/TypeScript file:

- `.archived-icon`: removed from templates in c85bb62635
- `.bottom-line`: removed from blame rendering in 9c6aeb47f7
- `.commit-status-link`: removed from templates in f3c4baa84b
- `.instruct-toggle`: removed from templates in 75e85c25c1
- `.runner-new-text`, `#runner-new`: never referenced outside CSS
- `.ap-terminal`: stale, asciinema-player uses `.ap-term`, still not
needed
- `.scrolling.dimmable.dimmed`: dimmer stand-in never adds this class
- `.markup span.align-center/align-right/float-left/float-right`: never
produced by any renderer, sanitizer strips class attributes
- `.markup ul.no-list`, `.markup ol.no-list`: same as above

---
This PR was written with the help of Claude Opus 4.6

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-11 10:41:56 +00:00
silverwind 09c2677b21 Fix flaky TestCatFileBatch/QueryTerminated test (#37159)
`TestCatFileBatch/QueryTerminated` relied on timing to distinguish
`os.ErrClosed` vs `io.EOF` error paths. Replace `time.Sleep`-based
synchronization with a channel-based hook on pipe close, making both
error paths fully deterministic regardless of CI runner speed.

Ref: https://github.com/go-gitea/gitea/actions/runs/24193070536/job/70615366804
Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-10 17:34:12 +00:00
Elisei Roca 16d7817338 Implement logout redirection for reverse proxy auth setups (#36085)
When authentication is handled externally by a reverse proxy SSO
provider, users can be redirected to an external logout URL or relative
path defined on the reverse proxy.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-10 13:02:35 +00:00
silverwind 681c4074e5 Add missing //nolint:depguard (#37162)
When running `golangci-lint` without `GOEXPERIMENT=jsonv2`, a lint error
`import 'encoding/json' is not allowed` is seen.

All other files in the module that import `encodings/json` have
`//nolint` already, so add it.

---
This PR was written with the help of Claude Opus 4.6

Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com>
2026-04-10 10:39:28 +00:00
wxiaoguang 45c80bfec1 Make Markdown fenced code block work with more syntaxes (#37154) 2026-04-09 23:54:39 +00:00
wxiaoguang c10a5b908a Remove unneeded doctor sub-commands (#37156)
Co-authored-by: Giteabot <teabot@gitea.io>
2026-04-09 22:22:17 +02:00
Nicolas 980a8995bc Report structurally invalid workflows to users (#37116)
`model.ReadWorkflow` succeeds for YAML that is syntactically valid but
fails deeper parsing in `jobparser.Parse` (e.g. blank lines inside `run:
|` blocks cause a SetJob round-trip error). Add
`ValidateWorkflowContent` which runs the full `jobparser.Parse` to catch
these cases, and use it in the file view, the actions workflow list, and
the workflow detection loop so users see the error instead of silently
getting a 500 or a dropped workflow.

Fixes #37115
Signed-off-by: Nicolas <bircni@icloud.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-09 15:03:32 +02:00
silverwind 04fb6f1c0b Replace rollup-plugin-license with rolldown-license-plugin (#37130)
Replace `rollup-plugin-license` and `wrap-ansi` with
[`rolldown-license-plugin`](https://github.com/silverwind/rolldown-license-plugin),
a zero-dependency plugin with async parallel I/O and built-in word
wrapping.

- Removes `rollup-plugin-license` (pulls in `lodash`, `moment`) and
`wrap-ansi` from the dependency tree
- License build time reduced by ~40% (370ms vs 640ms)
- Added e2e test for `licenses.txt`

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com>
2026-04-09 09:31:05 +00:00
silverwind 0914a44a9b Clean up and improve non-gitea js error filter (#37148)
1. Filter out errors that contain `chrome-extension://` etc protocols
2. Extract filtering into its own function and test it
3. Fix the `window.config.assetUrlPrefix` mock, guaranteed to end with
`/assets`
4. Remove useless `??` and `?.` for properties that always exist

Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com>
2026-04-09 08:36:08 +00:00
Copilot 6f9fa55785 models/fixtures: add "DO NOT add more test data" comment to all yml fixture files (#37150)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: wxiaoguang <2114189+wxiaoguang@users.noreply.github.com>
2026-04-09 13:26:21 +08:00
Lunny Xiao 8bf3c8b79d Frontport changelog of v1.26.0-rc0 (#37138) 2026-04-08 22:43:28 +02:00
Sebastian Ertz dfd495f823 Update go dependencies (#37141)
|     | from | to  |
| --- | ---- | --- |
| github.com/aws/aws-sdk-go-v2/credentials | `v1.19.13` | `v1.19.14` |
| github.com/go-co-op/gocron/v2 | `v2.19.1` | `v2.20.0` |
| github.com/go-enry/go-enry/v2 | `v2.9.5` | `v2.9.6` |
| github.com/go-webauthn/webauthn | `v0.16.1` | `v0.16.3` |
| github.com/google/pprof | `v0.0.0-20260302011040-a15ffb7f9dcc` |
`v0.0.0-20260402051712-545e8a4df936` |
| github.com/lib/pq | `v1.12.1` | `v1.12.3` |
| github.com/mattn/go-isatty | `v0.0.20` | `v0.0.21` |
| github.com/mattn/go-sqlite3 | `v1.14.38` | `v1.14.42` |
| github.com/minio/minio-go/v7 | `v7.0.99` | `v7.0.100` |
| golang.org/x/sys | `v0.42.0` | `v0.43.0` |
| google.golang.org/grpc | `v1.79.3` | `v1.80.0` |
2026-04-08 19:07:17 +00:00
Sebastian Ertz 714f4207d9 Update javascript dependencies (#37142)
---

|     | from | to  |
| --- | ---- | --- |
| esbuild | `0.27.4` | `0.28.0` |
| katex | `0.16.44` | `0.16.45` |
| postcss | `8.5.8` | `8.5.9` |
| swagger-ui-dist | `5.32.1` | `5.32.2` |
| vite | `8.0.5` | `8.0.7` |
| vue | `3.5.31` | `3.5.32` |
2026-04-08 16:45:02 +00:00
silverwind d600968aaf Bump min go version to 1.26.2 (#37139)
Update Go from 1.26.1 to 1.26.2 to fix 6 stdlib vulnerabilities:
- GO-2026-4947: `crypto/x509` chain building
- GO-2026-4946: `crypto/x509` policy validation
- GO-2026-4870: `crypto/tls` KeyUpdate DoS
- GO-2026-4869: `archive/tar` unbounded allocation
- GO-2026-4866: `crypto/x509` name constraints bypass
- GO-2026-4865: `html/template` XSS

Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com>
2026-04-08 17:56:06 +02:00
Karthik Bhandary fc178e3203 Add bulk repository deletion for organizations (#36763)
Fixes #36512

This PR adds a new API endpoint to delete all repositories within an
organization in a single operation, improving efficiency for
organization cleanup and management tasks.

---------

Signed-off-by: Karthik Bhandary <34509856+karthikbhandary2@users.noreply.github.com>
Co-authored-by: karthik.bhandary <karthik.bhandary@kfintech.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-08 04:32:22 +00:00
GiteaBot 03205d94da [skip ci] Updated translations via Crowdin 2026-04-08 00:55:16 +00:00
419 changed files with 42306 additions and 14057 deletions
+358
View File
@@ -0,0 +1,358 @@
.
./types.d.ts
./docker
./docker/manifest.rootless.tmpl
./docker/root
./docker/manifest.tmpl
./docker/README.md
./docker/rootless
./BSDmakefile
./tests
./tests/integration
./tests/gitea-lfs-meta
./tests/mysql.ini.tmpl
./tests/e2e
./tests/testdata
./tests/fuzz
./tests/test_utils.go
./tests/sqlite.ini.tmpl
./tests/gitea-repositories-meta
./tests/pgsql.ini.tmpl
./tests/mssql.ini.tmpl
./eslint.json.config.ts
./LICENSE
./models
./models/repo.go
./models/avatars
./models/system
./models/auth
./models/migrations
./models/pull
./models/main_test.go
./models/fixtures
./models/asymkey
./models/packages
./models/unittest
./models/admin
./models/repo
./models/activities
./models/unit
./models/db
./models/dbfs
./models/shared
./models/webhook
./models/secret
./models/perm
./models/user
./models/renderhelper
./models/actions
./models/git
./models/organization
./models/issues
./models/repo_test.go
./models/project
./eslint.config.ts
./flake.lock
./tools
./tools/generate-svg-vscode-extensions.json
./tools/test-e2e.sh
./tools/code-batch-process.go
./tools/gocovmerge.go
./tools/lint-templates-svg.ts
./tools/generate-images.ts
./tools/codeformat
./tools/generate-svg.ts
./tools/test-echo.go
./tools/watch.sh
./vitest.config.ts
./CHANGELOG.md
./+x
./CODE_OF_CONDUCT.md
./CLAUDE.md
./README.zh-tw.md
./web_src
./web_src/svg
./web_src/fomantic
./web_src/js
./web_src/css
./CHANGELOG-archived.md
./custom
./custom/conf
./contrib
./contrib/systemd
./contrib/init
./contrib/update_dependencies.sh
./contrib/fhs-compliant-script
./contrib/launchd
./contrib/backport
./contrib/README
./contrib/legal
./contrib/supervisor
./contrib/options
./contrib/upgrade.sh
./contrib/ide
./contrib/gitea-monitoring-mixin
./templates
./templates/package
./templates/post-install.tmpl
./templates/status
./templates/devtest
./templates/projects
./templates/base
./templates/org
./templates/swagger
./templates/custom
./templates/admin
./templates/repo
./templates/shared
./templates/webhook
./templates/api
./templates/home.tmpl
./templates/install.tmpl
./templates/user
./templates/explore
./templates/mail
./update-gitea.sh
./flake.nix
./DCO
./MAINTAINERS
./routers
./routers/common
./routers/install
./routers/web
./routers/private
./routers/init.go
./routers/api
./routers/utils
./pnpm
./package.json
./snap
./snap/snapcraft.yaml
./services
./services/uinotification
./services/convert
./services/secrets
./services/wiki
./services/auth
./services/migrations
./services/pull
./services/projects
./services/repository
./services/markup
./services/oauth2_provider
./services/asymkey
./services/org
./services/task
./services/packages
./services/mailer
./services/forms
./services/issue
./services/webtheme
./services/attachment
./services/mirror
./services/versioned_migration
./services/agit
./services/context
./services/release
./services/doctor
./services/gitdiff
./services/webhook
./services/automerge
./services/contexttest
./services/cron
./services/user
./services/automergequeue
./services/feed
./services/actions
./services/git
./services/lfs
./services/notify
./services/indexer
./services/externalaccount
./go.mod
./assets
./assets/misspellings.csv
./assets/logo.svg
./assets/emoji.json
./assets/go-licenses.json
./assets/favicon.svg
./smart-build.sh
./Dockerfile.rootless
./build
./build/generate-go-licenses.go
./build/update-locales.sh
./build/generate-emoji.go
./build/generate-bindata.go
./build/generate-gitignores.go
./build/test-env-check.sh
./build/test-env-prepare.sh
./pyproject.toml
./updates.config.ts
./tsconfig.json
./pnpm-lock.yaml
./crowdin.yml
./SECURITY.md
./options
./options/locale
./options/gitignore
./options/fileicon
./options/label
./options/license
./options/readme
./docs
./docs/guideline-frontend.md
./docs/release-management.md
./docs/guideline-backend.md
./docs/community-governance.md
./playwright.config.ts
./cmd
./cmd/manager_logging.go
./cmd/admin_auth_ldap_test.go
./cmd/web_acme.go
./cmd/admin_user_delete.go
./cmd/admin_user_must_change_password_test.go
./cmd/admin_user_create.go
./cmd/admin_regenerate.go
./cmd/generate.go
./cmd/admin_auth.go
./cmd/dump.go
./cmd/admin_user_must_change_password.go
./cmd/doctor_test.go
./cmd/migrate.go
./cmd/admin_auth_oauth.go
./cmd/main_test.go
./cmd/actions.go
./cmd/cmd_test.go
./cmd/cert_test.go
./cmd/migrate_storage_test.go
./cmd/web_graceful.go
./cmd/doctor.go
./cmd/admin_user_delete_test.go
./cmd/embedded.go
./cmd/manager.go
./cmd/config.go
./cmd/admin_user_change_password.go
./cmd/cert.go
./cmd/hook_test.go
./cmd/web.go
./cmd/hook.go
./cmd/admin_auth_ldap.go
./cmd/admin_user_list.go
./cmd/admin_user_change_password_test.go
./cmd/admin_auth_smtp_test.go
./cmd/web_https.go
./cmd/docs.go
./cmd/admin_user_create_test.go
./cmd/migrate_storage.go
./cmd/admin_auth_oauth_test.go
./cmd/serv.go
./cmd/admin_user_generate_access_token.go
./cmd/admin.go
./cmd/config_test.go
./cmd/doctor_convert.go
./cmd/main.go
./cmd/dump_repo.go
./cmd/keys.go
./cmd/admin_user.go
./cmd/admin_auth_smtp.go
./cmd/restore_repo.go
./cmd/mailer.go
./cmd/cmd.go
./AGENTS.md
./README.zh-cn.md
./Dockerfile
./tailwind.config.ts
./Makefile
./README.md
./main.go
./go.sum
./uv.lock
./stylelint.config.js
./CONTRIBUTING.md
./modules
./modules/reqctx
./modules/public
./modules/references
./modules/httplib
./modules/hcaptcha
./modules/generate
./modules/tailmsg
./modules/turnstile
./modules/system
./modules/badge
./modules/eventsource
./modules/htmlutil
./modules/setting
./modules/fileicon
./modules/auth
./modules/migration
./modules/svg
./modules/repository
./modules/markup
./modules/typesniffer
./modules/test
./modules/web
./modules/pprof
./modules/validation
./modules/base
./modules/tempdir
./modules/zstd
./modules/gitrepo
./modules/packages
./modules/testlogger
./modules/process
./modules/templates
./modules/label
./modules/issue
./modules/dump
./modules/metrics
./modules/assetfs
./modules/nosql
./modules/avatar
./modules/updatechecker
./modules/private
./modules/cache
./modules/regexplru
./modules/gtprof
./modules/log
./modules/commitstatus
./modules/session
./modules/highlight
./modules/csv
./modules/proxy
./modules/queue
./modules/uri
./modules/httpcache
./modules/lfstransfer
./modules/options
./modules/webhook
./modules/secret
./modules/json
./modules/globallock
./modules/emoji
./modules/charset
./modules/recaptcha
./modules/user
./modules/paginator
./modules/proxyprotocol
./modules/actions
./modules/optional
./modules/structs
./modules/ssh
./modules/timeutil
./modules/glob
./modules/git
./modules/lfs
./modules/mcaptcha
./modules/util
./modules/sitemap
./modules/graceful
./modules/storage
./modules/cachegroup
./modules/hostmatcher
./modules/container
./modules/translation
./modules/indexer
./modules/analyze
./vite.config.ts
./main_timezones.go
+67
View File
@@ -0,0 +1,67 @@
# Gitea Codex Context
This file is Codex's persistent operating context for this repository.
Related orientation documents:
- Full project change log: `./.codex-history.md`
- Persistent implementation map: `./.codex-project-map.md`
- Raw structural baseline: `./.ai-structure.md`
## Recommended Read Order
1. `./.codex-context.md`
2. `./.codex-project-map.md`
3. The concrete files involved in the current task
4. `./.codex-history.md` only through targeted search, tags, or the latest relevant entries
## High-Value Project Anchors
- App entry point and default version wiring: `main.go`
- Web command and server startup: `cmd/web.go`
- Installed-instance initialization and route mounting: `routers/init.go`
- Main web router: `routers/web/web.go`
- Authentication handlers: `routers/web/auth/`
- Request context, session, template data, and response helpers: `services/context/`
- Domain business logic: `services/`
- Persistence, DB infrastructure, and migrations: `models/`, `models/db/`, `models/migrations/`
- Server-side UI templates: `templates/`
- Browser-side JS/CSS/frontend: `web_src/`
For detailed request flow, auth flow, extension points, and task-oriented entry points, use `./.codex-project-map.md` instead of duplicating them here.
## Persistent Workflow Rules
- Update `./.codex-history.md` after real project code changes.
- Do not add Codex-only preference or memory edits to `./.codex-history.md`.
- Do not reread unchanged context files within the same session unless the current task explicitly depends on them.
- Prefer targeted search in `./.codex-history.md` by keyword, tag, or subsystem before reading larger ranges.
- When the user asks for `revert`:
- first show the latest 10 commits as a numbered list with short descriptions;
- wait for the user's numeric choice before doing anything;
- if the target change is not committed, explain that the safe path is `git restore`, not `git revert`.
- Revert flows must stay non-destructive by default; prefer `git revert` for committed changes and avoid destructive reset-style actions unless the user explicitly asks for them.
## Persistent `.codex-history.md` Rules
- Numeric IDs are reserved only for real project code changes.
- IDs start at `0` and increase sequentially by `1`.
- Use the format `N - [YYYY-MM-DD HH:MM:SS]`.
- Store the real repository-derived application version, without a `Version:` label.
- Keep only the final consolidated result of a task; do not keep intermediate attempts or failed correction steps.
- Append to the same task only while the changes are consecutive follow-ups to the same problem.
- If unrelated tasks happened in between, record the new work as a new task even if it returns to the same area.
## Persistent Communication Preferences
- After finishing a task, respond briefly and directly unless there are blockers or problems.
- Re-check the rules in this file before and after making changes.
## Current Working Notes
- This workstation has limited CPU and RAM resources; prefer targeted, lower-scope test runs first and avoid unnecessarily heavy concurrent verification unless the task truly requires it.
- `main.go` defaults `setting.AppVer` to `development`; derive the real build/version string from the repository when writing `./.codex-history.md`.
- The repository is predictably split across `cmd/`, `routers/`, `services/`, `models/`, `templates/`, and `web_src/`, so changes should normally stay localized to one or two layers plus their tests.
- For custom release maintenance and repo-sync tasks, consult `./.codex-script-notes.md` before reanalyzing the large helper scripts.
- New UI-visible functionality in this fork often also requires locale updates, so UI tasks and related history searches should usually consider `options/locale/`, especially `locale_en-US.json` and any actively maintained translated locale files.
- History rule: all changes for the same `git describe` version must be recorded under the same `.codex-history.md` entry; create a new history entry only when the version string changes.
+903
View File
@@ -0,0 +1,903 @@
Project Change ID[date-time] - application-version - Type - Summary:
History search guidance:
- Prefer targeted search by task tag, subsystem keyword, or file/path before reading long ranges.
- Entries are tagged inline as `[tag] [tag]` to support targeted search and filtering.
0 - [2026-04-16 02:46:18] - v.1.27.0-dev-38-g4b334df6d4 - Type: Modified - [repo-ui] [visibility] [badges] Added explicit repository visibility badges to match the requested GitHub-style presentation more closely.
- 1 - I modified `templates/repo/header.tmpl` so the repository page header now always shows a visibility badge on the right side: `Private`, `Internal`, or `Public`.
- 2 - I modified `templates/shared/repo/list.tmpl` so each repository entry in shared repository lists also shows an explicit visibility badge for `Private`, `Internal`, or `Public`.
- 3 - I added the `Public` label for repositories that previously had no explicit visibility badge, while preserving the existing archived, template, and sha256 labels.
- 4 - I reused existing translation keys and existing badge styling so the change stays visually consistent with the current Gitea UI.
1 - [2026-04-16 03:31:29] - v.1.27.0-dev-38-g4b334df6d4 - Type: Modified - [repo-ui] [visibility] [badges] [repo-settings] Refined repository visibility badges with semantic colors, owner-aware navigation, and broader coverage in repository settings views.
- 1 - I modified `templates/shared/repo/list.tmpl` so `Public` now uses a basic green badge and `Private` now uses a basic red badge, while `Internal` remains neutral.
- 2 - I modified `templates/repo/header.tmpl` so the repository header uses the same color-coded visibility badges and keeps the mobile icon behavior unchanged.
- 3 - I added owner-aware navigation for the `Public` and `Private` badges so they link to the repository `Settings` page only when the signed-in user is the repository owner.
- 4 - I modified `templates/user/settings/repos.tmpl` so the same visibility badge now appears next to repository names in `/user/settings/repos`, in both list variants rendered by that page.
- 5 - I preserved the existing archived, template, fork, mirror, and object-format indicators so only the requested visibility presentation changed.
2 - [2026-04-16 03:45:08] - v.1.27.0-dev-38-g4b334df6d4 - Type: Fixed - [user-settings] Corrected a template rendering error in /user/settings/repos caused by dereferencing a missing Owner object.
- 1 - I fixed `templates/user/settings/repos.tmpl` so the internal-visibility check now guards against a nil `Owner` before accessing `Owner.Visibility`.
- 2 - I applied the null-safe visibility guard in both repository list variants rendered by `/user/settings/repos`.
- 3 - I preserved the new green/red visibility badge styling and owner-aware settings links while removing the nil-pointer render failure.
3 - [2026-04-16 04:53:24] - v.1.27.0-dev-38-g4b334df6d4 - Type: Modified - [admin-users] Hid the admin privilege toggle when an administrator edits their own account from the admin user edit page.
- 1 - I modified `templates/admin/user/edit.tmpl` so the `Is Administrator` checkbox is no longer rendered when the edited user ID matches the signed-in admin ID.
- 2 - I preserved the existing checkbox behavior for editing other users, so administrators can still grant or revoke admin rights for other accounts.
- 3 - I kept the change limited to the admin edit UI without altering unrelated fields or backend update logic.
4 - [2026-04-16 03:11:08] - v.1.27.0-dev-38-g4b334df6d4 - Type: Modified - [admin-users] [account-deletion] Disabled the self-account deletion option only for the last administrator and aligned the backend rule with that behavior.
- 1 - I modified `templates/user/settings/account.tmpl` so the `Delete Your Account` action is disabled and shows the last-admin warning when the signed-in user is the only remaining admin.
- 2 - I modified `routers/web/user/setting/account.go` so the account settings page now receives an `IsLastAdminUser` flag used by the template.
- 3 - I updated the self-delete backend flow so it blocks account deletion only when the signed-in user is the last admin, instead of blocking every admin unconditionally.
5 - [2026-04-16 03:26:40] - v.1.27.0-dev-38-g4b334df6d4 - Type: Fixed - [admin-users] [account-deletion] Adjusted the shared last-admin detection to count only active administrators so account deletion and admin demotion rules behave correctly in real instances.
- 1 - I modified `models/user/user.go` so `IsLastAdminUser` now treats only active admins as candidates when deciding whether a user is the last admin.
- 2 - This aligns the shared last-admin protection used by account deletion and admin privilege update flows with practical instance behavior.
- 3 - The existing `/user/settings/account` UI and backend guards now work against the refined active-admin definition without additional template changes.
6 - [2026-04-16 03:43:20] - v.1.27.0-dev-38-g4b334df6d4 - Type: Modified - [user-settings] [admin-users] [account-deletion] [ui] Updated the Delete Your Account panel for the last-admin case so it shows a direct warning message and hides the deletion controls.
- 1 - I modified `templates/user/settings/account.tmpl` so the panel now shows `You cannot remove the last admin. There must be at least one admin.` while keeping the existing alert icon.
- 2 - I hid the `Password` field for the last-admin case.
- 3 - I hid the `Confirm Deletion` button for the last-admin case while preserving the normal delete flow for other users.
7 - [2026-04-16 17:37:53] - v.1.27.0-dev-40-gc3b9d21472 - Type: Added - [auth] [account-requests] [mailer] [locale] [en] Added administrator notifications for pending account requests and delayed the user activation email until manual approval.
- 1 - I added a new `email_notification.new_account_requests` user setting in `models/user/setting_options.go`, with an admin-default enabled preference and helper functions to read the preference consistently.
- 2 - I modified `routers/web/user/setting/notifications.go`, `routers/web/web.go`, and `templates/user/settings/notifications.tmpl` so administrators now get a `New account request notifications` checkbox in `/user/settings/notifications`, and the last active admin cannot disable it.
- 3 - I modified `routers/web/auth/auth.go`, `services/mailer/mail_user.go`, `templates/mail/user/auth/new_account_request.tmpl`, and `options/locale/locale_en-US.json` so manual account requests now send notification emails to opted-in active admins with a direct review link.
- 4 - I modified `routers/web/admin/users.go` so when an administrator activates a manually approved account while registration email confirmation is disabled, the applicant receives the standard account activation email at that approval moment.
8 - [2026-04-16 18:59:58] - v.1.27.0-dev-41-g97eee0a9a8 - Type: Fixed - [account-requests] [locale] [en] Corrected the new account request notification rule so at least one active administrator must remain subscribed.
- 1 - I modified `models/user/setting_options.go` to count active administrators who still have new account request notifications enabled and to detect when the current admin is the last enabled recipient.
- 2 - I modified `routers/web/user/setting/notifications.go` so the backend now blocks disabling the preference only when the signed-in admin is the last enabled notification recipient, instead of checking whether they are merely the last admin user.
- 3 - I modified `templates/user/settings/notifications.tmpl` so the checkbox and submit button are disabled only for the last enabled notification recipient.
- 4 - I updated `options/locale/locale_en-US.json` so the warning message now states the real rule clearly: at least one admin must keep these notifications enabled.
9 - [2026-04-16 20:53:32] - v.1.27.0-dev-41-g97eee0a9a8 - Type: Added - [account-requests] Added automatic notification fallback when deleting the only admin who still receives new account request notifications.
- 1 - I added `ShouldEnableNewAccountRequestNotificationsFallback` in `models/user/setting_options.go` so the code can detect when the deleted user is the last active admin with this notification enabled and the acting admin is currently unsubscribed.
- 2 - I modified `routers/web/admin/users.go` so, after a successful admin-driven user deletion, the acting admin is automatically subscribed to new account request notifications when they deleted the last subscribed admin.
- 3 - I modified `routers/api/v1/admin/user.go` so the same automatic fallback also applies to admin deletions performed through the API, keeping the behavior consistent across both deletion entry points.
10 - [2026-04-16 23:02:55] - v.1.27.0-dev-42-g81727dd3e9 - Type: Added - [account-requests] [mailer] [locale] [en] Implemented a staged new account request workflow with email validation, admin review, request statuses, and automatic expiry cleanup.
- 1 - I added `models/user/account_request.go` to store and manage account request states, validation expiry, retry counting, approval or rejection metadata, validation code generation, and expired pending-request cleanup.
- 2 - I modified `routers/web/auth/auth.go`, added `routers/web/auth/account_request.go`, and updated `templates/user/auth/signup_inner.tmpl` so registration now creates pending account requests, resends validation mail when appropriate, blocks repeated unconfirmed attempts after five tries, and moves validated requests into administrator review instead of activating them immediately.
- 3 - I modified `routers/web/admin/users.go`, added `routers/web/admin/account_request.go`, updated `routers/web/web.go`, and updated `templates/admin/user/edit.tmpl` so administrators can see the account request status for a user and explicitly activate, reject, or unblock requests from the admin user edit page.
- 4 - I modified `services/mailer/mail_user.go`, added the new account request mail templates, updated `options/locale/locale_en-US.json`, and modified `services/user/user.go` with `services/cron/tasks_extended.go` so the workflow now sends dedicated validation, approval, and rejection emails, preserves rejected or blocked accounts from inactive-user cleanup, and automatically deletes only expired requests that never completed email validation.
11 - [2026-04-16 23:18:45] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [account-requests] [locale] [en] Added the missing admin dashboard translation entries for the expired account request cleanup cron task.
- 1 - I modified `options/locale/locale_en-US.json` to add `admin.dashboard.delete_expired_account_requests` so the new cron task can be rendered correctly in the admin dashboard task list.
- 2 - I added `admin.dashboard.delete_expired_account_requests.started` alongside it so the matching task start message is also available and the cron task follows the same translation pattern as the existing dashboard tasks.
- 3 - I verified the locale file remains valid JSON after the change.
12 - [2026-04-17 00:05:29] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [account-requests] [mailer] [signup] Hardened the account request validation email flow so manual approval registrations do not silently skip or hide validation mail failures.
- 1 - I modified `routers/web/auth/auth.go` so the `RegisterManualConfirm` path now runs before the generic activation shortcut for normal self-registrations, while still preserving the first-user bootstrap exception.
- 2 - I modified `services/mailer/mail_user.go` so account request validation, approval, and rejection emails now return explicit errors when their templates cannot be rendered instead of failing silently.
- 3 - I modified `routers/web/auth/account_request.go` and `routers/web/admin/account_request.go` so resend and unblock flows now surface validation-email rendering failures immediately, while approval and rejection actions log mail errors without rolling back the already completed admin decision.
- 4 - I verified the updated flow builds cleanly after formatting with compile-only Go tests on the touched packages.
13 - [2026-04-17 00:53:04] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [account-requests] [mailer] Reworked the first-user bootstrap path so manual confirmation sends the validation email instead of bypassing the new account request flow.
- 1 - I modified `routers/web/auth/auth.go` so the automatic first-user admin bootstrap now only bypasses email handling when manual confirmation is disabled, while manual-confirm registrations still go through the validation email path.
- 2 - I modified `routers/web/auth/account_request.go` so when the validated account is the only user in the instance, the system activates it directly and grants admin rights immediately instead of sending it into an impossible admin-review deadlock.
- 3 - I preserved the normal staged workflow for all non-bootstrap registrations, so other users still go from email validation to pending admin review as before.
- 4 - I formatted the code and verified the touched packages with compile-only Go tests after the bootstrap flow change.
14 - [2026-04-17 01:14:35] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Added - [account-requests] [admin-users] [mailer] [locale] [en] Added an admin-side validation email send indicator with success or failure icon and attempt timestamp.
- 1 - I modified `models/user/account_request.go` to persist the last validation email attempt status and timestamp for each account request.
- 2 - I modified `routers/web/auth/auth.go`, `routers/web/auth/account_request.go`, and `routers/web/admin/account_request.go` so initial send, resend, and unblock flows now record whether the validation email send function returned success or error.
- 3 - I modified `routers/web/admin/account_request.go` and `templates/admin/user/edit.tmpl` so the account request panel in the admin user edit page now shows a `✔` or `❌` together with the last validation email attempt timestamp.
- 4 - I updated `options/locale/locale_en-US.json`, validated the JSON file, formatted the code, and verified the touched packages with compile-only Go tests.
15 - [2026-04-17 06:26:17] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [account-requests] [mailer] [ui] [signup] Extended the validation email attempt indicator so it is visible in the user-facing registration flow as well as in the admin account request panel.
- 1 - I modified `routers/web/auth/account_request.go` and `routers/web/auth/auth.go` so the last validation email attempt status and timestamp are loaded into the user-facing signup retry and activation prompt pages.
- 2 - I modified `templates/user/auth/signup_inner.tmpl` so the `✔` or `❌` indicator and timestamp now appear next to the pending request message and beside the `Resend` button area.
- 3 - I modified `templates/user/auth/activate_prompt.tmpl` so the same indicator and timestamp now appear after the initial validation email attempt triggered by account creation.
- 4 - I adjusted `templates/admin/user/edit.tmpl` so the admin panel also shows the indicator when there is mail-attempt data even if the current account request status line is otherwise absent.
16 - [2026-04-17 07:05:39] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [account-requests] [mailer] Switched the account request validation email to a real synchronous send path and added logging for silent mail queue enqueue failures.
- 1 - I modified `services/mailer/mail_user.go` so `SendAccountRequestValidationMail` now uses a synchronous sender path instead of only enqueueing the message asynchronously.
- 2 - I modified `services/mailer/mailer.go` to add `SendImmediately`, which uses the initialized configured sender directly and returns the real SMTP or sendmail error back to the caller.
- 3 - I modified `services/mailer/mailer.go` so `SendAsync` now logs queue initialization and enqueue failures instead of silently discarding them.
- 4 - This makes the new-user validation mail behave much closer to `SendTestMail`, which was already using direct sending and was one likely reason test emails succeeded while queued validation emails still appeared to disappear.
17 - [2026-04-17 08:20:46] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [auth] [mailer] Switched the remaining user-facing activation emails to synchronous delivery and stopped showing success when the actual send fails.
- 1 - I modified `services/mailer/mail_user.go` so `SendActivateAccountMail` and `SendActivateEmailMail` now return real errors and use direct synchronous sending instead of only queueing the message.
- 2 - I modified `services/mailer/mail_user.go` so account request approval and rejection emails sent to the user now use the same synchronous delivery path for consistent behavior.
- 3 - I modified `routers/web/auth/auth.go` and `routers/web/user/setting/account.go` so signup and email-confirmation flows stop reporting success when the mail send to the user fails.
- 4 - I modified `routers/web/admin/users.go` so administrator-triggered account activation now logs and warns when the activation email to the user could not be sent.
18 - [2026-04-17 18:54:53] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [auth] [account-requests] [signup] [locale] [en] Refined the account request resend UX so pending users can retry from both activation and signup pages without losing their entered registration data.
- 1 - I modified `templates/user/auth/activate_prompt.tmpl` so the activation page now shows a separate `Did not receive the email?` prompt, a standalone `Resend` button under the mail status indicator, and a Spam/Junk reminder.
- 2 - I modified `templates/user/auth/signup_inner.tmpl` so the pending-registration panel now uses plain prompt text plus a dedicated `Resend` button instead of the combined button label, while also preserving the signup form values through the resend action.
- 3 - I modified `models/user/account_request.go` and `routers/web/auth/account_request.go` so account request validation emails now track up to five resend actions and automatically hide the resend button after that limit is reached.
- 4 - I modified `routers/web/auth/auth.go` and `options/locale/locale_en-US.json` so the activation prompt receives the same resend controls immediately after registration and the new texts are available consistently across both user-facing flows.
19 - [2026-04-17 22:10:39] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [auth] [account-requests] [mailer] [signup] Prevented invalid signup email input from triggering an internal server error in the account request pre-check flow.
- 1 - I modified `models/user/account_request.go` so `GetUserByAnyEmail` now trims and validates the email address before querying, reusing the normal email validation behavior instead of treating malformed input like a server-side lookup problem.
- 2 - I modified `routers/web/auth/account_request.go` so the signup pre-check now treats invalid or unsupported email formats as normal invalid input and lets the standard registration validation flow handle the user-facing error message.
- 3 - I modified `routers/web/auth/account_request.go` so the resend endpoint also treats malformed email input as unavailable instead of escalating it into a 500 error.
20 - [2026-04-17 23:13:17] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [mailer] [signup] [locale] [en] Rolled back newly created self-registration accounts when the initial confirmation email cannot actually be sent.
- 1 - I modified `routers/web/auth/auth.go` so `createAndHandleCreatedUser` now passes the template and form context into the post-create flow, allowing failed registration emails to return a normal form error instead of a 500 page.
- 2 - I modified `routers/web/auth/auth.go` so the initial account-request validation mail and the initial standard activation mail both delete the newly created user if sending fails, preventing orphaned accounts from being left in the database.
- 3 - I added a dedicated `auth.confirmation_mail_failed` user-facing message in `options/locale/locale_en-US.json` so registration now tells the user that the account was not created because the confirmation email could not be sent.
- 4 - I preserved the existing resend behavior for already created inactive users, so the rollback applies only to the first mail send during new self-registration.
21 - [2026-04-26 22:55:56] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [scripts] [smart-build] Updated the smart build script for PNPM 10 and the repository frontend build flow.
- 1 - I modified `smart-build.sh` to remove the unsupported `--ignore-engines` PNPM option from dependency installation.
- 2 - I changed the frontend rebuild step to call `make frontend`, matching the Gitea Makefile target instead of calling a missing `pnpm run build` script.
- 3 - I fixed the architecture menu echo line so `Initialization checks` is no longer appended as stray shell text.
22 - [2026-04-26 23:01:28] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [scripts] [smart-build] Made the smart build script find the local Go toolchain before running backend builds.
- 1 - I modified `smart-build.sh` to prepend `/usr/local/go/bin` to `PATH` when the local Go binary exists.
- 2 - I added an early Go availability check so the script stops with a clear message before invoking `make build` if Go is not installed or visible.
- 3 - I added explicit failure handling for dependency installation and frontend asset builds so the script does not continue after a failed prerequisite step.
23 - [2026-04-26 23:20:08] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [scripts] [smart-build] [bindata] Added a smart build menu option for SQLite-enabled bindata builds.
- 1 - I modified `smart-build.sh` to add a build-tag selection menu with the existing `bindata` build and a new `bindata sqlite sqlite_unlock_notify` option.
- 2 - I changed the backend build command to use the selected tag set instead of always passing `TAGS="bindata"`.
- 3 - I made SQLite builds enable CGO and write artifacts with a `-sqlite` suffix so they are distinguishable from default bindata builds.
24 - [2026-04-27 00:18:15] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [account-requests] [auth] Made account request validation links robust after account data changes.
- 1 - I modified `models/user/account_request.go` so account request validation codes can be stored as hashes and later accepted as a fallback when the stateless code can no longer be recalculated from current user data.
- 2 - I modified the registration, resend, and admin unblock flows to generate one validation code, send that exact code by email, and store its hash only after the email send succeeds.
- 3 - I cleared stored validation-code hashes when account requests are reset, validated, or approved so old validation links cannot keep working after the request leaves email validation.
- 4 - I added focused tests for account request code verification and `/user/activate` handling, including the case where user data changes after the validation email is sent.
25 - [2026-04-27 00:49:34] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [account-requests] [signup] [auth] Corrected pending account request detection for validation links and repeated registration attempts.
- 1 - I modified account request status detection so inactive users with validation markers are treated as pending email validation even if `account_request.status` is missing.
- 2 - I added a dedicated account-request time-limit code purpose while keeping compatibility with older account-request links, preventing normal activation links from being intercepted by the account request path.
- 3 - I moved the pending account request pre-check before generic signup form errors so repeated registration attempts show the pending-request message and resend option instead of `The username is already taken`.
- 4 - I updated the pending signup message to include the email address that received the validation email and added focused tests for missing-status validation, classic activation separation, and repeated registration.
26 - [2026-04-27 01:10:03] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [account-requests] Restored the admin account request review flow link to the page with approval controls.
- 1 - I modified `services/mailer/mail_user.go` so new account request notification emails now link directly to `/-/admin/users/{id}/edit`, where the `Activate Request` and `Reject` controls are rendered.
- 2 - I added a focused mailer test to ensure future account request notifications keep pointing to the admin edit page instead of the read-only user view page.
27 - [2026-04-27 01:47:34] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [admin-users] [account-deletion] Hid admin-side account deletion controls for the last active administrator.
- 1 - I modified `routers/web/admin/users.go` so the admin user edit page receives `IsLastAdminUser` for the edited user.
- 2 - I modified `templates/admin/user/edit.tmpl` so `Delete User Account` is replaced by the existing last-admin warning when the edited user is the only active admin.
- 3 - I hid the admin delete confirmation modal for the last-admin case while preserving the backend `DeleteUser` last-admin guard as the final protection.
28 - [2026-04-27 02:06:06] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [admin-users] [account-deletion] Kept last-admin account deletion actions visible but disabled.
- 1 - I modified `templates/admin/user/edit.tmpl` so `Delete User Account` remains visible as a disabled button for the last active admin while showing the existing last-admin warning.
- 2 - I modified `templates/user/settings/account.tmpl` so the self-delete confirmation button remains visible as disabled for the last active admin while showing the same warning.
- 3 - I kept delete confirmation modals unavailable for the disabled last-admin actions so blocked actions cannot be submitted from the UI.
29 - [2026-04-27 09:12:11] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [admin-users] Adjusted last-admin delete warning placement and spacing.
- 1 - I modified `templates/admin/user/edit.tmpl` so the last-admin warning appears above the disabled `Delete User Account` button with vertical spacing.
- 2 - I modified `templates/user/settings/account.tmpl` so the disabled self-delete confirmation button has spacing below the warning message.
30 - [2026-04-27 09:28:16] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [admin-users] [ui] Restored admin edit action button alignment while keeping the last-admin warning above them.
- 1 - I modified `templates/admin/user/edit.tmpl` so the last-admin warning appears above the action button row.
- 2 - I kept `Update Profile` and the disabled `Delete User Account` button in the same button row and original order.
31 - [2026-04-27 10:07:15] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [account-requests] Adjusted account request resend button sizing and delivery-state feedback.
- 1 - I modified the pending signup and activation prompt templates so the resend button is smaller, blue by default, and spaced away from the spam-folder hint.
- 2 - I added resend result state rendering so successful sends turn the button green for five seconds and failed sends keep it red.
- 3 - I changed the resend handler to re-render the current account-request page with a failed send message instead of showing a server-error page when email delivery fails.
32 - [2026-04-27 14:41:33] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Added - [scripts] [build-env] Added a build environment configuration script.
- 1 - I added `configure.sh` to install and verify the system packages, Go version, Node version, pnpm version, and frontend dependencies required by this Gitea tree.
- 2 - I made the script read the required Go, Node, and pnpm versions from `go.mod` and `package.json`, while still allowing environment overrides.
- 3 - I added an optional `--with-cross-cgo` mode that installs/configures the heavier cross-CGO toolchains needed for SQLite builds targeting linux/armv7 and windows/amd64.
33 - [2026-04-27 14:51:16] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [scripts] [build-env] Added an interactive run menu to the build environment configuration script.
- 1 - I modified `configure.sh` so running it without arguments in an interactive terminal shows a description of what the script installs and verifies.
- 2 - I added a run menu with Normal, With cross cgo, Verify only, and Quit options.
- 3 - I added a `--menu` flag so the same interactive menu can be requested explicitly while keeping the existing command-line options for automated runs.
34 - [2026-04-27 14:59:01] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [scripts] [build-env] Made interactive environment verification report missing requirements without failing the menu run.
- 1 - I modified `configure.sh` so the interactive `Verify only` menu option lists all detected missing commands and configuration issues instead of stopping at the first missing requirement.
- 2 - I kept the direct `./configure.sh --verify-only` mode strict for automated checks, returning a failure when requirements are missing.
- 3 - I adjusted the final interactive verification message so it recommends rerunning the menu with Normal or With cross cgo instead of suggesting a build when requirements are still missing.
35 - [2026-04-27 15:20:01] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [scripts] [build-env] Translated the build environment configuration script text to English.
- 1 - I modified `configure.sh` so the interactive description is written in English.
- 2 - I translated the interactive menu option descriptions to English while keeping the existing script behavior unchanged.
36 - [2026-04-27 19:28:55] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [mailer] [mailer-ui] Moved test email feedback inline and aligned mail action button states.
- 1 - I modified `routers/web/admin/config.go` so the test email result redirects back to the config page with local test-mail state instead of using the global flash alert.
- 2 - I modified `templates/admin/config.tmpl` so the test email result appears beside the `Send` button, with the button using primary, green, or red state colors.
- 3 - I changed the account request `Resend` button default state from `blue` to `primary` so it uses the same visible blue styling as the rest of the Gitea UI.
37 - [2026-04-27 19:56:31] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [mailer] [mailer-ui] [scripts] [bindata] Forced mail action button colors and refreshed local template bindata.
- 1 - I modified the admin test mail and account request resend templates so their default, success, and failure colors are set directly with Gitea theme variables.
- 2 - I updated the success timeout scripts to restore the direct primary-color styling after five seconds.
- 3 - I regenerated the local ignored `modules/templates/bindata.dat` file so local bindata builds can include the updated templates.
38 - [2026-04-27 20:05:18] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [scripts] [smart-build] [bindata] Added bindata freshness checks to the smart build script.
- 1 - I modified `smart-build.sh` so bindata builds check the generated templates, options, public, and migration schema bindata files before compilation.
- 2 - I made the script regenerate any missing or stale bindata file with `go generate -tags bindata` before running `make build`.
- 3 - I kept the regeneration step neutral from cross-build environment variables by clearing `GOOS`, `GOARCH`, `CGO_ENABLED`, and `CC` for the go generate command.
39 - [2026-04-27 20:35:07] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [mailer] [mailer-ui] [admin-config] [ui] [sticky-layout] Preserved scroll position after sending a test email from the admin config page.
- 1 - I modified `templates/admin/config.tmpl` so the test email form records the current scroll position before submit.
- 2 - I modified `routers/web/admin/config.go` so the test email redirect carries the saved scroll position and returns to the local test-email anchor.
- 3 - I regenerated the local ignored `modules/templates/bindata.dat` file so bindata builds can include the scroll-preserving template update.
40 - [2026-04-27 21:03:25] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [mailer] [mailer-ui] [admin-config] [ui] Removed page reload and scroll movement from the admin test email action.
- 1 - I modified `templates/admin/config.tmpl` so the `Send Testing Email` form submits through `fetch` and updates the inline message without changing the page URL or scroll position.
- 2 - I modified `routers/web/admin/config.go` so inline test email requests return JSON state and message data instead of redirecting.
- 3 - I regenerated the local ignored `modules/templates/bindata.dat` file so bindata builds can include the no-jump test email behavior.
41 - [2026-04-27 21:14:20] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [mailer] [mailer-ui] [admin-config] Shortened admin test email delivery error messages.
- 1 - I modified `routers/web/admin/config.go` so `Send Testing Email` displays a concise SMTP failure reason instead of the full command chain.
- 2 - I added normalization for common mail errors such as user unknown, mailbox unavailable, relay access denied, and authentication failure.
- 3 - I added a focused unit test for the short test mail error formatter.
42 - [2026-04-27 21:47:26] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Added - [admin-users] [account-deletion] Added an admin user-list delete account action.
- 1 - I modified `templates/admin/user/list.tmpl` so each user row now shows a red trash icon beside the existing User Details and Edit actions.
- 2 - I added a shared delete-account confirmation modal on the user management list, including the existing purge option and delete-account warning text.
- 3 - I regenerated the local ignored `modules/templates/bindata.dat` file so bindata builds can include the new list action.
43 - [2026-04-27 22:17:13] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Modified - [admin-users] Matched the admin user-list delete action to the edit-page delete state.
- 1 - I modified `routers/web/explore/user.go` so user search pages can receive optional per-user extra data before rendering.
- 2 - I modified `routers/web/admin/users.go` so the admin user list marks rows where the user is the last active administrator using the same condition as the edit page.
- 3 - I modified `templates/admin/user/list.tmpl` so the trash icon is disabled with the existing last-admin warning tooltip whenever the edit-page `Delete User Account` button would be disabled.
44 - [2026-04-28 09:12:49] - v.1.27.0-dev-43-gb2b024d0b6 - Type: Fixed - [auth] [account-requests] Blocked inactive account-request users from getting a signed-in session.
- 1 - I modified the password sign-in flow so inactive account-request users are stopped before session, 2FA, or remember-cookie creation and are shown the activation prompt instead.
- 2 - I added account-request login prompts for pending email validation, pending admin review, rejected, and blocked states, while keeping the resend button available only for pending email validation.
- 3 - I modified existing inactive signed sessions on web pages to be signed out before rendering the activation/account-request prompt so the account menu and Sign Out action are not shown.
- 4 - I added targeted auth tests for pending email validation and pending admin review login attempts, including username and email login for the validation case.
- 5 - I regenerated the local ignored `modules/options/bindata.dat` file so bindata builds can include the new login prompt locale string.
45 - [2026-04-28 16:01:28] - v1.27.0-dev-47-gf21b6b7a3b - Type: Modified - [auth] [recovery] Added password confirmation to account recovery.
- 1 - I modified `templates/user/auth/reset_passwd.tmpl` so the account recovery reset form includes a required `Confirm Password` field.
- 2 - I modified `routers/web/auth/password.go` so reset submissions reject mismatched passwords before two-factor checks or password updates.
- 3 - I added a focused auth test for mismatched recovery password confirmation and regenerated the local ignored `modules/templates/bindata.dat` file for bindata builds.
46 - [2026-04-28 19:05:06] - v1.27.0-dev-48-g25a1d84c2e - Type: Fixed - [auth] [recovery] Used the reset-password lifetime for account recovery codes.
- 1 - I modified `models/user/user.go` so reset-password time-limit codes are generated and verified with `RESET_PASSWD_CODE_LIVE_MINUTES` instead of `ACTIVE_CODE_LIVE_MINUTES`.
- 2 - I kept activation, email activation, and account-request time-limit codes on the existing active-code lifetime.
- 3 - I added a focused user-model test that proves reset-password codes remain valid when only `RESET_PASSWD_CODE_LIVE_MINUTES` allows them.
47 - [2026-04-28 20:31:34] - v1.27.0-dev-48-g25a1d84c2e - Type: Added - [admin-invite] [admin-created-user] [signup] Added admin-created account invitation flow when registration is disabled.
- 1 - I modified admin user creation so `DISABLE_REGISTRATION = true` creates inactive, sign-in-prohibited accounts and checks `Send User Registration Notification` by default when mail is configured.
- 2 - I added a 24-hour admin invitation token and email template that lets the invited user accept the account, activate the email, and clear `Disable Sign-In`.
- 3 - I added targeted tests for invitation token lifetime, invitation acceptance, and disabled-registration admin account creation defaults, then regenerated local ignored template and options bindata.
48 - [2026-04-28 21:56:08] - v1.27.0-dev-48-g25a1d84c2e - Type: Modified - [scripts] [smart-build] Added smart-build load profile options.
- 1 - I modified `smart-build.sh` so it asks for a build load profile before dependency checks, frontend build, bindata generation, and Go compilation.
- 2 - I added Moderate and Low Resource profiles that set `GOMAXPROCS`, `MAKEFLAGS=-j1`, and a conservative Node memory limit to reduce CPU and RAM pressure.
- 3 - I kept the Normal profile available for the existing unrestricted build behavior.
49 - [2026-04-28 23:00:25] - v1.27.0-dev-49-g20405fe5e7 - Type: Added - [admin-invite] Notified inviting admins when admin-created invitations are accepted.
- 1 - I stored the creator admin ID on disabled-registration admin-created invitation accounts so the invitation acceptance flow knows who to notify.
- 2 - I added an invitation-accepted email template and mailer function that sends the accepting user's details back to the admin who created the account.
- 3 - I updated targeted admin/auth tests and regenerated local ignored template and options bindata for the new email template and locale strings.
50 - [2026-04-28 23:52:04] - v1.27.0-dev-50-g8147f7a798 - Type: Modified - [admin-created-user] [admin-users] [badges] Added creator-admin badges to the admin users list.
- 1 - I modified the admin user list data loader so users created through the disabled-registration invitation flow include the admin creator name.
- 2 - I modified `templates/admin/user/list.tmpl` so the Created column shows a `by <admin>` mini badge next to the creation date when creator data exists.
- 3 - I added a focused admin list test for the creator-admin mapping and regenerated local ignored template bindata.
51 - [2026-04-29 01:55:04] - v1.27.0-dev-51-gcfd7cfa1dc - Type: Fixed - [admin-invite] [admin-created-user] [badges] Kept creator-admin badges permanently attached to invited accounts.
- 1 - I modified the admin invitation acceptance notification flow so it no longer deletes the stored creator-admin ID.
- 2 - I updated the invitation acceptance test to assert the creator-admin marker remains after the user accepts the invitation.
52 - [2026-04-29 02:04:41] - v1.27.0-dev-52-gcd96c721e0 - Type: Modified - [admin-created-user] [badges] [mailer] Added persistent admin email tooltip to creator badges.
- 1 - I modified admin-created invitation account storage so it permanently saves the creator admin ID, username, and email address.
- 2 - I modified the admin users list creator badge so it shows `by <admin>` and exposes the stored admin email as a hover tooltip.
- 3 - I updated the focused admin list tests to prove the badge data still renders from stored name/email even without looking up the admin account, then regenerated local ignored template bindata.
53 - [2026-04-29 02:30:55] - v1.27.0-dev-52-gcd96c721e0 - Type: Modified - [auth] [admin-created-user] [badges] Added admin activation badges and first-admin GOD badge.
- 1 - I modified the admin users list so the Activated column can show a `by <admin>` badge with the stored admin email as a hover tooltip.
- 2 - I stored admin activation ID, username, and email address when account requests are approved or inactive users are manually activated by an admin.
- 3 - I added the special `by GOD` Created-column badge for the first admin account, updated focused admin list tests, and regenerated local ignored template bindata.
54 - [2026-04-29 08:25:36] - v1.27.0-dev-53-ga3e09bb819 - Type: Fixed - [admin-users] [badges] Prevented empty `by` badges in the admin users list.
- 1 - I changed the admin users list badge maps to use pointer values so missing entries render as empty instead of truthy zero-value structs.
- 2 - I guarded the Created and Activated badge rendering so badges only appear when a display name exists.
- 3 - I reran the focused admin badge tests and regenerated local ignored template bindata.
55 - [2026-04-29 09:02:42] - v1.27.0-dev-53-ga3e09bb819 - Type: Modified - [account-requests] [admin-users] [ui] Moved account request review controls to the top of the admin user edit panel.
- 1 - I moved the account request status message to the top of the admin user edit segment, immediately under the panel header.
- 2 - I moved the Activate/Reject/Unblock request controls above the profile edit form so admins can review pending accounts without scrolling down.
- 3 - I regenerated local ignored template bindata for the updated admin user edit template.
56 - [2026-04-29 09:32:09] - v1.27.0-dev-54-gc7c7af77a1 - Type: Modified - [admin-users] Defaulted admin user purge checkboxes to enabled.
- 1 - I set the Purge User checkbox to checked by default in the admin user edit delete modal.
- 2 - I set the Purge User checkbox to checked by default in the admin users list delete modal.
- 3 - I regenerated local ignored template bindata for the updated admin templates.
57 - [2026-04-29 09:53:08] - v1.27.0-dev-55-ga8d9e5e659 - Type: Added - [auth] [admin-users] [account-status] Added Disable Sign-In metadata to the admin users list.
- 1 - I added persistent admin metadata for Disable Sign-In actions, including timestamp, admin ID, admin name, and admin email.
- 2 - I added a Disable Sign-In column to the admin users list that displays the block date and `by <admin>` badge with email tooltip.
- 3 - I stored the same metadata when admin-created invitation accounts start disabled, when an admin disables sign-in from the edit form, and when an account request is rejected.
58 - [2026-04-29 10:09:41] - v1.27.0-dev-55-ga8d9e5e659 - Type: Modified - [auth] [admin-users] [account-status] Added inactive marker to the Disable Sign-In admin users column.
- 1 - I changed the Disable Sign-In column so users without sign-in disabled show the same `octicon-x` marker style as the other status columns.
- 2 - I kept the block date and `by <admin>` badge for users that do have Disable Sign-In metadata.
- 3 - I regenerated local ignored template bindata for the updated admin users list template.
59 - [2026-04-29 14:49:39] - v1.27.0-dev-56-g1dcd81b420 - Type: Added - [admin-users] [account-status] [mailer] Added admin status-change reasons and user email notifications.
- 1 - I added reason fields under the admin edit checkboxes for account activation, Disable Sign-In, and restricted status.
- 2 - I require a reason when an admin newly deactivates an account, enables Disable Sign-In, or enables restricted mode, then email the user with the action, admin name, and reason.
- 3 - I added the status-change email template, locale strings, regenerated local ignored template/options bindata, and reran the focused admin tests.
60 - [2026-04-29 19:01:39] - v1.27.0-dev-57-g210955465e - Type: Fixed - [auth] [account-status] [mailer] Corrected admin status reason behavior and reactivation emails.
- 1 - I changed the admin edit form so reason fields belong to the existing checkboxes and only appear for the restrictive state of each checkbox.
- 2 - I persisted the deactivation, Disable Sign-In, and restricted reasons in user settings so later administrators can see the saved reason.
- 3 - I changed status-change emails to describe the actual account effect, added notifications when restrictions are lifted, and stopped sending the old activation email on admin reactivation.
61 - [2026-04-29 19:56:22] - v1.27.0-dev-59-gb3204f3db6 - Type: Added - [admin-users] [badges] Added restricted-admin badges and reason actor badges.
- 1 - I added persistent admin metadata for Restricted actions, including timestamp, admin ID, admin name, and admin email.
- 2 - I changed the admin users list Restricted column so newly restricted users show the restriction date and `by <admin>` badge with email tooltip.
- 3 - I added `by <admin>` badges next to the saved Reason labels in the admin user edit panel for deactivation, Disable Sign-In, and Restricted reasons.
62 - [2026-04-29 21:00:30] - v1.27.0-dev-60-g396b15372d - Type: Added - [admin-users] [badges] Added Is Administrator reason and admin-grant badges.
- 1 - I added persistent metadata for granting administrator privileges, including timestamp, admin ID, admin name, admin email, and reason.
- 2 - I changed the admin users list so administrator accounts with grant metadata show an `Admin by <admin>` badge with email tooltip.
- 3 - I added the Is Administrator reason field, reason actor badge, grant/revoke email notifications, regenerated local ignored bindata, and added focused admin grant tests.
63 - [2026-04-29 21:30:55] - v1.27.0-dev-60-g396b15372d - Type: Fixed - [admin-users] Made Is Administrator reasons apply only when admin rights are revoked.
- 1 - I changed the Is Administrator reason field so it appears only when the checkbox is unchecked.
- 2 - I stopped requiring or sending a reason when administrator privileges are granted and changed that email to a congratulatory promotion message.
- 3 - I kept the reason on administrator privilege removal, regenerated template/options bindata, and reran the focused admin grant tests.
64 - [2026-04-29 22:03:18] - v1.27.0-dev-61-g067a09c2ac - Type: Fixed - [admin-users] Disabled critical self-edit account state checkboxes.
- 1 - I disabled User Account Is Activated and Is Restricted when an administrator edits their own account, matching the existing self-edit protection for Disable Sign-In.
- 2 - I hardened the admin user update handler so manually submitted self-edit forms cannot change the current admin's active, restricted, or prohibit-login state.
- 3 - I regenerated local ignored template bindata and verified the admin package compilation with reduced build pressure.
65 - [2026-04-29 22:37:56] - v1.27.0-dev-62-g3afb4e8afa - Type: Added - [auth] [scripts] Added Codex ChatGPT login helper script.
- 1 - I added `.codex_gpt_login`, an interactive helper for completing the local Codex ChatGPT auth callback in code-server environments.
- 2 - The script accepts either a raw received code or a full URL/query containing `code=...`, calls the local callback endpoint, extracts `id_token`, and completes the `/success` request.
- 3 - I made the script executable and verified its shell syntax with `bash -n`.
66 - [2026-04-29 22:55:08] - v1.27.0-dev-62-g3afb4e8afa - Type: Modified - [admin-users] [badges] Added admin actor badge beside the Is Administrator option.
- 1 - I updated the admin user edit panel so the Is Administrator checkbox label shows `by <admin>` when administrator grant metadata exists.
- 2 - I reused the stored admin email as the badge hover tooltip and regenerated local ignored template bindata.
67 - [2026-04-30 00:30:40] - v1.27.0-dev-63-g4aacf3bd20 - Type: Fixed - [admin-users] Hid Is Administrator reason unless admin rights were revoked.
- 1 - I changed the Is Administrator reason field so normal non-admin users do not see it just because the checkbox is unchecked.
- 2 - The reason field now appears only when a saved admin-revocation reason exists or when an existing administrator is being unchecked during the current edit.
- 3 - I regenerated local ignored template bindata and verified whitespace with `git diff --check`.
68 - [2026-04-30 01:44:17] - v1.27.0-dev-64-gcff1b46f50 - Type: Added - [admin-users] [super-admin] Added persistent super administrator protection.
- 1 - I added `SUPER_ADMIN_ENABLED` and `ADMIN_MANAGEMENT_POLICY` configuration options for administrator permission management.
- 2 - I stored the super administrator role and grant/revoke metadata in persistent user settings, with automatic `by GOD` bootstrap for the first active admin.
- 3 - I protected administrator and super administrator changes so regular admins cannot alter existing admins unless the selected policy allows a regular-user promotion.
- 4 - I added super administrator badges, reason tracking, and status-change emails, then regenerated template and options bindata.
69 - [2026-04-30 02:20:26] - v1.27.0-dev-64-gcff1b46f50 - Type: Fixed - [admin-users] [super-admin] Enabled super administrator bootstrap by default.
- 1 - I changed `SUPER_ADMIN_ENABLED` to default to `true` so existing installations without the new app.ini key bootstrap the first active administrator automatically.
- 2 - I updated the app.ini example to document the enabled default and kept `SUPER_ADMIN_ENABLED = false` available as the explicit opt-out.
- 3 - I made the super administrator list badge fall back to `by GOD` for the bootstrapped first administrator and regenerated options bindata.
70 - [2026-04-30 04:08:23] - v1.27.0-dev-66-g35b9fa65d3 - Type: Fixed - [admin-users] [super-admin] Blocked regular administrators from editing super administrator accounts.
- 1 - I modified `routers/web/admin/users.go` so non-super-admins are redirected away from super-admin edit actions, including profile edits and avatar changes.
- 2 - I modified `routers/api/v1/admin/user.go` so the admin user edit API now returns forbidden when a regular admin targets a super admin.
- 3 - I modified `templates/admin/user/list.tmpl` and `templates/admin/user/view.tmpl` so edit actions are hidden for super-admin accounts when the acting admin is not also a super admin.
- 4 - I added `TestAdminCannotEditSuperAdminUser` in `tests/integration/admin_user_test.go` to cover the denied web-edit flow.
71 - [2026-04-30 04:19:14] - v1.27.0-dev-67-g0fc6f30a30 - Type: Modified - [admin-users] [super-admin] Kept super administrator Edit and Delete controls visible but disabled for regular admins.
- 1 - I modified `templates/admin/user/list.tmpl` so super-admin rows still show the `Edit` and `Delete` icons for regular admins, but as disabled muted controls with the super-admin-required tooltip.
- 2 - I modified `templates/admin/user/view.tmpl` so the `Edit` button remains visible on the super-admin user details page for regular admins, but in a disabled state.
72 - [2026-04-30 04:58:16] - v1.27.0-dev-68-g5da24d2c7b - Type: Modified - [admin-users] [admin-policy] Protected GOD-granted admin accounts and blocked deleting the direct grantor.
- 1 - I added `models/user/admin_grant.go` with helpers to read admin and super-admin grantor metadata, detect `by GOD` bootstrap grants, and check whether a target user is the direct grantor of another admin.
- 2 - I modified `routers/web/admin/users.go` so GOD-granted accounts cannot be edited or deleted through admin actions, and regular admins may delete other admin accounts except their direct grantor and protected super-admin cases.
- 3 - I modified `routers/api/v1/admin/user.go` so the admin API now enforces the same GOD-protection and direct-grantor deletion rule.
- 4 - I added locale messages for the new admin restrictions and added focused integration coverage for deleting another admin versus the direct grantor, plus GOD-protected admin API edits.
73 - [2026-04-30 16:51:42] - v1.27.0-dev-71-g80497e4194 - Type: Modified - [admin-users] Restored normal self-edit access for super admins and disabled only the admin actions that are truly forbidden.
- 1 - I modified `routers/web/admin/users.go` so a GOD-granted or super-admin user can still edit their own ordinary account fields, while forbidden cross-user edits remain blocked and table action states are computed per target user.
- 2 - I modified `routers/api/v1/admin/user.go` so GOD-protection no longer blocks a user from editing their own account through the admin API.
- 3 - I modified `templates/admin/user/list.tmpl`, `templates/admin/user/view.tmpl`, and `templates/admin/user/edit.tmpl` so `Edit` stays enabled for allowed self-edits, while forbidden `Edit` and `Delete` actions are shown disabled with the specific reason tooltip or warning message.
74 - [2026-04-30 20:11:48] - v1.27.0-dev-72-g43161732e3 - Type: Modified - [installer] [locale] [en] Added install-time admin management policy choices with direct-grantor and inherited-grantor enforcement.
- 1 - I modified `modules/setting/admin.go`, `services/forms/user_form.go`, `routers/install/install.go`, `templates/install.tmpl`, and `options/locale/locale_en-US.json` so installation now exposes three administrator-management policies: `super_admin_only`, `grantor_only`, and `grantor_inheritance`, while normalizing the old legacy policy names.
- 2 - I modified `models/user/admin_grant.go` so the code can resolve the effective admin grantor by walking the admin-grant chain until it finds an active administrator who still has sign-in enabled.
- 3 - I modified `routers/web/admin/users.go` so regular admins can edit or delete only the administrator accounts allowed by the selected policy, while keeping super-admin protections, GOD protections, self-edit exceptions, and disabled forbidden actions intact in the admin UI.
- 4 - I modified `routers/api/v1/admin/user.go` so the admin API now applies the same grantor-based restrictions for editing and deleting administrator accounts.
- 5 - I added focused integration coverage in `tests/integration/admin_user_test.go` and `tests/integration/api_admin_test.go` for direct-grantor edits, inherited-grantor edits, and API denial for unrelated admins.
75 - [2026-04-30 20:37:01] - v1.27.0-dev-72-g43161732e3 - Type: Modified - [installer] [app-ini-import] [admin-policy] Updated the example app.ini documentation for the new administrator management policies.
- 1 - I modified `custom/conf/app.example.ini` so the `ADMIN_MANAGEMENT_POLICY` comments now document `super_admin_only`, `grantor_only`, and `grantor_inheritance`, and changed the documented default to `grantor_only`.
76 - [2026-04-30 22:03:50] - v1.27.0-dev-73-g1e13af4d6e - Type: Modified - [admin-users] [super-admin] [installer] [locale] [en] Updated install-page administrator labels to super administrator wording.
- 1 - I modified `options/locale/locale_en-US.json` so the install-page administrator account title, description, and username label now refer to the super administrator role.
- 2 - I renamed the install-page policy label from `Administrator Management Policy` to `Administration Management Policy`.
77 - [2026-04-30 23:05:46] - v1.27.0-dev-75-gd4a1b88385 - Type: Modified - [mailer] [installer] [locale] [en] Added install-page testing email verification using the entered SMTP settings.
- 1 - I modified `routers/install/routes.go`, `routers/install/install.go`, and `templates/install.tmpl` so the install page now has an inline `Send Testing Email` action that posts the current SMTP form values to a dedicated install endpoint.
- 2 - I modified `services/mailer/mail.go` and `routers/web/admin/config.go` so compact test-mail error formatting is shared and install can send a test message with a temporary mailer configuration instead of relying on saved global settings.
- 3 - I modified `options/locale/locale_en-US.json` for the install-page test-mail labels and regenerated template and options bindata after verifying the affected Go packages compile.
78 - [2026-04-30 23:25:10] - v1.27.0-dev-75-gd4a1b88385 - Type: Modified - [mailer] [mailer-ui] [installer] Repositioned install-page Send Testing Email under SMTP Password.
- 1 - I modified `templates/install.tmpl` so the `Send Testing Email` row now appears immediately below the `SMTP Password` field inside `Email Settings`.
- 2 - I kept the existing selectors, inline message area, and button behavior unchanged while preserving the remaining field order.
- 3 - I regenerated template bindata and rechecked the install package compile path after the layout-only change.
79 - [2026-04-30 23:48:41] - v1.27.0-dev-75-gd4a1b88385 - Type: Fixed - [mailer] [mailer-ui] [installer] Aligned install-page Send Testing Email with the standard inline form grid.
- 1 - I modified `templates/install.tmpl` so the `Send Testing Email` input, button, and message now render inside the same `right-content` column used by the other install-page inline fields.
- 2 - I kept the existing selectors and behavior unchanged and only corrected the layout alignment relative to `SMTP Password`.
80 - [2026-05-01 00:36:35] - v1.27.0-dev-75-gd4a1b88385 - Type: Fixed - [mailer] [mailer-ui] [installer] [ui] Matched install-page Send Testing Email row to the target inline layout.
- 1 - I modified `templates/install.tmpl` so the `Send Testing Email` controls now use an inline wrapper with the same 60 percent content width as the standard install-form inputs instead of the block-style `right-content` helper.
- 2 - I kept the existing selectors and behavior unchanged and only corrected the horizontal alignment to match the target SMTP Password row layout.
81 - [2026-05-01 00:56:45] - v1.27.0-dev-75-gd4a1b88385 - Type: Modified - [mailer] [mailer-ui] [installer] [ui] Brightened install-page Send Testing Email status message colors.
- 1 - I modified `templates/install.tmpl` so the inline status message now uses `var(--color-green)` for success and `var(--color-red)` for failure instead of the softer Tailwind utility classes.
- 2 - I kept the existing button behavior unchanged and only adjusted the message text color handling in the install-page JavaScript.
82 - [2026-05-01 13:09:43] - v1.27.0-dev-76-g362d01abbc - Type: Modified - [installer] [signup] [locale] [en] Added install-page Registration Management with coherent mode-driven registration settings.
- 1 - I modified `templates/install.tmpl`, `services/forms/user_form.go`, and `routers/install/install.go` so the install page now exposes a dedicated `Registration Management` section with radio-button registration modes plus dependent local and external sub-options.
- 2 - I mapped the new UI to the existing service settings by deriving `DISABLE_REGISTRATION`, `ALLOW_ONLY_INTERNAL_REGISTRATION`, `ALLOW_ONLY_EXTERNAL_REGISTRATION`, `REGISTER_EMAIL_CONFIRM`, and `REGISTER_MANUAL_CONFIRM` consistently from the selected mode and sub-options.
- 3 - I updated `web_src/js/features/install.ts` and `options/locale/locale_en-US.json` so contradictory options are hidden or disabled in the browser, added the new English labels and descriptions, and regenerated template and options bindata.
83 - [2026-05-01 18:14:40] - v1.27.0-dev-77-g19fb194db6 - Type: Modified - [installer] [locale] [en] Completed install-page admin-managed account modes and aligned locale install sections.
- 1 - I modified `modules/setting/service.go`, `custom/conf/app.example.ini`, `services/forms/user_form.go`, `routers/install/install.go`, `templates/install.tmpl`, and `web_src/js/features/install.ts` so `Registration Management` now includes administrator-managed local versus invitation-based account provisioning, plus a helper for `Enable Email Notifications`.
- 2 - I updated `routers/web/admin/users.go` and `routers/api/v1/admin/user.go` so disabled-registration account creation follows the configured administrator-created account mode, stores creator metadata for admin-created users, and sends either invitation mail or standard registration notification accordingly.
- 3 - I aligned every `options/locale/locale_*.json` install section to the new key set and en-US fallback order, regenerated template and options bindata, and verified the affected install, admin web, and admin API packages.
84 - [2026-05-02 00:16:23] - v1.27.0-dev-78-gad0ab4be60 - Type: Modified - [admin-created-user] [admin-users] [installer] [locale] [en] Moved admin-created account delivery mode selection from install to the admin new-user form.
- 1 - I updated `templates/install.tmpl` and `web_src/js/features/install.ts` to remove the install-page `Administrator-managed accounts only` sub-mode choice so registration mode no longer decides how `/admin/users/new` delivers newly created accounts.
- 2 - I extended `services/forms/admin.go`, `templates/admin/user/new.tmpl`, `web_src/js/features/admin/common.ts`, and `routers/web/admin/users.go` so `/admin/users/new` now offers mutually exclusive `Send User Registration Notification` and `Send User Registration Invitation` checkboxes, defaults the invitation checkbox when mail is available, preserves checkbox state on form re-render, and sends the matching email flow.
- 3 - I adjusted `routers/web/admin/users_test.go`, added the new `admin.users.send_register_invite` locale key across `options/locale/locale_*.json`, regenerated template and options bindata, and re-verified the focused admin user flow.
85 - [2026-05-02 01:52:40] - v1.27.0-dev-79-ga6695a6e73 - Type: Modified - [auth] [mailer] [signup] [locale] [en] Unified classic email-confirmation signup with the resend-based pending validation flow.
- 1 - I updated `routers/web/auth/auth.go` and `routers/web/auth/account_request.go` so classic `REGISTER_EMAIL_CONFIRM` signups now render the same resend-capable activation prompt after account creation, redirect repeated signups with the same unconfirmed email to the resend-capable pending state instead of `The username is already taken`, and show the same resend-capable prompt when an unconfirmed user attempts to sign in.
- 2 - I added classic activation resend state tracking in `models/user/account_request.go`, re-used the existing resend UI data contract for both signup and activation prompts, and extended `/user/sign_up/resend` to handle classic email-confirmation accounts with a five-resend limit.
- 3 - I added focused auth tests in `routers/web/auth/auth_test.go`, aligned all `options/locale/locale_*.json` files with the new confirmation-mail keys, regenerated options bindata, and re-verified the affected auth package.
86 - [2026-05-02 02:20:53] - v1.27.0-dev-80-g4ab8063966 - Type: Modified - [installer] [locale] [en] Added default language selection to the install page initial configuration.
- 1 - I extended `services/forms/user_form.go`, `routers/install/install.go`, and `templates/install.tmpl` so `General Settings` now includes a `Default Language` selector backed by the existing `AllLangs` list and validated against configured locales.
- 2 - I wired install submission to persist the selection by reordering `[i18n] LANGS` so the chosen language becomes the first fallback/default locale, while keeping the remaining languages available.
- 3 - I added focused install tests in `routers/install/routes_test.go`, aligned all `options/locale/locale_*.json` files with the new install language keys, regenerated template and options bindata, and re-verified the install package.
87 - [2026-05-02 02:36:07] - v1.27.0-dev-80-g4ab8063966 - Type: Modified - [mailer] Disabled forbidden email deletion actions in the admin email list.
- 1 - I extended `routers/web/admin/emails.go` so each listed email now carries explicit delete permission state and, for primary addresses, the existing `admin.emails.delete_primary_email_error` reason for the disabled UI.
- 2 - I updated `templates/admin/emails/list.tmpl` so the trash icon remains clickable only for deletable addresses and renders as a muted disabled control with a tooltip when deletion is forbidden, such as for a primary email address.
- 3 - I kept the existing backend deletion guard in place, regenerated template bindata, and re-verified the affected admin package plus whitespace consistency.
88 - [2026-05-02 03:12:25] - v1.27.0-dev-82-gf8f988e85e - Type: Modified - [admin-invite] [installer] [sticky-layout] [locale] [en] Added a dedicated pending-invitation flow for admin-created invite accounts and pinned the install footer.
- 1 - I updated `templates/admin/user/new.tmpl`, `routers/web/admin/users.go`, `routers/api/v1/admin/user.go`, `models/user/account_request.go`, and `services/mailer/mail_user.go` so admin-created invitation accounts remain inactive without forcing `Disable Sign-In`, carry explicit pending-invitation state, and show helper text for the notification versus invitation options.
- 2 - I added the dedicated invitation prompt and resend flow through `templates/user/auth/invite_prompt.tmpl`, `routers/web/auth/auth.go`, `routers/web/auth/account_request.go`, and `routers/web/web.go`, including sign-in redirection for pending invitations, backward-compatible handling for legacy prohibited invite accounts, and resend tracking for invitation emails.
- 3 - I updated `templates/base/footer_content.tmpl`, `web_src/css/install.css`, and all `options/locale/locale_*.json` files so the install footer stays continuously visible on the install page, the new invitation strings are available across locales, template and option bindata were regenerated, and the affected auth/admin/API packages were re-verified.
89 - [2026-05-02 04:05:54] - v1.27.0-dev-83-gf7bc24d4e8 - Type: Modified - [admin-invite] [installer] [ui] Aligned the admin new-user invitation help text with the install-page help layout.
- 1 - I updated `templates/admin/user/new.tmpl` so the `Send User Registration Notification` and `Send User Registration Invitation` rows now use a dedicated right-side content wrapper instead of rendering the help text directly under the checkbox.
- 2 - I extended `web_src/css/admin.css` with scoped layout rules for `.admin-user-mail-option` so the help text sits under the checkbox content in the same visual column style used on the install page, including responsive behavior for narrow screens.
- 3 - I regenerated template bindata after the markup change and re-verified whitespace consistency for the affected files.
90 - [2026-05-02 12:11:50] - v1.27.0-dev-84-gf60b2af5a6 - Type: Modified - [installer] [locale] [en] [ui] [sticky-layout] Added an install-page language hint balloon anchored to the footer language selector.
- 1 - I updated `templates/base/footer_content.tmpl` and `templates/install.tmpl` so the install page now renders a green `Choose a language` hint balloon tied to the footer language selector and dismisses it on the first page click.
- 2 - I extended `web_src/css/install.css` with fixed-position balloon styling and responsive placement above the install footer so the hint remains visible without overlapping the footer controls.
- 3 - I added the new `install.language_balloon` locale key to `options/locale/locale_en-US.json`, aligned all `options/locale/locale_*.json` files to include it, and re-generated the template and options bindata assets.
91 - [2026-05-02 12:28:12] - v1.27.0-dev-84-gf60b2af5a6 - Type: Fixed - [installer] [locale] [ui] [sticky-layout] Delayed the install-page language hint balloon initialization until the footer exists in the DOM.
- 1 - I updated `templates/install.tmpl` so the `Choose a language` balloon now initializes on `DOMContentLoaded` instead of running before the footer language selector has been parsed.
- 2 - I kept the existing dismiss-on-first-click behavior unchanged and only fixed the timing issue that prevented the balloon from appearing at first page load.
- 3 - I regenerated the template bindata assets and re-verified whitespace consistency after the template-only fix.
92 - [2026-05-02 13:31:45] - v1.27.0-dev-85-g4eaa42bccd - Type: Modified - [locale] [en] [ro] Added official bootstrap support for the Romanian locale.
- 1 - I updated `modules/setting/i18n.go` so `ro-RO` is now part of the built-in language list with the display name `Română`.
- 2 - I updated `custom/conf/app.example.ini` so the example `[i18n] LANGS` and `NAMES` lists now include `ro-RO` and `Română`.
- 3 - I added `options/locale/locale_ro-RO.json` as an initial bootstrap locale copied from `locale_en-US.json`, so the Romanian locale can be selected and loaded cleanly before the dedicated translation pass.
93 - [2026-05-02 14:41:58] - v1.27.0-dev-86-g414c77278b - Type: Modified - [locale] [en] [ro] Added a first complete Romanian translation pass for `locale_ro-RO.json`.
- 1 - I translated `options/locale/locale_ro-RO.json` from the current `locale_en-US.json` structure, preserving placeholders and HTML fragments, then applied targeted manual overrides for the install, auth, mail, and admin account-management flows customized in this fork.
- 2 - I normalized key Git and administration terms in Romanian and fixed token-protection artifacts that surfaced during the automated translation pass, including the affected `WebAuthn`, `OpenID`, `CAPTCHA`, `Gitea`, milestone completeness, delete-warning, and GPG warning strings.
- 3 - I regenerated `modules/options/bindata.dat` so the updated Romanian locale is embedded in the build output.
94 - [2026-05-05 02:30:50] - v1.27.0-dev-86-g414c77278b - Type: Modified - [locale] [ro] Refined Romanian UI wording in `locale_ro-RO.json`.
- 1 - I adjusted Romanian phrasing across the translated locale to improve readability and consistency in general UI strings.
- 2 - I normalized terminology for navigation, repository, authentication, and administration labels to better match the existing Gitea interface.
- 3 - I kept placeholders, HTML fragments, and technical tokens intact while polishing the translated text.
95 - [2026-05-06 03:15:10] - v1.27.0-dev-86-g414c77278b - Type: Modified - [locale] [ro] Corrected Romanian wording and grammar in `locale_ro-RO.json`.
- 1 - I fixed a small set of Romanian phrasing and grammar issues identified after the previous translation polish pass.
- 2 - I kept the scope limited to wording corrections without changing the locale structure or translation coverage.
- 3 - I preserved existing placeholders, HTML fragments, and technical tokens while applying the text fixes.
96 - [2026-05-06 00:47:16] - v1.27.0-dev-90-g75a9dbf7d7 - Type: Modified - [org-ui] [ui] Restyled the organization creation panel and added a cancel action.
- 1 - I updated `templates/org/create.tmpl` so `/org/create` now renders inside a settings-style attached header and segment panel instead of the older standalone form block.
- 2 - I kept the existing organization creation fields intact, but changed the action row to a right-aligned button group with a new `Cancel` button beside `Create Organization`.
- 3 - I updated `routers/web/org/org.go` to provide a `CancelLink` back to `/user/settings/organization`, regenerated template bindata, and re-verified the `routers/web/org` package.
97 - [2026-05-06 01:08:23] - v1.27.0-dev-90-g75a9dbf7d7 - Type: Modified - [org-ui] [modal] Converted the organization creation page to a modal-style dialog and preserved the caller page for cancel.
- 1 - I updated `templates/org/create.tmpl` so `/org/create` now renders as a visible `ui small modal` dialog with header, content, and actions matching the visual structure used by the Actions secrets and variables modals.
- 2 - I extended `web_src/css/org.css` with page-scoped layout rules that center the active modal on the standalone page while keeping the styling limited to `page-content.organization.new.org`.
- 3 - I updated `routers/web/org/org.go` so `Cancel` now returns to a safe current-site `redirect_to` target or same-site referrer instead of always forcing `/user/settings/organization`, regenerated template bindata, and re-verified the `routers/web/org` package.
98 - [2026-05-06 02:02:33] - v1.27.0-dev-91-gba0da47957 - Type: Added - [codex-docs] Added persistent Codex project-orientation documents for fast task handoff and recovery.
- 1 - I added `.codex-project-map.md` as a durable project guide that captures the web request flow, authentication architecture, practical extension points, and a restart procedure for new tasks.
- 2 - I modified `.codex-context.md` so it now points explicitly to `.codex-project-map.md` and documents the recommended read order for resuming work after a blocked session.
- 3 - I refreshed the repository-derived version reference in `.codex-context.md` so future history updates can use the current application version format consistently.
99 - [2026-05-06 02:18:58] - v1.27.0-dev-91-gba0da47957 - Type: Modified - [org-ui] [modal] [ui] Reworked organization creation into a real overlay modal on top of the organization settings page and made outside clicks close it.
- 1 - I modified `templates/user/settings/organization.tmpl` so the `New Organization` action now opens the create dialog with the standard `show-modal` flow while keeping the organization settings page visible in the background.
- 2 - I converted `templates/org/create.tmpl` into a reusable modal partial and updated `routers/web/org/org.go` so `/org/create` now renders the same organization settings page with that modal auto-opened, preserving `CancelLink` for close and validation-error flows.
- 3 - I simplified `web_src/css/org.css` to keep only the create-modal helper text styling and removed the previous fake standalone modal layout that replaced the background page.
100 - [2026-05-06 10:13:49] - v1.27.0-dev-91-gba0da47957 - Type: Fixed - [org-ui] [ui] Corrected the organization settings cancel-link build regression.
- 1 - I fixed `routers/web/user/setting/profile.go` so it uses the `ctx.Req.RequestURI` field instead of calling it like a function.
- 2 - This removes the compile error in `code.gitea.io/gitea/routers/web/user/setting` that was blocking the Windows build after the organization-create modal refactor.
101 - [2026-05-06 10:54:10] - v1.27.0-dev-91-gba0da47957 - Type: Modified - [org-ui] [modal] Made the new-organization modal open in place from the UI and reset its default values consistently.
- 1 - I moved the reusable `create-org-modal` inclusion to `templates/base/footer.tmpl` so signed-in users who can create organizations have the modal available on normal pages without navigating away first.
- 2 - I updated the `New Organization` triggers in `templates/base/head_navbar.tmpl`, `templates/user/dashboard/navbar.tmpl`, `templates/admin/org/list.tmpl`, and `templates/user/settings/organization.tmpl` to use `show-modal` with `/org/create` as a non-JavaScript fallback, preserving the current page and scroll position when JavaScript is enabled.
- 3 - I added explicit reset attributes for organization name, `redirect_to`, visibility radios, and the `repo_admin_change_team_access` checkbox so the modal opened from `/user/settings/organization` now uses the same defaults as the one opened from the global create menu.
102 - [2026-05-06 10:55:13] - v1.27.0-dev-91-gba0da47957 - Type: Modified - [org-ui] [modal] Extended the in-place new-organization modal behavior to the dashboard organization list component.
- 1 - I modified `web_src/js/components/DashboardRepoList.vue` so the `New Organization` trigger in the organizations dashboard tab now also uses the shared `show-modal` flow instead of forcing navigation when JavaScript is enabled.
- 2 - I kept `/org/create` as the fallback `href` in the component so the non-JavaScript path remains available.
103 - [2026-05-06 18:03:33] - v1.27.0-dev-91-gba0da47957 - Type: Modified - [locale] [ro] Somes correction Romanian wording and grammar in `locale_ro-RO.json`.
104 - [2026-05-06 18:19:21] - v1.27.0-dev-91-gba0da47957 - Type: Modified - [ui] Fix align new-user check-boxes help text.
105 - [2026-05-06 18:47:44] - v1.27.0-dev-91-gba0da47957 - Type: Modified - [locale] [ro] Some new correction Romanian wording and grammar in `locale_ro-RO.json`.
106 - [2026-05-06 15:54:50] - v1.27.0-dev-96-g7c7357f314 - Type: Modified - [admin-invite] [auth] Reduced the resend button size on the invitation acceptance prompt.
- 1 - I modified `templates/user/auth/invite_prompt.tmpl` so the `Resend` button on `/user/invitation?email=...` now uses the smaller `ui mini button` size instead of `ui tiny button`.
- 2 - I kept the existing inline resend states, colors, and success reset behavior unchanged.
107 - [2026-05-06 18:57:49] - v1.27.0-dev-98-g5f0f52d04f - Type: Fixed - [org-ui] [modal] Prevented the new-organization modal from inheriting unrelated global success flashes from the underlying page.
- 1 - I modified `templates/org/create.tmpl` so the modal now renders only its local error flash instead of the full `base/alert` block.
- 2 - This keeps `/org/create` validation errors visible in the modal while preventing inherited success, info, or warning flash messages from the background page from appearing inside it.
108 - [2026-05-06 21:07:26] - v1.27.0-dev-99-gfc43980a5c - Type: Fixed - [admin-invite] [admin-created-user] [mailer] [locale] Made admin-created user notification and invitation emails use the current page locale.
- 1 - I modified `services/mailer/mail_user.go` to add locale-aware variants for registration-notify and admin-invite emails, while preserving the existing user-language fallback helpers for other call sites.
- 2 - I modified `routers/web/admin/users.go` and `routers/api/v1/admin/user.go` so admin-created account emails now use `ctx.Locale` from the current request instead of always rendering in the new account's empty or default language.
109 - [2026-05-06 22:11:33] - v1.27.0-dev-100-g70ef46362e - Type: Modified - [admin-created-user] [mailer] [locale] [en] [ro] Personalized the admin-created account notification email with the creator name and a direct set-password link.
- 1 - I modified `services/mailer/mail_user.go` so the registration notification email now accepts the admin user, generates a time-limited `reset_password` token URL for the new account, and passes both values into the mail template.
- 2 - I modified `routers/web/admin/users.go` and `routers/api/v1/admin/user.go` so the admin-created account notification now includes `ctx.Doer` when sending the non-invite email variant.
- 3 - I modified `templates/mail/user/auth/register_notify.tmpl`, `options/locale/locale_en-US.json`, and `options/locale/locale_ro-RO.json` so the email explicitly states that the administrator created the account and instructs the recipient to use a personal password-setup link before signing in.
110 - [2026-05-06 22:11:33] - v1.27.0-dev-100-g70ef46362e - Type: Fixed - [admin-created-user] [mailer] Corrected the admin-created account password-setup email link to use the public recovery route.
- 1 - I modified `services/mailer/mail_user.go` so the personalized password-setup link now targets `/user/recover_account?code=...`, which is the actual public route mounted for password reset token handling.
- 2 - This fixes the 404 triggered by the previous `/user/reset_password?code=...` link, because the router exposes `auth.ResetPasswd` on `/user/recover_account` instead.
111 - [2026-05-06 23:43:34] - v1.27.0-dev-102-g146013827c - Type: Modified - [admin-invite] [admin-created-user] Made the admin-created account notification link behave like an invitation by signing the user in through `/user/activate`.
- 1 - I modified `models/user/user.go` to add a dedicated `TimeLimitCodeAdminAccess` purpose that reuses the password-reset lifetime but remains separate from reset-password and invite tokens.
- 2 - I modified `services/mailer/mail_user.go` so the `Send User Registration Notification` email now points to `/user/activate?code=...` with the new admin-access token instead of sending the recipient through the recovery form flow.
- 3 - I modified `routers/web/auth/auth.go` so `auth.Activate` and `auth.ActivatePost` can consume the new token, rotate `Rands`, create the session, refresh locale, update last-login metadata, and then rely on the existing `MustChangePassword` redirect to land the user on `/user/settings/change_password`.
- 4 - I added `TestActivateAdminAccessSignsInAndInvalidatesCode` in `routers/web/auth/auth_test.go` to cover the new direct-access flow and confirm the token is invalidated after first use.
112 - [2026-05-06 23:43:34] - v1.27.0-dev-102-g146013827c - Type: Modified - [auth] [admin-created-user] [mailer] Simplified the admin-created account notification email to show only the personalized activation link.
- 1 - I modified `templates/mail/user/auth/register_notify.tmpl` so the mail no longer shows the generic `/user/login` URL and instead displays the personalized admin-access link directly under the username.
- 2 - I removed the trailing explanatory paragraph below that link to avoid repeating the same password-setup action twice in the same email.
113 - [2026-05-07 01:01:44] - v1.27.0-dev-104-g10495b7cd1 - Type: Modified - [user-settings] [sticky-layout] [appearance] [locale] [en] [ro] Reverted the global fixed-footer behavior and replaced it with a persistent per-user footer preference in `/user/settings/appearance`.
- 1 - I modified `templates/user/settings/appearance.tmpl`, `routers/web/user/setting/profile.go`, and `routers/web/web.go` to add a new footer section with a checkbox that saves whether the footer should stay visible at the bottom of the viewport for the current user.
- 2 - I modified `models/user/setting_options.go`, `routers/common/pagetmpl.go`, `templates/base/head.tmpl`, `modules/web/middleware/cookie.go`, `web_src/css/base.css`, and `web_src/css/home.css` so the preference is stored in `user_settings`, propagated into the page layout, and applied only when the `show-persistent-footer` body class is enabled.
- 3 - I modified `options/locale/locale_en-US.json`, `options/locale/locale_ro-RO.json`, and `models/user/setting_test.go` to add the new UI strings and a focused test covering the new persisted setting key.
114 - [2026-05-07 09:30:56] - v1.27.0-dev-105-gb3a7692ce9 - Type: Modified - [ui] [sticky-layout] Moved the persistent footer outside the page scroll area.
- 1 - I modified `web_src/css/base.css` so pages with `show-persistent-footer` stop scrolling the whole `body` and instead scroll the `.full.height` content container, keeping the footer in its own fixed viewport slot.
- 2 - I modified `web_src/css/home.css` so the persistent footer no longer overlays the page with `position: fixed`, but stays permanently visible as a non-scrolling sibling below the main content area.
115 - [2026-05-07 09:54:43] - v1.27.0-dev-106-g61a9e4bd06 - Type: Modified - [user-settings] [sticky-layout] [locale] [en] [ro] Added the persistent sticky side-menu preference and the finalized sidebar behavior for `/user/settings` and `/-/admin`.
- 1 - I modified `models/user/setting_options.go`, `routers/common/pagetmpl.go`, `templates/base/head.tmpl`, `routers/web/user/setting/profile.go`, `routers/web/web.go`, `templates/user/settings/appearance.tmpl`, `options/locale/locale_en-US.json`, `options/locale/locale_ro-RO.json`, and `models/user/setting_test.go` to add the persisted `ui.sticky_side_menus` preference, expose it to templates as `ShowStickySideMenus`, save it from `/user/settings/appearance`, document it in the UI, and cover it with a focused test.
- 2 - I modified `templates/user/settings/actions_general.tmpl` so `/user/settings/actions/general` passes the expected `pageClass` and participates in the same sticky-sidebar behavior as the other settings subpages.
- 3 - I modified `web_src/css/modules/flexcontainer.css` so, when the preference is enabled, the shared left menus on `/user/settings` and `/-/admin` use the current sticky layout: sticky positioning on the inner menu, `top: var(--page-spacing)`, footer-aware `max-height` handling for both persistent and non-persistent footer modes, hidden desktop scrollbars, green overflow hints, local menu scrolling, and the current `/user/settings` item padding.
- 4 - I modified `web_src/js/features/common-page.ts` so the sticky side menus update their overflow-hint classes dynamically as their scroll position, size, or expanded sections change.
116 - [2026-05-07 20:41:28] - v1.27.0-dev-106-g61a9e4bd06 - Type: Modified - [user-settings] [sticky-layout] [appearance] [locale] [en] [ro] Added a persistent navigation-bar preference in `/user/settings/appearance`.
- 1 - I modified `models/user/setting_options.go`, `models/user/setting_test.go`, `routers/common/pagetmpl.go`, `routers/web/user/setting/profile.go`, `routers/web/web.go`, `templates/base/head.tmpl`, `templates/user/settings/appearance.tmpl`, `options/locale/locale_en-US.json`, and `options/locale/locale_ro-RO.json` to add the persisted `ui.persistent_navbar` preference, expose it to templates as `ShowPersistentNavbar`, save it from `/user/settings/appearance`, and document it in the UI.
- 2 - I modified `web_src/css/modules/navbar.css` so the main `#navbar` becomes sticky at the top of the viewport when the new preference is enabled.
- 3 - I modified `web_src/css/modules/flexcontainer.css` so sticky side menus take the persistent navbar height into account on desktop, preventing the left menus from sliding underneath the navbar when both preferences are enabled.
117 - [2026-05-07 20:49:16] - v1.27.0-dev-106-g61a9e4bd06 - Type: Modified - [user-settings] [ui] [sticky-layout] Preserved the `/user/settings` left-menu scroll position across settings-page navigation.
- 1 - I modified `web_src/js/features/common-page.ts` so the sticky `/user/settings` menu saves its current `scrollTop` to `sessionStorage` while scrolling and immediately before clicking a menu link.
- 2 - I also made the same code restore that saved scroll position after the next settings page renders, keeping the left menu at the same viewport position when navigating between items and subitems.
118 - [2026-05-07 20:57:42] - v1.27.0-dev-106-g61a9e4bd06 - Type: Modified - [ui] [sticky-layout] Made the footer `Licenses` and `API` links open in a new browser tab and finalized the sticky `User Settings` header plus its top green scroll indicator.
- 1 - I modified `templates/base/footer_content.tmpl` so both footer links now use `target="_blank"` with `rel="noreferrer"`.
- 2 - I modified `web_src/css/modules/flexcontainer.css` so the `.header.item` at the top of the `/user/settings` sticky side menu now uses `position: sticky` inside the menu itself, with its own background and bottom separator.
- 3 - I modified `web_src/css/modules/flexcontainer.css` so, after making the `User Settings` header sticky, the top overflow hint is rendered on the bottom edge of that header and its gradient is drawn by a dedicated `::after` element extending into the scrollable area, while the menu container keeps only the bottom hint when both are active.
119 - [2026-05-07 21:14:11] - v1.27.0-dev-106-g61a9e4bd06 - Type: Modified - [ui] [sticky-layout] Made the `Admin Settings` menu header sticky while the admin left-menu options scroll.
- 1 - I modified `web_src/css/modules/flexcontainer.css` so the `.header.item` at the top of the `/-/admin` sticky side menu now uses the same sticky header treatment as `/user/settings`, with its own background and bottom separator.
- 2 - I modified `web_src/css/modules/flexcontainer.css` so the top green overflow indicator for `/-/admin` is also rendered on the bottom edge of the sticky header, with the gradient drawn by the same dedicated `::after` element used in `/user/settings`.
120 - [2026-05-07 21:31:18] - v1.27.0-dev-106-g61a9e4bd06 - Type: Modified - [user-settings] [ui] [sticky-layout] Preserved the `/user/settings` left-menu scroll position without the visible reset flicker during navigation.
- 1 - I modified `templates/user/settings/navbar.tmpl` to add a small inline restore hook around the menu markup, so a saved `scrollTop` is applied from `sessionStorage` before the menu becomes visible on the next settings page.
- 2 - I modified `web_src/css/modules/flexcontainer.css` so, while that inline restore is in progress, only the `/user/settings` left menu is temporarily hidden, preventing the brief flash of the menu reset at the top.
- 3 - I kept `web_src/js/features/common-page.ts` focused on saving the menu scroll position and refreshing the scroll indicators, removing the now-redundant late restore path from the global initializer.
121 - [2026-05-07 21:41:44] - v1.27.0-dev-106-g61a9e4bd06 - Type: Modified - [user-settings] [sticky-layout] Restored the agreed `/user/settings` sticky-menu item padding behavior.
- 1 - I also updated the same CSS so the `/user/settings` menu padding is applied at the item level inside `.ui.vertical.menu`, using `0.9em 1.14285714em` instead of relying on a menu-level spacing adjustment.
122 - [2026-05-07 22:11:06] - v1.27.0-dev-106-g61a9e4bd06 - Type: Modified - [user-settings] [ui] [sticky-layout] Restored the pre-`122` `/user/settings` layout baseline while keeping the current sticky-menu behavior.
- 1 - I modified `templates/user/settings/layout_head.tmpl` to return the settings page wrapper from `ui container fluid padded flex-container` to `ui container flex-container`.
- 2 - I restored the `/user/settings` menu to the same single scroll container structure used before, removing the ineffective inner-body split and keeping the inline restore hook in `templates/user/settings/navbar.tmpl`.
- 3 - I modified `web_src/css/modules/flexcontainer.css` so the `/user/settings` left menu remains temporarily hidden only during the inline scroll restore, keeps the `/user/settings`-only 24px non-persistent-footer bottom padding on the left navigation column, and supports the small `--sticky-side-menu-correction` transform without affecting admin pages.
- 4 - I kept the matching logic in `web_src/js/features/common-page.ts`, so the `/user/settings` menu still restores its saved scroll position after navigation, refreshes the green overflow indicators, and applies the modest runtime correction only when the sticky menu drifts slightly above its configured top offset.
123 - [2026-05-09 12:47:10] - v1.27.0-dev-114-gbb77e80bf5 - Type: Modified - [sticky-layout] Finalized the sticky side-menu bottom-edge behavior by compacting menu items and increasing the viewport reserve.
- 1 - I modified `web_src/css/modules/menu.css` so shared menu items now use `padding: 0.75em 1.14285714em`, reducing vertical item height across the sticky left menus.
- 2 - I modified `web_src/css/modules/flexcontainer.css` so the sticky side menus in both `/user/settings` and `/-/admin` now reserve `40px` instead of `24px` at the bottom of their `max-height` calculation for the non-persistent-footer case.
- 3 - This combination keeps the sticky menus from jumping upward at the bottom of the page scroll while preserving the current sticky headers, scroll hints, and `/user/settings` scroll-position restore behavior.
124 - [2026-05-09 15:31:52] - v1.27.0-dev-115-g06b7bd3ca1 - Type: Modified - [sticky-layout] Highlighted the active submenu entry with the standard active background color.
- 1 - I modified `web_src/css/modules/menu.css` so `.ui.vertical.menu .item .menu .active.item` now uses `background-color: var(--color-active)` instead of `transparent`.
- 2 - I kept the existing medium font weight and text color unchanged, so only the active submenu background treatment changed.
125 - [2026-05-09 15:56:47] - v1.27.0-dev-116-g8a0d319607 - Type: Added - [permissions-table] [locale] [en] [ro] Added column-wide Select all controls to the user access-token permissions table.
- 1 - I modified `templates/user/settings/applications.tmpl` to add a `Select all` row above the token-scope category rows, with per-column `All` radio buttons for No access, Read, and Write.
- 2 - I added `web_src/js/features/access-token-settings.ts` and registered it in `web_src/js/index.ts` so selecting one of those top-row radios automatically applies the matching permission choice to every category row in the same column.
- 3 - I added the `settings.select_all` locale string in both `options/locale/locale_en-US.json` and `options/locale/locale_ro-RO.json` for the new control row label.
- 4 - I extended the same `web_src/js/features/access-token-settings.ts` logic so each top-row `All` radio now becomes active only when every category row in its column is selected, becomes inactive when the column is no longer fully selected, and can still be reselected to apply that column choice to all rows again.
- 5 - I corrected the select-all synchronization fallback so no top-row radio stays selected when no permission column is fully matched, instead of incorrectly defaulting back to the `No access` column.
126 - [2026-05-09 17:16:12] - v1.27.0-dev-117-gab1135d1c6 - Type: Added - [permissions-table] Added header-level Select all controls to the shared Actions maximum-permissions table.
- 1 - I modified `templates/shared/actions/permissions_table.tmpl` to add a second header row with `Select all` on the left and per-column `All` radio controls for None, Read, and Write.
- 2 - I extended `web_src/js/features/common-actions-permissions.ts` so those header radios apply the chosen permission to every row in the table and stay synchronized bidirectionally with the current per-row selections.
- 3 - Because the change is implemented in the shared Actions permissions partial and its existing initializer, the same behavior now applies consistently to `/user/settings/actions/general` and the other pages that reuse that table.
127 - [2026-05-09 17:34:41] - v1.27.0-dev-118-g021f12509f - Type: Modified - [org-ui] [sticky-layout] Applied the shared sticky side-menu behavior to organization settings pages.
- 1 - I modified `web_src/css/modules/flexcontainer.css` so the same sticky left-menu layout, hidden scrollbar styling, sticky header behavior, and green overflow indicators used by user settings and admin pages now also apply to `.page-content.organization.settings`.
- 2 - I modified `web_src/js/features/common-page.ts` so organization settings menus participate in the shared sticky-menu overflow indicator logic.
- 3 - I modified `templates/org/settings/actions_general.tmpl` to pass `pageClass: "organization settings actions"` into the shared organization settings layout, so the Actions General page also matches the shared organization settings selectors.
128 - [2026-05-09 18:46:07] - v1.27.0-dev-120-g01e3eb1306 - Type: Added - [auth] [password-ui] [signup] [locale] [en] [ro] Added password visibility toggles to the login and signup forms.
- 1 - I modified `templates/user/auth/signin_inner.tmpl` to add an eye button beside the `/user/login` password field.
- 2 - I modified `templates/user/auth/signup_inner.tmpl` to add the same eye button beside the `/user/sign_up` password field and marked the `Confirm Password` field for toggle-aware behavior.
- 3 - I added `web_src/js/features/password-visibility.ts` and registered it in `web_src/js/index.ts` so the eye button toggles between hidden and visible password states.
- 4 - In the signup form, when password visibility is enabled, the script now hides the `Confirm Password` field, removes its `required` state, and keeps its value synchronized with the main password field; when visibility is disabled again, the field is shown and required again.
- 5 - I added `auth.show_password` and `auth.hide_password` locale strings in both `options/locale/locale_en-US.json` and `options/locale/locale_ro-RO.json` for the button tooltip and accessibility label.
- 6 - I corrected the login and signup password-toggle button templates so their `data-hide-label` attributes close the Go template expression properly, removing the template parsing error that prevented startup.
- 7 - I added `octicon-eye-closed` to `web_src/js/svg.ts`, fixing the runtime JavaScript error raised when the password toggle switched from the visible-eye icon to the hidden-eye icon.
129 - [2026-05-09 19:36:18] - v1.27.0-dev-121-gbfb584f161 - Type: Modified - [sticky-layout] [repo-settings] Applied the shared sticky side-menu behavior to repository settings pages.
- 1 - I modified `web_src/css/modules/flexcontainer.css` so the same sticky left-menu layout, hidden scrollbar styling, sticky header behavior, and green overflow indicators used by user settings, organization settings, and admin pages now also apply to `.page-content.repository.settings`.
- 2 - I modified `web_src/js/features/common-page.ts` so repository settings menus participate in the shared sticky-menu overflow indicator logic.
130 - [2026-05-09 20:07:36] - v1.27.0-dev-122-g652d3c20da - Type: Modified - [sticky-layout] [repo-actions] Applied the shared sticky side-menu behavior to repository Actions pages.
- 1 - I modified `templates/repo/actions/list.tmpl` to mark the workflow sidebar menu with a dedicated hook class for the shared sticky-menu initializer.
- 2 - I modified `web_src/css/modules/flexcontainer.css` so the same sticky left-menu layout, hidden scrollbar styling, and green overflow indicators now also apply to `.page-content.repository.actions`.
- 3 - I modified `web_src/js/features/common-page.ts` so the repository Actions sidebar participates in the shared sticky-menu overflow indicator logic.
- 4 - I refined the same CSS for repository Actions so the top green scroll hint is drawn directly on the menu container, because that sidebar has no `.header.item` for the shared header-based top-gradient treatment.
- 5 - I extended `templates/repo/actions/list.tmpl` with the same inline `sessionStorage` restore hook pattern used by `/user/settings`, so the repository Actions sidebar can restore its scroll position before becoming visible.
- 6 - I modified `web_src/css/modules/flexcontainer.css` so the repository Actions sidebar is temporarily hidden only during that inline restore step, preventing the visible reset flicker.
- 7 - I extended `web_src/js/features/common-page.ts` so the repository Actions sidebar now saves its own scroll position on scroll and before navigation clicks, using the dedicated `sticky-side-menu-scroll:repo-actions` session key.
131 - [2026-05-09 20:54:41] - v1.27.0-dev-123-g0f3876c0b1 - Type: Added - [repo-actions] Added pilot partial navigation for the repository Actions sidebar.
- 1 - I added `web_src/js/features/repo-actions-sidebar.ts` and registered it in `web_src/js/index.ts` to intercept plain left-click navigation on `/<user>/<repo>/actions` sidebar workflow links.
- 2 - The new client-side flow fetches the target page, replaces only the Actions page `.ui.container` content, updates `document.title`, and pushes the new URL into browser history instead of reloading the full page.
- 3 - The same logic also handles browser back/forward through `popstate`, keeping the pilot partial navigation limited to repository Actions pages.
- 4 - I extended the same pilot so, after each partial `.ui.container` swap, the repository Actions sidebar re-runs the shared sticky-menu indicator initializer on the new DOM, restoring the green overflow hints that disappeared after the first in-page navigation.
132 - [2026-05-09 21:10:27] - v1.27.0-dev-123-g0f3876c0b1 - Type: Modified - [scripts] [smart-build] Added an audio bell for interactive prompts in `smart-build.sh`.
- 1 - I added a small `notify_human_interaction()` helper to `smart-build.sh` that emits a terminal bell only when the script is running on an interactive terminal.
- 2 - I call that helper immediately before the build-load, architecture, and build-tags interactive menus, so the user gets an audible prompt exactly when human input is needed.
- 3 - I extended the same helper so VS Code and code-server terminals also get a high-visibility fallback banner when browser-controlled terminal bells do not produce an audible sound.
- 4 - I extended the same helper again to send a Linux desktop notification through `notify-send` before each interactive menu, while keeping the existing audio and terminal fallbacks for environments where no notification daemon is available.
133 - [2026-05-09 22:32:57] - v1.27.0-dev-125-g1525c9c8ee - Type: Modified - [auth] [password-ui] [signup] Finalized the manual-only password visibility toggle behavior for login and signup.
- 1 - I removed the static eye button from the login and signup templates and now create it from `web_src/js/features/password-visibility.ts` only when the current password value qualifies for manual reveal.
- 2 - The final reveal rules are now strict: prefilled or browser-autofilled passwords never show the eye, appending characters to an already non-empty password still keeps it hidden, and the eye appears only after a trusted manual empty-to-non-empty entry or a full manual replacement of a selected existing value.
- 3 - Once the eye has legitimately appeared, it stays visible through continued typing until the password is cleared again, preserves focus plus caret/selection on click, and keeps the signup confirm-password field synchronized while reveal mode is active.
- 4 - I converted the toggle into an overlaid control inside the password field, hid the browser-native reveal buttons, and kept the final transparent eye-button background styling that was adjusted manually in `web_src/css/user.css`.
134 - [2026-05-09 23:58:22] - v1.27.0-dev-125-g1525c9c8ee - Type: Modified - [build-artifacts] Ignored the local frontend hash artifact.
- 1 - I added `/.frontend.hash` to `.gitignore` so local frontend rebuild hash churn no longer appears in the repository working tree.
- 2 - I removed `.frontend.hash` from Git tracking with `git rm --cached`, so the ignore rule now fully suppresses future local hash churn instead of only affecting newly untracked copies.
135 - [2026-05-10 00:06:54] - v1.27.0-dev-125-g1525c9c8ee - Type: Modified - [user-settings] [appearance] Unified the persistent appearance toggles into a single settings group.
- 1 - I merged the top navigation bar, side menus, and footer persistence controls in `templates/user/settings/appearance.tmpl` into one shared `Persistent layout` section with a single Save button.
- 2 - I added `UpdatePersistentLayout` in `routers/web/user/setting/profile.go` and routed `/user/settings/appearance/layout` to save all three preferences in one request while preserving the footer cookie update.
- 3 - I added the `settings.persistent_layout` and `settings.persistent_layout_desc` locale strings and finalized the section markup so the shared description sits in its own `.field` container and each per-option help paragraph is separated with a `<br>` after the checkbox row.
136 - [2026-05-10 18:40:36] - v1.27.0-dev-125-g1525c9c8ee - Type: Added - [org-ui] [permissions-table] Added column-wide Select all controls to the organization team-units permissions table.
- 1 - I extended `templates/org/team/new.tmpl` so the team-units permissions table in `org/<team_name>/teams/new` gets the same header-level Select row used by the Actions permissions table, with `All` radios for none, read, and write.
- 2 - I extended `web_src/js/features/org-team.ts` to synchronize those header radios bidirectionally with the per-unit permission rows, while correctly ignoring globally disabled read/write cells when applying or computing a column-wide selection.
137 - [2026-05-10 19:02:14] - v1.27.0-dev-125-g1525c9c8ee - Type: Added - [installer] [password-ui] Added the password visibility toggle to the SMTP password field on the install page.
- 1 - I wrapped the `smtp_passwd` input in `templates/install.tmpl` with the same `js-password-toggle-group` used by login and signup, reusing the existing password-visibility initializer and show/hide labels so the install-page SMTP password field gets the same eye toggle behavior.
138 - [2026-05-10 19:08:32] - v1.27.0-dev-125-g1525c9c8ee - Type: Modified - [mailer] [installer] Enabled install-page email notifications by default for fresh setups.
- 1 - I updated `routers/install/install.go` so the install form defaults `mail_notify` to enabled when there is no existing mailer configuration and notify-mail was still unset, while preserving an explicit existing configuration during reinstall/edit scenarios.
139 - [2026-05-10 19:15:41] - v1.27.0-dev-125-g1525c9c8ee - Type: Added - [installer] [password-ui] Added the password visibility toggle and confirm-password behavior to the install-page super-admin password fields.
- 1 - I wrapped the install-page `admin_passwd` field in the same `js-password-toggle-group` used by signup and login, so the super-admin password now gets the same eye toggle UI and manual-entry reveal behavior.
- 2 - I wired the install-page `admin_confirm_passwd` field into the existing confirm-password flow, so revealing the admin password hides the confirm field and keeps it synchronized just like the signup form.
- 3 - I refined `web_src/js/features/password-visibility.ts` so confirm-field synchronization is opt-in per toggle group via explicit selectors, preventing the install-page SMTP password toggle from accidentally targeting the super-admin confirm field in the same form.
- 4 - I adjusted `web_src/css/install.css` so install-page password fields that use the overlaid eye wrapper keep the same 60% inline-field width as the original plain inputs instead of shrinking or stretching when the wrapper is present.
140 - [2026-05-10 19:22:04] - v1.27.0-dev-125-g1525c9c8ee - Type: Added - [installer] [password-ui] Added the password visibility toggle to the install-page database password field.
- 1 - I wrapped `db_passwd` in `templates/install.tmpl` with the same `js-password-toggle-group` used by the other install-page password fields, so the database password now gets the same eye control without changing its inline width or reusing any confirm-password logic.
141 - [2026-05-10 19:27:48] - v1.27.0-dev-125-g1525c9c8ee - Type: Added - [user-settings] [password-ui] Added the password visibility toggle and confirm-password behavior to `/user/settings/account`.
- 1 - I wrapped the `settings.new_password` field in `templates/user/settings/account.tmpl` with the shared `js-password-toggle-group`, reusing the existing eye-toggle logic and show/hide labels.
- 2 - I wired the `settings.retype_new_password` field into the existing confirm-password flow through dedicated selectors, so revealing the new password hides the confirm field and keeps it synchronized the same way as signup and the install-page super-admin password form.
142 - [2026-05-10 19:43:11] - v1.27.0-dev-125-g1525c9c8ee - Type: Added - [installer] [branding] Added optional custom branding uploads to the install page.
- 1 - I finalized the installer `Branding` section with optional uploads for `logo.svg`, `logo.png`, `loading.png`, `favicon.svg`, and `favicon.png`, including clear format/size guidance plus a shared-assets checkbox for using one SVG and one PNG upload for both logo and favicon.
- 2 - I implemented backend validation and persistence for all branding uploads in `routers/install/install.go` (expected type checks, 1 MB limit, square PNG with minimum 64x64) and save accepted overrides under `custom/public/assets/img/`.
- 3 - I completed the runtime behavior so uploaded branding files override built-in assets through layered serving, `logo.svg` is mirrored to `gitea.svg` for legacy lookups, post-install progress prefers a custom `loading.png`, and the shared-assets mode hides favicon fields while relabeling logo fields to `Logo & Favicon SVG/PNG`.
- 4 - I manually updated Romanian locale wording for the final branding texts and labels.
143 - [2026-05-12 00:02:10] - v1.27.0-dev-125-g1525c9c8ee - Type: Modified - [auth] [signup] [admin-created-user] [locale] [en] [ro] Finalized Register behavior for admin-created notification accounts without altering the invitation flow.
- 1 - I extended `POST /user/sign_up` in `routers/web/auth/auth.go` for existing active local accounts created by an admin when `username` and `email` match, while explicitly leaving pending admin invitations on their existing flow.
- 2 - If password is correct, the user is now authenticated into that existing account; when `MustChangePassword` is enabled, the flow redirects directly to `/user/settings/change_password`, otherwise it follows the normal post-auth redirect.
- 3 - If password is incorrect, the flow now redirects to `/user/forgot_password?email=<email>` and shows a warning to use account recovery plus check Spam/Junk.
- 4 - I added the locale key `auth.admin_notify_recover_password_spam_hint` in both `options/locale/locale_en-US.json` and `options/locale/locale_ro-RO.json`.
- 5 - I added regression tests in `routers/web/auth/auth_test.go` for normal sign-in, forced change-password redirect, wrong-password recovery redirect, and a guard that the admin-invitation flow still redirects to `/user/invitation`.
144 - [2026-05-12 00:47:20] - v1.27.0-dev-125-g1525c9c8ee - Type: Added - [user-settings] [password-ui] Added the password visibility toggle to `/user/settings/change_password`.
- 1 - I wrapped the forced-change password field in `templates/user/auth/change_passwd_inner.tmpl` with the shared `js-password-toggle-group`, reusing the existing eye-toggle logic and show/hide labels.
- 2 - I wired the confirm-password field into the existing toggle sync behavior so revealing the new password hides the confirm field and keeps it synchronized like the other password-update forms.
145 - [2026-05-12 01:16:50] - v1.27.0-dev-125-g1525c9c8ee - Type: Added - [installer] [app-ini-import] [locale] [en] [ro] Added installer support for importing an existing `app.ini`.
- 1 - I added an `Import Existing Configuration` section at the top of `templates/install.tmpl` with an `app.ini` upload control that imports automatically as soon as a file is selected, without a separate `Load app.ini` button.
- 2 - I kept the dedicated installer route `POST /import_app_ini` in `routers/install/routes.go`, but the page now posts to it via `fetch` and applies the imported values back into the existing form with `DOMParser`, so the browser is not visibly navigated to `/import_app_ini` and the page scripts are not re-executed.
- 3 - In `routers/install/install.go`, I factored the installer defaults into reusable helpers, added `app.ini` upload parsing with size/error handling, and mapped the imported config into the existing install form fields for database, general server paths, mailer, registration, OpenID, security, and admin policy settings.
- 4 - I added installer locale strings in both `options/locale/locale_en-US.json` and `options/locale/locale_ro-RO.json` for the new import UI, success message, and import errors, and the success flash now auto-dismisses after 5 seconds both on initial page load and after the AJAX import injects a new flash message.
- 5 - I added regression coverage in `routers/install/routes_test.go` for the new upload control and the config-to-form mapping behavior.
146 - [2026-05-12 01:30:10] - v1.27.0-dev-125-g1525c9c8ee - Type: Modified - [installer] [branding] Enabled shared branding assets by default in the installer.
- 1 - I updated `routers/install/install.go` so `BrandingUseSharedAssets` starts as enabled on the install form, making `Use the same logo files for favicon assets` checked by default.
147 - [2026-05-12 01:43:10] - v1.27.0-dev-125-g1525c9c8ee - Type: Added - [installer] [app-ini-import] [secrets] Added optional sensitive-secret import for installer `app.ini` uploads.
- 1 - I added an explicit installer checkbox for importing sensitive secrets from `app.ini` in `templates/install.tmpl`.
- 2 - I extended the installer form, submit pipeline, and final config writer so the optional import reuses `LFS_JWT_SECRET`, `INTERNAL_TOKEN`, and `oauth2.JWT_SECRET` from the uploaded `app.ini` instead of generating new values, including a submit-time fallback that re-reads the uploaded file if the checkbox was enabled after the first auto-import.
- 3 - I finalized secret resolution for both direct values and `LFS_JWT_SECRET_URI` / `INTERNAL_TOKEN_URI` / `JWT_SECRET_URI` file-based references, and added regression coverage for direct imports, URI-based imports, the real `POST /import_app_ini` flow, and the persisted `app.ini` output.
148 - [2026-05-12 22:44:38] - v1.27.0-dev-143-g512e577c3f - Type: Added - [scripts] [repo-sync] [rollback] Finalized the safe upstream update helper script as `.update-gitea.sh`.
- 1 - I renamed the updater to `.update-gitea.sh`, documented its purpose and ordered usage steps, including the explicit "dry-run has conflicts" path before any real sync, and added an interactive menu plus direct commands for `sync`, `dry-run`, `fetch`, `backup`, `status`, `list-backups`, `rollback`, `restore-stash`, `restore-snapshot`, and `clean-dry-run`.
- 2 - I hardened real update actions so they verify repository state, create or offer safety backup branches, retain the original pre-sync stash for rollback, and record the active restore metadata inside `.git`.
- 3 - I added exact worktree snapshots under `.git/.update-gitea-snapshots`, showed the latest/saved snapshot paths in `status`, and made `rollback` plus `restore-snapshot` restore the saved starting commit, the original local changes, and the exact worktree contents including untracked and ignored files while preserving a fresh safety snapshot of the state being replaced.
- 4 - I implemented a reusable dry-run workspace under `.git/.update-gitea-dry-run`, added cleanup for both that workspace and legacy temporary dry-run directories, and made dry-run collect and report all detected rebase conflict steps without modifying the real repository.
- 5 - I improved conflict reporting so package.json conflicts show the upstream scripts block, the conflicting commit side, and the current branch working-tree side, and the final dry-run summary now includes the total conflict-step count, the local commits that conflicted, and the unique conflicted files.
149 - [2026-05-13 00:05:18] - v1.27.0-dev-143-g512e577c3f - Type: Added - [scripts] [repo-sync] [cherry-pick] Added a dedicated safe upstream import helper based on `cherry-pick`.
- 1 - I added [`.import-upstream-cherry-pick.sh`](/config/workspace/gitea-dev/gitea/.import-upstream-cherry-pick.sh) as a separate helper that fetches upstream, lists importable upstream-only commits, and imports either selected commits or an inclusive upstream range through `git cherry-pick -x` so the imported commits keep a visible reference to the original upstream hashes.
- 2 - I gave the script the same safety model as the updater flow by creating a fresh backup branch, an exact worktree snapshot, and a saved tracked/untracked stash before every real import action, while recording the active restore metadata in `.git/.import-upstream-cherry-pick-state`.
- 3 - I added safe recovery commands for `continue`, `rollback`, `restore-stash`, and `restore-snapshot`, so interrupted or unwanted imports can be resumed or reverted back to the saved starting commit and exact worktree state, including untracked and ignored files.
- 4 - I added both command-line usage and an interactive menu for fetch, list, import, import-range, continue, backup, rollback, restore, and status workflows.
150 - [2026-05-13 00:18:42] - v1.27.0-dev-143-g512e577c3f - Type: Added - [scripts] [custom-release] [interactive] Added an interactive custom-release maintenance helper for stable patch lines.
- 1 - I added [`.maintain-custom-release.sh`](/config/workspace/gitea-dev/gitea/.maintain-custom-release.sh) to maintain a persistent custom branch such as `release/v1.26-custom`, starting from a base tag like `v1.26.0-rc0`, importing the missing upstream commits from the real upstream minor release branch such as `release/v1.26`, and then importing only the custom commits from a chosen local source branch.
- 2 - I made the helper interactive with a menu plus a guided `configure` step, so the base tag, upstream release branch, maintenance branch, custom source branch, upstream compare branch, and custom tag suffix can all be adjusted from prompts instead of only through environment variables, and I added automatic fallback from mistyped patch-style branch names like `release/v1.26.0` to the real upstream branch `release/v1.26` when it exists.
- 3 - I gave the script the same safety model as the other local Git helpers by creating a fresh backup branch, an exact worktree snapshot, and a saved tracked/untracked stash before every real import action, while also storing pending cherry-pick state so interrupted sequences can be continued.
- 4 - I added recovery commands for `continue`, `rollback`, `restore-stash`, and `restore-snapshot`, and a `tag` command that creates annotated custom release tags such as `v1.26.0-custom` on the maintained custom release branch.
151 - [2026-05-13 00:34:10] - v1.27.0-dev-143-g512e577c3f - Type: Modified - [scripts] [repo-sync] [fetch] Narrowed local upstream fetch scope and cleaned unused upstream tracking refs.
- 1 - I updated [`.update-gitea.sh`](/config/workspace/gitea-dev/gitea/.update-gitea.sh) and [`.import-upstream-cherry-pick.sh`](/config/workspace/gitea-dev/gitea/.import-upstream-cherry-pick.sh) so they fetch only the explicitly requested upstream branch instead of all upstream branches.
- 2 - I updated [`.maintain-custom-release.sh`](/config/workspace/gitea-dev/gitea/.maintain-custom-release.sh) so it fetches only the configured upstream release branch, the configured compare branch, and tags, while also normalizing mistaken patch-style release branch names like `release/v1.26.0` to the real upstream branch `release/v1.26`.
- 3 - I narrowed the local `remote.upstream.fetch` refspec to `upstream/main` and `upstream/release/v1.26`, then removed the other local `upstream/*` remote-tracking refs so Git Graph no longer shows the unused upstream branches by default.
152 - [2026-05-13 20:23:40] - v1.27.0-dev-143-g512e577c3f - Type: Modified - [scripts] [custom-release] [restore-points] Extended the custom-release maintenance helper with manual restore points and corrected its fetch and interactive configuration behavior.
- 1 - I updated [`.maintain-custom-release.sh`](/config/workspace/gitea-dev/gitea/.maintain-custom-release.sh) so it no longer auto-fetches upstream tags during release-branch synchronization, preventing patch tags like `v1.26.1` from being pulled in just because the release branch history was fetched.
- 2 - I added manual restore-point management commands for `create-restore-point`, `list-restore-points`, `restore-point`, and `delete-restore-point`, each backed by an exact worktree snapshot plus an associated backup branch stored under `.git/.maintain-custom-release-restore-points`.
- 3 - I integrated the new restore-point workflow into the interactive menu, the `help` text, and `status`, including support for restoring by full path or by the final restore-point directory name, automatically using the latest restore point for the current branch when no target is provided, recognizing the older manual restore points already stored under `.git/.manual-restore-points`, and fixing the interactive configuration prompts so they are shown correctly during `Edit configuration`.
153 - [2026-05-13 21:51:32] - v1.27.0-dev-143-g512e577c3f - Type: Modified - [scripts] [custom-release] [rollback] Finalized the custom-release maintenance helper workflow and recovery behavior.
- 1 - I made `bootstrap` a clean branch-creation step from `BASE_TAG`, separated fetch and sync into explicit compare/release-target/custom actions, added `UPSTREAM_RELEASE_TARGET_REF`, and updated the built-in help so the recommended workflow matches the current menu structure.
- 2 - I hardened recovery so rollback, restore-point, restore-snapshot, restore-stash, and restore-deletion correctly preserve or clean script-managed refs, maintenance branches, state files, backup branches, and snapshots, including rollback from the original entry branch after a bootstrap-created maintenance branch, cleanup of legacy restore-point leftovers, and removal of the correctly paired `backup/maint-*` Git Graph marker when a saved snapshot is deleted.
- 3 - I finalized the interactive UX by keeping a self-updating runtime copy in `/tmp`, persisting the last-used settings in `/tmp/.maintain-custom-release.env`, and reorganizing the menu into `Manual Backups >`, `Fetch upstreams >`, `Sync >`, `Rollback >`, and `Restore >` submenus, including `Delete Restore >` with numbered stash and snapshot selection, with numbered selections, `b`/`B` or `Enter` for Back, correct return-to-parent behavior from every submenu, and `0` for Exit.
154 - [2026-05-18 17:33:14] - v1.27.0-dev-165-gee30675569 - Type: Modified - [docs] [changelog] [github-links] Converted remaining bare pull-request references in `CHANGELOG.md` and `CHANGELOG-archived.md` to explicit GitHub links.
- 1 - I updated `CHANGELOG.md` and `CHANGELOG-archived.md` so bare changelog references of the form `#123` now use explicit Markdown links to `https://github.com/go-gitea/gitea/pull/123`, while preserving the existing local changelog edits already present in the working tree.
155 - [2026-05-17 00:18:43] - v1.26.0-rc0-154-gfc98a14014 - Type: Fixed - [admin-users] [terminology] [locale] [en] [ro] Corrected the bootstrap-admin label from `GOOD` to `GOD`.
- 1 - I renamed the bootstrap admin actor label and the related immutable-account locale key from `good` to `god` in the admin grant helpers and admin users UI flow.
- 2 - I updated the admin API and admin-panel restriction messages, tests, and both English and Romanian locale strings so bootstrap-protected accounts are consistently labeled as `GOD`-granted.
- 3 - I updated the matching historical task descriptions in `.codex-history.md` so the earlier admin-policy entries now use the corrected `GOD` terminology.
156 - [2026-05-17 18:14:08] - v1.26.0-by-petru-24-gadb90b3453 - Type: Modified - [scripts] [smart-build] [artifacts] Renamed smart-build outputs to include the tag/ref and generated per-file SHA-256 checksums.
- 1 - I updated [`.smart-build.sh`](/config/workspace/gitea-dev/gitea/.smart-build.sh) so each build artifact is now written as `gitea-<tag-or-ref>-<os>-<platform><-sqlite>` with the original executable extension preserved, and each output also gets its own adjacent `.sha256` file generated with `sha256sum` or `shasum -a 256`.
157 - [2026-05-17 15:35:49] - v1.26.0-by-petru - Type: Fixed - [scripts] [custom-release] [release-target] Stopped release-target sync from requiring the remote release branch when an explicit target tag/ref is configured.
- 1 - I updated [`.maintain-custom-release.sh`](/config/workspace/gitea-dev/gitea/.maintain-custom-release.sh) so `Sync upstream release target commits` validates only the configured `UPSTREAM_RELEASE_TARGET_REF` when one is set, instead of still failing on a missing local `upstream/release/...` remote-tracking branch after successfully fetching a target tag such as `v1.26.1`.
158 - [2026-05-18 23:03:13] - v1.27.0-dev-169-g69356f6de0 - Type: Modified - [repo-diff] [sticky-ui] [navbar] Prevented sticky diff headers from sliding under the persistent navigation bar.
- 1 - I updated `web_src/css/repo.css` so the sticky repository diff summary bar, the sticky second-row file headers, and the diff file scroll anchor margin now all include `--persistent-navbar-offset`, keeping them visible below the navbar when `Keep the navigation bar visible while scrolling` is enabled.
- 2 - I extended the same offset handling to `#diff-file-tree` so the sticky diff file tree no longer slides under the diff summary bar after the persistent-navbar preference shifts the sticky stack downward.
159 - [2026-05-19 01:10:25] - v1.27.0-dev-171-gc40e1cf08f - Type: Modified - [navbar] [sticky-ui] [user-settings] Added a show/hide toggle tab for the persistent navigation bar.
- 1 - I updated `templates/base/head_navbar.tmpl`, `web_src/css/modules/navbar.css`, and `web_src/css/modules/flexcontainer.css` so pages with `Keep the navigation bar visible while scrolling` now show a small bottom-right toggle tab that collapses the sticky navbar to a minimal visible handle and restores it on demand while keeping sticky offsets aligned.
- 2 - I updated `web_src/js/features/common-page.ts` so the toggle state is applied on page load and stored in local user settings under `persistent-navbar-collapsed`, preserving the chosen shown/hidden state across navigation.
- 3 - I added the new show/hide navbar labels to `options/locale/locale_en-US.json` and `options/locale/locale_ro-RO.json`.
- 4 - I refined the navbar toggle geometry in `web_src/css/modules/navbar.css` and `web_src/css/modules/flexcontainer.css` so the handle now sits like a slim tab just below the navbar border, is pushed closer to the right edge, and leaves only the handle visible when the persistent navbar is collapsed.
160 - [2026-05-19 21:31:45] - v1.27.0-dev-172-g3a6684178a - Type: Modified - [scripts] [smart-build] [darwin] Added macOS amd64/arm64 smart-build support, including SQLite-aware Docker-host handling for containerized workspaces.
- 1 - I updated `smart-build.sh` so its interactive architecture menu now offers `macos-amd64`, `macos-arm64`, and includes both Darwin targets in `All Arch`, while preserving the existing `darwin` artifact naming in `dist/`.
- 2 - I added a dedicated Darwin SQLite build path in `smart-build.sh` that routes macOS `bindata sqlite sqlite_unlock_notify` builds through `make release-darwin`, and I updated `Makefile` to make `release-darwin` configurable through `DARWIN_ARCHS` so helper scripts can request only `darwin-10.12/amd64` or `darwin-10.12/arm64`.
- 3 - I hardened the Darwin SQLite flow in `smart-build.sh` for `code-server`-style containerized workspaces by distinguishing between a missing Docker CLI and an unreachable Docker daemon, by validating that the host Docker daemon can see the same mounted repository `go.mod` path as the current workspace, and by moving the temporary release output under `dist/` instead of `/tmp`.
- 4 - I added `SMART_BUILD_DARWIN_HOST_REPO_PATH` support to `smart-build.sh` so Darwin SQLite builds can be redirected to a host-visible repository mount path when the interactive workspace path inside the container differs from the real host path used by the Docker daemon.
161 - [2026-05-19 23:43:29] - v1.27.0-dev-172-g06e5bd7f46 - Type: Modified - [scripts] [configure] [git-lfs] Added conditional Git LFS setup to `configure.sh` when repository LFS hooks are installed.
- 1 - I updated `.configure.sh` so repositories that already have Git LFS hook scripts in `.git/hooks` now treat `git-lfs` as a required dependency during verification, install the `git-lfs` system package on supported package managers, and run `git lfs install --local` during non-verify setup.
162 - [2026-05-20 00:31:49] - v1.27.0-dev-173-gb66ec8c19d - Type: Fixed - [navbar] [sticky-ui] [cookies] Kept the persistent navigation bar sticky for signed-out pages by reusing the saved preference from a site cookie.
- 1 - I updated `modules/web/middleware/cookie.go`, `routers/common/pagetmpl.go`, and `routers/web/user/setting/profile.go` to add a dedicated `gitea_persistent_navbar` cookie, synchronize it when authenticated users save or load the preference, and reuse that cookie as the anonymous-page fallback so the navbar stays sticky after logout just like the footer already does.
163 - [2026-05-20 00:37:42] - v1.27.0-dev-174-gef319c5c07 - Type: Modified - [navbar] [sticky-ui] Refined the persistent navbar toggle lip to be shorter and vertically center the arrow icon.
- 1 - I updated `web_src/css/modules/navbar.css` so the bottom-right persistent-navbar toggle tab now uses a slimmer 8px lip, sits 8px below the navbar edge, and centers a smaller chevron within the lip instead of bottom-aligning it.
164 - [2026-05-20 00:48:53] - v1.27.0-dev-175-g78f429361d - Type: Modified - [footer] [sticky-ui] Added a top lip show/hide toggle for the persistent footer.
- 1 - I updated `templates/base/footer_content.tmpl`, `web_src/css/home.css`, and `web_src/js/features/common-page.ts` so pages with the persistent footer preference now render a top-edge toggle lip on desktop, remember the collapsed state in local user settings under `persistent-footer-collapsed`, measure the live footer height for smooth hide/show motion, and keep only the lip visible when the footer is collapsed.
- 2 - I added the new footer show/hide labels to `options/locale/locale_en-US.json` and `options/locale/locale_ro-RO.json`.
165 - [2026-05-20 01:03:21] - v1.27.0-dev-176-gced65dc5cd - Type: Modified - [repo-header] [sticky-ui] Let the secondary navigation use the full available page width and added a little extra clearance for the sticky toggle lip.
- 1 - I updated `templates/repo/header.tmpl` and `web_src/css/modules/container.css` so the two repository `secondary-nav` containers now opt into a dedicated full-width `ui container nav` layout while still respecting the shared page margins.
- 2 - I updated `web_src/css/repo/header.css` to add 2px of extra top padding on `.repository .secondary-nav`, preventing the sticky lip from crowding the existing content at the top of the repository header area.
166 - [2026-05-20 01:09:19] - v1.27.0-dev-177-g18c3bd2a67 - Type: Modified - [navbar] [sticky-ui] Fine-tuned the persistent navbar lip geometry for better visual balance.
- 1 - I updated `web_src/css/modules/navbar.css` so the persistent-navbar toggle lip now sits 2px lower and is 1px taller, giving the handle a slightly more relaxed fit against the navbar edge.
167 - [2026-05-20 01:12:06] - v1.27.0-dev-178-gf09229e739 - Type: Modified - [footer] [sticky-ui] Fine-tuned the persistent footer lip geometry for better visual balance.
- 1 - I updated `web_src/css/home.css` so the persistent-footer toggle lip now rises a bit higher above the footer edge and is slightly taller, giving the handle a more relaxed fit against the footer border.
168 - [2026-05-21 01:08:54] - v1.27.0-dev-179-g953a7c08be - Type: Modified - [install] [mailer] Split the installer mail sender field into display name and address, auto-filled the sender name from Site Title, and reused that site name in test mails.
- 1 - I updated `services/forms/user_form.go`, `routers/install/install.go`, `templates/install.tmpl`, `options/locale/locale_en-US.json`, and `options/locale/locale_ro-RO.json` so the installer now edits `Send Email As` through separate sender-name and sender-address inputs on the same line, auto-fills the sender name from the part of `Site Title` before `:`, or from the first word when no `:` is present, and composes `[mailer] FROM = site_name <mail@address>` server-side during test mail and install submission.
- 2 - I updated `services/mailer/mail.go` so the installer test mail subject/body reuse that derived site name instead of the hardcoded `Gitea` label.
- 3 - I added targeted coverage in `routers/install/routes_test.go` and `services/mailer/mail_test.go` for the derived site-name logic and the composed installer `FROM` address.
- 4 - I updated `routers/install/install.go`, `templates/install.tmpl`, and the installer locale strings so the primary install button now renders `Install <site_name>` from the same derived site-name rule and updates live as `Site Title` changes.
169 - [2026-05-21 01:18:41] - v1.27.0-dev-180-gb1db0705d8 - Type: Modified - [locale] [i18n] Synchronized the locale files with the current installer and sticky-layout strings.
- 1 - I updated all translated `options/locale/locale_*.json` files so `install.install_btn_confirm` now accepts a `%s` site-name placeholder instead of hardcoding `Gitea`, matching the current installer button behavior.
- 2 - I added the missing `footer.show`, `footer.hide`, `install.smtp_from_name_placeholder`, and `install.smtp_from_address_placeholder` keys across the locale files, using the current English fallback text where no localized variant was available in this change.
170 - [2026-05-21 04:51:22] - v1.27.0-dev-181-g7f0a7db812 - Type: Modified - [migrate] [lfs] [ui] Refined the advanced LFS migration option layout on the repository migrate form.
- 1 - I updated `templates/repo/migrate/options.tmpl` and `web_src/css/modules/form.css` so the advanced LFS endpoint block now uses dedicated `lfs` layout hooks, giving the help text and inline input row a cleaner alignment on `/repo/migrate?service_type=2&org=&mirror=`.
171 - [2026-05-22 03:45:09] - v1.27.0-dev-182-g64f260a06d - Type: Modified - [commit] [diff] [ui] Refined the sticky commit and diff panel spacing on the repository commit view.
- 1 - I updated `web_src/css/repo.css` so the sticky `.repository .diff-detail-box` gets extra top padding, the sticky `#diff-file-tree` sits 1px lower under the persistent navbar offset, and the sticky second-row `.diff-file-header` is pushed further down to visually clear the adjusted top panel on `/user/repo/commit/xxxx`.
172 - [2026-05-22 03:49:04] - v1.27.0-dev-183-gd931966231 - Type: Modified - [locale] [ro] Adjusted the Romanian repo visibility badge labels to use concise badge-friendly wording.
- 1 - I updated `options/locale/locale_ro-RO.json` so `settings.visibility.public`, `settings.visibility.limited`, and `settings.visibility.private` now read `Public`, `Limitat`, and `Privat`, matching the compact badge style used in the repository UI.
173 - [2026-05-22 04:05:32] - v1.27.0-dev-184-gc57da3e249 - Type: Modified - [commit] [segment] [ui] Tightened the attached segment spacing in the repository commit view.
- 1 - I updated `web_src/css/modules/segment.css` so bottom-attached segments no longer keep the extra `1rem` bottom margin, helping the stacked commit-panel blocks on `/user/repo/commit/xxxx` sit more tightly together.
174 - [2026-05-22 19:36:16] - v1.27.0-dev-185-ga36bddc1c2 - Type: Modified - [badge] [label] [repo] [repo-explore] [visibility-badge] [admin] Refined the repo visibility badges (`Public` / `Privat`) and the small `by ...` labels, and kept long admin badge slugs on a single line.
- 1 - I updated `web_src/css/modules/label.css` so the repo visibility badges and the small attribution labels such as `by ...` now use a pill-style border radius with tighter horizontal padding, giving both label families a more compact visual treatment.
- 2 - I updated `templates/admin/badge/list.tmpl` to keep badge slug cells on a single line with `tw-whitespace-nowrap`, preventing awkward wrapping in the admin badge list.
175 - [2026-05-22 20:53:37] - v1.27.0-dev-186-gc498ee9b9c - Type: Fixed - [install] [app-ini-import] [mailer] Corrected installer `app.ini` import so imported mailer sender details and `Site Title` branding fully replace the current form state.
- 1 - I updated `routers/install/install.go`, `routers/install/routes_test.go`, and `templates/install.tmpl` so importing `app.ini` now replaces stale split mailer sender fields with the imported `FROM = site_name <email@example.com>` value and immediately refreshes the derived `Install %s` button label from the imported `APP_NAME`.
176 - [2026-05-22 21:27:38] - v1.27.0-dev-187-ga3b699bc70 - Type: Modified - [install] [repository-release] [ui] Added release attachment limits to the installer under "Server and Third-Party Service Settings".
- 1 - I updated `services/forms/user_form.go`, `routers/install/install.go`, `templates/install.tmpl`, and the EN/RO locale files so the installer now exposes `[repository.release] MAX_FILES` and `FILE_MAX_SIZE`, preloads them from the current settings or imported `app.ini`, and persists them back into the generated configuration with inline help text.
177 - [2026-05-22 23:38:31] - v1.27.0-dev-189-gc350a52b95 - Type: Modified - [admin] [users] [table] [nowrap] Kept the username column and its role badges on a single line in the admin user list.
- 1 - I updated `templates/admin/user/list.tmpl` so the username cell on `/-/admin/users` now uses `tw-whitespace-nowrap`, preventing the username plus `Admin by ...` or `Super Admin by ...` badges from wrapping awkwardly in the table.
178 - [2026-05-23 03:18:45] - v1.27.0-dev-190-gb7661af8d7 - Type: Fixed - [adopt] [repository] [visibility] Added an explicit `Privat` checkbox to the pre-existing repository adopt dialogs.
- 1 - I updated `templates/user/settings/repos.tmpl`, `templates/admin/repo/unadopted.tmpl`, `routers/web/user/setting/adopt.go`, and `routers/web/admin/repos.go` so the `Adopt pre-existing files` panels now submit a `private` checkbox: checked adopts the repository as private, unchecked adopts it as public. Repositories that already exist in the database continue to be shown as existing repos instead of appearing in the adopt flow.
179 - [2026-05-23 04:31:23] - v1.27.0-dev-191-gefbd83def5 - Type: Modified - [install] [repository] [app-ini-import] Exposed repository recovery options in the installer and auto-enabled them for imported `app.ini` installs without a previously used database.
- 1 - I updated `services/forms/user_form.go`, `routers/install/install.go`, `templates/install.tmpl`, `routers/install/routes_test.go`, and the EN/RO locale files so the installer now shows `ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES` and `ALLOW_DELETE_OF_UNADOPTED_REPOSITORIES` under `Repository Options` with helper descriptions, defaults both checkboxes to enabled, imports their values from `app.ini`, and forces them back to `true` during save when an imported configuration is being installed against a database that has not been used before.
- 2 - I updated `custom/conf/app.example.ini` to document both repository recovery options with the live config key names and added inline explanations that match the new installer behavior, including the imported-`app.ini` recovery auto-enable case.
180 - [2026-05-23 05:05:14] - v1.27.0-dev-192-g26e30f5ac2 - Type: Added - [org] [settings] [repository] [adopt] Added an organization-scoped pre-existing repository adoption flow under organization settings.
- 1 - I added `routers/web/org/setting_repos.go`, `templates/org/settings/repos.tmpl`, `templates/org/settings/navbar.tmpl`, and the corresponding route wiring in `routers/web/web.go`, then aligned the user and organization repository settings pages so both now separate normal adopted repositories from `Unadopted Repositories`; the final organization implementation correctly resolves adopted repos by `OwnerID`, preventing newly adopted organization repositories from lingering in the unadopted list.
181 - [2026-05-23 21:45:53] - v1.27.0-dev-193-g66093c1564 - Type: Modified - [install] [reinstall] [modal] [app-ini-import] [secrets] Reworked the installer recovery flow around existing databases and imported `app.ini` secrets.
- 1 - Compared to the previous project state, the installer no longer mixes the existing-database reinstall warning into the main page body and instead runs that confirmation flow in a dedicated modal with the warning content grouped at the top, a `Back` exit path, and an `Install %s` action that stays disabled until all required confirmations are checked; in the same recovery-oriented flow, importing `app.ini` now comes back with `Import sensitive secrets from app.ini` enabled by default, preserves the imported secret values in the form, and keeps the derived site-name label for the install action stable during validation rerenders.
182 - [2026-05-24 01:27:20] - v1.27.0-dev-194-gf293572182 - Type: Modified - [locale] [ro] Refined several Romanian UI strings for clearer wording and corrected grammar in settings, migration, repository, and admin badge messages.
- 1 - I updated `options/locale/locale_ro-RO.json` so several existing Romanian translations now use clearer and more natural phrasing, including the account deletion warning, Git migration progress text, archive action wording, workflow notification label order, and a few admin badge status messages with corrected agreement and grammar.
183 - [2026-05-24 01:44:32] - v1.27.0-dev-195-g70659dc6c3 - Type: Modified - [migrate] [cancel] [ui] Distinguished user-stopped repository migrations from genuine migration failures in the status UI.
- 1 - I updated `routers/web/repo/migrate.go`, `templates/repo/migrate/migrating.tmpl`, `web_src/js/features/repo-migrate.ts`, and the EN/RO locale files so a migration canceled by the user still uses the existing failed task state internally, but the repository migration page now renders it as `stopped` instead of `failed`, with dedicated stopped wording in both the main status title and the follow-up status message.
184 - [2026-05-24 03:12:34] - v1.27.0-dev-195-g70659dc6c3 - Type: Modified - [migrate] [cancel] [windows] [git] [retry] Made canceled repository migrations wait for the real clone shutdown before exposing retry/delete actions, and added Windows process-tree termination for migration clones.
- 1 - Fix: canceling a repository migration no longer marks the page as failed while the Git clone is still running.
- 2 - Mod: `Retry` and `Delete This Repository` stay hidden until the migration task is fully stopped.
- 3 - Fix: canceled migrations now persist as `stopped` and no longer show the raw `clone error: context canceled ...` message.
- 4 - Fix: added an opt-in Windows process-tree kill for migration clone commands via `taskkill /T /F`, because Git helper processes could remain alive after `Cancel`, keep writing `tmp_pack_*`, and block cleanup or retry.
185 - [2026-05-24 04:23:19] - v1.27.0-dev-196-g6ea9c8660f - Type: Modified - [admin] [badges] [orgs] [delete] Added direct delete actions in the admin badges and organizations tables.
- 1 - Mod: `/-/admin/badges` now shows a delete button in each row that opens the badge delete modal directly from the table.
- 2 - Mod: `/-/admin/orgs` now shows a delete button in each row that opens an organization delete modal directly from the table.
- 3 - Mod: the new table actions reuse the original delete modal layouts already used in badge edit and organization settings, and deleting an organization from `/-/admin/orgs` now returns to the admin organizations list instead of `/`.
186 - [2026-06-01 00:01:11] - v1.27.0-dev-198-g78fc93ad7a - Type: Modified - [install] [backup] [database] [recovery] Consolidated database backup and installer recovery support.
- 1 - Add: Gitea now creates timestamped database backup bundles under `[backup].PATH`, exposes the backup schedule in the installer, and surfaces the `database_backup` cron task in admin monitoring.
- 2 - Add: installed instances now use `.gitea-installed` and `.gitea-recovery.ini` to enter email-gated recovery instead of falling back to public install mode when configuration or database access is broken.
- 3 - Mod: the installer recovery flow now covers backup-bundle restore, bundled or manual `app.ini` reuse, uploaded SQL/GZ database restores, and repository-filesystem recovery with source-specific validation, confirmations, and preserved launcher state.
- 4 - Fix: recovery now restores bundled `app.ini` snapshots when needed, discovers backup bundles from both the active backup path and persisted `.gitea-recovery.ini` path, and preserves SMTP and other rebuilt settings correctly when `app.ini` is missing or incomplete.
- 5 - Fix: recovery validation and restore handling now accept either a selected backup bundle or an uploaded SQL/GZ dump, keep sensitive secrets and existing `LFS_JWT_SECRET` when appropriate, clear SQLite restore targets before import, and complete the post-install handoff without redirect loops.
- 6 - Mod: fresh installs now default recovery email authorization to enabled with first-admin fallback, and the install/recovery UI, styling, and EN/RO wording were refined to match the final launcher behavior.
+337
View File
@@ -0,0 +1,337 @@
# Gitea Project Map for Codex
This file is the persistent implementation map for fast project orientation.
Use it after `./.codex-context.md` when a task needs architecture, flow, or extension-point context.
## 1. Fast Entry Points Index
- auth -> `routers/web/auth/`, `templates/user/auth/`, `services/auth/`
- installer -> `routers/install/`, `templates/install.tmpl`, `options/locale/`
- user settings UI -> `routers/web/user/setting/`, `templates/user/settings/`, `web_src/js/features/`, `web_src/css/modules/`
- sticky menus / persistent layout UI -> `templates/*/navbar*.tmpl`, `web_src/css/modules/menu.css`, `web_src/css/modules/flexcontainer.css`, `web_src/js/features/common-page.ts`
- repo settings / actions UI -> `routers/web/repo/`, `templates/repo/`, `templates/repo/settings/`
- admin UI -> `routers/web/admin/`, `templates/admin/`
- mail / notifications -> `services/mailer/`, `templates/mail/`, `routers/web/admin/`, `routers/web/auth/`
- custom release maintenance and repo-sync helpers -> `./.maintain-custom-release.sh`, `./.update-gitea.sh`, `./.import-upstream-cherry-pick.sh`, `./.codex-script-notes.md`
## 2. Repository Map
- Executable entry point: `main.go`
- CLI lifecycle and command startup: `cmd/`
- Installed-instance initialization and route-tree mounting: `routers/init.go`
- Web SSR routes: `routers/web/`
- API routes: `routers/api/`
- Request context, session, template data, response helpers: `services/context/`
- Business logic: `services/`
- Persistence and domain models: `models/`
- Cross-cutting infrastructure: `modules/`
- Server-side templates: `templates/`
- Browser-side frontend: `web_src/`
## 3. Bootstrap and Request Flow
### 2.1 Application Bootstrap
1. `main.go`
- Sets `setting.AppVer`, `setting.AppBuiltWith`, and `setting.AppStartTime`.
- Starts the CLI app through `cmd.NewMainApp(...)` and `cmd.RunMainApp(...)`.
2. `cmd/web.go`
- `newWebCommand()` defines the `web` command.
- `runWeb(...)` prepares graceful shutdown.
- `serveInstalled(...)` calls `routers.InitWebInstalled(...)` and then `routers.NormalRoutes()`.
3. `routers/init.go`
- `InitWebInstalled(...)` initializes Git, settings, storage, cache, DB, models, auth, indexers, webhooks, SSH, Actions, and cron.
- `NormalRoutes()` mounts:
- `/` -> `routers/web.Routes()`
- `/api/v1` -> public API
- `/api/internal` -> private API
- optional package and Actions API areas when enabled
### 2.2 Web Request Pipeline
1. `routers/web/web.go:Routes()`
- Builds the main web router.
- Exposes static assets, avatars, `robots.txt`, `metrics`, and `healthz`.
2. Core middleware
- `common.MustInitSessioner()` prepares the session.
- `context.Contexter()` builds the web context and template data.
- `newWebAuthMiddleware()` resolves optional or required authentication.
3. `services/context/`
- `NewBaseContext(...)` creates the base request context.
- `NewWebContext(...)` attaches `Doer`, `Repo`, `Org`, `Session`, `Flash`, and `PageData`.
- `Contexter()` injects global template and page data such as:
- `Link`
- `PageData`
- flash cookie
- `SystemConfig`
- shared template state
4. Auth and access validation
- `verifyAuthWithOptions(...)` enforces:
- `SignInRequired`
- `SignOutRequired`
- `AdminRequired`
- cross-origin rules
- inactive-user and forced-password-change constraints
5. Domain handler
- The request reaches `routers/web/...` or `routers/api/...`.
- Handlers should stay thin and delegate to `services/...`.
6. Business logic and persistence
- `services/...` orchestrate business rules.
- `models/...` read or write the DB and represent domain state.
- `modules/...` provide reusable infrastructure such as git, storage, cache, markup, logging, web helpers, SSH, and indexing.
7. Response
- Web:
- templates from `templates/...`
- optional page JS data for `web_src/js/...`
- API:
- JSON or file responses through helpers in `services/context/`
## 4. Authentication Map
### 3.1 Where Auth Routes Live
Auth routes are mainly declared in `routers/web/web.go`, especially around:
- `/user/login`
- `/user/sign_up`
- `/user/two_factor/...`
- `/user/webauthn/...`
- `/user/openid/...`
- `/login/oauth/...`
- `/user/settings/security/...`
- `/user/settings/applications/oauth2/...`
### 3.2 Key Auth Files
- `routers/web/auth/auth.go`
- classic login
- signup
- remember-cookie login
- post-login redirect
- branching toward 2FA or WebAuthn
- `routers/web/auth/password.go`
- forgot password
- reset password
- forced password change
- `routers/web/auth/2fa.go`
- TOTP
- scratch codes
- `routers/web/auth/webauthn.go`
- passkeys
- WebAuthn challenge/assertion flow
- `routers/web/auth/openid.go`
- OpenID sign-in
- connect
- register
- `routers/web/auth/oauth.go`
- OAuth2 / OIDC provider login start and callback
- link account
- auto-registration
- provider-data sync triggers
- `routers/web/auth/oauth_signin_sync.go`
- post-login provider-data synchronization
- `routers/web/auth/oauth2_provider.go`
- Gitea as an OAuth2 / OIDC provider
- authorize, access token, userinfo, introspection, JWKS
- `routers/web/auth/linkaccount.go`
- external-account linking to a local account
### 3.3 Classic Web Login Flow
1. Browser requests `/user/login`.
2. `context.Contexter()` prepares context and page data.
3. `newWebAuthMiddleware()` attempts authentication through available strategies:
- OAuth2 header/bearer where allowed
- Basic auth where allowed
- reverse-proxy auth if enabled
- session
- SSPI on Windows if enabled
4. `auth.SignIn` renders the page.
5. `POST /user/login` enters `auth.SignInPost`.
6. On success, the flow may:
- branch to 2FA
- branch to WebAuthn
- create a remember cookie
- redirect to `redirect_to` or the default target
7. Inactive, blocked, or forced-password-change users are stopped by auth logic or `verifyAuthWithOptions(...)`.
### 3.4 Auth Services and UI
- `services/auth/` contains reusable auth strategies such as:
- `Basic`
- `OAuth2`
- `Session`
- `ReverseProxy`
- `SSPI`
- Auth UI lives in `templates/user/auth/`
- Relevant browser-side auth code includes:
- `web_src/js/features/user-auth-webauthn.ts`
- `web_src/js/features/captcha.ts`
### 3.5 Where to Extend Auth
- New auth UI step:
- `routers/web/auth/...`
- `templates/user/auth/...`
- optional `web_src/js/features/...`
- New authentication rule or source:
- `services/auth/...`
- optionally `models/auth/...`
- integrate through `newWebAuthMiddleware()`
- New OAuth2/OIDC provider endpoint:
- `routers/web/auth/oauth2_provider.go`
- `services/oauth2_provider/...`
## 5. Change Entry Points
### 4.1 New Web Route
- Add handler in `routers/web/<domain>/`
- Register in `routers/web/web.go`
- If it has UI:
- template in `templates/...`
- optional JS/CSS in `web_src/...`
### 4.2 New API Route
- Add handler in `routers/api/v1/...` or the proper API subtree
- Mount through `routers/init.go` or the existing API router
- Use `services/context/` helpers for validation and response consistency
### 4.3 New Business Rule
- Orchestration in `services/<domain>/`
- Persistence in `models/<domain>/`
- Keep routing logic thin
### 4.4 New Template Data
- Put page-specific data in handlers or domain middleware
- Put global data there only if it is truly cross-cutting
- For data consumed by page JS, use `ctx.PageData`
### 4.5 New SSR Screen or UI Change
- Template in `templates/...`
- If client-side interaction is needed:
- logic in `web_src/js/features/...`
- styles in `web_src/css/...`
### 4.6 Global Navigation and Template Hooks
- Main top navigation:
- `templates/base/head_navbar.tmpl`
- Extra global links without rewriting the standard navbar:
- `templates/custom/`
- `custom/extra_links` hook in `templates/base/head_navbar.tmpl`
- Repository header and main repo tabs:
- `templates/repo/header.tmpl`
- Extra repo tabs without rewriting the standard header:
- `custom/extra_tabs` hook in `templates/repo/header.tmpl`
- Repo submenu areas:
- `templates/repo/navbar.tmpl`
- `templates/repo/sub_menu.tmpl`
### 4.7 User, Org, Repo, and Admin Areas
- Repo:
- `routers/web/repo/`
- `services/repository/`, `services/pull/`, `services/issue/`, `services/git/`
- `templates/repo/`
- User:
- `routers/web/user/`
- `routers/web/user/setting/`
- `services/user/`
- `templates/user/`
- `templates/user/settings/`
- Org:
- `routers/web/org/`
- `services/org/`
- `templates/org/`
- `templates/org/settings/`
- Admin:
- `routers/web/admin/`
- support often spans `models/`, `services/`, and `modules/setting/`
- `templates/admin/`
## 6. Frequent Task Shortcuts
- Login / signup / account recovery:
- `routers/web/auth/`
- `templates/user/auth/`
- `services/auth/`
- `models/auth/`
- `models/user/`
- User settings / security / applications:
- `routers/web/user/setting/`
- `templates/user/settings/`
- Repository header / tabs / page chrome:
- `templates/repo/header.tmpl`
- `templates/repo/navbar.tmpl`
- `templates/repo/sub_menu.tmpl`
- Top navigation / global links:
- `templates/base/head_navbar.tmpl`
- `templates/custom/`
- Packages:
- `routers/api/packages/`
- `services/packages/`
- `models/packages/`
- Actions:
- `routers/api/actions/`
- `routers/web/repo/actions/`
- `services/actions/`
- `models/actions/`
## 7. Technology and Validation Notes
- Backend: Go
- Server-side rendering: Go `.tmpl` templates
- Frontend: TypeScript
- Vue components exist in the repo
- Styling: CSS, Tailwind CSS, Fomantic UI
- Frontend verification tooling: Vitest, Playwright, ESLint, Stylelint
For area-specific validation:
- Go:
- `make fmt`
- `make lint-go`
- targeted Go tests
- TypeScript / frontend:
- `make lint-js`
- `make test-frontend` or targeted frontend tests when needed
- `go.mod` changes:
- `make tidy`
- targeted frontend tests when needed
- `go.mod` changes:
- `make tidy`
+62
View File
@@ -0,0 +1,62 @@
# Codex Script Notes
This file is a fast-reference companion for the large local helper scripts.
## `.maintain-custom-release.sh`
Purpose:
- maintain a custom stable branch such as `release/v1.26-custom`
- start from `BASE_TAG`
- fetch and sync upstream compare / release-target refs explicitly
- cherry-pick selected custom work from a local source branch
Current interaction model:
- interactive menu with submenus:
- `Manual Backups >`
- `Fetch upstreams >`
- `Sync >`
- `Rollback >`
- `Restore >`
- submenu navigation:
- `Enter` or `b` / `B` => Back
- `0` => Exit
Persistent runtime state:
- runtime copy: `/tmp/.maintain-custom-release.sh`
- persisted settings: `/tmp/.maintain-custom-release.env`
- restore points: `.git/.maintain-custom-release-restore-points/`
- snapshots: `.git/.maintain-custom-release-snapshots/`
- active state file: `.git/.maintain-custom-release-state`
Recommended order:
1. `Bootstrap maintenance branch`
2. `Fetch upstream/main compare ref`
3. `Fetch upstream release target ref`
4. `Show import plan`
5. `Sync` actions as needed
Important behavior:
- `bootstrap` should only create/switch the maintenance branch from `BASE_TAG`; it should not fetch automatically
- `rollback` should remove bootstrap-created maintenance branches and clean script-managed refs/artifacts
- deleting a saved exact snapshot should also remove its paired `backup/maint-*` Git Graph marker
## `.update-gitea.sh`
Purpose:
- safe upstream sync helper for the working tree
- create safety backups before real sync actions
- provide `dry-run`, `rollback`, `restore-stash`, and `restore-snapshot`
Key safety expectations:
- `dry-run` must not modify the real repository
- real sync actions must preserve enough state for exact rollback
## `.import-upstream-cherry-pick.sh`
Purpose:
- import upstream commits through `git cherry-pick -x`
- support commit-by-commit or range-based import
Key safety expectations:
- save backup branch, snapshot, and stash before real import actions
- support `continue`, `rollback`, `restore-stash`, and `restore-snapshot`
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -euo pipefail
CALLBACK_URL="http://127.0.0.1:1455/auth/callback"
SUCCESS_URL="http://localhost:1455/success"
die() {
printf 'ERROR: %s\n' "$*" >&2
exit 1
}
extract_code() {
local input="$1"
case "$input" in
*code=*)
input="${input#*code=}"
input="${input%%&*}"
input="${input%%#*}"
;;
esac
printf '%s' "$input"
}
extract_id_token() {
local response_file="$1"
sed -n 's/.*id_token=\([^&[:space:]"'"'"'<>]*\).*/\1/p' "$response_file" |
tr -d '\r' |
head -n 1
}
printf 'Codex ChatGPT login helper\n'
printf 'Paste the received code, full callback URL, or query string containing code=...\n'
printf 'Received key: '
IFS= read -r received_key
[ -n "$received_key" ] || die "empty received key"
code="$(extract_code "$received_key")"
[ -n "$code" ] || die "could not extract code"
response_file="$(mktemp)"
trap 'rm -f "$response_file"' EXIT
printf '\nCalling Codex auth callback...\n'
curl -sv -H "Host: localhost" --get --data-urlencode "code=$code" "$CALLBACK_URL" >"$response_file" 2>&1 || {
cat "$response_file" >&2
die "callback request failed"
}
id_token="$(extract_id_token "$response_file")"
[ -n "$id_token" ] || {
cat "$response_file" >&2
die "could not find id_token in callback response"
}
printf 'id_token received. Completing login...\n'
curl -sv --get --data-urlencode "id_token=$id_token" "$SUCCESS_URL"
printf '\nDone.\n'
Executable
+722
View File
@@ -0,0 +1,722 @@
#!/usr/bin/env bash
set -Eeuo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_go_version() {
sed -n 's/^go //p' "$SCRIPT_DIR/go.mod" 2>/dev/null | head -n 1
}
repo_node_version() {
sed -n 's/.*"node": ">= *\([^"]*\)".*/\1/p' "$SCRIPT_DIR/package.json" 2>/dev/null | head -n 1
}
repo_pnpm_version() {
sed -n 's/.*"packageManager": "pnpm@\([^"]*\)".*/\1/p' "$SCRIPT_DIR/package.json" 2>/dev/null | head -n 1
}
GO_VERSION="${GO_VERSION:-$(repo_go_version)}"
GO_VERSION="${GO_VERSION:-1.26.2}"
NODE_VERSION="${NODE_VERSION:-$(repo_node_version)}"
NODE_VERSION="${NODE_VERSION:-22.18.0}"
PNPM_VERSION="${PNPM_VERSION:-$(repo_pnpm_version)}"
PNPM_VERSION="${PNPM_VERSION:-10.33.0}"
NVM_VERSION="${NVM_VERSION:-v0.40.3}"
INSTALL_SYSTEM=1
INSTALL_GO=1
INSTALL_NODE=1
INSTALL_FRONTEND_DEPS=1
VERIFY_ONLY=0
WITH_CROSS_CGO=0
SHOW_MENU=0
VERIFY_REPORT_ONLY=0
VERIFY_HAD_ISSUES=0
usage() {
cat <<EOF
Usage: ./configure.sh [options]
Installs and configures the local build requirements for this Gitea tree.
Options:
--with-cross-cgo Also install/configure cross-CGO toolchains for
sqlite builds targeting linux/armv7 and windows/amd64.
This is useful for "All Arch" + sqlite builds, but it
downloads noticeably larger packages.
--skip-system Do not install system packages.
--skip-go Do not install Go.
--skip-node Do not install NVM/Node/pnpm.
--skip-frontend-deps Do not run pnpm install --frozen-lockfile.
--verify-only Only check the current environment.
--menu Show the interactive run menu.
-h, --help Show this help.
Environment overrides:
GO_VERSION=$GO_VERSION
NODE_VERSION=$NODE_VERSION
PNPM_VERSION=$PNPM_VERSION
NVM_VERSION=$NVM_VERSION
EOF
}
show_description() {
cat <<EOF
Gitea build environment setup
This script prepares the local machine for the Gitea build used in this tree.
It can install or verify:
- the required system build packages, including gcc, make, git, pkg-config,
and the SQLite/PAM libraries;
- git-lfs when this repository has Git LFS hooks installed;
- Go $GO_VERSION, as required by go.mod;
- Node $NODE_VERSION and pnpm $PNPM_VERSION, as required by package.json;
- frontend dependencies with pnpm install --frozen-lockfile;
- optional cross-CGO compilers for SQLite builds targeting linux/armv7
and windows/amd64.
For automated runs, you can keep using CLI options, for example:
./configure.sh --verify-only
./configure.sh --with-cross-cgo
EOF
}
interactive_menu() {
show_description
cat <<EOF
Select install mode:
1) Normal mode
2) With cross cgo
3) Verify only
4) Quit
EOF
# Install the standard requirements: system packages, Go, Node, pnpm, and frontend deps.
# Normal mode plus cross-CGO toolchains for multi-arch SQLite builds.
# Install nothing; only check the current environment.
while true; do
printf 'Choose option [1-4]: '
if ! read -r choice; then
die "No menu option selected."
fi
case "$choice" in
1)
printf 'Selected: Normal\n'
return
;;
2)
WITH_CROSS_CGO=1
printf 'Selected: With cross cgo\n'
return
;;
3)
VERIFY_ONLY=1
INSTALL_SYSTEM=0
INSTALL_GO=0
INSTALL_NODE=0
INSTALL_FRONTEND_DEPS=0
VERIFY_REPORT_ONLY=1
printf 'Selected: Verify only\n'
return
;;
4)
printf 'Canceled.\n'
exit 0
;;
*)
printf 'Invalid option: %s\n' "$choice"
;;
esac
done
}
log() {
printf '\n==> %s\n' "$*"
}
warn() {
printf 'WARNING: %s\n' "$*" >&2
}
die() {
printf 'ERROR: %s\n' "$*" >&2
exit 1
}
command_exists() {
command -v "$1" >/dev/null 2>&1
}
repo_has_git_lfs_hooks() {
local hook
for hook in pre-push post-checkout post-commit post-merge; do
[ -f "$SCRIPT_DIR/.git/hooks/$hook" ] || continue
if grep -q 'git-lfs' "$SCRIPT_DIR/.git/hooks/$hook"; then
return 0
fi
done
return 1
}
repo_requires_git_lfs() {
repo_has_git_lfs_hooks
}
run_as_root() {
if [ "$(id -u)" -eq 0 ]; then
"$@"
elif command_exists sudo; then
sudo "$@"
else
die "This step needs root privileges. Install sudo or run the script as root."
fi
}
fetch_to() {
local url="$1"
local output="$2"
if command_exists curl; then
curl -fL --retry 3 --retry-delay 2 -o "$output" "$url"
elif command_exists wget; then
wget -O "$output" "$url"
else
die "curl or wget is required to download $url"
fi
}
version_ge() {
local actual="$1"
local required="$2"
[ "$(printf '%s\n%s\n' "$required" "$actual" | sort -V | head -n 1)" = "$required" ]
}
append_profile_line() {
local file="$1"
local line="$2"
touch "$file"
if ! grep -qxF "$line" "$file"; then
printf '\n%s\n' "$line" >>"$file"
fi
}
ensure_go_path() {
activate_go_path
append_profile_line "$HOME/.profile" 'export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"'
append_profile_line "$HOME/.bashrc" 'export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"'
}
activate_go_path() {
export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"
}
install_system_packages() {
log "Installing system packages"
if command_exists apt-get; then
local -a packages=(
bash
build-essential
ca-certificates
coreutils
curl
findutils
gawk
git
gzip
libpam0g-dev
libsqlite3-dev
make
openssh-client
perl
pkg-config
python3
sed
sqlite3
tar
unzip
wget
xz-utils
zip
)
repo_requires_git_lfs && packages+=(git-lfs)
if [ "$WITH_CROSS_CGO" -eq 1 ]; then
packages+=(
gcc-arm-linux-gnueabihf
g++-arm-linux-gnueabihf
gcc-mingw-w64-x86-64
g++-mingw-w64-x86-64
)
fi
run_as_root apt-get update
run_as_root env DEBIAN_FRONTEND=noninteractive apt-get install -y "${packages[@]}"
return
fi
if command_exists dnf; then
local -a packages=(
bash
ca-certificates
coreutils
curl
findutils
gawk
gcc
gcc-c++
git
gzip
make
openssh-clients
pam-devel
perl-core
pkgconf-pkg-config
python3
sed
sqlite
sqlite-devel
tar
unzip
wget
xz
zip
)
repo_requires_git_lfs && packages+=(git-lfs)
run_as_root dnf install -y "${packages[@]}"
[ "$WITH_CROSS_CGO" -eq 0 ] || warn "Cross-CGO package setup is only automated for apt-based systems."
return
fi
if command_exists yum; then
local -a packages=(
bash
ca-certificates
coreutils
curl
findutils
gawk
gcc
gcc-c++
git
gzip
make
openssh-clients
pam-devel
perl
pkgconfig
python3
sed
sqlite
sqlite-devel
tar
unzip
wget
xz
zip
)
repo_requires_git_lfs && packages+=(git-lfs)
run_as_root yum install -y "${packages[@]}"
[ "$WITH_CROSS_CGO" -eq 0 ] || warn "Cross-CGO package setup is only automated for apt-based systems."
return
fi
if command_exists pacman; then
local -a packages=(
base-devel
bash
ca-certificates
coreutils
curl
findutils
gawk
git
gzip
make
openssh
pam
perl
pkgconf
python
sed
sqlite
tar
unzip
wget
xz
zip
)
repo_requires_git_lfs && packages+=(git-lfs)
run_as_root pacman -Sy --needed --noconfirm "${packages[@]}"
[ "$WITH_CROSS_CGO" -eq 0 ] || warn "Cross-CGO package setup is only automated for apt-based systems."
return
fi
if command_exists zypper; then
local -a packages=(
bash
ca-certificates
coreutils
curl
findutils
gawk
gcc
gcc-c++
git
gzip
make
openssh
pam-devel
perl
pkg-config
python3
sed
sqlite3
sqlite3-devel
tar
unzip
wget
xz
zip
)
repo_requires_git_lfs && packages+=(git-lfs)
run_as_root zypper install -y "${packages[@]}"
[ "$WITH_CROSS_CGO" -eq 0 ] || warn "Cross-CGO package setup is only automated for apt-based systems."
return
fi
die "Unsupported package manager. Install git, make, gcc/g++, pkg-config, sqlite3 headers, curl/wget, tar, unzip, xz, python3, and then rerun with --skip-system."
}
go_download_arch() {
case "$(uname -m)" in
x86_64 | amd64)
printf 'amd64'
;;
aarch64 | arm64)
printf 'arm64'
;;
i386 | i686)
printf '386'
;;
armv6l | armv7l)
printf 'armv6l'
;;
*)
die "Unsupported CPU architecture for automatic Go install: $(uname -m)"
;;
esac
}
current_go_version() {
if command_exists go; then
go version | awk '{print $3}' | sed 's/^go//'
fi
}
install_go() {
log "Configuring Go $GO_VERSION"
ensure_go_path
if [ "$(current_go_version)" = "$GO_VERSION" ]; then
printf 'Go %s is already installed.\n' "$GO_VERSION"
return
fi
local arch
arch="$(go_download_arch)"
local archive="/tmp/go${GO_VERSION}.linux-${arch}.tar.gz"
local url="https://go.dev/dl/go${GO_VERSION}.linux-${arch}.tar.gz"
fetch_to "$url" "$archive"
run_as_root rm -rf /usr/local/go
run_as_root tar -C /usr/local -xzf "$archive"
ensure_go_path
[ "$(current_go_version)" = "$GO_VERSION" ] || die "Go install finished, but go version is not $GO_VERSION."
}
load_nvm() {
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
# shellcheck disable=SC1091
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
}
install_nvm() {
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
if [ -s "$NVM_DIR/nvm.sh" ]; then
load_nvm
return
fi
log "Installing NVM $NVM_VERSION"
local installer="/tmp/nvm-install-${NVM_VERSION}.sh"
fetch_to "https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh" "$installer"
bash "$installer"
load_nvm
command_exists nvm || die "NVM could not be loaded after installation."
}
current_node_version() {
if command_exists node; then
node -p 'process.versions.node'
fi
}
current_pnpm_version() {
if command_exists pnpm; then
pnpm --version
fi
}
install_node_and_pnpm() {
log "Configuring Node $NODE_VERSION and pnpm $PNPM_VERSION"
install_nvm
nvm install "$NODE_VERSION"
nvm alias default "$NODE_VERSION" >/dev/null
nvm use "$NODE_VERSION" >/dev/null
hash -r
if command_exists corepack; then
corepack enable
corepack prepare "pnpm@${PNPM_VERSION}" --activate
hash -r
fi
if ! command_exists pnpm || ! version_ge "$(current_pnpm_version)" "$PNPM_VERSION"; then
npm install -g "pnpm@${PNPM_VERSION}"
hash -r
fi
if ! version_ge "$(current_node_version)" "$NODE_VERSION"; then
die "Node $(current_node_version) is older than required $NODE_VERSION."
fi
if ! version_ge "$(current_pnpm_version)" "$PNPM_VERSION"; then
die "pnpm $(current_pnpm_version) is older than required $PNPM_VERSION."
fi
}
install_frontend_deps() {
log "Installing frontend dependencies"
cd "$SCRIPT_DIR"
pnpm install --frozen-lockfile
}
configure_git_lfs() {
repo_requires_git_lfs || return
log "Configuring Git LFS"
command_exists git-lfs || die "git-lfs is required for this repository but is not installed."
cd "$SCRIPT_DIR"
git lfs install --local >/dev/null
}
configure_cross_cgo() {
[ "$WITH_CROSS_CGO" -eq 1 ] || return
log "Configuring Makefile.local for cross-CGO sqlite builds"
cd "$SCRIPT_DIR"
if [ -f Makefile.local ] && grep -qF '# BEGIN configure.sh cross-cgo' Makefile.local; then
printf 'Makefile.local already contains configure.sh cross-CGO settings.\n'
return
fi
cat >>Makefile.local <<'EOF'
# BEGIN configure.sh cross-cgo
ifeq ($(GOOS)/$(GOARCH),windows/amd64)
CC := x86_64-w64-mingw32-gcc
CXX := x86_64-w64-mingw32-g++
export CC
export CXX
endif
ifeq ($(GOOS)/$(GOARCH)/$(GOARM),linux/arm/7)
CC := arm-linux-gnueabihf-gcc
CXX := arm-linux-gnueabihf-g++
export CC
export CXX
endif
# END configure.sh cross-cgo
EOF
}
verify_environment() {
log "Verifying build environment"
activate_go_path
load_nvm || true
hash -r
local -a missing=()
local -a problems=()
local command_name
for command_name in git make go node pnpm gcc pkg-config; do
if ! command_exists "$command_name"; then
missing+=("$command_name")
fi
done
if repo_requires_git_lfs && ! command_exists git-lfs; then
missing+=("git-lfs")
fi
if command_exists go; then
local found_go
found_go="$(current_go_version)"
[ "$found_go" = "$GO_VERSION" ] || problems+=("Go $found_go found, but $GO_VERSION is required.")
fi
if command_exists node; then
local found_node
found_node="$(current_node_version)"
version_ge "$found_node" "$NODE_VERSION" || problems+=("Node $found_node found, but >= $NODE_VERSION is required.")
fi
if command_exists pnpm; then
local found_pnpm
found_pnpm="$(current_pnpm_version)"
version_ge "$found_pnpm" "$PNPM_VERSION" || problems+=("pnpm $found_pnpm found, but >= $PNPM_VERSION is required.")
fi
cd "$SCRIPT_DIR"
if command_exists make && ! make help >/dev/null; then
problems+=("make help failed.")
fi
if [ "$WITH_CROSS_CGO" -eq 1 ]; then
for command_name in arm-linux-gnueabihf-gcc x86_64-w64-mingw32-gcc; do
if ! command_exists "$command_name"; then
missing+=("$command_name")
fi
done
fi
if [ ! -d "$SCRIPT_DIR/node_modules" ]; then
problems+=("node_modules is missing; frontend dependencies are not installed.")
fi
if [ "${#missing[@]}" -gt 0 ] || [ "${#problems[@]}" -gt 0 ]; then
VERIFY_HAD_ISSUES=1
if [ "${#missing[@]}" -gt 0 ]; then
printf '\nMissing commands:\n'
for command_name in "${missing[@]}"; do
printf ' - %s\n' "$command_name"
done
fi
if [ "${#problems[@]}" -gt 0 ]; then
printf '\nConfiguration issues:\n'
local problem
for problem in "${problems[@]}"; do
printf ' - %s\n' "$problem"
done
fi
printf '\nTo fix the standard build environment, run ./configure.sh and choose 1) Normal.\n'
printf 'For sqlite multi-arch builds, choose 2) With cross cgo.\n'
if [ "$VERIFY_REPORT_ONLY" -eq 1 ]; then
printf '\nVerify only completed; no changes were made.\n'
return 0
fi
return 1
fi
printf 'Go: %s\n' "$(go version)"
printf 'Node: %s\n' "$(node --version)"
printf 'pnpm: %s\n' "$(pnpm --version)"
printf 'gcc: %s\n' "$(gcc --version | head -n 1)"
if repo_requires_git_lfs; then
printf 'git-lfs: %s\n' "$(git lfs version)"
fi
if [ -d "$SCRIPT_DIR/node_modules" ]; then
printf 'node_modules: present\n'
else
printf 'node_modules: missing; run ./configure.sh or pnpm install --frozen-lockfile\n'
fi
}
if [ "$#" -eq 0 ] && [ -t 0 ]; then
SHOW_MENU=1
fi
while [ "$#" -gt 0 ]; do
case "$1" in
--with-cross-cgo)
WITH_CROSS_CGO=1
;;
--skip-system)
INSTALL_SYSTEM=0
;;
--skip-go)
INSTALL_GO=0
;;
--skip-node)
INSTALL_NODE=0
;;
--skip-frontend-deps)
INSTALL_FRONTEND_DEPS=0
;;
--verify-only)
VERIFY_ONLY=1
INSTALL_SYSTEM=0
INSTALL_GO=0
INSTALL_NODE=0
INSTALL_FRONTEND_DEPS=0
;;
--menu)
SHOW_MENU=1
;;
-h | --help)
usage
exit 0
;;
*)
usage
die "Unknown option: $1"
;;
esac
shift
done
if [ "$SHOW_MENU" -eq 1 ]; then
interactive_menu
fi
if [ "$(id -u)" -eq 0 ]; then
warn "You are running as root. NVM/Node will be configured for root, not for your normal user."
fi
if [ "$VERIFY_ONLY" -eq 0 ]; then
[ "$INSTALL_SYSTEM" -eq 0 ] || install_system_packages
configure_git_lfs
[ "$INSTALL_GO" -eq 0 ] || install_go
[ "$INSTALL_NODE" -eq 0 ] || install_node_and_pnpm
configure_cross_cgo
[ "$INSTALL_FRONTEND_DEPS" -eq 0 ] || install_frontend_deps
fi
verify_environment
if [ "$VERIFY_HAD_ISSUES" -eq 1 ]; then
cat <<EOF
Done. Missing requirements were reported above and no changes were made.
Run ./configure.sh again and choose:
1) Normal
For sqlite builds across all smart-build architectures, choose:
2) With cross cgo
EOF
else
cat <<EOF
Done.
Recommended next steps:
./smart-build.sh
For sqlite builds across all smart-build architectures, prepare the heavier
cross-CGO tools with:
./configure.sh --with-cross-cgo
EOF
fi
+7
View File
@@ -113,6 +113,13 @@ prime/
/.claude/
/.cursorrules
/.cursor/
# /.configure.sh
# /configure.sh
/.frontend.hash
# /.smart-build.sh
# /smart-build.sh
# /.update-gitea.sh
# /update-gitea.sh
/.goosehints
/.windsurfrules
/.github/copilot-instructions.md
+894
View File
@@ -0,0 +1,894 @@
#!/usr/bin/env bash
set -euo pipefail
# This script safely imports selected upstream commits onto the current local
# branch through cherry-pick.
# It:
# 1. checks that no conflicting git operation is already in progress;
# 2. ensures the upstream remote exists and points to the official repository;
# 3. lists upstream commits whose changes are not yet present on the current
# branch;
# 4. creates a safety backup branch and an exact worktree snapshot;
# 5. stashes tracked and untracked local changes before the import;
# 6. cherry-picks the selected upstream commits with `-x` so the original
# upstream commit hash remains visible in the imported commit message;
# 7. restores the stashed local changes only after the import completes.
# If a conflict happens, the backup branch, the exact snapshot, and the saved
# stash are all kept so the original state can be restored safely.
BRANCH="${BRANCH:-main}"
REMOTE_NAME="${REMOTE_NAME:-upstream}"
REMOTE_URL="${REMOTE_URL:-https://github.com/go-gitea/gitea.git}"
REPO_ROOT=""
GIT_DIR=""
STATE_FILE=""
SNAPSHOT_ROOT=""
CURRENT_BRANCH=""
BACKUP_BRANCH=""
STASH_REF=""
STASH_HASH=""
STATE_BRANCH=""
STATE_BACKUP_BRANCH=""
STATE_STASH_HASH=""
STATE_REMOTE_NAME=""
STATE_REMOTE_URL=""
STATE_TARGET_BRANCH=""
STATE_START_HEAD=""
STATE_SNAPSHOT_PATH=""
STATE_IMPORT_COMMITS=""
STATE_STATUS=""
STATE_UPDATED_AT=""
say() {
printf '%s\n' "$*"
}
die() {
say "ERROR: $*" >&2
exit 1
}
show_usage() {
cat <<EOF
Usage: $(basename "$0") [command]
Available commands:
fetch
Fetch the latest upstream changes only.
list
Show upstream commits whose changes are not yet present on the current branch.
import <commit> [commit...]
Cherry-pick one or more selected upstream commits with \`-x\`.
import-range <from-commit> <to-commit>
Cherry-pick an inclusive upstream commit range in upstream order.
continue
Continue an interrupted cherry-pick and restore the saved local stash once the import finishes.
backup
Create a safety backup branch from the current HEAD only.
rollback [backup-branch|snapshot-dir]
Restore the saved pre-import state, or an explicit backup branch / snapshot.
restore-stash
Re-apply the saved pre-import local stash from the last recorded import state.
restore-snapshot [snapshot-dir]
Restore the exact saved repository snapshot from the last recorded real action, or from a specific snapshot directory.
status
Show the current repository, branch, remote, local-change state, and saved import metadata.
help
Show this help text.
If no command is provided and the script is run from a terminal, an interactive
menu is shown.
Recommended order:
1. Run: ./.import-upstream-cherry-pick.sh status
2. Run: ./.import-upstream-cherry-pick.sh list
3. Choose the exact upstream commits you want to import.
4. Run: ./.import-upstream-cherry-pick.sh import <commit...>
or: ./.import-upstream-cherry-pick.sh import-range <from> <to>
5. If cherry-pick stops with conflicts:
- either resolve them and continue with: ./.import-upstream-cherry-pick.sh continue
- or return safely with: ./.import-upstream-cherry-pick.sh rollback
6. If restoring local changes after the import causes conflicts:
- either resolve them manually
- or return safely with: ./.import-upstream-cherry-pick.sh rollback
7. Use: ./.import-upstream-cherry-pick.sh restore-snapshot
when you want to restore the exact saved repository state, including
untracked and ignored files that existed at snapshot time.
EOF
}
ensure_git_repo() {
local raw_git_dir
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || die "This script must be run inside a git repository."
raw_git_dir="$(git rev-parse --git-dir)"
case "$raw_git_dir" in
/*) GIT_DIR="$raw_git_dir" ;;
*) GIT_DIR="$REPO_ROOT/$raw_git_dir" ;;
esac
STATE_FILE="$GIT_DIR/.import-upstream-cherry-pick-state"
SNAPSHOT_ROOT="$GIT_DIR/.import-upstream-cherry-pick-snapshots"
}
write_state() {
{
printf 'STATE_BRANCH=%q\n' "$STATE_BRANCH"
printf 'STATE_BACKUP_BRANCH=%q\n' "$STATE_BACKUP_BRANCH"
printf 'STATE_STASH_HASH=%q\n' "$STATE_STASH_HASH"
printf 'STATE_REMOTE_NAME=%q\n' "$STATE_REMOTE_NAME"
printf 'STATE_REMOTE_URL=%q\n' "$STATE_REMOTE_URL"
printf 'STATE_TARGET_BRANCH=%q\n' "$STATE_TARGET_BRANCH"
printf 'STATE_START_HEAD=%q\n' "$STATE_START_HEAD"
printf 'STATE_SNAPSHOT_PATH=%q\n' "$STATE_SNAPSHOT_PATH"
printf 'STATE_IMPORT_COMMITS=%q\n' "$STATE_IMPORT_COMMITS"
printf 'STATE_STATUS=%q\n' "$STATE_STATUS"
printf 'STATE_UPDATED_AT=%q\n' "$(date +%Y-%m-%dT%H:%M:%S)"
} >"$STATE_FILE"
}
load_state() {
ensure_git_repo
[ -f "$STATE_FILE" ] || return 1
# shellcheck disable=SC1090
. "$STATE_FILE"
return 0
}
worktree_has_local_changes() {
! git diff --quiet || ! git diff --cached --quiet || [ -n "$(git ls-files --others --exclude-standard)" ]
}
has_cherry_pick_in_progress() {
[ -e "$(git rev-parse --git-path CHERRY_PICK_HEAD)" ]
}
sanitize_ref_name() {
printf '%s\n' "${1//\//-}"
}
ensure_rsync_available() {
command -v rsync >/dev/null 2>&1 || die "rsync is required for exact repository snapshots."
}
snapshot_repo_dir() {
printf '%s\n' "$1/repo"
}
is_valid_snapshot_dir() {
[ -d "$1" ] && [ -d "$(snapshot_repo_dir "$1")" ]
}
snapshot_metadata_value() {
local snapshot_dir="$1" key="$2"
[ -f "$snapshot_dir/metadata.txt" ] || return 1
sed -n "s/^${key}=//p" "$snapshot_dir/metadata.txt" | head -n 1
}
create_worktree_snapshot_for_reason() {
local reason="$1" safe_branch_name timestamp snapshot_dir snapshot_dir_repo
ensure_rsync_available
safe_branch_name="$(sanitize_ref_name "$CURRENT_BRANCH")"
timestamp="$(date +%Y%m%d-%H%M%S)"
snapshot_dir="$SNAPSHOT_ROOT/$safe_branch_name/${timestamp}-${reason}"
snapshot_dir_repo="$(snapshot_repo_dir "$snapshot_dir")"
mkdir -p "$snapshot_dir_repo"
rsync --archive --delete --exclude='.git' "$REPO_ROOT"/ "$snapshot_dir_repo"/
{
printf 'branch=%s\n' "$CURRENT_BRANCH"
printf 'head=%s\n' "$(git rev-parse HEAD)"
printf 'created_at=%s\n' "$(date +%Y-%m-%dT%H:%M:%S)"
printf 'reason=%s\n' "$reason"
} >"$snapshot_dir/metadata.txt"
printf '%s\n' "$snapshot_dir"
}
restore_worktree_snapshot() {
local snapshot_dir="$1" snapshot_dir_repo
ensure_rsync_available
is_valid_snapshot_dir "$snapshot_dir" || die "Snapshot directory '$snapshot_dir' is not valid."
snapshot_dir_repo="$(snapshot_repo_dir "$snapshot_dir")"
rsync --archive --delete --exclude='.git' "$snapshot_dir_repo"/ "$REPO_ROOT"/
}
find_latest_snapshot_for_current() {
local safe_branch_name snapshot_branch_dir
safe_branch_name="$(sanitize_ref_name "$CURRENT_BRANCH")"
snapshot_branch_dir="$SNAPSHOT_ROOT/$safe_branch_name"
[ -d "$snapshot_branch_dir" ] || return 1
find "$snapshot_branch_dir" -mindepth 1 -maxdepth 1 -type d | sort -r | head -n 1
}
ensure_no_noncherrypick_git_operation_in_progress() {
local git_path
for git_path in MERGE_HEAD REVERT_HEAD BISECT_LOG rebase-merge rebase-apply; do
if [ -e "$(git rev-parse --git-path "$git_path")" ]; then
die "A git operation is already in progress ($git_path). Finish it before running this script."
fi
done
}
ensure_no_git_operation_in_progress() {
local git_path
for git_path in CHERRY_PICK_HEAD MERGE_HEAD REVERT_HEAD BISECT_LOG rebase-merge rebase-apply; do
if [ -e "$(git rev-parse --git-path "$git_path")" ]; then
die "A git operation is already in progress ($git_path). Finish it before running this script."
fi
done
if [ -n "$(git diff --name-only --diff-filter=U)" ]; then
die "There are unmerged files in the working tree. Resolve them first."
fi
}
ensure_current_branch() {
CURRENT_BRANCH="$(git symbolic-ref --quiet --short HEAD || true)"
[ -n "$CURRENT_BRANCH" ] || die "Detached HEAD is not supported. Check out a branch first."
}
ensure_current_branch_with_state_fallback() {
CURRENT_BRANCH="$(git symbolic-ref --quiet --short HEAD || true)"
if [ -n "$CURRENT_BRANCH" ]; then
return
fi
if load_state && [ -n "${STATE_BRANCH:-}" ]; then
CURRENT_BRANCH="$STATE_BRANCH"
return
fi
die "Detached HEAD is not supported here and no saved branch state was found."
}
ensure_upstream_remote() {
local current_remote_url
if current_remote_url="$(git remote get-url "$REMOTE_NAME" 2>/dev/null)"; then
if [ "$current_remote_url" != "$REMOTE_URL" ]; then
die "Remote '$REMOTE_NAME' points to '$current_remote_url', expected '$REMOTE_URL'."
fi
return
fi
say "Adding remote '$REMOTE_NAME'..."
git remote add "$REMOTE_NAME" "$REMOTE_URL"
}
create_backup_branch_for_reason() {
local reason="$1" safe_branch_name timestamp branch_name
safe_branch_name="$(sanitize_ref_name "$CURRENT_BRANCH")"
timestamp="$(date +%Y%m%d-%H%M%S)"
branch_name="backup/cherry-pick-${safe_branch_name}-${reason}-${timestamp}"
git branch "$branch_name" HEAD >/dev/null
printf '%s\n' "$branch_name"
}
find_latest_backup_branch_for_current() {
local safe_branch_name
safe_branch_name="$(sanitize_ref_name "$CURRENT_BRANCH")"
git for-each-ref --sort=-creatordate --format='%(refname:short)' "refs/heads/backup/cherry-pick-${safe_branch_name}-*" | head -n 1
}
prepare_safety_before_real_action() {
local backup_reason="$1"
STATE_START_HEAD="$(git rev-parse HEAD)"
BACKUP_BRANCH="$(create_backup_branch_for_reason "$backup_reason")"
STATE_SNAPSHOT_PATH="$(create_worktree_snapshot_for_reason "$backup_reason")"
say "Safety backup branch created: $BACKUP_BRANCH"
say "Exact worktree snapshot created: $STATE_SNAPSHOT_PATH"
}
stash_current_changes() {
local stash_prefix="$1" timestamp stash_name
STASH_REF=""
STASH_HASH=""
if ! worktree_has_local_changes; then
say "No local tracked/untracked changes to stash."
return
fi
timestamp="$(date +%Y%m%d-%H%M%S)"
stash_name="${stash_prefix}-$(sanitize_ref_name "$CURRENT_BRANCH")-${timestamp}"
say "Stashing local tracked and untracked changes..."
git stash push --include-untracked --message "$stash_name" >/dev/null
STASH_REF="$(git stash list -1 --format='%gd')"
[ -n "$STASH_REF" ] || die "Failed to locate the created stash entry."
STASH_HASH="$(git rev-parse "$STASH_REF")"
[ -n "$STASH_HASH" ] || die "Failed to resolve the created stash hash."
say "Local changes saved in $STASH_REF"
}
fetch_upstream() {
say "Fetching latest changes from $REMOTE_NAME/$BRANCH..."
git fetch --prune "$REMOTE_NAME" "+refs/heads/$BRANCH:refs/remotes/$REMOTE_NAME/$BRANCH"
git show-ref --verify --quiet "refs/remotes/$REMOTE_NAME/$BRANCH" || die "Remote branch '$REMOTE_NAME/$BRANCH' was not found."
}
update_state() {
STATE_BRANCH="$CURRENT_BRANCH"
STATE_BACKUP_BRANCH="$BACKUP_BRANCH"
STATE_STASH_HASH="$STASH_HASH"
STATE_REMOTE_NAME="$REMOTE_NAME"
STATE_REMOTE_URL="$REMOTE_URL"
STATE_TARGET_BRANCH="$BRANCH"
write_state
}
find_stash_ref_by_hash() {
local target_hash="$1" hash ref
while read -r hash ref; do
if [ "$hash" = "$target_hash" ]; then
printf '%s\n' "$ref"
return 0
fi
done < <(git stash list --format='%H %gd')
return 1
}
drop_stash_by_hash_if_present() {
local target_hash="$1" stash_ref
[ -n "$target_hash" ] || return 0
if stash_ref="$(find_stash_ref_by_hash "$target_hash")"; then
git stash drop "$stash_ref" >/dev/null
fi
}
restore_stash() {
local keep_saved_copy="${1:-0}" restore_target
if [ -z "$STASH_HASH" ] && [ -z "$STASH_REF" ]; then
return
fi
restore_target="${STASH_HASH:-$STASH_REF}"
say "Restoring stashed local changes from $restore_target..."
if git stash apply --index "$restore_target"; then
STASH_REF=""
if [ "$keep_saved_copy" -eq 0 ]; then
drop_stash_by_hash_if_present "$STASH_HASH"
STASH_HASH=""
STATE_STASH_HASH=""
else
STATE_STASH_HASH="${STASH_HASH:-$restore_target}"
fi
STATE_STATUS="completed"
update_state
if [ "$keep_saved_copy" -eq 0 ]; then
say "Local changes restored successfully."
else
say "Local changes restored successfully. The original stash was kept for rollback safety."
fi
return
fi
STATE_STATUS="restore_conflict"
update_state
say "Conflicts occurred while restoring local changes."
say "Backup branch kept at: $BACKUP_BRANCH"
say "Stash kept at: $restore_target"
say "Resolve the conflicts manually, or return safely with: ./.import-upstream-cherry-pick.sh rollback"
exit 1
}
ordered_available_upstream_commits() {
local available_commit_shas="" commit
available_commit_shas="$(git cherry -v HEAD "$REMOTE_NAME/$BRANCH" | awk '$1=="+"{print $2}')"
[ -n "$available_commit_shas" ] || return 0
while IFS= read -r commit; do
[ -n "$commit" ] || continue
if printf '%s\n' "$available_commit_shas" | grep -Fxq "$commit"; then
printf '%s\n' "$commit"
fi
done < <(git rev-list --reverse HEAD.."$REMOTE_NAME/$BRANCH")
}
commit_is_available_for_import() {
local commit="$1"
ordered_available_upstream_commits | grep -Fxq "$commit"
}
resolve_import_commit() {
local commit="$1"
git rev-parse --verify "${commit}^{commit}" 2>/dev/null || die "Commit '$commit' could not be resolved."
}
validate_importable_commit() {
local commit="$1"
git merge-base --is-ancestor "$commit" "$REMOTE_NAME/$BRANCH" || die "Commit '$commit' is not reachable from $REMOTE_NAME/$BRANCH."
commit_is_available_for_import "$commit" || die "Commit '$commit' is not currently available for import into '$CURRENT_BRANCH'."
}
show_available_commits() {
local found_any=0 commit
while IFS= read -r commit; do
[ -n "$commit" ] || continue
found_any=1
git show --no-patch --date=short --format=' - %h | %ad | %s' "$commit"
done < <(ordered_available_upstream_commits)
if [ "$found_any" -eq 0 ]; then
say "No upstream commits are currently available for cherry-pick import."
fi
}
run_status() {
local stash_count latest_backup latest_snapshot
ensure_git_repo
ensure_current_branch_with_state_fallback
ensure_upstream_remote
stash_count="$(git stash list | wc -l | tr -d ' ')"
latest_backup="$(find_latest_backup_branch_for_current || true)"
latest_snapshot="$(find_latest_snapshot_for_current || true)"
say "Repository: $(git rev-parse --show-toplevel)"
say "Current branch: $CURRENT_BRANCH"
say "Upstream remote: $REMOTE_NAME -> $REMOTE_URL"
say "Working tree:"
if ! worktree_has_local_changes; then
say " clean"
else
git status --short
fi
say "Stash entries: $stash_count"
say "Latest backup for current branch: ${latest_backup:-none}"
say "Latest snapshot for current branch: ${latest_snapshot:-none}"
if load_state; then
say "Saved import state: $STATE_STATUS"
say "Saved backup branch: ${STATE_BACKUP_BRANCH:-none}"
say "Saved starting commit: ${STATE_START_HEAD:-none}"
say "Saved exact snapshot: ${STATE_SNAPSHOT_PATH:-none}"
say "Saved original stash: ${STATE_STASH_HASH:-none}"
say "Saved import commits: ${STATE_IMPORT_COMMITS:-none}"
else
say "Saved import state: none"
fi
}
run_fetch_only() {
ensure_git_repo
ensure_no_git_operation_in_progress
ensure_current_branch
ensure_upstream_remote
fetch_upstream
say "Latest changes fetched from $REMOTE_NAME/$BRANCH."
}
run_list() {
ensure_git_repo
ensure_no_git_operation_in_progress
ensure_current_branch
ensure_upstream_remote
fetch_upstream
show_available_commits
}
run_backup_only() {
ensure_git_repo
ensure_no_git_operation_in_progress
ensure_current_branch
ensure_upstream_remote
BACKUP_BRANCH="$(create_backup_branch_for_reason "manual-backup")"
say "Safety backup branch created: $BACKUP_BRANCH"
}
run_import_commits() {
local requested_commits=("$@") commit resolved_commit
local -a selected_commits=()
[ "${#requested_commits[@]}" -gt 0 ] || die "Provide at least one upstream commit to import."
ensure_git_repo
ensure_no_git_operation_in_progress
ensure_current_branch
ensure_upstream_remote
fetch_upstream
for commit in "${requested_commits[@]}"; do
resolved_commit="$(resolve_import_commit "$commit")"
validate_importable_commit "$resolved_commit"
selected_commits+=("$resolved_commit")
done
STATE_IMPORT_COMMITS="${selected_commits[*]}"
prepare_safety_before_real_action "before-cherry-pick-import"
stash_current_changes "pre-cherry-pick-import"
STATE_STATUS="prepared"
update_state
for commit in "${selected_commits[@]}"; do
say "Cherry-picking upstream commit: $(git show --no-patch --format='%h %s' "$commit")"
if ! git cherry-pick -x "$commit"; then
STATE_STATUS="cherry_pick_conflict"
update_state
say "Cherry-pick stopped because of conflicts."
say "Conflicting upstream commit: $(git show --no-patch --format='%h %s' CHERRY_PICK_HEAD)"
say "Resolve conflicts and continue with: ./.import-upstream-cherry-pick.sh continue"
say "Or return safely with: ./.import-upstream-cherry-pick.sh rollback"
exit 1
fi
done
restore_stash 1
say "Imported ${#selected_commits[@]} upstream commit(s) by cherry-pick."
say "Safety backup branch available at: $BACKUP_BRANCH"
say "Safety snapshot available at: $STATE_SNAPSHOT_PATH"
if [ -n "$STATE_STASH_HASH" ]; then
say "Original pre-import stash retained for rollback at: $STATE_STASH_HASH"
fi
}
run_import_range() {
local from_commit="${1:-}" to_commit="${2:-}" from_resolved to_resolved commit
local -a selected_commits=()
[ -n "$from_commit" ] || die "Provide the start commit for import-range."
[ -n "$to_commit" ] || die "Provide the end commit for import-range."
ensure_git_repo
ensure_no_git_operation_in_progress
ensure_current_branch
ensure_upstream_remote
fetch_upstream
from_resolved="$(resolve_import_commit "$from_commit")"
to_resolved="$(resolve_import_commit "$to_commit")"
git merge-base --is-ancestor "$from_resolved" "$REMOTE_NAME/$BRANCH" || die "Start commit '$from_commit' is not reachable from $REMOTE_NAME/$BRANCH."
git merge-base --is-ancestor "$to_resolved" "$REMOTE_NAME/$BRANCH" || die "End commit '$to_commit' is not reachable from $REMOTE_NAME/$BRANCH."
git merge-base --is-ancestor "$from_resolved" "$to_resolved" || die "Start commit '$from_commit' must be an ancestor of end commit '$to_commit' on $REMOTE_NAME/$BRANCH."
while IFS= read -r commit; do
[ -n "$commit" ] || continue
if commit_is_available_for_import "$commit"; then
selected_commits+=("$commit")
fi
done < <(git rev-list --reverse "${from_resolved}^..${to_resolved}")
[ "${#selected_commits[@]}" -gt 0 ] || die "No importable commits were found in the requested range."
run_import_commits "${selected_commits[@]}"
}
run_continue() {
ensure_git_repo
ensure_current_branch_with_state_fallback
ensure_upstream_remote
load_state || die "No saved cherry-pick state was found."
[ "$CURRENT_BRANCH" = "${STATE_BRANCH:-$CURRENT_BRANCH}" ] || die "Saved cherry-pick state belongs to branch '$STATE_BRANCH'. Check out that branch first."
has_cherry_pick_in_progress || die "There is no in-progress cherry-pick to continue."
say "Continuing cherry-pick..."
GIT_EDITOR=: git cherry-pick --continue
if has_cherry_pick_in_progress; then
STATE_STATUS="cherry_pick_conflict"
update_state
say "Cherry-pick hit another conflict."
say "Current conflicting upstream commit: $(git show --no-patch --format='%h %s' CHERRY_PICK_HEAD)"
say "Resolve conflicts and run: ./.import-upstream-cherry-pick.sh continue"
say "Or return safely with: ./.import-upstream-cherry-pick.sh rollback"
exit 1
fi
STASH_HASH="${STATE_STASH_HASH:-}"
STASH_REF=""
BACKUP_BRANCH="${STATE_BACKUP_BRANCH:-}"
restore_stash 1
say "Cherry-pick import completed."
}
run_restore_saved_stash() {
ensure_git_repo
ensure_no_git_operation_in_progress
ensure_current_branch_with_state_fallback
load_state || die "No saved import state was found."
[ "$CURRENT_BRANCH" = "${STATE_BRANCH:-$CURRENT_BRANCH}" ] || die "Saved import state belongs to branch '$STATE_BRANCH'. Check out that branch first."
[ -n "${STATE_STASH_HASH:-}" ] || die "There is no saved pre-import stash to restore."
if worktree_has_local_changes; then
die "The working tree is not clean. Commit, stash, or discard current changes before restoring the saved stash."
fi
prepare_safety_before_real_action "before-restore-stash"
STASH_HASH="$STATE_STASH_HASH"
STASH_REF=""
restore_stash 1
say "Saved pre-import local changes restored."
}
run_rollback() {
local explicit_target="${1:-}" reset_target="" reset_snapshot=""
local original_restore_stash_hash="" original_restore_start_head=""
local rollback_safety_snapshot="" rollback_safety_backup="" rollback_safety_start_head=""
local preserve_stash_hash=""
ensure_git_repo
ensure_no_noncherrypick_git_operation_in_progress
load_state || true
ensure_current_branch_with_state_fallback
ensure_upstream_remote
if [ -n "$explicit_target" ] && is_valid_snapshot_dir "$explicit_target"; then
reset_snapshot="$explicit_target"
elif [ -n "$explicit_target" ]; then
git show-ref --verify --quiet "refs/heads/$explicit_target" || die "Backup branch '$explicit_target' does not exist."
reset_target="$explicit_target"
else
if [ -n "${STATE_BRANCH:-}" ] && [ "$CURRENT_BRANCH" != "$STATE_BRANCH" ]; then
die "Saved import state belongs to branch '$STATE_BRANCH'. Check out that branch or pass an explicit backup branch or snapshot."
fi
if [ -n "${STATE_SNAPSHOT_PATH:-}" ] && is_valid_snapshot_dir "$STATE_SNAPSHOT_PATH"; then
reset_snapshot="$STATE_SNAPSHOT_PATH"
fi
if [ -n "${STATE_START_HEAD:-}" ]; then
reset_target="$STATE_START_HEAD"
elif [ -n "${STATE_BACKUP_BRANCH:-}" ]; then
reset_target="$STATE_BACKUP_BRANCH"
else
reset_target="$(find_latest_backup_branch_for_current || true)"
fi
fi
if [ -z "$reset_target" ] && [ -n "$reset_snapshot" ]; then
reset_target="$(snapshot_metadata_value "$reset_snapshot" head || true)"
fi
[ -n "$reset_target" ] || [ -n "$reset_snapshot" ] || die "No saved rollback target was found."
original_restore_stash_hash="${STATE_STASH_HASH:-}"
original_restore_start_head="${STATE_START_HEAD:-}"
if [ -z "$original_restore_start_head" ] && [ -n "$reset_snapshot" ]; then
original_restore_start_head="$(snapshot_metadata_value "$reset_snapshot" head || true)"
fi
if has_cherry_pick_in_progress; then
say "Aborting in-progress cherry-pick before rollback..."
git cherry-pick --abort || die "Failed to abort the in-progress cherry-pick."
fi
if [ -n "$(git diff --name-only --diff-filter=U)" ]; then
die "There are still unmerged files in the working tree. Resolve or discard them before rollback."
fi
prepare_safety_before_real_action "before-rollback"
rollback_safety_backup="$BACKUP_BRANCH"
rollback_safety_snapshot="$STATE_SNAPSHOT_PATH"
rollback_safety_start_head="$STATE_START_HEAD"
preserve_stash_hash=""
if worktree_has_local_changes; then
stash_current_changes "pre-rollback-preserve"
preserve_stash_hash="$STASH_HASH"
fi
if [ -n "$reset_target" ]; then
say "Resetting '$CURRENT_BRANCH' to '$reset_target'..."
git reset --hard "$reset_target" >/dev/null
fi
if [ -n "$original_restore_stash_hash" ]; then
STASH_HASH="$original_restore_stash_hash"
STASH_REF=""
BACKUP_BRANCH="$rollback_safety_backup"
say "Restoring original pre-import local changes..."
restore_stash 1
fi
if [ -n "$reset_snapshot" ]; then
say "Restoring exact worktree snapshot from: $reset_snapshot"
restore_worktree_snapshot "$reset_snapshot"
fi
STATE_BRANCH="$CURRENT_BRANCH"
STATE_BACKUP_BRANCH="$rollback_safety_backup"
STATE_STASH_HASH="$preserve_stash_hash"
STATE_REMOTE_NAME="$REMOTE_NAME"
STATE_REMOTE_URL="$REMOTE_URL"
STATE_TARGET_BRANCH="$BRANCH"
STATE_START_HEAD="$rollback_safety_start_head"
STATE_SNAPSHOT_PATH="$rollback_safety_snapshot"
STATE_IMPORT_COMMITS=""
STATE_STATUS="rollback_completed"
write_state
say "Rollback completed."
say "Restored starting commit: ${original_restore_start_head:-$reset_target}"
if [ -n "$reset_snapshot" ]; then
say "Restored snapshot: $reset_snapshot"
fi
say "Safety backup of the pre-rollback state kept at: $rollback_safety_backup"
say "Safety snapshot of the pre-rollback state kept at: $rollback_safety_snapshot"
if [ -n "$preserve_stash_hash" ]; then
say "Safety stash of the pre-rollback local changes kept at: $preserve_stash_hash"
fi
}
run_restore_snapshot() {
local target_snapshot="${1:-}" restore_safety_backup="" restore_safety_snapshot=""
local restore_safety_start_head="" restore_start_head="" preserve_stash_hash=""
ensure_git_repo
ensure_no_noncherrypick_git_operation_in_progress
load_state || die "No saved import state was found."
ensure_current_branch_with_state_fallback
ensure_upstream_remote
if [ -z "$target_snapshot" ]; then
target_snapshot="${STATE_SNAPSHOT_PATH:-}"
fi
is_valid_snapshot_dir "$target_snapshot" || die "No valid saved snapshot was found to restore."
restore_start_head="${STATE_START_HEAD:-}"
if [ -z "$restore_start_head" ]; then
restore_start_head="$(snapshot_metadata_value "$target_snapshot" head || true)"
fi
[ -n "$restore_start_head" ] || die "No saved starting commit was found for the snapshot restore."
if has_cherry_pick_in_progress; then
say "Aborting in-progress cherry-pick before snapshot restore..."
git cherry-pick --abort || die "Failed to abort the in-progress cherry-pick."
fi
if [ -n "$(git diff --name-only --diff-filter=U)" ]; then
die "There are still unmerged files in the working tree. Resolve or discard them before restoring the snapshot."
fi
prepare_safety_before_real_action "before-restore-snapshot"
restore_safety_backup="$BACKUP_BRANCH"
restore_safety_snapshot="$STATE_SNAPSHOT_PATH"
restore_safety_start_head="$STATE_START_HEAD"
if worktree_has_local_changes; then
stash_current_changes "pre-restore-snapshot-preserve"
preserve_stash_hash="$STASH_HASH"
fi
say "Resetting '$CURRENT_BRANCH' to '$restore_start_head' before snapshot restore..."
git reset --hard "$restore_start_head" >/dev/null
if [ -n "${STATE_STASH_HASH:-}" ]; then
STASH_HASH="$STATE_STASH_HASH"
STASH_REF=""
BACKUP_BRANCH="$restore_safety_backup"
say "Restoring saved pre-import local changes..."
restore_stash 1
fi
say "Restoring exact worktree snapshot from: $target_snapshot"
restore_worktree_snapshot "$target_snapshot"
STATE_BRANCH="$CURRENT_BRANCH"
STATE_BACKUP_BRANCH="$restore_safety_backup"
STATE_STASH_HASH="$preserve_stash_hash"
STATE_REMOTE_NAME="$REMOTE_NAME"
STATE_REMOTE_URL="$REMOTE_URL"
STATE_TARGET_BRANCH="$BRANCH"
STATE_START_HEAD="$restore_safety_start_head"
STATE_SNAPSHOT_PATH="$restore_safety_snapshot"
STATE_IMPORT_COMMITS=""
STATE_STATUS="snapshot_restored"
write_state
say "Snapshot restore completed."
say "Safety backup of the pre-restore state kept at: $restore_safety_backup"
say "Safety snapshot of the pre-restore state kept at: $restore_safety_snapshot"
if [ -n "$preserve_stash_hash" ]; then
say "Safety stash of the pre-restore local changes kept at: $preserve_stash_hash"
fi
}
show_menu() {
local choice import_commits range_from range_to snapshot_target rollback_target
while true; do
cat <<EOF
Available actions:
1) Fetch upstream only
2) List available upstream commits
3) Import selected commit(s)
4) Import an inclusive commit range
5) Continue in-progress cherry-pick
6) Rollback last import
7) Restore saved stash
8) Restore exact snapshot
9) Create backup branch only
10) Show repository status
11) Help
0) Exit
EOF
printf 'Choose an action: '
read -r choice
case "$choice" in
1) run_fetch_only ;;
2) run_list ;;
3)
printf 'Enter upstream commit hash(es), separated by spaces: '
read -r -a import_commits
run_import_commits "${import_commits[@]}"
return
;;
4)
printf 'Enter the start commit hash: '
read -r range_from
printf 'Enter the end commit hash: '
read -r range_to
run_import_range "$range_from" "$range_to"
return
;;
5)
run_continue
return
;;
6)
printf 'Optional backup branch or snapshot path (leave empty for saved state): '
read -r rollback_target
run_rollback "$rollback_target"
return
;;
7)
run_restore_saved_stash
return
;;
8)
printf 'Optional snapshot path (leave empty for saved state): '
read -r snapshot_target
run_restore_snapshot "$snapshot_target"
return
;;
9) run_backup_only ;;
10) run_status ;;
11) show_usage ;;
0) exit 0 ;;
*) say "Invalid menu selection: $choice" ;;
esac
done
}
main() {
case "${1:-menu}" in
fetch) run_fetch_only ;;
list) run_list ;;
import)
shift
run_import_commits "$@"
;;
import-range) run_import_range "${2:-}" "${3:-}" ;;
continue) run_continue ;;
backup) run_backup_only ;;
rollback) run_rollback "${2:-}" ;;
restore-stash) run_restore_saved_stash ;;
restore-snapshot) run_restore_snapshot "${2:-}" ;;
status) run_status ;;
help|-h|--help) show_usage ;;
menu)
if [ -t 0 ] && [ -t 1 ]; then
show_menu
else
show_usage
fi
;;
*)
die "Unknown command: $1. Run with 'help' to see available options."
;;
esac
}
main "$@"
+2440
View File
File diff suppressed because it is too large Load Diff
+435
View File
@@ -0,0 +1,435 @@
#!/bin/bash
# Folosește instalarea Go standard dacă există, chiar dacă nu este în PATH.
if [ -x "/usr/local/go/bin/go" ]; then
export PATH="/usr/local/go/bin:$PATH"
fi
# Încarcă NVM dacă este disponibil
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# Forțează folosirea versiunii 22
nvm use 22 > /dev/null 2>&1 || echo "⚠️ NVM nu a putut activa Node 22 automatically."
resolve_build_ref() {
git describe --tags --exact-match 2>/dev/null || git describe --tags --always
}
require_docker_for_darwin_sqlite() {
if ! command -v docker > /dev/null 2>&1; then
echo "❌ Docker is required for macOS SQLite cross-builds."
echo " Install the Docker CLI in this environment, or use the non-SQLite macOS build option."
echo " If you are running inside a code-server container, also mount the host Docker socket."
exit 1
fi
if ! docker info > /dev/null 2>&1; then
echo "❌ Docker is installed but the daemon is not reachable."
echo " Start Docker, or expose the host Docker daemon to this container."
echo " For a code-server container, mount /var/run/docker.sock from the host."
if [ -n "${DOCKER_HOST:-}" ]; then
echo " Current DOCKER_HOST: ${DOCKER_HOST}"
else
echo " Current DOCKER_HOST is unset."
fi
exit 1
fi
}
resolve_xgo_image() {
local xgo_version
xgo_version="$(awk '$1 == "XGO_VERSION" { print $3; exit }' Makefile 2>/dev/null)"
if [ -z "$xgo_version" ]; then
xgo_version="go-1.25.x"
fi
printf 'ghcr.io/techknowlogick/xgo:%s' "$xgo_version"
}
resolve_darwin_sqlite_repo_root() {
local override_path
override_path="${SMART_BUILD_DARWIN_HOST_REPO_PATH:-}"
if [ -z "$override_path" ]; then
pwd -P
return
fi
if [ ! -d "$override_path" ] || [ ! -f "$override_path/go.mod" ]; then
echo "❌ SMART_BUILD_DARWIN_HOST_REPO_PATH is set, but the path is not usable in this container:"
echo " $override_path"
echo " Mount the host repository path into the container at the same absolute path, then retry."
exit 1
fi
printf '%s' "$override_path"
}
validate_repo_bind_mount_for_darwin_sqlite() {
local repo_path="$1"
local xgo_image
xgo_image="$(resolve_xgo_image)"
if ! docker run --rm -v "$repo_path":/probe:ro --entrypoint sh "$xgo_image" -lc 'test -f /probe/go.mod'; then
echo "❌ Docker can reach the daemon, but the daemon cannot mount this repository path correctly:"
echo " $repo_path"
echo " The xgo container only sees an empty or different host path, so /source/go.mod is missing there."
echo " If smart-build runs inside a code-server container with the host Docker socket,"
echo " the repository must be mounted from a host bind path that exists at the same absolute path."
exit 1
fi
}
write_sha256_file() {
local artifact_path="$1"
local artifact_dir artifact_name
artifact_dir="$(dirname "$artifact_path")"
artifact_name="$(basename "$artifact_path")"
if command -v sha256sum > /dev/null 2>&1; then
(
cd "$artifact_dir" || exit 1
sha256sum "$artifact_name" > "$artifact_name.sha256"
)
return
fi
if command -v shasum > /dev/null 2>&1; then
(
cd "$artifact_dir" || exit 1
shasum -a 256 "$artifact_name" > "$artifact_name.sha256"
)
return
fi
echo "❌ Neither sha256sum nor shasum is available for checksum generation."
exit 1
}
# --- 1. VERIFICARE INTEGRITATE ȘI CURĂȚARE CACHE INIȚIALĂ ---
echo "🔍 Initialization checks..."
if ! command -v go > /dev/null 2>&1; then
echo "❌ Go nu este disponibil în PATH. Instalează Go 1.26.2 sau adaugă binarul go în PATH."
exit 1
fi
notify_human_interaction() {
local bell_oga="/usr/share/sounds/freedesktop/stereo/bell.oga"
local bell_wav="/usr/share/sounds/alsa/Front_Center.wav"
local in_vscode_terminal=0
local notification_sent=0
if [ "${TERM_PROGRAM:-}" = "vscode" ] || [ -n "${VSCODE_IPC_HOOK_CLI:-}" ] || [ -n "${VSCODE_GIT_IPC_HANDLE:-}" ]; then
in_vscode_terminal=1
fi
if command -v notify-send > /dev/null 2>&1; then
notify-send "Gitea smart-build" "Human input required in smart-build.sh" > /dev/null 2>&1 && notification_sent=1
fi
if command -v canberra-gtk-play > /dev/null 2>&1; then
canberra-gtk-play -i bell > /dev/null 2>&1 && return
fi
if [ -f "$bell_oga" ] && command -v paplay > /dev/null 2>&1; then
paplay "$bell_oga" > /dev/null 2>&1 && return
fi
if [ -f "$bell_wav" ] && command -v aplay > /dev/null 2>&1; then
aplay -q "$bell_wav" > /dev/null 2>&1 && return
fi
if [ -f "$bell_wav" ] && command -v play > /dev/null 2>&1; then
play -q "$bell_wav" > /dev/null 2>&1 && return
fi
if [ -t 1 ]; then
printf '\a'
fi
if [ "$notification_sent" -eq 0 ] && [ "$in_vscode_terminal" -eq 1 ]; then
printf '\033[1;33m%s\033[0m\n' ">>> Human input required below <<<"
fi
}
apply_moderate_build_limits() {
local go_procs="$1"
local node_memory="$2"
export GOMAXPROCS="$go_procs"
export MAKEFLAGS="-j1"
if [[ "$NODE_OPTIONS" != *"--max-old-space-size="* ]]; then
export NODE_OPTIONS="${NODE_OPTIONS:+$NODE_OPTIONS }--max-old-space-size=$node_memory"
fi
}
echo ""
echo "⚙️ Select Build Load Profile:"
echo " Normal keeps the default build behavior."
echo " Moderate limits parallel jobs and keeps CPU/RAM usage lower."
echo " Low Resource is slower, but safest for weaker machines."
notify_human_interaction
load_options=("Normal" "Moderate (GOMAXPROCS=2, make -j1)" "Low Resource (GOMAXPROCS=1, make -j1)" "Quit")
select opt in "${load_options[@]}"
do
case $opt in
"Normal")
echo "✅ Selected: Normal build profile."
break
;;
"Moderate (GOMAXPROCS=2, make -j1)")
apply_moderate_build_limits 2 2048
echo "✅ Selected: Moderate build profile."
echo " GOMAXPROCS=$GOMAXPROCS MAKEFLAGS=\"$MAKEFLAGS\" NODE_OPTIONS=\"$NODE_OPTIONS\""
break
;;
"Low Resource (GOMAXPROCS=1, make -j1)")
apply_moderate_build_limits 1 2048
echo "✅ Selected: Low Resource build profile."
echo " GOMAXPROCS=$GOMAXPROCS MAKEFLAGS=\"$MAKEFLAGS\" NODE_OPTIONS=\"$NODE_OPTIONS\""
break
;;
"Quit")
exit 0
;;
*) echo "Opțiune invalidă $REPLY";;
esac
done
# Dacă compilarea anterioară a fost întreruptă, ștergem binarul parțial
if [ -f "gitea" ] || [ -f "gitea.exe" ]; then
echo "🧹 Garbages found. Cleanning..."
rm -f gitea gitea.exe
fi
# Verificăm dacă node_modules există. Dacă nu, forțăm pnpm install
if [ ! -d "node_modules" ]; then
echo "⚠️ node_modules missing. Instaling..."
if ! pnpm install --frozen-lockfile; then
echo "❌ Fail to install frontend dependencies."
exit 1
fi
fi
# --- 2. LOGICĂ FRONTEND (CHECKSUM) ---
CHECKSUM_FILE=".frontend.hash"
CURRENT_HASH=$(find web_src package.json tailwind.config.js -type f -print0 2>/dev/null | xargs -0 sha1sum | sha1sum | awk '{print $1}')
if [ -f "$CHECKSUM_FILE" ] && [ "$CURRENT_HASH" == "$(cat $CHECKSUM_FILE)" ]; then
echo "✅ Frontend is unchanged."
else
echo "🚀 Code changes detected. Running frontend build..."
if ! make frontend; then
echo "❌ Fail to build frontend assets."
exit 1
fi
echo "$CURRENT_HASH" > "$CHECKSUM_FILE"
fi
# --- 3. MENIU INTERACTIV PENTRU ARHITECTURĂ ---
echo ""
echo "🎯 Select Arch to build:"
notify_human_interaction
arch_options=("linux-amd64" "linux-armv7" "windows-amd64" "macos-amd64" "macos-arm64" "All Arch" "Quit")
select opt in "${arch_options[@]}"
do
case $opt in
"linux-amd64")
TARGETS=("linux/amd64")
break
;;
"linux-armv7")
TARGETS=("linux/arm/7")
break
;;
"windows-amd64")
TARGETS=("windows/amd64")
break
;;
"macos-amd64")
TARGETS=("darwin/amd64")
break
;;
"macos-arm64")
TARGETS=("darwin/arm64")
break
;;
"All Arch")
TARGETS=("linux/amd64" "linux/arm/7" "windows/amd64" "darwin/amd64" "darwin/arm64")
break
;;
"Quit")
exit 0
;;
*) echo "Opțiune invalidă $REPLY";;
esac
done
echo ""
echo "🏷️ Select Build Tags:"
notify_human_interaction
tag_options=("bindata" "bindata sqlite sqlite_unlock_notify" "Quit")
select opt in "${tag_options[@]}"
do
case $opt in
"bindata")
BUILD_TAGS="bindata"
break
;;
"bindata sqlite sqlite_unlock_notify")
BUILD_TAGS="bindata sqlite sqlite_unlock_notify"
BUILD_VARIANT="sqlite"
break
;;
"Quit")
exit 0
;;
*) echo "Opțiune invalidă $REPLY";;
esac
done
if [ -z "$BUILD_VARIANT" ]; then
BUILD_VARIANT="default"
fi
BUILD_REF="$(resolve_build_ref)"
BUILD_REF="${BUILD_REF//\//-}"
echo "🏷️ Build tag/reference: $BUILD_REF"
bindata_needs_update() {
local source_dir="$1"
local bindata_file="$2"
if [ ! -f "$bindata_file" ]; then
return 0
fi
find "$source_dir" -type f -newer "$bindata_file" -print -quit 2>/dev/null | grep -q .
}
ensure_bindata_asset() {
local label="$1"
local source_dir="$2"
local go_package="$3"
local bindata_file="$4"
if bindata_needs_update "$source_dir" "$bindata_file"; then
echo "♻️ Regenerating $label bindata..."
if ! CC= GOOS= GOARCH= CGO_ENABLED=0 go generate -tags bindata "$go_package"; then
echo "❌ Failed to regenerate $label bindata."
exit 1
fi
else
echo "$label bindata is up to date."
fi
}
ensure_bindata_assets() {
if [[ " $BUILD_TAGS " != *" bindata "* ]]; then
return
fi
echo "🔎 Checking embedded bindata assets..."
ensure_bindata_asset "templates" "templates" "./modules/templates" "modules/templates/bindata.dat"
ensure_bindata_asset "options" "options" "./modules/options" "modules/options/bindata.dat"
ensure_bindata_asset "public" "public" "./modules/public" "modules/public/bindata.dat"
ensure_bindata_asset "migration schemas" "modules/migration/schemas" "./modules/migration" "modules/migration/bindata.dat"
}
ensure_bindata_assets
build_darwin_sqlite_target() {
local arch="$1"
local output="$2"
local repo_root temp_dist built_file output_abs
local built_files=()
require_docker_for_darwin_sqlite
repo_root="$(resolve_darwin_sqlite_repo_root)"
validate_repo_bind_mount_for_darwin_sqlite "$repo_root"
output_abs="$(pwd -P)/$output"
temp_dist="$repo_root/dist/.smart-build-darwin-${arch}-$$"
rm -rf "$temp_dist"
if ! mkdir -p "$temp_dist"; then
echo "❌ Failed to create a temporary macOS release directory in dist/."
exit 1
fi
echo "📦 Building for darwin/$arch with TAGS=\"$BUILD_TAGS\" via release-darwin..."
if ! make -C "$repo_root" release-darwin TAGS="$BUILD_TAGS" DARWIN_ARCHS="darwin-10.12/$arch" DIST="$temp_dist"; then
rm -rf "$temp_dist"
echo "❌ Fail to build for darwin/$arch with SQLite"
exit 1
fi
mapfile -t built_files < <(find "$temp_dist/binaries" -maxdepth 1 -type f | sort)
if [ "${#built_files[@]}" -ne 1 ]; then
rm -rf "$temp_dist"
echo "❌ Unexpected macOS artifact count for darwin/$arch: ${#built_files[@]}"
exit 1
fi
built_file="${built_files[0]}"
mv "$built_file" "$output_abs"
rm -rf "$temp_dist"
write_sha256_file "$output_abs"
echo "✅ Created: $output_abs"
echo "✅ Created: $output_abs.sha256"
}
build_standard_target() {
local os="$1"
local arch="$2"
local arm_ver="$3"
local output="$4"
local ext="$5"
export GOOS=$os
export GOARCH=$arch
export GOARM=$arm_ver
export CGO_ENABLED=0
if [ "$BUILD_VARIANT" == "sqlite" ]; then
export CGO_ENABLED=1
fi
if make build TAGS="$BUILD_TAGS"; then
mv "gitea$ext" "$output"
write_sha256_file "$output"
echo "✅ Created: $output"
echo "✅ Created: $output.sha256"
else
echo "❌ Fail to build for $os/$arch${arm_ver:+/v$arm_ver}"
exit 1
fi
}
# --- 4. COMPILARE ---
mkdir -p dist
for TARGET in "${TARGETS[@]}"; do
IFS="/" read -r OS ARCH ARM_VER <<< "$TARGET"
EXT="" && [ "$OS" == "windows" ] && EXT=".exe"
PLATFORM="$ARCH" && [ ! -z "$ARM_VER" ] && PLATFORM="armv$ARM_VER"
VARIANT_SUFFIX="" && [ "$BUILD_VARIANT" == "sqlite" ] && VARIANT_SUFFIX="-sqlite"
OUTPUT="dist/gitea-$BUILD_REF-$OS-$PLATFORM$VARIANT_SUFFIX$EXT"
if [ "$OS" == "darwin" ] && [ "$BUILD_VARIANT" == "sqlite" ]; then
build_darwin_sqlite_target "$ARCH" "$OUTPUT"
else
echo "📦 Building for $OS/$ARCH ${ARM_VER:+(v$ARM_VER) }with TAGS=\"$BUILD_TAGS\"..."
build_standard_target "$OS" "$ARCH" "$ARM_VER" "$OUTPUT" "$EXT"
fi
unset GOOS GOARCH GOARM CGO_ENABLED
done
echo "✨ Buid finished. Get file(s) from /dist"
go clean -cache # || true
+1091
View File
File diff suppressed because it is too large Load Diff
+28
View File
@@ -1,3 +1,5 @@
## Core Repository Rules
- Use `make help` to find available development targets
- Run `make fmt` to format `.go` files, and run `make lint-go` to lint them
- Run `make lint-js` to lint `.ts` files
@@ -9,3 +11,29 @@
- In TypeScript, use `!` (non-null assertion) instead of `?.`/`??` when a value is known to always exist
- Include authorship attribution in issue and pull request comments
- Add `Co-Authored-By` lines to all commits, indicating name and model used
- Mark each code change with `edit/add - by petru @ codex` wherever the target file format supports comments without breaking syntax or generated output
- For single-line changes, mark only that line with `edit/add - by petru @ codex`
- For multi-line changes, wrap the changed block with `start edit/add - by petru @ codex` and `end edit/add - by petru @ codex`
## Execution Rules (Token Optimization)
- DO NOT read full files unless they are explicitly targeted with `@filename`, referenced from instruction `*.md` files, or required to complete the user's task.
- Assume the workspace structure described in `./.codex-context.md` and `./.codex-project-map.md` is the current baseline unless the user indicates otherwise.
- DO NOT read `./.codex-history.md` end-to-end by default; search by keyword, subsystem, tag, or read only the latest relevant entries first.
## Project Context
- Read and follow `./.codex-context.md` as the persistent repository context before starting work and when validating final changes.
- Use `./.codex-project-map.md` for the persistent structural and architectural map of the repository.
## Routing Rules for Tasks (Multi-Model Delegation)
Apply these routing preferences when the environment supports model selection. If the preferred model is unavailable, use the closest available model and note the fallback.
Priority for mixed tasks:
Architecture & Orchestration > Go & Database Coding > Frontend & Template Tasks > DevOps & Terminal Execution
1. Architecture & Orchestration Tasks: Prefer `gpt-5.4` (Reasoning: High/Extra High). Use for complex requirement breakdown, solution design, and validation of large structural updates.
2. Go & Database Coding Tasks: Prefer `gpt-5.3-codex` (Reasoning: Medium). This includes writing HTTP handlers, database queries, internal Go business logic, and server-side integration work.
3. Frontend & Template Tasks: Prefer `gpt-5.3-codex` (Reasoning: Medium). This includes `templates/`, `web_src/`, CSS, and TypeScript changes.
4. DevOps & Terminal Commands: Prefer `gpt-5.4-mini` (Reasoning: Low). Use for `pnpm`, `git`, `go mod`, `npm`, `make`, or `bash` execution flows and shell-oriented maintenance tasks.
+4496 -4496
View File
File diff suppressed because it is too large Load Diff
+5584 -4767
View File
File diff suppressed because it is too large Load Diff
+23 -376
View File
@@ -1,5 +1,14 @@
# Contribution Guidelines
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.
| Topic | Document |
| :---- | :------- |
| Backend (Go modules, API v1) | [docs/guideline-backend.md](docs/guideline-backend.md) |
| Frontend (npm, UI guidelines) | [docs/guideline-frontend.md](docs/guideline-frontend.md) |
| Maintainers, TOC, labels, merge queue, commit format for mergers | [docs/community-governance.md](docs/community-governance.md) |
| Release cycle, backports, tagging releases | [docs/release-management.md](docs/release-management.md) |
<details><summary>Table of Contents</summary>
- [Contribution Guidelines](#contribution-guidelines)
@@ -11,10 +20,6 @@
- [Discuss your design before the implementation](#discuss-your-design-before-the-implementation)
- [Issue locking](#issue-locking)
- [Building Gitea](#building-gitea)
- [Dependencies](#dependencies)
- [Backend](#backend)
- [Frontend](#frontend)
- [Design guideline](#design-guideline)
- [Styleguide](#styleguide)
- [Copyright](#copyright)
- [Testing](#testing)
@@ -22,47 +27,19 @@
- [Code review](#code-review)
- [Pull request format](#pull-request-format)
- [PR title and summary](#pr-title-and-summary)
- [Milestone](#milestone)
- [Labels](#labels)
- [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)
- [Getting PRs merged](#getting-prs-merged)
- [Final call](#final-call)
- [Commit messages](#commit-messages)
- [PR Co-authors](#pr-co-authors)
- [PRs targeting `main`](#prs-targeting-main)
- [Backport PRs](#backport-prs)
- [Reviewing PRs](#reviewing-prs)
- [For PR authors](#for-pr-authors)
- [Documentation](#documentation)
- [API v1](#api-v1)
- [GitHub API compatibility](#github-api-compatibility)
- [Adding/Maintaining API routes](#addingmaintaining-api-routes)
- [When to use what HTTP method](#when-to-use-what-http-method)
- [Requirements for API routes](#requirements-for-api-routes)
- [Backports and Frontports](#backports-and-frontports)
- [What is backported?](#what-is-backported)
- [How to backport?](#how-to-backport)
- [Format of backport PRs](#format-of-backport-prs)
- [Frontports](#frontports)
- [Developer Certificate of Origin (DCO)](#developer-certificate-of-origin-dco)
- [Release Cycle](#release-cycle)
- [Maintainers](#maintainers)
- [Technical Oversight Committee (TOC)](#technical-oversight-committee-toc)
- [TOC election process](#toc-election-process)
- [Current TOC members](#current-toc-members)
- [Previous TOC/owners members](#previous-tocowners-members)
- [Governance Compensation](#governance-compensation)
- [TOC \& Working groups](#toc--working-groups)
- [Roadmap](#roadmap)
- [Versions](#versions)
- [Releasing Gitea](#releasing-gitea)
</details>
## Introduction
This document explains how to contribute changes to the Gitea project. \
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).
@@ -131,34 +108,6 @@ If further discussion is needed, we encourage you to open a new issue instead an
See the [development setup instructions](https://docs.gitea.com/development/hacking-on-gitea).
## Dependencies
### Backend
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.
### Frontend
For the frontend, we use [npm](https://www.npmjs.com/).
The same restrictions apply for frontend dependencies as for backend 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)
- [refactoring guideline](https://docs.gitea.com/contributing/guidelines-refactoring)
## Styleguide
You should always run `make fmt` before committing to conform to Gitea's styleguide.
@@ -216,6 +165,8 @@ The tool `go run build/backport-locale.go` can be used to backport locales from
## Code review
How labels, milestones, and the merge queue work is documented in [docs/community-governance.md](docs/community-governance.md).
### Pull request format
Please try to make your pull request easy to review for us. \
@@ -260,29 +211,6 @@ Fixes/Closes/Resolves #<ISSUE_NR_Y>.
to your summary. \
Each issue that will be closed must stand on a separate line.
### Milestone
A PR should only be assigned to a milestone if it will likely be merged into the given version. \
As a rule of thumb, assume that a PR will stay open for an additional month for every 100 added lines. \
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/…` / `pr/…`: 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 `pr/need-2-approvals`
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
### Breaking PRs
#### What is a breaking PR?
@@ -311,165 +239,29 @@ Breaking PRs will not be merged as long as not both of these requirements are me
### Maintaining open PRs
The moment you create a non-draft PR or the moment you convert a draft PR to a non-draft PR is the moment code review starts for it. \
Once that happens, do not rebase or squash your branch anymore as it makes it difficult to review the new changes. \
Merge the base branch into your branch only when you really need to, i.e. because of conflicting changes in the mean time. \
This reduces unnecessary CI runs. \
Don't worry about merge commits messing up your commit history as every PR will be squash merged. \
This means that all changes are joined into a single new commit whose message is as described below.
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.
### Getting PRs merged
Merge the base branch into yours only when you need to, for example because of conflicting changes elsewhere. That limits unnecessary CI runs.
Changes to Gitea must be reviewed before they are accepted — no matter who
makes the change, even if they are an owner or a maintainer. \
The only exception are critical bugs that prevent Gitea from being compiled or started. \
Specifically, we require two approvals from maintainers for every PR. \
Once this criteria has been met, your PR receives the `lgtm/done` label. \
From this point on, your only responsibility is to fix merge conflicts or respond to/implement requests by maintainers. \
It is the responsibility of the maintainers from this point to get your PR merged.
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.
If a PR has the `lgtm/done` label and there are no open discussions or merge conflicts anymore, any maintainer can add the `reviewed/wait-merge` label. \
This label means that the PR is part of the merge queue and will be merged as soon as possible. \
The merge queue will be cleared in the order of the list below:
### Reviewing PRs
<https://github.com/go-gitea/gitea/pulls?q=is%3Apr+label%3Areviewed%2Fwait-merge+sort%3Acreated-asc+is%3Aopen>
Maintainers are encouraged to review pull requests in areas where they have expertise or particular interest.
Gitea uses it's own tool, the <https://github.com/GiteaBot/gitea-backporter> to automate parts of the review process. \
This tool does the things listed below automatically:
#### For PR authors
- create a backport PR if needed once the initial PR was merged
- remove the PR from the merge queue after the PR merged
- keep the oldest branch in the merge queue up to date with merges
- **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.
### 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 able and required to rewrite the PR title and summary (the first comment of a PR) so that it can produce an easily understandable commit message if necessary. \
The final commit message should no longer contain any uncertainty such as `hopefully, <x> won't happen anymore`. Replace uncertainty with certainty.
#### PR Co-authors
A person counts as a PR co-author the moment they (co-)authored a commit that is not simply a `Merge base branch into branch` commit. \
Mergers are required to remove such "false-positive" co-authors when writing the commit message. \
The true co-authors 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
```
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.**
## 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))
## 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.
## 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). \
@@ -483,148 +275,3 @@ Signed-off-by: Joe Smith <joe.smith@email.com>
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`.
We assume in good faith that the information you provide is legally binding.
## Release Cycle
We adopted a release schedule to streamline the process of working on, finishing, and issuing releases. \
The overall goal is to make a major release every three or four months, which breaks down into two or three months of general development followed by one month of testing and polishing known as the release freeze. \
All the feature pull requests should be
merged before feature freeze. All feature pull requests haven't been merged before this feature freeze will be moved to next milestone, please notice our feature freeze announcement on discord. And, during the frozen period, a corresponding
release branch is open for fixes backported from main branch. Release candidates
are made during this period for user testing to
obtain a final version that is maintained in this branch.
During a development cycle, we may also publish any necessary minor releases
for the previous version. For example, if the latest, published release is
v1.2, then minor changes for the previous release—e.g., v1.1.0 -> v1.1.1—are
still possible.
## Maintainers
To make sure every PR is checked, we have [maintainers](MAINTAINERS). \
Every PR **must** be reviewed by at least two maintainers (or owners) before it can get merged. \
For refactoring PRs after a week and documentation only PRs, the approval of only one maintainer is enough. \
A maintainer should be a contributor of Gitea and contributed at least
4 accepted PRs. A contributor should apply as a maintainer in the
[Discord](https://discord.gg/Gitea) `#develop` channel. The team maintainers may invite the contributor. A maintainer
should spend some time on code reviews. If a maintainer has no
time to do that, they should apply to leave the maintainers team
and we will give them the honor of being a member of the [advisors
team](https://github.com/orgs/go-gitea/teams/advisors). Of course, if
an advisor has time to code review, we will gladly welcome them back
to the maintainers team. If a maintainer is inactive for more than 3
months and forgets to leave the maintainers team, the owners may move
him or her from the maintainers team to the advisors team.
For security reasons, Maintainers should use 2FA for their accounts and
if possible provide GPG signed commits.
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
https://help.github.com/articles/signing-commits-with-gpg/
Furthermore, any account with write access (like bots and TOC members) **must** use 2FA.
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
## 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.
### Current TOC members
- 2024-01-01 ~ 2024-12-31
- Company
- [Jason Song](https://gitea.com/wolfogre) <i@wolfogre.com>
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.com>
- Community
- [6543](https://gitea.com/6543) <6543@obermui.de>
- [delvh](https://gitea.com/delvh) <dev.lh@web.de>
- [John Olheiser](https://gitea.com/jolheiser) <john.olheiser@gmail.com>
### Previous TOC/owners members
Here's the history of the owners and the time they served:
- [Lunny Xiao](https://gitea.com/lunny) - 2016, 2017, [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [Kim Carlbäcker](https://github.com/bkcsoft) - 2016, 2017
- [Thomas Boerger](https://gitea.com/tboerger) - 2016, 2017
- [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) - [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801)
- [Matti Ranta](https://gitea.com/techknowlogick) - [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [Andrew Thornton](https://gitea.com/zeripath) - [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [6543](https://gitea.com/6543) - 2023
- [John Olheiser](https://gitea.com/jolheiser) - 2023
- [Jason Song](https://gitea.com/wolfogre) - 2023
## Governance Compensation
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.
You can visit our roadmap on the wiki.
## 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 $vmaj, $vmin and $vpat be Major, Minor and Patch version numbers, $vpat should be rc1, rc2, 0, 1, ...... $vmaj.$vmin 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 v$vmaj.$vmin.0-dev` and push the tag as `git push origin v$vmaj.$vmin.0-dev`.
- When CI has finished building tag then you have to create a new branch named `release/v$vmaj.$vmin`
- If it is bugfix version create PR for changelog on branch `release/v$vmaj.$vmin` and wait till it is reviewed and merged.
- Add a tag as `git tag -s -F release.notes v$vmaj.$vmin.$`, 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 v$vmaj.$vmin.$`. Drone 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`
+2 -1
View File
@@ -107,6 +107,7 @@ endif
LDFLAGS := $(LDFLAGS) -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/riscv64
DARWIN_ARCHS ?= darwin-10.12/amd64,darwin-10.12/arm64
GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration,$(shell $(GO) list ./... | grep -v /vendor/))
MIGRATE_TEST_PACKAGES ?= $(shell $(GO) list code.gitea.io/gitea/models/migrations/...)
@@ -685,7 +686,7 @@ release-linux: | $(DIST_DIRS)
.PHONY: release-darwin
release-darwin: | $(DIST_DIRS)
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w $(LDFLAGS)' -targets 'darwin-10.12/amd64,darwin-10.12/arm64' -out gitea-$(VERSION) .
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w $(LDFLAGS)' -targets '$(DARWIN_ARCHS)' -out gitea-$(VERSION) .
.PHONY: release-freebsd
release-freebsd: | $(DIST_DIRS)
+1
View File
@@ -19,6 +19,7 @@ import (
// regexp is based on go-license, excluding README and NOTICE
// https://github.com/google/go-licenses/blob/master/licenses/find.go
// also defined in vite.config.ts
var licenseRe = regexp.MustCompile(`^(?i)((UN)?LICEN(S|C)E|COPYING).*$`)
// primaryLicenseRe matches exact primary license filenames without suffixes.
+605
View File
@@ -0,0 +1,605 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"context"
"errors"
"fmt"
"html"
"net/http"
"net/mail"
"net/url"
"os"
"strconv"
"strings"
"time"
"code.gitea.io/gitea/models/db"
db_install "code.gitea.io/gitea/models/db/install"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/public"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers"
"code.gitea.io/gitea/routers/common"
install_router "code.gitea.io/gitea/routers/install"
svc_context "code.gitea.io/gitea/services/context"
sender_service "code.gitea.io/gitea/services/mailer/sender"
"github.com/urfave/cli/v3"
)
// start edit/add - by petru @ codex
const (
recoverySessionEmailKey = "recovery_unlocked_email"
recoverySessionUntilKey = "recovery_unlocked_until"
recoveryUnlockCookieName = "gitea_recovery_unlock"
recoveryUnlockHostCookie = "gitea_recovery_unlock_host"
recoveryInstallQueryKey = "recovery"
recoveryInstallQuery = "recovery=1"
recoveryPageStatusKey = "recovery_status"
recoveryPageErrorKey = "recovery_error"
recoveryPageStatusSent = "sent"
recoveryPageErrorRequiresAddresses = "requires_addresses"
recoveryPageErrorEmailInvalid = "email_invalid"
recoveryReasonMissingConfig = "missing_config"
recoveryReasonDatabaseUnavailable = "database_unavailable"
)
func recoverySiteName(recoveryCfg *setting.RecoveryConfig, recoveryReason string) string {
if recoveryReason == recoveryReasonMissingConfig && recoveryCfg != nil {
if parsedFrom, err := mail.ParseAddress(strings.TrimSpace(recoveryCfg.SMTPFrom)); err == nil {
if fromName := strings.TrimSpace(parsedFrom.Name); fromName != "" {
return fromName
}
}
}
appName := strings.TrimSpace(setting.AppName)
if appName == "" {
return "Gitea"
}
if siteName, _, found := strings.Cut(appName, ":"); found {
siteName = strings.TrimSpace(siteName)
if siteName != "" {
return siteName
}
}
if parts := strings.Fields(appName); len(parts) > 0 {
return parts[0]
}
return appName
}
func loadEnabledRecoveryConfig() (*setting.RecoveryConfig, error) {
recoveryCfg, err := setting.LoadRecoveryConfig()
if err != nil || recoveryCfg == nil || !recoveryCfg.Enabled {
return recoveryCfg, err
}
if strings.TrimSpace(recoveryCfg.TokenSecret) == "" || recoveryCfg.TokenTTLMin <= 0 {
if err := setting.SaveRecoveryConfig(recoveryCfg); err != nil {
return nil, err
}
return setting.LoadRecoveryConfig()
}
return recoveryCfg, nil
}
func shouldServeInstalledRecovery(ctx context.Context) (*setting.RecoveryConfig, bool, error) {
if !setting.HasInstallSentinel() {
return nil, false, nil
}
recoveryCfg, err := loadEnabledRecoveryConfig()
if err != nil || recoveryCfg == nil {
return recoveryCfg, false, err
}
if missingDB, err := missingInstalledSQLiteDatabase(); err != nil {
return nil, false, err
} else if missingDB {
return recoveryCfg, true, nil
}
db.UnsetDefaultEngine()
defer db.UnsetDefaultEngine()
if err := db.InitEngine(ctx); err != nil {
log.Warn("Recovery mode preflight: database engine init failed: %v", err)
return recoveryCfg, true, nil
}
if err := db_install.CheckDatabaseConnection(ctx); err != nil {
log.Warn("Recovery mode preflight: database connection failed: %v", err)
return recoveryCfg, true, nil
}
if _, err := db_install.HasPostInstallationUsers(ctx); err != nil {
log.Warn("Recovery mode preflight: installed user table check failed: %v", err)
return recoveryCfg, true, nil
}
if _, err := db_install.GetMigrationVersion(ctx); err != nil {
log.Warn("Recovery mode preflight: migration version check failed: %v", err)
return recoveryCfg, true, nil
}
return nil, false, nil
}
func serveRecovery(cmd *cli.Command, recoveryCfg *setting.RecoveryConfig, recoveryReason string) error {
showWebStartupMessage("Prepare to run recovery page")
routers.InitWebInstallPage(graceful.GetManager().HammerContext())
if cmd.IsSet("port") {
if err := setPort(cmd.String("port")); err != nil {
return err
}
}
if cmd.IsSet("install-port") {
if err := setPort(cmd.String("install-port")); err != nil {
return err
}
}
err := listen(recoveryRoutes(recoveryCfg, recoveryReason), false)
if err != nil {
log.Critical("Unable to open listener for recovery. Is Gitea already running?") // edit/add - by petru @ codex
graceful.GetManager().DoGracefulShutdown() // edit/add - by petru @ codex
}
select {
case <-graceful.GetManager().IsShutdown():
<-graceful.GetManager().Done()
log.Info("PID: %d Gitea Recovery Finished", os.Getpid())
return err
default:
}
return nil
}
func recoveryRoutes(recoveryCfg *setting.RecoveryConfig, recoveryReason string) *web.Router {
base := web.NewRouter()
base.BeforeRouting(common.ProtocolMiddlewares()...)
base.Methods("GET, HEAD", "/assets/*", public.FileHandlerFunc()) // edit/add - by petru @ codex
installHandler := install_router.Routes()
r := web.NewRouter()
r.AfterRouting(common.MustInitSessioner(), svc_context.ContexterInstallPage(map[string]any{}))
r.Get("/recovery", func(ctx *svc_context.Context) {
if recoverySessionUnlocked(ctx, recoveryCfg) {
ctx.Redirect(setting.AppSubURL + "/?" + recoveryInstallQuery)
return
}
statusMessage, errorMessage := recoveryPageMessagesFromRequest(ctx) // edit/add - by petru @ codex
renderRecoveryPage(ctx, recoveryCfg, recoveryReason, statusMessage, errorMessage)
})
r.Post("/recovery/request", func(ctx *svc_context.Context) {
handleRecoverySendLink(ctx, recoveryCfg, recoveryReason)
})
r.Get("/recovery/access", func(ctx *svc_context.Context) {
handleRecoveryAccess(ctx, recoveryCfg, recoveryReason)
})
r.Any("/", func(ctx *svc_context.Context) {
serveRecoveryInstaller(ctx, installHandler, recoveryCfg, recoveryReason)
})
r.Any("/*", func(ctx *svc_context.Context) {
serveRecoveryInstaller(ctx, installHandler, recoveryCfg, recoveryReason)
})
base.Mount("", r)
return base
}
func recoverySessionUnlocked(ctx *svc_context.Context, recoveryCfg *setting.RecoveryConfig) bool {
if recoverySessionUnlockedBySession(ctx, recoveryCfg) {
return true
}
return recoverySessionUnlockedByCookie(ctx, recoveryCfg)
}
func recoverySessionUnlockedBySession(ctx *svc_context.Context, recoveryCfg *setting.RecoveryConfig) bool {
email, ok := ctx.Session.Get(recoverySessionEmailKey).(string)
if !ok || strings.TrimSpace(email) == "" {
return false
}
until, ok := sessionInt64(ctx.Session.Get(recoverySessionUntilKey))
if !ok || time.Now().Unix() > until {
_ = ctx.Session.Delete(recoverySessionEmailKey)
_ = ctx.Session.Delete(recoverySessionUntilKey)
ctx.DeleteSiteCookie(recoveryUnlockCookieName)
deleteRecoveryHostCookie(ctx) // edit/add - by petru @ codex
return false
}
if recoveryCfg == nil || !recoveryCfg.AllowsEmail(email) {
_ = ctx.Session.Delete(recoverySessionEmailKey)
_ = ctx.Session.Delete(recoverySessionUntilKey)
ctx.DeleteSiteCookie(recoveryUnlockCookieName)
deleteRecoveryHostCookie(ctx) // edit/add - by petru @ codex
return false
}
return true
}
func recoverySessionUnlockedByCookie(ctx *svc_context.Context, recoveryCfg *setting.RecoveryConfig) bool {
unlockToken := strings.TrimSpace(ctx.GetSiteCookie(recoveryUnlockCookieName))
if unlockToken == "" {
unlockToken = strings.TrimSpace(getRecoveryHostCookie(ctx)) // edit/add - by petru @ codex
}
if unlockToken == "" || recoveryCfg == nil {
return false
}
claims, err := setting.ValidateRecoveryUnlockToken(recoveryCfg, unlockToken, time.Now())
if err != nil || !recoveryCfg.AllowsEmail(claims.Email) {
ctx.DeleteSiteCookie(recoveryUnlockCookieName)
deleteRecoveryHostCookie(ctx) // edit/add - by petru @ codex
return false
}
return true
}
func sessionInt64(value any) (int64, bool) {
switch v := value.(type) {
case int64:
return v, true
case int:
return int64(v), true
case int32:
return int64(v), true
case int16:
return int64(v), true
case int8:
return int64(v), true
case uint64:
return int64(v), true
case uint:
return int64(v), true
case float64:
return int64(v), true
case string:
if v == "" {
return 0, false
}
parsed, err := strconv.ParseInt(v, 10, 64)
if err == nil {
return parsed, true
}
}
return 0, false
}
func serveRecoveryInstaller(ctx *svc_context.Context, installHandler http.Handler, recoveryCfg *setting.RecoveryConfig, recoveryReason string) {
allowUnlockedPath := ctx.Req.URL.Path == setting.AppSubURL+"/post-install" || ctx.Req.URL.Path == "/post-install" // edit/add - by petru @ codex
if !recoverySessionUnlocked(ctx, recoveryCfg) || (ctx.Req.URL.Query().Get(recoveryInstallQueryKey) != "1" && !allowUnlockedPath) {
ctx.Redirect(setting.AppSubURL + "/recovery")
return
}
installHandler.ServeHTTP(ctx.Resp, install_router.WithRecoveryRequest(ctx.Req))
}
func handleRecoverySendLink(ctx *svc_context.Context, recoveryCfg *setting.RecoveryConfig, recoveryReason string) {
rawEmail := strings.TrimSpace(ctx.FormString("recovery_email"))
if rawEmail == "" {
ctx.Redirect(recoveryPageURL(ctx.Req, recoveryPageStatusKey, "", recoveryPageErrorKey, recoveryPageErrorRequiresAddresses))
return
}
parsedEmail, err := mail.ParseAddress(rawEmail)
if err != nil {
ctx.Redirect(recoveryPageURL(ctx.Req, recoveryPageStatusKey, "", recoveryPageErrorKey, recoveryPageErrorEmailInvalid))
return
}
if recoveryCfg != nil && recoveryCfg.AllowsEmail(parsedEmail.Address) {
if err := sendRecoveryAccessMail(ctx, recoveryCfg, parsedEmail.Address); err != nil {
log.Error("Failed to send recovery access mail to %s: %v", parsedEmail.Address, err)
}
}
ctx.Redirect(recoveryPageURL(ctx.Req, recoveryPageStatusKey, recoveryPageStatusSent, recoveryPageErrorKey, ""))
}
func handleRecoveryAccess(ctx *svc_context.Context, recoveryCfg *setting.RecoveryConfig, recoveryReason string) {
token := strings.TrimSpace(ctx.FormString("token"))
if token == "" {
renderRecoveryPage(ctx, recoveryCfg, recoveryReason, "", string(ctx.Tr("install.recovery_token_invalid")))
return
}
claims, err := setting.ValidateRecoveryToken(recoveryCfg, token, time.Now())
if err != nil {
renderRecoveryPage(ctx, recoveryCfg, recoveryReason, "", string(ctx.Tr("install.recovery_token_invalid")))
return
}
if !recoveryCfg.AllowsEmail(claims.Email) {
renderRecoveryPage(ctx, recoveryCfg, recoveryReason, "", string(ctx.Tr("install.recovery_token_invalid")))
return
}
if err := setting.ConsumeRecoveryToken(claims.ID); err != nil {
if errors.Is(err, setting.ErrRecoveryTokenUsed) {
renderRecoveryPage(ctx, recoveryCfg, recoveryReason, "", string(ctx.Tr("install.recovery_token_invalid")))
return
}
ctx.ServerError("ConsumeRecoveryToken", err)
return
}
if err := ctx.Session.Set(recoverySessionEmailKey, claims.Email); err != nil {
ctx.ServerError("Session.Set(recoverySessionEmailKey)", err)
return
}
if err := ctx.Session.Set(recoverySessionUntilKey, claims.ExpiresAt.Unix()); err != nil {
ctx.ServerError("Session.Set(recoverySessionUntilKey)", err)
return
}
unlockToken, err := setting.IssueRecoveryUnlockToken(recoveryCfg, claims.Email, time.Now())
if err != nil {
ctx.ServerError("IssueRecoveryUnlockToken", err)
return
}
ctx.SetSiteCookie(recoveryUnlockCookieName, unlockToken, int(recoveryCfg.EffectiveTokenTTL().Seconds())) // edit/add - by petru @ codex
setRecoveryHostCookie(ctx, unlockToken, int(recoveryCfg.EffectiveTokenTTL().Seconds())) // edit/add - by petru @ codex
if err := ctx.Session.Release(); err != nil {
ctx.ServerError("Session.Release", err)
return
}
ctx.Redirect(setting.AppSubURL + "/?" + recoveryInstallQuery)
}
func sendRecoveryAccessMail(ctx *svc_context.Context, recoveryCfg *setting.RecoveryConfig, email string) error {
token, err := setting.IssueRecoveryToken(recoveryCfg, email, time.Now())
if err != nil {
return err
}
accessURL := recoveryRequestBaseURL(ctx.Req) + "/recovery/access?token=" + url.QueryEscape(token)
siteName := recoverySiteName(recoveryCfg, recoveryReasonMissingConfig)
subject := string(ctx.Tr("install.recovery_access_mail_subject", siteName))
log.Info("Recovery access link for %s: %s", email, accessURL) // edit/add - by petru @ codex
mailService, err := buildRecoveryMailService(recoveryCfg)
if err != nil {
log.Info("Recovery access email for %s skipped: %v", email, err) // edit/add - by petru @ codex
return nil
}
body := fmt.Sprintf(
"<p>%s</p><p><a href=\"%s\">%s</a></p><p>%s</p><p>%s</p>",
html.EscapeString(string(ctx.Tr("install.recovery_access_mail_intro", siteName))),
html.EscapeString(accessURL),
html.EscapeString(string(ctx.Tr("install.recovery_access_mail_action"))),
html.EscapeString(string(ctx.Tr("install.recovery_access_mail_expiry", int(recoveryCfg.EffectiveTokenTTL().Minutes())))),
html.EscapeString(string(ctx.Tr("install.recovery_access_mail_ignore"))),
)
previousMailService := setting.MailService
setting.MailService = mailService
defer func() {
setting.MailService = previousMailService
}()
msg := sender_service.NewMessageFrom(email, mailService.FromName, mailService.FromEmail, subject, body)
return sender_service.Send(&sender_service.SMTPSender{}, msg)
}
func buildRecoveryMailService(recoveryCfg *setting.RecoveryConfig) (*setting.Mailer, error) {
if recoveryCfg == nil || strings.TrimSpace(recoveryCfg.SMTPAddr) == "" || strings.TrimSpace(recoveryCfg.SMTPFrom) == "" {
return nil, errors.New("recovery mail service is not configured")
}
from, err := mail.ParseAddress(recoveryCfg.SMTPFrom)
if err != nil {
return nil, err
}
smtpPort := strings.TrimSpace(recoveryCfg.SMTPPort)
protocol := inferRecoveryMailProtocol(recoveryCfg.SMTPAddr, smtpPort)
if smtpPort == "" {
switch protocol {
case "smtp":
smtpPort = "25"
case "smtp+starttls":
smtpPort = "587"
default:
smtpPort = "465"
}
}
return &setting.Mailer{
Name: setting.AppName,
From: recoveryCfg.SMTPFrom,
FromName: from.Name,
FromEmail: from.Address,
Protocol: protocol,
SMTPAddr: recoveryCfg.SMTPAddr,
SMTPPort: smtpPort,
User: recoveryCfg.SMTPUser,
Passwd: recoveryCfg.SMTPPasswd,
EnableHelo: true,
OverrideHeader: map[string][]string{},
}, nil
}
func inferRecoveryMailProtocol(smtpAddr, smtpPort string) string {
if strings.ContainsAny(smtpAddr, "/\\") {
return "smtp+unix"
}
switch smtpPort {
case "25":
return "smtp"
case "587":
return "smtp+starttls"
default:
return "smtps"
}
}
func recoveryRequestBaseURL(req *http.Request) string {
if setting.InstallLock && strings.TrimSpace(setting.AppURL) != "" {
// start edit/add - by petru @ codex
if parsedAppURL, err := url.Parse(strings.TrimSpace(setting.AppURL)); err == nil {
parsedAppURL.RawQuery = ""
parsedAppURL.Fragment = ""
if setting.AppSubURL != "" {
parsedAppURL.Path = setting.AppSubURL
}
return strings.TrimRight(parsedAppURL.String(), "/")
}
return strings.TrimRight(strings.Split(strings.TrimSpace(setting.AppURL), "?")[0], "/")
// end edit/add - by petru @ codex
}
scheme := "http"
if req.TLS != nil {
scheme = "https"
} else if forwardedProto := strings.TrimSpace(strings.Split(req.Header.Get("X-Forwarded-Proto"), ",")[0]); forwardedProto != "" {
scheme = forwardedProto
}
host := req.Host
if host == "" {
host = "localhost"
}
return scheme + "://" + host + strings.TrimRight(setting.AppSubURL, "/")
}
func getRecoveryHostCookie(ctx *svc_context.Context) string {
// start edit/add - by petru @ codex
cookie, err := ctx.Req.Cookie(recoveryUnlockHostCookie)
if err != nil {
return ""
}
value, err := url.QueryUnescape(cookie.Value)
if err != nil {
return ""
}
return value
// end edit/add - by petru @ codex
}
func setRecoveryHostCookie(ctx *svc_context.Context, value string, maxAge int) {
// start edit/add - by petru @ codex
http.SetCookie(ctx.Resp, &http.Cookie{
Name: recoveryUnlockHostCookie,
Value: url.QueryEscape(value),
MaxAge: maxAge,
Path: "/",
Secure: setting.SessionConfig.Secure,
HttpOnly: true,
SameSite: setting.SessionConfig.SameSite,
})
// end edit/add - by petru @ codex
}
func deleteRecoveryHostCookie(ctx *svc_context.Context) {
// start edit/add - by petru @ codex
http.SetCookie(ctx.Resp, &http.Cookie{
Name: recoveryUnlockHostCookie,
Value: "",
MaxAge: -1,
Path: "/",
Secure: setting.SessionConfig.Secure,
HttpOnly: true,
SameSite: setting.SessionConfig.SameSite,
})
// end edit/add - by petru @ codex
}
// start edit/add - by petru @ codex
func recoveryLanguageOptions(req *http.Request, currentLang string) string {
var b strings.Builder
for _, lang := range translation.AllLangs() {
selectedAttribute := ""
if currentLang == lang.Lang {
selectedAttribute = " selected"
}
b.WriteString(fmt.Sprintf(
`<option value="%s"%s>%s</option>`,
html.EscapeString(lang.Lang),
selectedAttribute,
html.EscapeString(lang.Name),
))
}
return b.String()
}
// end edit/add - by petru @ codex
func recoveryPageURL(req *http.Request, firstKey, firstValue, secondKey, secondValue string) string {
recoveryURL := *req.URL
recoveryURL.Path = strings.TrimRight(setting.AppSubURL, "/") + "/recovery"
query := recoveryURL.Query()
query.Del(recoveryPageStatusKey)
query.Del(recoveryPageErrorKey)
if firstKey != "" && firstValue != "" {
query.Set(firstKey, firstValue)
}
if secondKey != "" && secondValue != "" {
query.Set(secondKey, secondValue)
}
recoveryURL.RawQuery = query.Encode()
return recoveryURL.RequestURI()
}
func recoveryPageMessagesFromRequest(ctx *svc_context.Context) (statusMessage, errorMessage string) {
switch ctx.Req.URL.Query().Get(recoveryPageStatusKey) {
case recoveryPageStatusSent:
statusMessage = string(ctx.Tr("install.recovery_email_sent_notice"))
}
switch ctx.Req.URL.Query().Get(recoveryPageErrorKey) {
case recoveryPageErrorRequiresAddresses:
errorMessage = string(ctx.Tr("install.recovery_email_requires_addresses"))
case recoveryPageErrorEmailInvalid:
errorMessage = string(ctx.Tr("form.email_invalid"))
}
return statusMessage, errorMessage
}
func renderRecoveryPage(ctx *svc_context.Context, recoveryCfg *setting.RecoveryConfig, recoveryReason, statusMessage, errorMessage string) {
siteName := recoverySiteName(recoveryCfg, recoveryReason)
reasonMessage := string(ctx.Tr("install.recovery_reason_database_unavailable"))
if recoveryReason == recoveryReasonMissingConfig {
reasonMessage = string(ctx.Tr("install.recovery_reason_missing_config"))
}
statusHTML := ""
if statusMessage != "" {
statusHTML = fmt.Sprintf(`<div class="status">%s</div>`, html.EscapeString(statusMessage))
}
errorHTML := ""
if errorMessage != "" {
errorHTML = fmt.Sprintf(`<div class="error">%s</div>`, html.EscapeString(errorMessage))
}
languageOptionsHTML := recoveryLanguageOptions(ctx.Req, ctx.Locale.Language()) // edit/add - by petru @ codex
ctx.Resp.Header().Set("Content-Type", "text/html; charset=utf-8")
ctx.Resp.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate") // edit/add - by petru @ codex
ctx.Resp.Header().Set("Pragma", "no-cache") // edit/add - by petru @ codex
ctx.Resp.Header().Set("Expires", "0") // edit/add - by petru @ codex
ctx.Resp.WriteHeader(http.StatusOK) // edit/add - by petru @ codex
_, _ = fmt.Fprintf(ctx.Resp, `<!doctype html><html lang="%s"><head><meta charset="utf-8"><title>%s</title><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="%s/assets/img/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="%s/assets/img/favicon.png" type="image/png"><style>body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;background:#111827;color:#f3f4f6}main{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}.card{max-width:720px;width:100%%;border:1px solid #374151;border-radius:12px;background:#1f2937;padding:32px;box-shadow:0 20px 40px rgba(0,0,0,.35)}h1{margin:0 0 12px;font-size:32px;line-height:1.2;text-align:center}p{margin:0 0 16px;color:#d1d5db;font-size:16px;line-height:1.6}.status,.error{border-radius:10px;padding:14px 16px;margin:0 0 18px}.status{background:#0f2a1f;color:#d1fae5;border:1px solid #14532d}.error{background:#3f1d1d;color:#fecaca;border:1px solid #7f1d1d}label{display:block;margin:0 0 8px;font-weight:600}select#recovery_lang{padding: 8px 14px;}input,select{width:100%%;box-sizing:border-box;border:1px solid #4b5563;border-radius:8px;background:#111827;color:#f3f4f6;padding:12px 14px;font-size:16px}button{margin-top:16px;width:100%%;border:0;border-radius:8px;background:#3b82f6;color:white;padding:12px 16px;font-size:16px;font-weight:600;cursor:pointer}.muted{font-size:14px;color:#9ca3af;margin-top:18px}.footer{margin-top:24px;padding-top:18px;border-top:1px solid #374151;display:flex;justify-content:flex-end}.footer-label{font-size:14px;color:#d1d5db;font-weight:600;margin:0 0 8px}.lang-picker{min-width:215px}.lang-picker form{margin:0}</style></head><body><main><div class="card"><h1>%s</h1><p>%s</p>%s%s<form action="%s/recovery/request" method="post"><label for="recovery_email">%s</label><input id="recovery_email" name="recovery_email" type="email" autocomplete="email" required><button type="submit">%s</button></form><p class="muted">%s</p><div class="footer"><div class="lang-picker"><form action="%s/recovery" method="get"><label class="footer-label" for="recovery_lang">%s</label><select id="recovery_lang" name="lang" onchange="this.form.submit()">%s</select></form></div></div></div></main></body></html>`,
html.EscapeString(ctx.Locale.Language()),
html.EscapeString(string(ctx.Tr("install.recovery_identify_title"))),
html.EscapeString(setting.AppSubURL),
html.EscapeString(setting.AppSubURL),
html.EscapeString(string(ctx.Tr("install.recovery_identify_title"))),
html.EscapeString(reasonMessage),
statusHTML,
errorHTML,
html.EscapeString(setting.AppSubURL),
html.EscapeString(string(ctx.Tr("install.recovery_identify_email"))),
html.EscapeString(string(ctx.Tr("install.recovery_identify_submit"))),
html.EscapeString(string(ctx.Tr("install.recovery_identify_helper", siteName))),
html.EscapeString(setting.AppSubURL),
html.EscapeString(string(ctx.Tr("language"))),
languageOptionsHTML,
)
}
// end edit/add - by petru @ codex
+169 -1
View File
@@ -6,6 +6,7 @@ package cmd
import (
"context"
"fmt"
"html"
"net"
"net/http"
"net/http/pprof"
@@ -15,6 +16,8 @@ import (
"strings"
"time"
db_model "code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/gtprof"
@@ -23,9 +26,13 @@ import (
"code.gitea.io/gitea/modules/public"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/routers/install"
web_context "code.gitea.io/gitea/services/context"
"github.com/felixge/fgprof"
"github.com/urfave/cli/v3"
@@ -163,8 +170,151 @@ func serveInstall(cmd *cli.Command) error {
return nil
}
// start edit/add - by petru @ codex
func missingInstalledSQLiteDatabase() (bool, error) {
if !setting.Database.Type.IsSQLite3() {
return false, nil
}
if !(setting.InstallLock || setting.HasInstallSentinel()) {
return false, nil
}
_, err := os.Stat(setting.Database.Path)
if err == nil {
return false, nil
}
if os.IsNotExist(err) {
return true, nil
}
return false, err
}
func serviceUnavailableRoutes() *web.Router {
base := web.NewRouter()
base.BeforeRouting(common.ProtocolMiddlewares()...)
r := web.NewRouter()
r.AfterRouting(common.MustInitSessioner(), web_context.Contexter())
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
ctx := web_context.GetWebContext(req.Context())
// The full 503 template depends on dynamic config backed by the database,
// so the bootstrap fallback must render a standalone response here.
message := html.EscapeString(ctx.Locale.TrString("error503")) // edit/add - by petru @ codex
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusServiceUnavailable)
_, _ = fmt.Fprintf(w, `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>503 Service Unavailable</title><meta name="viewport" content="width=device-width, initial-scale=1"><style>body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;background:#111827;color:#f3f4f6}main{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}.card{max-width:720px;width:100%%;border:1px solid #374151;border-radius:12px;background:#1f2937;padding:32px;text-align:center;box-shadow:0 20px 40px rgba(0,0,0,.35)}h1{margin:0 0 16px;font-size:32px;line-height:1.2}p{margin:0;color:#d1d5db;font-size:18px;line-height:1.6}</style></head><body><main><div class="card"><h1>503 Service Unavailable</h1><p>%s</p></div></main></body></html>`, message)
})
r.Any("/", handler) // edit/add - by petru @ codex
r.Any("/*", handler) // edit/add - by petru @ codex
base.Mount("", r)
return base
}
func serveInstalledUnavailable(cmd *cli.Command) error {
showWebStartupMessage("Prepare to run service unavailable page")
translation.InitLocales(graceful.GetManager().HammerContext())
if cmd.IsSet("port") {
if err := setPort(cmd.String("port")); err != nil {
return err
}
}
err := listen(serviceUnavailableRoutes(), false)
<-graceful.GetManager().Done()
log.Info("PID: %d Gitea Web Finished", os.Getpid())
return err
}
func buildAutoRecoveryConfigFromInstalledState(ctx context.Context) (*setting.RecoveryConfig, error) {
recoveryEmail := "" // edit/add - by petru @ codex
if setting.Admin.SuperAdminEnabled {
superAdminSettings := make([]*user_model.Setting, 0, 4)
if err := db_model.GetEngine(ctx).Where("setting_key=? AND setting_value=?", user_model.SettingsKeySuperAdminEnabled, "true").Asc("id").Find(&superAdminSettings); err != nil {
return nil, err
}
for _, superAdminSetting := range superAdminSettings {
u, err := user_model.GetUserByID(ctx, superAdminSetting.UserID)
if err != nil {
if user_model.IsErrUserNotExist(err) {
continue
}
return nil, err
}
if u.IsAdmin && u.IsActive && !u.ProhibitLogin && strings.TrimSpace(u.Email) != "" {
recoveryEmail = strings.TrimSpace(u.Email)
break
}
}
}
if recoveryEmail == "" {
adminUser, err := user_model.GetAdminUser(ctx)
if err != nil {
if user_model.IsErrUserNotExist(err) {
return nil, nil
}
return nil, err
}
if adminUser == nil || strings.TrimSpace(adminUser.Email) == "" {
return nil, nil
}
recoveryEmail = strings.TrimSpace(adminUser.Email)
}
recoveryCfg := &setting.RecoveryConfig{
Enabled: true,
AllowedEmails: recoveryEmail,
BackupPath: setting.Backup.Path,
RepoRootPath: setting.RepoRootPath,
}
if setting.MailService != nil {
recoveryCfg.SMTPAddr = setting.MailService.SMTPAddr
recoveryCfg.SMTPPort = setting.MailService.SMTPPort
recoveryCfg.SMTPFrom = setting.MailService.From
recoveryCfg.SMTPUser = setting.MailService.User
recoveryCfg.SMTPPasswd = setting.MailService.Passwd
}
return recoveryCfg, nil
}
func ensureRecoveryConfigFromInstalledState(ctx context.Context) error {
recoveryCfg, err := setting.LoadRecoveryConfig()
if err != nil {
return err
}
if recoveryCfg != nil {
return nil
}
recoveryCfg, err = buildAutoRecoveryConfigFromInstalledState(ctx)
if err != nil {
return err
}
if recoveryCfg == nil {
return nil
}
return setting.SaveRecoveryConfig(recoveryCfg)
}
// end edit/add - by petru @ codex
func serveInstalled(c *cli.Command) error {
setting.MustInstalled()
setting.LoadDBSetting() // edit/add - by petru @ codex
if recoveryCfg, shouldServeRecovery, err := shouldServeInstalledRecovery(graceful.GetManager().HammerContext()); err != nil {
return err
} else if shouldServeRecovery {
if err := serveRecovery(c, recoveryCfg, recoveryReasonDatabaseUnavailable); err != nil {
return err
}
return serveInstalled(c)
}
if missingDB, err := missingInstalledSQLiteDatabase(); err != nil {
return err
} else if missingDB {
return serveInstalledUnavailable(c)
}
showWebStartupMessage("Prepare to run web server")
@@ -210,6 +360,12 @@ func serveInstalled(c *cli.Command) error {
if _, err := os.Stat(setting.AppDataPath); err != nil {
log.Fatal("Can not find APP_DATA_PATH %q", setting.AppDataPath)
}
if err := setting.EnsureInstallSentinel(); err != nil {
log.Error("Unable to create install sentinel %q: %v", setting.InstallSentinelPath(), err) // edit/add - by petru @ codex
}
if err := ensureRecoveryConfigFromInstalledState(graceful.GetManager().HammerContext()); err != nil {
log.Error("Unable to create recovery config %q: %v", setting.RecoveryConfigPath(), err) // edit/add - by petru @ codex
}
// the AppDataTempDir is fully managed by us with a safe sub-path
// so it's safe to automatically remove the outdated files
@@ -273,7 +429,19 @@ func runWeb(ctx context.Context, cmd *cli.Command) error {
_ = templates.PageRenderer()
if !setting.InstallLock {
if err := serveInstall(cmd); err != nil {
if setting.HasInstallSentinel() {
recoveryCfg, err := loadEnabledRecoveryConfig()
if err != nil {
return err
}
if recoveryCfg != nil {
if err := serveRecovery(cmd, recoveryCfg, recoveryReasonMissingConfig); err != nil {
return err
}
} else {
return fmt.Errorf("install mode is disabled because the install sentinel exists at %q; fix the configured database or use an explicit recovery flow instead", setting.InstallSentinelPath()) // edit/add - by petru @ codex
}
} else if err := serveInstall(cmd); err != nil {
return err
}
} else {
+146
View File
@@ -0,0 +1,146 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"context"
"net/http/httptest"
"os"
"path/filepath"
"testing"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// start edit/add - by petru @ codex
func TestMissingInstalledSQLiteDatabase(t *testing.T) {
oldDatabase := setting.Database
oldInstallLock := setting.InstallLock
oldCustomConf := setting.CustomConf
defer func() {
setting.Database = oldDatabase
setting.InstallLock = oldInstallLock
setting.CustomConf = oldCustomConf
}()
tmpDir := t.TempDir()
setting.CustomConf = filepath.Join(tmpDir, "custom", "conf", "app.ini")
setting.Database.Type = "sqlite3"
setting.Database.Path = filepath.Join(tmpDir, "data", "gitea.db")
setting.InstallLock = false // edit/add - by petru @ codex
missing, err := missingInstalledSQLiteDatabase()
require.NoError(t, err)
assert.False(t, missing)
setting.InstallLock = true
missing, err = missingInstalledSQLiteDatabase()
require.NoError(t, err)
assert.True(t, missing)
require.NoError(t, os.MkdirAll(filepath.Dir(setting.Database.Path), 0o755))
require.NoError(t, os.WriteFile(setting.Database.Path, []byte("db"), 0o600))
missing, err = missingInstalledSQLiteDatabase()
require.NoError(t, err)
assert.False(t, missing)
require.NoError(t, os.Remove(setting.Database.Path))
setting.InstallLock = false
require.NoError(t, os.MkdirAll(filepath.Dir(setting.InstallSentinelPath()), 0o755))
require.NoError(t, os.WriteFile(setting.InstallSentinelPath(), []byte("installed\n"), 0o600))
missing, err = missingInstalledSQLiteDatabase()
require.NoError(t, err)
assert.True(t, missing)
setting.Database.Type = "postgres"
missing, err = missingInstalledSQLiteDatabase()
require.NoError(t, err)
assert.False(t, missing)
}
func TestBuildAutoRecoveryConfigFromInstalledState(t *testing.T) {
adminUser, adminErr := user_model.GetAdminUser(context.Background())
recoveryCfg, err := buildAutoRecoveryConfigFromInstalledState(context.Background())
require.NoError(t, err)
if adminErr != nil {
require.True(t, user_model.IsErrUserNotExist(adminErr))
assert.Nil(t, recoveryCfg)
return
}
require.NotNil(t, adminUser)
if adminUser.Email == "" {
assert.Nil(t, recoveryCfg)
return
}
require.NotNil(t, recoveryCfg)
assert.True(t, recoveryCfg.Enabled)
assert.Equal(t, adminUser.Email, recoveryCfg.AllowedEmails)
assert.Equal(t, setting.Backup.Path, recoveryCfg.BackupPath)
assert.Equal(t, setting.RepoRootPath, recoveryCfg.RepoRootPath)
if setting.MailService != nil {
assert.Equal(t, setting.MailService.SMTPAddr, recoveryCfg.SMTPAddr)
assert.Equal(t, setting.MailService.SMTPPort, recoveryCfg.SMTPPort)
assert.Equal(t, setting.MailService.From, recoveryCfg.SMTPFrom)
assert.Equal(t, setting.MailService.User, recoveryCfg.SMTPUser)
assert.Equal(t, setting.MailService.Passwd, recoveryCfg.SMTPPasswd)
}
}
func TestShouldServeInstalledRecoveryWithMissingSQLite(t *testing.T) {
oldDatabase := setting.Database
oldInstallLock := setting.InstallLock
oldCustomConf := setting.CustomConf
defer func() {
setting.Database = oldDatabase
setting.InstallLock = oldInstallLock
setting.CustomConf = oldCustomConf
}()
tmpDir := t.TempDir()
setting.CustomConf = filepath.Join(tmpDir, "custom", "conf", "app.ini")
setting.Database.Type = "sqlite3"
setting.Database.Path = filepath.Join(tmpDir, "data", "gitea.db")
setting.InstallLock = true
require.NoError(t, os.MkdirAll(filepath.Dir(setting.InstallSentinelPath()), 0o755))
require.NoError(t, os.WriteFile(setting.InstallSentinelPath(), []byte("installed\n"), 0o600))
require.NoError(t, setting.SaveRecoveryConfig(&setting.RecoveryConfig{
Enabled: true,
AllowedEmails: "admin@example.com",
SMTPAddr: "smtp.example.com",
SMTPPort: "587",
SMTPFrom: "Gitea <noreply@example.com>",
}))
recoveryCfg, shouldServeRecovery, err := shouldServeInstalledRecovery(context.Background())
require.NoError(t, err)
require.True(t, shouldServeRecovery)
require.NotNil(t, recoveryCfg)
assert.Equal(t, "admin@example.com", recoveryCfg.AllowedEmails)
}
func TestRecoveryRequestBaseURLStripsRecoveryQueryFromAppURL(t *testing.T) {
// start edit/add - by petru @ codex
oldInstallLock := setting.InstallLock
oldAppURL := setting.AppURL
oldAppSubURL := setting.AppSubURL
defer func() {
setting.InstallLock = oldInstallLock
setting.AppURL = oldAppURL
setting.AppSubURL = oldAppSubURL
}()
setting.InstallLock = true
setting.AppURL = "http://example.com:3000/?recovery=1"
setting.AppSubURL = ""
req := httptest.NewRequest("GET", "http://example.com:3000/recovery", nil)
assert.Equal(t, "http://example.com:3000", recoveryRequestBaseURL(req))
// end edit/add - by petru @ codex
}
// end edit/add - by petru @ codex
+62 -6
View File
@@ -41,10 +41,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; App name that shows in every page title
APP_NAME = ; Gitea: Git with a cup of tea
;APP_NAME = Gitea: Git with a cup of tea
;;
;; RUN_USER will automatically detect the current user - but you can set it here change it if you run locally
RUN_USER = ; git
;RUN_USER =
;;
;; Application run mode, affects performance and debugging: "dev" or "prod", default is "prod"
;; Mode "dev" makes Gitea easier to develop and debug, values other than "dev" are treated as "prod" which is for production use.
@@ -461,6 +461,11 @@ INTERNAL_TOKEN =
;; Name of cookie used to store authentication information.
;COOKIE_REMEMBER_NAME = gitea_incredible
;;
;; URL or path that Gitea should redirect users to *after* performing its own logout.
;; Use this, if needed, when authentication is handled by a reverse proxy or SSO.
;; For example: "/my-sso/logout?return=/my-sso/home"
;REVERSE_PROXY_LOGOUT_REDIRECT =
;;
;; Reverse proxy authentication header name of user name, email, and full name
;REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
;REVERSE_PROXY_AUTHENTICATION_EMAIL = X-WEBAUTH-EMAIL
@@ -778,6 +783,11 @@ LEVEL = Info
;; Disallow registration, only allow admins to create accounts.
;DISABLE_REGISTRATION = false
;;
;; When DISABLE_REGISTRATION is true, choose how administrator-created accounts are provisioned.
;; - local: create active local accounts immediately
;; - invite: create inactive accounts that require the emailed invitation link before sign-in is enabled
;ADMIN_CREATED_ACCOUNT_MODE = invite
;;
;; Allow registration only using gitea itself, it works only when DISABLE_REGISTRATION is false
;ALLOW_ONLY_INTERNAL_REGISTRATION = false
;;
@@ -1071,10 +1081,12 @@ LEVEL = Info
;DEFAULT_BRANCH = main
;;
;; Allow adoption of unadopted repositories
;ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES = false
;ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES = false ; edit/add - by petru @ codex
;; Users and administrators can adopt pre-existing repository directories that exist on disk but do not yet have database records. The installer can auto-enable this during imported app.ini recovery without a previously used database.
;;
;; Allow deletion of unadopted repositories
;ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES = false
;ALLOW_DELETE_OF_UNADOPTED_REPOSITORIES = false ; edit/add - by petru @ codex
;; Users and administrators can delete pre-existing repository directories that are still not adopted into the database. The installer can auto-enable this during imported app.ini recovery without a previously used database.
;; Don't allow download source archive files from UI
;DISABLE_DOWNLOAD_SOURCE_ARCHIVES = false
@@ -1608,6 +1620,16 @@ LEVEL = Info
;;
;; Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
;DEFAULT_EMAIL_NOTIFICATIONS = enabled
;;
;; Enable the persistent Super Administrator role for protecting administrator management.
;SUPER_ADMIN_ENABLED = true
;;
;; Controls who can change administrator and super administrator permissions.
;; Options:
;; - super_admin_only: only super administrators can modify or delete administrator accounts and manage all administrator privilege changes.
;; - grantor_only: administrators can promote regular users to administrator and later manage only the administrator accounts they directly promoted.
;; - grantor_inheritance: like grantor_only, but if the direct grantor becomes inactive or has sign-in disabled, management passes up the admin grant chain until an eligible administrator is found.
;ADMIN_MANAGEMENT_POLICY = grantor_only
;; Disabled features for users could be "deletion", "manage_ssh_keys", "manage_gpg_keys", "manage_mfa", "manage_credentials" more features can be disabled in future
;; - deletion: a user cannot delete their own account
;; - manage_ssh_keys: a user cannot configure ssh keys
@@ -2086,6 +2108,22 @@ LEVEL = Info
;; Empty means server's location setting
;DEFAULT_UI_LOCATION =
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[backup]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; start edit/add - by petru @ codex
;; Directory where periodic database backups are written.
;PATH = data/backups/db
;; Number of backups to keep. Set to 0 to disable pruning.
;RETENTION_COUNT = 7
;; Compress the SQL dump as `database.sql.gz`.
;COMPRESS = true
;; Save a copy of the current app.ini alongside the backup manifest.
;INCLUDE_APP_INI_SNAPSHOT = true
;; end edit/add - by petru @ codex
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[cron]
@@ -2108,6 +2146,24 @@ LEVEL = Info
;; Basic cron tasks - enabled by default
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Create database backups
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[cron.database_backup]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; start edit/add - by petru @ codex
;; Enable running the periodic database backup task.
;ENABLED = true
;; Run the database backup task when Gitea starts.
;RUN_AT_START = false
;; Whether to emit notice on successful execution too.
;NOTICE_ON_SUCCESS = false
;; Time interval for job to run.
;SCHEDULE = @daily
;; end edit/add - by petru @ codex
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Clean up old repository archives
@@ -2580,8 +2636,8 @@ LEVEL = Info
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The first locale will be used as the default if user browser's language doesn't match any locale in the list.
;LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pt-PT,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sv-SE,ko-KR,el-GR,fa-IR,hu-HU,id-ID,ml-IN
;NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,Français,Nederlands,Latviešu,Русский,Українська,日本語,Español,Português do Brasil,Português de Portugal,Polski,Български,Italiano,Suomi,Türkçe,Čeština,Српски,Svenska,한국어,Ελληνικά,فارسی,Magyar nyelv,Bahasa Indonesia,മലയാളം
;LANGS = en-US,ro-RO,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pt-PT,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sv-SE,ko-KR,el-GR,fa-IR,hu-HU,id-ID,ml-IN
;NAMES = English,Română,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,Français,Nederlands,Latviešu,Русский,Українська,日本語,Español,Português do Brasil,Português de Portugal,Polski,Български,Italiano,Suomi,Türkçe,Čeština,Српски,Svenska,한국어,Ελληνικά,فارسی,Magyar nyelv,Bahasa Indonesia,മലയാളം
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+198
View File
@@ -0,0 +1,198 @@
# Community governance and review process
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:
<https://github.com/go-gitea/gitea/pulls?q=is%3Apr+label%3Areviewed%2Fwait-merge+sort%3Acreated-asc+is%3Aopen>
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:
- [Two-factor authentication](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication)
- [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.
### Current TOC members
- 2024-01-01 ~ 2024-12-31
- Company
- [Jason Song](https://gitea.com/wolfogre) <i@wolfogre.com>
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.com>
- Community
- [6543](https://gitea.com/6543) <6543@obermui.de>
- [delvh](https://gitea.com/delvh) <dev.lh@web.de>
- [John Olheiser](https://gitea.com/jolheiser) <john.olheiser@gmail.com>
### Previous TOC/owners members
Here's the history of the owners and the time they served:
- [Lunny Xiao](https://gitea.com/lunny) - 2016, 2017, [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [Kim Carlbäcker](https://github.com/bkcsoft) - 2016, 2017
- [Thomas Boerger](https://gitea.com/tboerger) - 2016, 2017
- [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) - [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801)
- [Matti Ranta](https://gitea.com/techknowlogick) - [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [Andrew Thornton](https://gitea.com/zeripath) - [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [6543](https://gitea.com/6543) - 2023
- [John Olheiser](https://gitea.com/jolheiser) - 2023
- [Jason Song](https://gitea.com/wolfogre) - 2023
## Governance Compensation
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.
You can visit our roadmap on the wiki.
+58
View File
@@ -0,0 +1,58 @@
# Backend development
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))
+17
View File
@@ -0,0 +1,17 @@
# Frontend development
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)
- [refactoring guideline](https://docs.gitea.com/contributing/guidelines-refactoring)
+115
View File
@@ -0,0 +1,115 @@
# Release management
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`
-1
View File
@@ -575,7 +575,6 @@ export default defineConfig([
'no-restricted-imports': [2, {paths: [
{name: 'jquery', message: 'Use the global $ instead', allowTypeImports: true},
{name: 'htmx.org', message: 'Use the global htmx instead', allowTypeImports: true},
{name: 'idiomorph/htmx', message: 'Loaded in globals.ts', allowTypeImports: true},
]}],
'no-restricted-syntax': [2, 'WithStatement', 'ForInStatement', 'LabeledStatement', 'SequenceExpression'],
'no-return-assign': [0],
Generated
+3 -3
View File
@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1775036866,
"narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=",
"lastModified": 1775710090,
"narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "6201e203d09599479a3b3450ed24fa81537ebc4e",
"rev": "4c1018dae018162ec878d42fec712642d214fdfa",
"type": "github"
},
"original": {
+20 -20
View File
@@ -1,6 +1,6 @@
module code.gitea.io/gitea
go 1.26.1
go 1.26.2
// rfc5280 said: "The serial number is an integer assigned by the CA to each certificate."
// But some CAs use negative serial number, just relax the check. related:
@@ -12,7 +12,7 @@ require (
code.gitea.io/sdk/gitea v0.24.1
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
connectrpc.com/connect v1.19.1
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed
gitea.com/go-chi/binding v0.0.0-20260414111559-654cea7ac60a
gitea.com/go-chi/cache v0.2.1
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098
gitea.com/go-chi/session v0.0.0-20251124165456-68e0254e989e
@@ -27,7 +27,7 @@ require (
github.com/PuerkitoBio/goquery v1.12.0
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0
github.com/alecthomas/chroma/v2 v2.23.1
github.com/aws/aws-sdk-go-v2/credentials v1.19.13
github.com/aws/aws-sdk-go-v2/credentials v1.19.14
github.com/aws/aws-sdk-go-v2/service/codecommit v1.33.12
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/blevesearch/bleve/v2 v2.5.7
@@ -49,21 +49,20 @@ require (
github.com/gliderlabs/ssh v0.3.8
github.com/go-chi/chi/v5 v5.2.5
github.com/go-chi/cors v1.2.2
github.com/go-co-op/gocron/v2 v2.19.1
github.com/go-enry/go-enry/v2 v2.9.5
github.com/go-co-op/gocron/v2 v2.20.0
github.com/go-enry/go-enry/v2 v2.9.6
github.com/go-git/go-billy/v5 v5.8.0
github.com/go-git/go-git/v5 v5.17.2
github.com/go-ldap/ldap/v3 v3.4.13
github.com/go-redsync/redsync/v4 v4.16.0
github.com/go-sql-driver/mysql v1.9.3
github.com/go-webauthn/webauthn v0.16.1
github.com/goccy/go-json v0.10.6
github.com/go-webauthn/webauthn v0.16.4
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/google/go-github/v84 v84.0.0
github.com/google/licenseclassifier/v2 v2.0.0
github.com/google/pprof v0.0.0-20260302011040-a15ffb7f9dcc
github.com/google/pprof v0.0.0-20260402051712-545e8a4df936
github.com/google/uuid v1.6.0
github.com/gorilla/feeds v1.2.0
github.com/gorilla/sessions v1.4.0
@@ -75,15 +74,15 @@ require (
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/klauspost/compress v1.18.5
github.com/klauspost/cpuid/v2 v2.3.0
github.com/lib/pq v1.12.1
github.com/lib/pq v1.12.3
github.com/markbates/goth v1.82.0
github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-sqlite3 v1.14.38
github.com/meilisearch/meilisearch-go v0.36.1
github.com/mattn/go-isatty v0.0.21
github.com/mattn/go-sqlite3 v1.14.42
github.com/meilisearch/meilisearch-go v0.36.2
github.com/mholt/archives v0.1.5
github.com/microcosm-cc/bluemonday v1.0.27
github.com/microsoft/go-mssqldb v1.9.6
github.com/minio/minio-go/v7 v7.0.99
github.com/minio/minio-go/v7 v7.0.100
github.com/msteinert/pam/v2 v2.1.0
github.com/nektos/act v0.2.63
github.com/niklasfasching/go-org v1.9.1
@@ -111,14 +110,14 @@ require (
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
gitlab.com/gitlab-org/api/client-go v1.46.0
go.yaml.in/yaml/v4 v4.0.0-rc.3
golang.org/x/crypto v0.49.0
golang.org/x/image v0.38.0
golang.org/x/net v0.52.0
golang.org/x/crypto v0.50.0
golang.org/x/image v0.39.0
golang.org/x/net v0.53.0
golang.org/x/oauth2 v0.36.0
golang.org/x/sync v0.20.0
golang.org/x/sys v0.42.0
golang.org/x/text v0.35.0
google.golang.org/grpc v1.79.3
golang.org/x/sys v0.43.0
golang.org/x/text v0.36.0
google.golang.org/grpc v1.80.0
google.golang.org/protobuf v1.36.11
gopkg.in/ini.v1 v1.67.1
gopkg.in/yaml.v3 v3.0.1
@@ -195,7 +194,8 @@ require (
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/go-webauthn/x v0.2.2 // indirect
github.com/go-webauthn/x v0.2.3 // indirect
github.com/goccy/go-json v0.10.6 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
+38 -38
View File
@@ -18,8 +18,8 @@ filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
gitea.com/gitea/act v0.261.10 h1:ndwbtuMXXz1dpYF2iwY1/PkgKNETo4jmPXfinTZt8cs=
gitea.com/gitea/act v0.261.10/go.mod h1:oIkqQHvU0lfuIWwcpqa4FmU+t3prA89tgkuHUTsrI2c=
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed h1:EZZBtilMLSZNWtHHcgq2mt6NSGhJSZBuduAlinMEmso=
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed/go.mod h1:E3i3cgB04dDx0v3CytCgRTTn9Z/9x891aet3r456RVw=
gitea.com/go-chi/binding v0.0.0-20260414111559-654cea7ac60a h1:JHoBrfuTSF9Ke9aNfSYj1XRPBHjKPgCApVprnt2Am0M=
gitea.com/go-chi/binding v0.0.0-20260414111559-654cea7ac60a/go.mod h1:FOsLJIMdpiHzBp3Vby6Wfkdw2ppGscrjgU1IC7E4/zQ=
gitea.com/go-chi/cache v0.2.1 h1:bfAPkvXlbcZxPCpcmDVCWoHgiBSBmZN/QosnZvEC0+g=
gitea.com/go-chi/cache v0.2.1/go.mod h1:Qic0HZ8hOHW62ETGbonpwz8WYypj9NieU9659wFUJ8Q=
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098 h1:p2ki+WK0cIeNQuqjR98IP2KZQKRzJJiV7aTeMAFwaWo=
@@ -96,8 +96,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY=
github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o=
github.com/aws/aws-sdk-go-v2/credentials v1.19.13 h1:mA59E3fokBvyEGHKFdnpNNrvaR351cqiHgRg+JzOSRI=
github.com/aws/aws-sdk-go-v2/credentials v1.19.13/go.mod h1:yoTXOQKea18nrM69wGF9jBdG4WocSZA1h38A+t/MAsk=
github.com/aws/aws-sdk-go-v2/credentials v1.19.14 h1:n+UcGWAIZHkXzYt87uMFBv/l8THYELoX6gVcUvgl6fI=
github.com/aws/aws-sdk-go-v2/credentials v1.19.14/go.mod h1:cJKuyWB59Mqi0jM3nFYQRmnHVQIcgoxjEMAbLkpr62w=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A=
@@ -290,10 +290,10 @@ github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-co-op/gocron/v2 v2.19.1 h1:B4iLeA0NB/2iO3EKQ7NfKn5KsQgZfjb2fkvoZJU3yBI=
github.com/go-co-op/gocron/v2 v2.19.1/go.mod h1:5lEiCKk1oVJV39Zg7/YG10OnaVrDAV5GGR6O0663k6U=
github.com/go-enry/go-enry/v2 v2.9.5 h1:HPhAQQHYwJgihL2PxBZiUMFWiROsGwOBdB6/D8zCUhY=
github.com/go-enry/go-enry/v2 v2.9.5/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
github.com/go-co-op/gocron/v2 v2.20.0 h1:9IMrnnVSWjfSh3E54gWmWCHbloQJLh6f9+nwyKfLNpc=
github.com/go-co-op/gocron/v2 v2.20.0/go.mod h1:5lEiCKk1oVJV39Zg7/YG10OnaVrDAV5GGR6O0663k6U=
github.com/go-enry/go-enry/v2 v2.9.6 h1:np63eOtMV56zfYDHnFVgpEVOk8fr2kmylcMnAZUDbSs=
github.com/go-enry/go-enry/v2 v2.9.6/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=
github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e h1:oRq/fiirun5HqlEWMLIcDmLpIELlG4iGbd0s8iqgPi8=
@@ -327,10 +327,10 @@ github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-webauthn/webauthn v0.16.1 h1:x5/SSki5/aIfogaRukqvbg/RXa3Sgxy/9vU7UfFPHKU=
github.com/go-webauthn/webauthn v0.16.1/go.mod h1:RBS+rtQJMkE5VfMQ4diDA2VNrEL8OeUhp4Srz37FHbQ=
github.com/go-webauthn/x v0.2.2 h1:zIiipvMbr48CXi5RG0XdBJR94kd8I5LfzHPb/q+YYmk=
github.com/go-webauthn/x v0.2.2/go.mod h1:IpJ5qyWB9NRhLX3C7gIfjTU7RZLXEP6kzFkoVSE7Fz4=
github.com/go-webauthn/webauthn v0.16.4 h1:R9jqR/cYZa7hRquFF7Za/8qoH/K/TIs1/Q/4CyGN+1Q=
github.com/go-webauthn/webauthn v0.16.4/go.mod h1:SU2ljAgToTV/YLPI0C05QS4qn+e04WpB5g1RMfcZfS4=
github.com/go-webauthn/x v0.2.3 h1:8oArS+Rc1SWFLXhE17KZNx258Z4kUSyaDgsSncCO5RA=
github.com/go-webauthn/x v0.2.3/go.mod h1:tM04GF3V6VYq79AZMl7vbj4q6pz9r7L2criWRzbWhPk=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
@@ -391,8 +391,8 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/licenseclassifier/v2 v2.0.0 h1:1Y57HHILNf4m0ABuMVb6xk4vAJYEUO0gDxNpog0pyeA=
github.com/google/licenseclassifier/v2 v2.0.0/go.mod h1:cOjbdH0kyC9R22sdQbYsFkto4NGCAc+ZSwbeThazEtM=
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/pprof v0.0.0-20260302011040-a15ffb7f9dcc h1:VBbFa1lDYWEeV5FZKUiYKYT0VxCp9twUmmaq9eb8sXw=
github.com/google/pprof v0.0.0-20260302011040-a15ffb7f9dcc/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 h1:EwtI+Al+DeppwYX2oXJCETMO23COyaKGP6fHVpkpWpg=
github.com/google/pprof v0.0.0-20260402051712-545e8a4df936/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -498,8 +498,8 @@ github.com/letsencrypt/challtestsrv v1.4.2 h1:0ON3ldMhZyWlfVNYYpFuWRTmZNnyfiL9Hh
github.com/letsencrypt/challtestsrv v1.4.2/go.mod h1:GhqMqcSoeGpYd5zX5TgwA6er/1MbWzx/o7yuuVya+Wk=
github.com/letsencrypt/pebble/v2 v2.10.0 h1:Wq6gYXlsY6ubqI3hhxsTzdyotvfdjFBxuwYqCLCnj/U=
github.com/letsencrypt/pebble/v2 v2.10.0/go.mod h1:Sk8cmUIPcIdv2nINo+9PB4L+ZBhzY+F9A1a/h/xmWiQ=
github.com/lib/pq v1.12.1 h1:x1nbl/338GLqeDJ/FAiILallhAsqubLzEZu/pXtHUow=
github.com/lib/pq v1.12.1/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ=
github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
github.com/libdns/libdns v1.1.1 h1:wPrHrXILoSHKWJKGd0EiAVmiJbFShguILTg9leS/P/U=
github.com/libdns/libdns v1.1.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -512,16 +512,16 @@ github.com/markbates/goth v1.82.0 h1:8j/c34AjBSTNzO7zTsOyP5IYCQCMBTRBHAbBt/PI0bQ
github.com/markbates/goth v1.82.0/go.mod h1:/DRlcq0pyqkKToyZjsL2KgiA1zbF1HIjE7u2uC79rUk=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs=
github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w=
github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.14.38 h1:tDUzL85kMvOrvpCt8P64SbGgVFtJB11GPi2AdmITgb4=
github.com/mattn/go-sqlite3 v1.14.38/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/meilisearch/meilisearch-go v0.36.1 h1:mJTCJE5g7tRvaqKco6DfqOuJEjX+rRltDEnkEC02Y0M=
github.com/meilisearch/meilisearch-go v0.36.1/go.mod h1:hWcR0MuWLSzHfbz9GGzIr3s9rnXLm1jqkmHkJPbUSvM=
github.com/mattn/go-sqlite3 v1.14.42 h1:MigqEP4ZmHw3aIdIT7T+9TLa90Z6smwcthx+Azv4Cgo=
github.com/mattn/go-sqlite3 v1.14.42/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
github.com/meilisearch/meilisearch-go v0.36.2 h1:MYaMPCpdLh2aYPt+zK+19mLoA4dfBY3S1L7T0FADCjU=
github.com/meilisearch/meilisearch-go v0.36.2/go.mod h1:hWcR0MuWLSzHfbz9GGzIr3s9rnXLm1jqkmHkJPbUSvM=
github.com/mholt/acmez/v3 v3.1.6 h1:eGVQNObP0pBN4sxqrXeg7MYqTOWyoiYpQqITVWlrevk=
github.com/mholt/acmez/v3 v3.1.6/go.mod h1:5nTPosTGosLxF3+LU4ygbgMRFDhbAVpqMI4+a4aHLBY=
github.com/mholt/archives v0.1.5 h1:Fh2hl1j7VEhc6DZs2DLMgiBNChUux154a1G+2esNvzQ=
@@ -538,8 +538,8 @@ github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI
github.com/minio/crc64nvme v1.1.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.99 h1:2vH/byrwUkIpFQFOilvTfaUpvAX3fEFhEzO+DR3DlCE=
github.com/minio/minio-go/v7 v7.0.99/go.mod h1:EtGNKtlX20iL2yaYnxEigaIvj0G0GwSDnifnG8ClIdw=
github.com/minio/minio-go/v7 v7.0.100 h1:ShkWi8Tyj9RtU57OQB2HIXKz4bFgtVib0bbT1sbtLI8=
github.com/minio/minio-go/v7 v7.0.100/go.mod h1:EtGNKtlX20iL2yaYnxEigaIvj0G0GwSDnifnG8ClIdw=
github.com/minio/minlz v1.1.0 h1:rUOGu3EP4EqJC5k3qCsIwEnZiJULKqtRyDdqbhlvMmQ=
github.com/minio/minlz v1.1.0/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -785,12 +785,12 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
golang.org/x/image v0.38.0 h1:5l+q+Y9JDC7mBOMjo4/aPhMDcxEptsX+Tt3GgRQRPuE=
golang.org/x/image v0.38.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY=
golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww=
golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -819,8 +819,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -868,8 +868,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -880,8 +880,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -892,8 +892,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -914,8 +914,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401020348-3a24fdc17823 h1:YedBIttDguBl/zy2wJauEUm+DZZg4UXseWj0g/3N+yo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401020348-3a24fdc17823/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+1 -1
View File
@@ -32,7 +32,7 @@ func TestUpdateRepoRunsNumbers(t *testing.T) {
err = UpdateRepoRunsNumbers(t.Context(), repo)
assert.NoError(t, err)
repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
assert.Equal(t, 5, repo.NumActionRuns)
assert.Equal(t, 4, repo.NumActionRuns)
assert.Equal(t, 3, repo.NumClosedActionRuns)
}
+1
View File
@@ -62,6 +62,7 @@ func getUserHeatmapData(ctx context.Context, user *user_model.User, team *organi
return nil, err
}
// HINT: USER-ACTIVITY-PUSH-COMMITS: it only uses the doer's action time, it doesn't use git commit's time
return hdata, db.GetEngine(ctx).
Select(groupBy+" AS timestamp, count(user_id) as contributions").
Table("action").
+9
View File
@@ -31,3 +31,12 @@ func DumpDatabase(filePath, dbType string) error {
}
return xormEngine.DumpTablesToFile(tbs, filePath)
}
// start edit/add - by petru @ codex
// ImportDatabase imports SQL statements from a file into the current default engine.
func ImportDatabase(filePath string) error {
_, err := xormEngine.ImportFile(filePath)
return err
}
// end edit/add - by petru @ codex
+2
View File
@@ -177,3 +177,5 @@
user_id: 40
repo_id: 1
mode: 2
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -31,3 +31,5 @@
created_unix: 946687980
updated_unix: 946687980
# commented out tokens so you can see what they are in plaintext
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -73,3 +73,5 @@
is_private: false
created_unix: 1680454039
content: '4|' # issueId 5
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -177,3 +177,5 @@
created_unix: 1730330775
updated_unix: 1730330775
expired_unix: 1738106775
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+1 -20
View File
@@ -140,23 +140,4 @@
need_approval: 0
approved_by: 0
-
id: 805
title: "update actions"
repo_id: 4
owner_id: 1
workflow_id: "artifact.yaml"
index: 191
trigger_user_id: 1
ref: "refs/heads/master"
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
event: "push"
trigger_event: "push"
is_fork_pull_request: 0
status: 5
started: 1683636528
stopped: 1683636626
created: 1683636108
updated: 1683636626
need_approval: 0
approved_by: 0
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+1 -14
View File
@@ -130,17 +130,4 @@
started: 1683636528
stopped: 1683636626
-
id: 206
run_id: 805
repo_id: 4
owner_id: 1
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
is_fork_pull_request: 0
name: job_2
attempt: 1
job_id: job_2
task_id: 56
status: 3
started: 1683636528
stopped: 1683636626
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -49,3 +49,5 @@
repo_id: 0
description: "This runner is going to be deleted"
agent_labels: '["runner_to_be_deleted","linux"]'
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -33,3 +33,5 @@
is_active: 1
created: 1695617751
updated: 1695617751
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+1 -19
View File
@@ -178,22 +178,4 @@
log_size: 0
log_expired: 0
-
id: 56
attempt: 1
runner_id: 1
status: 3 # 3 is the status code for "cancelled"
started: 1683636528
stopped: 1683636626
repo_id: 4
owner_id: 1
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
is_fork_pull_request: 0
token_hash: 6d8ef48297195edcc8e22c70b3020eaa06c52976db67d39b4240c64a69a2cc1508825121b7b8394e48e00b1bf3718b2aaaab
token_salt: eeeeeeee
token_last_eight: eeeeeeee
log_filename: artifact-test2/2f/47.log
log_in_storage: 1
log_length: 707
log_size: 90179
log_expired: 0
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -18,3 +18,5 @@
task_id: 50
output_key: output_b
output_value: bbb
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -166,3 +166,5 @@
download_count: 0
size: 0
created_unix: 946684800
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -3,3 +3,5 @@
slug: badge1
description: just a test badge
image_url: badge1.png
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -249,3 +249,5 @@
is_deleted: false
deleted_by_id: 0
deleted_unix: 0
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -63,3 +63,5 @@
repo_id: 32
user_id: 10
mode: 2 # write
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -102,3 +102,5 @@
review_id: 22
assignee_id: 5
created_unix: 946684817
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -57,3 +57,5 @@
context: deploy/awesomeness
context_hash: ae9547713a6665fc4261d0756904932085a41cf2
creator_id: 2
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -3,3 +3,5 @@
repo_id: 1
sha: "1234123412341234123412341234123412341234"
max_index: 5
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -1 +1,3 @@
[] # empty
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -317,3 +317,5 @@
lower_email: user40@example.com
is_activated: true
is_primary: true
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -1 +1,3 @@
[] # empty
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -17,3 +17,5 @@
id: 4
user_id: 31
follow_id: 33
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -21,3 +21,5 @@
can_encrypt_comms: true
can_encrypt_storage: true
can_certify: true
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -1 +1,3 @@
[] # empty
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -35,3 +35,5 @@
"X-Head": "42"
}
}
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -372,3 +372,5 @@
created_unix: 1707270422
updated_unix: 1707270422
is_locked: false
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -18,3 +18,5 @@
id: 5
assignee_id: 10
issue_id: 6
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -33,3 +33,5 @@
-
group_id: 51
max_index: 1
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -17,3 +17,5 @@
id: 4
issue_id: 2
label_id: 4
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -4,3 +4,5 @@
issue_id: 4
is_pull: false
pin_order: 1
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -18,3 +18,5 @@
issue_id: 1
is_read: false
is_mentioned: true
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -29,3 +29,5 @@
is_watching: false
created_unix: 946684800
updated_unix: 946684800
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -107,3 +107,5 @@
num_issues: 0
num_closed_issues: 0
archived_unix: 0
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -30,3 +30,5 @@
size: 25
repository_id: 54
created_unix: 1671607299
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -1 +1,3 @@
[] # empty
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -52,3 +52,5 @@
num_closed_issues: 0
completeness: 0
deadline_unix: 253370764800
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -47,3 +47,5 @@
next_update_unix: 0
lfs_enabled: false
lfs_endpoint: ""
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -12,3 +12,5 @@
id: 3
type: 1 # NoticeRepository
description: description3
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -52,3 +52,5 @@
issue_id: 4
created_unix: 946688800
updated_unix: 946688820
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -18,3 +18,5 @@
created_unix: 1546869730
updated_unix: 1546869730
confidential_client: false
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
@@ -13,3 +13,5 @@
code_challenge_method: "S256"
redirect_uri: "http://127.0.0.1/"
valid_until: 3546869730
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -29,3 +29,5 @@
scope: "whatever"
created_unix: 1546869730
updated_unix: 1546869730
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -135,3 +135,5 @@
uid: 20
org_id: 17
is_public: false
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -69,3 +69,5 @@
type: 2
created_unix: 1688973000
updated_unix: 1688973000
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -75,3 +75,5 @@
default: true
created_unix: 1588117528
updated_unix: 1588117528
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -21,3 +21,5 @@
issue_id: 5
project_id: 1
project_board_id: 3
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -1 +1,3 @@
[] # empty
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -22,3 +22,5 @@
allowlist_team_i_ds: "[]"
created_unix: 1715596037
updated_unix: 1715596037
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -10,3 +10,5 @@
updated_unix: 1565224552
login_source_id: 0
verified: false
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -117,3 +117,5 @@
index: 1
head_repo_id: 61
base_repo_id: 61
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -37,3 +37,5 @@
comment_id: 2
user_id: 1
created_unix: 1573248005
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -150,3 +150,5 @@
is_prerelease: false
is_tag: false
created_unix: 946684803
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -3,3 +3,5 @@
repo_id: 1
from: dev
to: master
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -1 +1,3 @@
[] # empty
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -1 +1,3 @@
[] # empty
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -1 +1,3 @@
[] # empty
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -3,3 +3,5 @@
owner_id: 2
lower_name: oldrepo1
redirect_repo_id: 1
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -25,3 +25,5 @@
-
repo_id: 2
topic_id: 6
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -29,3 +29,5 @@
repo_id: 5
created_unix: 1553610671
updated_unix: 1553610671
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -747,3 +747,5 @@
type: 10
config: "{}"
created_unix: 946684810
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -1788,3 +1788,5 @@
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -214,3 +214,5 @@
original_author_id: 0
updated_unix: 946684817
created_unix: 946684817
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -17,3 +17,5 @@
id: 4
uid: 10
repo_id: 32
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -9,3 +9,5 @@
user_id: 2
issue_id: 2
created_unix: 1500988002
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -13,3 +13,5 @@
version: 1
created: 1653533198
updated: 1653533198
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -261,3 +261,5 @@
num_members: 1
includes_all_repositories: true
can_create_org_repo: false
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -75,3 +75,5 @@
org_id: 41
team_id: 22
repo_id: 61
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly
+2
View File
@@ -340,3 +340,5 @@
team_id: 24
type: 1 # code
access_mode: 2
# DO NOT add more test data in the fixtures, test case should prepare their own test data separately and clearly

Some files were not shown because too many files have changed in this diff Show More