mirror of
https://github.com/go-gitea/gitea.git
synced 2026-06-17 19:10:22 +03:00
docs: add development setup guide (#37960)
Moves the "Hacking on Gitea" page out of the documentation website and into the repository as `docs/development.md`, so contributors find build and test instructions next to the code. The content has been cleaned up and corrected for in-repo use. --------- Signed-off-by: bircni <bircni@icloud.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
+15
-35
@@ -2,12 +2,17 @@
|
|||||||
|
|
||||||
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.
|
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 |
|
| Topic | Document |
|
||||||
| :---- | :------- |
|
|:-----------------------|:-----------------------------------------------------------------|
|
||||||
| Backend (Go modules, API v1) | [docs/guideline-backend.md](docs/guideline-backend.md) |
|
| Setup and requirements | [docs/build-setup.md](docs/build-setup.md) |
|
||||||
| Frontend (npm, UI guidelines) | [docs/guideline-frontend.md](docs/guideline-frontend.md) |
|
| Development workflow | [docs/development.md](docs/development.md) |
|
||||||
| Maintainers, TOC, labels, merge queue, commit format for mergers | [docs/community-governance.md](docs/community-governance.md) |
|
| Build from source | [docs/build-source.md](docs/build-source.md) |
|
||||||
| Release cycle, backports, tagging releases | [docs/release-management.md](docs/release-management.md) |
|
| Running the tests | [docs/testing.md](docs/testing.md) |
|
||||||
|
| Frontend guidelines | [docs/guidelines-frontend.md](docs/guidelines-frontend.md) |
|
||||||
|
| Backend guidelines | [docs/guidelines-backend.md](docs/guidelines-backend.md) |
|
||||||
|
| Refactoring | [docs/guidelines-refactoring.md](docs/guidelines-refactoring.md) |
|
||||||
|
| Community Governance | [docs/community-governance.md](docs/community-governance.md) |
|
||||||
|
| Release management | [docs/release-management.md](docs/release-management.md) |
|
||||||
|
|
||||||
<details><summary>Table of Contents</summary>
|
<details><summary>Table of Contents</summary>
|
||||||
|
|
||||||
@@ -43,7 +48,7 @@ This document explains how to contribute changes to the Gitea project. Topic-spe
|
|||||||
It assumes you have followed the [installation instructions](https://docs.gitea.com/category/installation). \
|
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).
|
Sensitive security-related issues should be reported to [security@gitea.io](mailto:security@gitea.io).
|
||||||
|
|
||||||
For configuring IDEs for Gitea development, see the [contributed IDE configurations](contrib/ide/).
|
For configuring IDEs for Gitea development, see the [IDE setup notes](docs/development.md#ide-configuration) and the [contributed configurations](contrib/development/).
|
||||||
|
|
||||||
## AI Contribution Policy
|
## AI Contribution Policy
|
||||||
|
|
||||||
@@ -106,7 +111,8 @@ If further discussion is needed, we encourage you to open a new issue instead an
|
|||||||
|
|
||||||
## Building Gitea
|
## Building Gitea
|
||||||
|
|
||||||
See the [development setup instructions](https://docs.gitea.com/development/hacking-on-gitea).
|
See [docs/setup.md](docs/setup.md) for prerequisites and [docs/development.md](docs/development.md)
|
||||||
|
for building Gitea and the development workflow.
|
||||||
|
|
||||||
## Styleguide
|
## Styleguide
|
||||||
|
|
||||||
@@ -125,33 +131,7 @@ Afterwards, copyright should only be modified when the copyright author changes.
|
|||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
Before submitting a pull request, run all tests to make sure your changes don't cause a regression elsewhere.
|
Before submitting a pull request, run the linters (`make lint`, or the scoped `make lint-backend` / `make lint-frontend`) and the tests to make sure your changes don't cause a regression elsewhere. See [docs/testing.md](docs/testing.md) for how to run the unit, integration, end-to-end, and migration tests.
|
||||||
|
|
||||||
Here's how to run the test suite:
|
|
||||||
|
|
||||||
- code lint
|
|
||||||
|
|
||||||
| | |
|
|
||||||
| :-------------------- | :--------------------------------------------------------------------------- |
|
|
||||||
|``make lint`` | lint everything (not needed if you only change the front- **or** backend) |
|
|
||||||
|``make lint-frontend`` | lint frontend files |
|
|
||||||
|``make lint-backend`` | lint backend files |
|
|
||||||
|
|
||||||
- run tests (we suggest running them on Linux)
|
|
||||||
|
|
||||||
| Command | Action | |
|
|
||||||
|:----------------------------------------------|:-----------------------------------------------------| ------------------------------------------- |
|
|
||||||
| ``make test-backend[\#SpecificTestName]`` | run unit test(s) | |
|
|
||||||
| ``make test-integration[\#SpecificTestName]`` | run [integration](tests/integration) test(s) | [More details](tests/integration/README.md) |
|
|
||||||
| ``make test-e2e`` | run [end-to-end](tests/e2e) test(s) using Playwright | |
|
|
||||||
|
|
||||||
- E2E test environment variables
|
|
||||||
|
|
||||||
| Variable | Description |
|
|
||||||
| :-------------------------------- | :---------------------------------------------------------- |
|
|
||||||
| ``GITEA_TEST_E2E_DEBUG`` | When set, show Gitea server output |
|
|
||||||
| ``GITEA_TEST_E2E_FLAGS`` | Additional flags passed to Playwright, for example ``--ui`` |
|
|
||||||
| ``GITEA_TEST_E2E_TIMEOUT_FACTOR`` | Timeout multiplier (default: 4 on CI, 1 locally) |
|
|
||||||
|
|
||||||
## Translation
|
## Translation
|
||||||
|
|
||||||
|
|||||||
@@ -14,21 +14,21 @@
|
|||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
The goal of this project is to make the easiest, fastest, and most
|
The goal of Gitea is to make the easiest, fastest, and most painless way of
|
||||||
painless way of setting up a self-hosted Git service.
|
setting up a self-hosted all-in-one software development service,
|
||||||
|
including Git hosting, code management, code review, issue tracking, project kanban, wiki,
|
||||||
|
team collaboration, package registry and CI/CD which can reuse GitHub Actions.
|
||||||
|
|
||||||
As Gitea is written in Go, it works across **all** the platforms and
|
As Gitea is written in Go, it works across **all** the platforms and
|
||||||
architectures that are supported by Go, including Linux, macOS, and
|
architectures that are supported by Go, including Linux, macOS, FreeBSD/OpenBSD and Windows
|
||||||
Windows on x86, amd64, ARM and PowerPC architectures.
|
on x86, amd64, ARM, RISC-V 64 and PowerPC architectures.
|
||||||
This project has been
|
|
||||||
[forked](https://blog.gitea.com/welcome-to-gitea/) from
|
|
||||||
[Gogs](https://gogs.io) since November of 2016, but a lot has changed.
|
|
||||||
|
|
||||||
For online demonstrations, you can visit [demo.gitea.com](https://demo.gitea.com).
|
For online demonstrations, you can visit [demo.gitea.com](https://demo.gitea.com).
|
||||||
|
|
||||||
For accessing free Gitea service (with a limited number of repositories), you can visit [gitea.com](https://gitea.com/user/login).
|
For accessing free Gitea service (with a limited number of repositories), you can visit [gitea.com](https://gitea.com/user/login).
|
||||||
|
|
||||||
To quickly deploy your own dedicated Gitea instance on Gitea Cloud, you can start a free trial at [cloud.gitea.com](https://cloud.gitea.com).
|
To quickly deploy your own dedicated Gitea instance on Gitea Cloud, you can start a free trial at [cloud.gitea.com](https://cloud.gitea.com),
|
||||||
|
or use container (docker/podman/etc) to deploy on your own server with the [official image](https://hub.docker.com/r/gitea/gitea).
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
@@ -40,27 +40,12 @@ If you have any suggestions or would like to contribute to it, you can visit the
|
|||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
From the root of the source tree, run:
|
See [docs/build-setup.md](docs/build-setup.md) for prerequisites
|
||||||
|
and [docs/development.md](docs/development.md) for setting up a local development environment, linting, and testing.
|
||||||
|
|
||||||
TAGS="bindata" make build
|
If you'd like to build from source or make a distribution package, see [docs/build-source.md](docs/build-source.md) for more information.
|
||||||
|
|
||||||
The `build` target is split into two sub-targets:
|
After building, you can run `./gitea web` to start the server, or `./gitea help` to see all available commands.
|
||||||
|
|
||||||
- `make backend` which requires [Go Stable](https://go.dev/dl/), the required version is defined in [go.mod](/go.mod).
|
|
||||||
- `make frontend` which requires [Node.js LTS](https://nodejs.org/en/download/) or greater and [pnpm](https://pnpm.io/installation).
|
|
||||||
|
|
||||||
Internet connectivity is required to download the go and npm modules. When building from the official source tarballs which include pre-built frontend files, the `frontend` target will not be triggered, making it possible to build without Node.js.
|
|
||||||
|
|
||||||
More info: https://docs.gitea.com/installation/install-from-source
|
|
||||||
|
|
||||||
## Using
|
|
||||||
|
|
||||||
After building, a binary file named `gitea` will be generated in the root of the source tree by default. To run it, use:
|
|
||||||
|
|
||||||
./gitea web
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> If you're interested in using our APIs, we have experimental support with [documentation](https://docs.gitea.com/api).
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
@@ -69,7 +54,8 @@ Expected workflow is: Fork -> Patch -> Push -> Pull Request
|
|||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
>
|
>
|
||||||
> 1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.**
|
> 1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.**
|
||||||
> 2. If you have found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks!
|
> 2. New to the codebase? The [development guide](docs/development.md) walks through setting up a local environment and building from source.
|
||||||
|
> 3. If you have found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks!
|
||||||
|
|
||||||
## Translating
|
## Translating
|
||||||
|
|
||||||
@@ -126,14 +112,19 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
|
|||||||
|
|
||||||
Gitea is pronounced [/ɡɪ’ti:/](https://youtu.be/EM71-2uDAoY) as in "gi-tea" with a hard g.
|
Gitea is pronounced [/ɡɪ’ti:/](https://youtu.be/EM71-2uDAoY) as in "gi-tea" with a hard g.
|
||||||
|
|
||||||
**Why is this not hosted on a Gitea instance?**
|
**How do I configure Gitea?**
|
||||||
|
|
||||||
We're [working on it](https://github.com/go-gitea/gitea/issues/1029).
|
For dynamic config options, you can change it on your admin panel's configuration section.
|
||||||
|
|
||||||
|
For static config options, you can edit your `app.ini` file and resart the instance.
|
||||||
|
See [app.example.ini](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini) or [configuration documentation](https://docs.gitea.com/administration/config-cheat-sheet) for more details.
|
||||||
|
|
||||||
**Where can I find the security patches?**
|
**Where can I find the security patches?**
|
||||||
|
|
||||||
In the [release log](https://github.com/go-gitea/gitea/releases) or the [change log](https://github.com/go-gitea/gitea/blob/main/CHANGELOG.md), search for the keyword `SECURITY` to find the security patches.
|
In the [release log](https://github.com/go-gitea/gitea/releases) or the [change log](https://github.com/go-gitea/gitea/blob/main/CHANGELOG.md), search for the keyword `SECURITY` to find the security patches.
|
||||||
|
|
||||||
|
(more FAQs are listed in [FAQ documentation](https://docs.gitea.com/help/faq))
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the MIT License.
|
This project is licensed under the MIT License.
|
||||||
@@ -143,7 +134,7 @@ for the full license text.
|
|||||||
## Further information
|
## Further information
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Looking for an overview of the interface? Check it out!</summary>
|
<summary>Looking for an overview of the interface? Check it out the screenshots!</summary>
|
||||||
|
|
||||||
### Login/Register Page
|
### Login/Register Page
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
# IDE and code editor configuration
|
# IDE and code editor configuration
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [IDE and code editor configuration](#ide-and-code-editor-configuration)
|
- [IDE and code editor configuration](#ide-and-code-editor-configuration)
|
||||||
- [Microsoft Visual Studio Code](#microsoft-visual-studio-code)
|
- [Microsoft Visual Studio Code](#microsoft-visual-studio-code)
|
||||||
|
|
||||||
## Microsoft Visual Studio Code
|
## Microsoft Visual Studio Code
|
||||||
|
|
||||||
Download Microsoft Visual Studio Code at https://code.visualstudio.com/ and follow instructions at https://code.visualstudio.com/docs/languages/go to setup Go extension for it.
|
Download Microsoft Visual Studio Code at https://code.visualstudio.com/ and follow instructions at https://code.visualstudio.com/docs/languages/go to setup Go extension for it.
|
||||||
|
|
||||||
Create new directory `.vscode` in Gitea root folder and copy contents of folder [contrib/ide/vscode](vscode/) to it. You can now use `Ctrl`+`Shift`+`B` to build gitea executable and `F5` to run it in debug mode.
|
Create new directory `.vscode` in Gitea root folder and copy contents of folder [contrib/development/vscode](vscode/) to it. You can now use `Ctrl`+`Shift`+`B` to build gitea executable and `F5` to run it in debug mode.
|
||||||
|
|
||||||
Supported on Debian, Ubuntu, Red Hat, Fedora, SUSE Linux, MacOS and Microsoft Windows.
|
Supported on Debian, Ubuntu, Red Hat, Fedora, SUSE Linux, MacOS and Microsoft Windows.
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
# Setup and requirements
|
||||||
|
|
||||||
|
This document lists the tools you need to build Gitea from source and how to get
|
||||||
|
the code. Once your environment is ready, see [development.md](development.md) for
|
||||||
|
the build and development workflow, and [testing.md](testing.md) for running tests.
|
||||||
|
|
||||||
|
For the contribution workflow and review process, see [CONTRIBUTING.md](../CONTRIBUTING.md).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Go
|
||||||
|
|
||||||
|
[Install Go](https://go.dev/doc/install) and set up your Go environment. The
|
||||||
|
required version is the one declared in [`go.mod`](../go.mod); installing the same
|
||||||
|
version your continuous integration uses avoids `gofmt` differences between Go
|
||||||
|
releases.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Some `make` tasks build external Go tools on demand (for example `make
|
||||||
|
> watch-backend`). To use them, the `"$GOPATH"/bin` directory must be on your
|
||||||
|
> executable `PATH`; otherwise you have to manage those tools yourself.
|
||||||
|
|
||||||
|
### Node.js and pnpm
|
||||||
|
|
||||||
|
[Install Node.js](https://nodejs.org/en/download/) to build the JavaScript and CSS
|
||||||
|
files. The minimum supported version is the one declared in
|
||||||
|
[`package.json`](../package.json) (`engines.node`); the latest LTS is recommended.
|
||||||
|
|
||||||
|
Gitea manages frontend dependencies with [pnpm](https://pnpm.io/). The `make`
|
||||||
|
targets invoke it for you, so installing pnpm manually is only needed if you want
|
||||||
|
to run `pnpm` commands directly.
|
||||||
|
|
||||||
|
### Make
|
||||||
|
|
||||||
|
Gitea uses [Make](https://www.gnu.org/software/make/) to drive builds, linting, and
|
||||||
|
tests. On Windows it can be installed via [MSYS2](https://www.msys2.org/) or
|
||||||
|
[Chocolatey](https://chocolatey.org/packages/make).
|
||||||
|
|
||||||
|
### Python with uv (optional)
|
||||||
|
|
||||||
|
Linting the templates, workflow files, and YAML requires Python tooling that Gitea
|
||||||
|
runs through [uv](https://docs.astral.sh/uv/). After installing uv, `make` creates
|
||||||
|
the environment automatically (`uv sync`); you only need this if you run
|
||||||
|
`make lint-templates`, `make lint-yaml`, or `make lint-actions` locally.
|
||||||
|
|
||||||
|
### Git LFS
|
||||||
|
|
||||||
|
The integration tests require [Git LFS](https://git-lfs.com/) to be installed.
|
||||||
|
|
||||||
|
## Getting the source code
|
||||||
|
|
||||||
|
Clone the repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/go-gitea/gitea
|
||||||
|
```
|
||||||
|
|
||||||
|
To contribute changes, [fork the repository](https://github.com/go-gitea/gitea) on
|
||||||
|
GitHub and add your fork as a git remote so you can push branches and open pull
|
||||||
|
requests. See GitHub's [working with forks](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks)
|
||||||
|
documentation for the details.
|
||||||
|
|
||||||
|
## Installing dependencies
|
||||||
|
|
||||||
|
Most build and test targets install the dependencies they need on their own. To
|
||||||
|
fetch everything up front, run `make deps` (or the per-group `make deps-frontend`,
|
||||||
|
`make deps-backend`, `make deps-tools`, `make deps-py`).
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
# Prepare build environment
|
||||||
|
|
||||||
|
Complete the steps in [build-setup.md](build-setup.md) to prepare your environment for building Gitea from source.
|
||||||
|
|
||||||
|
## Choose a branch
|
||||||
|
|
||||||
|
By default, the cloned repository is on main branch (the current development branch for next major release, aka: main nightly).
|
||||||
|
|
||||||
|
You can switch to a versioned branch (the branch for the next minor stable release, aka: stable nightly )
|
||||||
|
or a versioned tag (matches the official releases with version numbers)
|
||||||
|
|
||||||
|
To test a Pull Request, you can fetch its code by its Pull Request number (take `PR #123456` as example):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git fetch origin pull/123456/head:pr-123456
|
||||||
|
```
|
||||||
|
|
||||||
|
# Build
|
||||||
|
|
||||||
|
Various [make tasks](https://github.com/go-gitea/gitea/blob/main/Makefile)
|
||||||
|
are provided to keep the build process as simple as possible.
|
||||||
|
|
||||||
|
Depending on requirements, the following build tags can be included.
|
||||||
|
|
||||||
|
- `bindata`: Build a single monolithic binary, with all assets included. Required for distribution and production build.
|
||||||
|
- `pam`: Enable support for PAM (Linux Pluggable Authentication Modules).
|
||||||
|
Can be used to authenticate local users or extend authentication to methods available to PAM.
|
||||||
|
- `gogit`: (EXPERIMENTAL) Use go-git variants of Git commands.
|
||||||
|
|
||||||
|
To include all assets, use the `bindata` tag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
TAGS="bindata" make build
|
||||||
|
```
|
||||||
|
|
||||||
|
Tag `gogit` is used to try to resolve some Windows-specific performance problems, POSIX systems don't need it.
|
||||||
|
You can build a Windows binary by:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GOOS=windows TAGS="bindata gogit" make build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Changing default paths
|
||||||
|
|
||||||
|
Gitea will search for a number of things from the _`CustomPath`_.
|
||||||
|
By default, this is the `custom/` directory in the current working directory when running Gitea.
|
||||||
|
It will also look for its configuration file _`CustomConf`_ in `$(CustomPath)/conf/app.ini`,
|
||||||
|
and will use the current working directory as the relative base path _`AppWorkPath`_.
|
||||||
|
|
||||||
|
These values, although useful when developing, may conflict with downstream users preferences.
|
||||||
|
|
||||||
|
For packagers who need to use paths like `/etc/gitea/app.ini`,
|
||||||
|
they should define these values at build time for `make build` by environment variable like
|
||||||
|
`LDFLAGS='-X "module.Var1=Value1" -X "module.Var2=Value2"' TAGS="bindata" make build`.
|
||||||
|
|
||||||
|
- _`CustomConf`_: `-X "code.gitea.io/gitea/modules/setting.CustomConf=/etc/gitea/app.ini"`
|
||||||
|
- _`AppWorkPath`_: `-X "code.gitea.io/gitea/modules/setting.AppWorkPath=/var/lib/gitea"`
|
||||||
|
- _`CustomPath`_: `-X "code.gitea.io/gitea/modules/setting.CustomPath=/var/lib/gitea/custom"`
|
||||||
|
- Default PID file location: `-X "code.gitea.io/gitea/cmd.PIDFile=/run/gitea.pid"`
|
||||||
|
|
||||||
|
Add as many of the strings with their preceding `-X` to the `LDFLAGS` variable and run `make build`
|
||||||
|
with the appropriate `TAGS` as above.
|
||||||
|
|
||||||
|
Running `gitea help` will allow you to review what the computed settings will be for your `gitea`.
|
||||||
|
|
||||||
|
## Cross Build
|
||||||
|
|
||||||
|
Gitea use's Golang's toolchain variables for cross-building.
|
||||||
|
|
||||||
|
For example, to cross build for Linux ARM64:
|
||||||
|
|
||||||
|
```
|
||||||
|
GOOS=linux GOARCH=arm64 TAGS="bindata" make build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding shell autocompletion
|
||||||
|
|
||||||
|
Shell completion can be generated directly from binary with:
|
||||||
|
```sh
|
||||||
|
gitea completion <shell>
|
||||||
|
```
|
||||||
|
|
||||||
|
Supported values for `<shell>` are `bash`, `fish`, `pwsh` and `zsh`.
|
||||||
|
Details on how to load the completion for your shell can be found in the completion command help.
|
||||||
|
|
||||||
|
## Source Maps
|
||||||
|
|
||||||
|
By default, gitea generates reduced source maps for frontend files to conserve space. This can be controlled with the `ENABLE_SOURCEMAP` environment variable:
|
||||||
|
|
||||||
|
- `ENABLE_SOURCEMAP=true` generates all source maps, the default for development builds
|
||||||
|
- `ENABLE_SOURCEMAP=reduced` generates limited source maps, the default for production builds
|
||||||
|
- `ENABLE_SOURCEMAP=false` generates no source maps
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
# Development
|
||||||
|
|
||||||
|
This document describes how to build Gitea from source and the day-to-day
|
||||||
|
development workflow. For prerequisites and how to obtain the code, see
|
||||||
|
[build-setup.md](build-setup.md). For running tests, see [testing.md](testing.md). For the
|
||||||
|
contribution workflow and review process, see [CONTRIBUTING.md](../CONTRIBUTING.md).
|
||||||
|
|
||||||
|
Area-specific guidelines:
|
||||||
|
|
||||||
|
- [Backend development guidelines](guidelines-backend.md)
|
||||||
|
- [Frontend development guidelines](guidelines-frontend.md)
|
||||||
|
- [Refactoring guidelines](guidelines-refactoring.md)
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To build Gitea for development, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make build
|
||||||
|
```
|
||||||
|
|
||||||
|
No build tags are required: SQLite support is compiled in by default, which is
|
||||||
|
enough for local development. The `build` target runs two sub-targets, `frontend`
|
||||||
|
and `backend`. The `bindata` tag embeds the frontend assets into the binary and is
|
||||||
|
only needed when packaging a self-contained build, so leave it out during
|
||||||
|
development.
|
||||||
|
|
||||||
|
See `make help` for all available targets, and the workflows in
|
||||||
|
[`.github/workflows`](https://github.com/go-gitea/gitea/tree/main/.github/workflows)
|
||||||
|
to see how continuous integration builds and checks Gitea.
|
||||||
|
|
||||||
|
## Building continuously
|
||||||
|
|
||||||
|
To rebuild automatically when source files change:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# watch both frontend and backend
|
||||||
|
make watch
|
||||||
|
|
||||||
|
# or watch only the frontend (starts the Vite dev server)
|
||||||
|
make watch-frontend
|
||||||
|
|
||||||
|
# or watch only the backend (Go)
|
||||||
|
make watch-backend
|
||||||
|
```
|
||||||
|
|
||||||
|
Watching all backend source files may hit the default open-files limit on macOS or
|
||||||
|
Linux; raise it with `ulimit -n 12288` for the current shell, or in your shell
|
||||||
|
startup file to make it permanent.
|
||||||
|
|
||||||
|
## Formatting, linting and checks
|
||||||
|
|
||||||
|
Continuous integration rejects pull requests that fail formatting, linting, or
|
||||||
|
consistency checks. Format your code first:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make fmt
|
||||||
|
```
|
||||||
|
|
||||||
|
Then lint:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# lint everything
|
||||||
|
make lint
|
||||||
|
# or only one side
|
||||||
|
make lint-backend
|
||||||
|
make lint-frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
Many linters can fix issues automatically with `make lint-fix` (or the scoped
|
||||||
|
`make lint-backend-fix` / `make lint-frontend-fix`). The combined consistency
|
||||||
|
checks that CI runs are available as `make checks`.
|
||||||
|
|
||||||
|
## Building and adding SVGs
|
||||||
|
|
||||||
|
SVG icons are built with `make svg`, which compiles the icon sources into
|
||||||
|
`public/assets/img/svg`. Custom icons can be added under `web_src/svg`.
|
||||||
|
|
||||||
|
## Updating the API
|
||||||
|
|
||||||
|
When you create or change API routes, you **must** update the
|
||||||
|
[Swagger](https://swagger.io/docs/specification/2-0/what-is-swagger/) documentation
|
||||||
|
using [go-swagger](https://goswagger.io/) comments. See the
|
||||||
|
[backend development guidelines](guidelines-backend.md) for how API routes,
|
||||||
|
request/response structs, and swagger definitions fit together.
|
||||||
|
|
||||||
|
Regenerate and validate the spec after changing an endpoint, then commit the
|
||||||
|
updated JSON:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make generate-swagger
|
||||||
|
make swagger-validate
|
||||||
|
```
|
||||||
|
|
||||||
|
CI verifies the committed spec is up to date with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make swagger-check
|
||||||
|
```
|
||||||
|
|
||||||
|
## Creating new configuration options
|
||||||
|
|
||||||
|
When adding configuration options it is not enough to add them to the
|
||||||
|
`modules/setting` files. Also update
|
||||||
|
[`custom/conf/app.example.ini`](../custom/conf/app.example.ini), and document them in
|
||||||
|
the [configuration cheat sheet](https://docs.gitea.com/administration/config-cheat-sheet),
|
||||||
|
which lives in the [documentation repository](https://gitea.com/gitea/docs).
|
||||||
|
|
||||||
|
## Database migrations
|
||||||
|
|
||||||
|
If you make breaking changes to a database-persisted struct under `models/`, add a
|
||||||
|
new migration in `models/migrations/`. See [testing.md](testing.md#migration-tests)
|
||||||
|
for running the migration tests.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
For unit, integration, end-to-end, and migration tests, see [testing.md](testing.md).
|
||||||
|
|
||||||
|
## IDE configuration
|
||||||
|
|
||||||
|
### Visual Studio Code
|
||||||
|
|
||||||
|
A `launch.json` and `tasks.json` are provided in
|
||||||
|
[`contrib/development/vscode`](../contrib/development/vscode). See
|
||||||
|
[`contrib/development/README.md`](../contrib/development/README.md) for details.
|
||||||
|
|
||||||
|
### GoLand
|
||||||
|
|
||||||
|
Clicking the `Run Application` arrow on `func main()` in `/main.go` starts a
|
||||||
|
debuggable Gitea instance.
|
||||||
|
|
||||||
|
The `Output Directory` in `Run/Debug Configuration` **must** be set to the Gitea
|
||||||
|
project directory (the one containing `main.go` and `go.mod`). Otherwise the working
|
||||||
|
directory is a GoLand temporary directory, which prevents Gitea from loading dynamic
|
||||||
|
resources (such as templates) in development.
|
||||||
|
|
||||||
|
## Submitting your changes
|
||||||
|
|
||||||
|
Push your branch and open a pull request. See [CONTRIBUTING.md](../CONTRIBUTING.md)
|
||||||
|
for the review process and PR requirements. For help, join the `#Develop` channel on
|
||||||
|
[Discord](https://discord.gg/gitea).
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
# 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))
|
|
||||||
|
|
||||||
### Knowledge
|
|
||||||
|
|
||||||
- Partially database table migration must use `SyncWithOptions(IgnoreDrop...)`
|
|
||||||
- Template variables with "camelCase" or "snake_case" are used for restoring the form values from a submitted form
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# 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)
|
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
# Backend development guidelines
|
||||||
|
|
||||||
|
This document covers backend-specific architecture and contribution expectations.
|
||||||
|
For the general workflow see [CONTRIBUTING.md](../CONTRIBUTING.md), and for building
|
||||||
|
and testing see [development.md](development.md) and [testing.md](testing.md).
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
The backend is written in Go. Web routing is handled by
|
||||||
|
[chi](https://github.com/go-chi/chi) and database access goes through the
|
||||||
|
[XORM](https://xorm.io/) ORM. Understanding how the packages depend on each other is
|
||||||
|
essential before contributing backend code.
|
||||||
|
|
||||||
|
## Package design
|
||||||
|
|
||||||
|
### Package layout
|
||||||
|
|
||||||
|
The backend is split into top-level packages, each with a focused responsibility:
|
||||||
|
|
||||||
|
- `build`: helper scripts used at compile time
|
||||||
|
- `cmd`: subcommands such as `web`, `serv`, `hooks`, `doctor`, and admin utilities
|
||||||
|
- `models`: data structures and database operations (XORM); keeps external
|
||||||
|
dependencies to a minimum
|
||||||
|
- `models/db`: core database operations
|
||||||
|
- `models/fixtures`: sample data used by tests
|
||||||
|
- `models/migrations`: schema migration scripts
|
||||||
|
- `modules`: standalone functionality with few dependencies
|
||||||
|
- `modules/setting`: configuration handling
|
||||||
|
- `modules/git`: interaction with the Git command line
|
||||||
|
- `routers`: request handlers, split into `api`, `web`, `install`, and `private`
|
||||||
|
- `services`: business logic that ties routers and models together
|
||||||
|
- `templates`: Go HTML templates
|
||||||
|
- `public`: compiled frontend assets
|
||||||
|
- `tests`: integration and end-to-end test helpers
|
||||||
|
|
||||||
|
### Dependency direction
|
||||||
|
|
||||||
|
Dependencies only flow in one direction:
|
||||||
|
|
||||||
|
```text
|
||||||
|
cmd → routers → services → models → modules
|
||||||
|
```
|
||||||
|
|
||||||
|
A package on the left may import a package on its right, but never the reverse.
|
||||||
|
|
||||||
|
### Naming conventions
|
||||||
|
|
||||||
|
- Top-level packages use the plural form: `services`, `models`, `routers`.
|
||||||
|
- Subpackages use the singular form: `services/user`, `models/repository`.
|
||||||
|
|
||||||
|
When packages from different layers share a name, use a snake_case import alias to
|
||||||
|
disambiguate:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import user_service "gitea.dev/services/user"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database transactions
|
||||||
|
|
||||||
|
Operations that must roll back together should run inside `db.WithTx()` (or
|
||||||
|
`db.WithTx2()` when a value must be returned), defined in `models/db/context.go`.
|
||||||
|
Functions that participate in a transaction take a `context.Context` as their first
|
||||||
|
parameter so the transaction can be propagated.
|
||||||
|
|
||||||
|
### XORM gotchas
|
||||||
|
|
||||||
|
- Never call `x.Update(exemplar)` without an explicit `WHERE` clause — it updates
|
||||||
|
every row in the table.
|
||||||
|
- Partial table migrations must use `SyncWithOptions(IgnoreDrop...)` rather than a
|
||||||
|
plain `Sync`.
|
||||||
|
- When inserting rows with preset IDs, MSSQL requires `SET IDENTITY_INSERT` to be
|
||||||
|
enabled and PostgreSQL requires the sequence to be updated afterwards.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
Go dependencies are managed with [Go Modules](https://go.dev/ref/mod).
|
||||||
|
|
||||||
|
Pull requests should only modify `go.mod` and `go.sum` where it relates to the
|
||||||
|
change at hand, be it a bug fix or a new feature. Otherwise, these files should only
|
||||||
|
be touched by pull requests whose sole purpose is updating dependencies. Run
|
||||||
|
`make tidy` after any change to `go.mod`.
|
||||||
|
|
||||||
|
Any `go.mod` / `go.sum` update must be justified in the PR description and must be
|
||||||
|
verified by reviewers and the merger to reference an existing upstream commit.
|
||||||
|
|
||||||
|
## API v1
|
||||||
|
|
||||||
|
The API is documented with [Swagger](https://gitea.com/api/swagger) and is modelled
|
||||||
|
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 where
|
||||||
|
possible, unless there is a good reason to deviate.
|
||||||
|
|
||||||
|
- If Gitea offers functionality GitHub does not, a new endpoint may be added.
|
||||||
|
- If Gitea exposes information the GitHub API does not, a new field may be added as
|
||||||
|
long as it does not collide with a GitHub field.
|
||||||
|
- Existing fields should not be removed unless there is a strong reason; the same
|
||||||
|
applies to status responses.
|
||||||
|
|
||||||
|
If you notice a problem that would require a breaking change, leave a comment in the
|
||||||
|
code for a future refactor to API v2 (which is currently not planned) rather than
|
||||||
|
breaking v1.
|
||||||
|
|
||||||
|
### Adding and maintaining API routes
|
||||||
|
|
||||||
|
- All possible results (errors, success, and failure messages) must be documented in
|
||||||
|
the swagger comments on the route.
|
||||||
|
- Every JSON request body must be defined as a struct in `modules/structs/` and
|
||||||
|
registered in [`routers/api/v1/swagger/options.go`](../routers/api/v1/swagger/options.go).
|
||||||
|
- Every JSON response must be defined as a struct in `modules/structs/` and
|
||||||
|
registered with its category under [`routers/api/v1/swagger/`](../routers/api/v1/swagger).
|
||||||
|
|
||||||
|
### HTTP methods and status codes
|
||||||
|
|
||||||
|
In general, choose HTTP methods as follows:
|
||||||
|
|
||||||
|
- **GET** returns the requested object(s) with status **200 OK**.
|
||||||
|
- **POST** creates a new object (e.g. a user) and returns **201 Created** with the
|
||||||
|
created object.
|
||||||
|
- **PUT** adds or assigns an existing object (e.g. a user to a team) and returns
|
||||||
|
**204 No Content** with no body.
|
||||||
|
- **PATCH** edits an existing object and returns the changed object with **200 OK**.
|
||||||
|
- **DELETE** removes an object and returns **204 No Content** with no body.
|
||||||
|
|
||||||
|
### Requirements for API routes
|
||||||
|
|
||||||
|
- All parameters of endpoints that edit an object must be optional, except those
|
||||||
|
needed to identify the object, which are required.
|
||||||
|
- Endpoints returning lists must support pagination (`page` and `limit` query
|
||||||
|
options) and set the `X-Total-Count` header via `ctx.SetTotalCountHeader(...)`.
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# Frontend development guidelines
|
||||||
|
|
||||||
|
This document covers frontend-specific architecture and contribution expectations.
|
||||||
|
For the general workflow see [CONTRIBUTING.md](../CONTRIBUTING.md), and for building
|
||||||
|
and testing see [development.md](development.md) and [testing.md](testing.md).
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
The frontend uses [Vue 3](https://vuejs.org/), [Fomantic-UI](https://fomantic-ui.com/) (built on jQuery)
|
||||||
|
and [Tailwind CSS](https://tailwindcss.com/). Pages are rendered with Go HTML templates.
|
||||||
|
Source files live in:
|
||||||
|
|
||||||
|
- `web_src/css/`: CSS styles
|
||||||
|
- `web_src/js/`: JavaScript and TypeScript
|
||||||
|
- `web_src/js/components/`: Vue components
|
||||||
|
- `web_src/js/features/`: feature modules wired up at page load
|
||||||
|
- `templates/`: Go HTML templates
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
Frontend dependencies are managed with [pnpm](https://pnpm.io/). The same rules as
|
||||||
|
for [backend dependencies](guidelines-backend.md#dependencies) apply, except the
|
||||||
|
relevant files are `package.json` and `pnpm-lock.yaml`, and new versions must always
|
||||||
|
reference an existing published version.
|
||||||
|
|
||||||
|
## Framework usage
|
||||||
|
|
||||||
|
Mixing frameworks arbitrarily makes code hard to maintain. Recommended combinations:
|
||||||
|
|
||||||
|
- Vue3
|
||||||
|
- Vanilla JavaScript
|
||||||
|
- Fomantic-UI (jQuery), deprecated, we vendored a specific version with a lot of changes.
|
||||||
|
|
||||||
|
Avoid combinations such as Vue with Fomantic-UI.
|
||||||
|
Vue components may reuse Fomantic-UI CSS classes for visual consistency.
|
||||||
|
Use Go templates for simple or SEO-relevant pages and Vue for complex, interactive pages.
|
||||||
|
Gitea uses Vue 3 **without** JSX to keep HTML and JavaScript separate.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Fomantic-UI is not an accessibility-friendly framework. Gitea patches some ARIA
|
||||||
|
> behavior, but accessibility work is ongoing — prefer semantic HTML and test
|
||||||
|
> keyboard/screen-reader behavior where you can.
|
||||||
|
|
||||||
|
## Gitea-specific conventions
|
||||||
|
|
||||||
|
- Keep features in their own files or directories.
|
||||||
|
- Use kebab-case for HTML `id`s and classes, ideally with 2-3 feature keywords.
|
||||||
|
- Prefix classes to avoid short-name conflicts between different frameworks.
|
||||||
|
- Create a new class name when overriding framework styles instead of editing the framework's own classes,
|
||||||
|
or fix the framework's source to fix all cases.
|
||||||
|
- Prefer semantic elements such as `<button>` over generic `<div>`s.
|
||||||
|
- Avoid `!important`; when it is unavoidable, document why.
|
||||||
|
- Prefix custom DOM events with `ce-`.
|
||||||
|
|
||||||
|
## CSS
|
||||||
|
|
||||||
|
Prefer Tailwind utility classes with the `tw-` prefix, and the `flex-*` layout
|
||||||
|
helpers over per-child margins. Gitea also ships a small set of custom helpers:
|
||||||
|
`gt-` for general helpers and `g-` for framework-level helpers (see
|
||||||
|
`web_src/css/helpers.css`); use these only when a Tailwind utility does not exist.
|
||||||
|
|
||||||
|
Write class attributes as a single readable unit in templates:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div class="flex-text-inline {{if .IsFoo}}tw-hidden{{end}}"></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
## TypeScript
|
||||||
|
|
||||||
|
- Use `import type` for type-only imports.
|
||||||
|
- Prefer `@ts-expect-error` over `@ts-ignore`.
|
||||||
|
- Use the `!` non-null assertion (rather than `?.`/`??`) when a value is known to always exist.
|
||||||
|
- Only mark a function `async` when it actually uses `await` or returns a `Promise`.
|
||||||
|
Avoid async event listeners; if unavoidable, call `e.preventDefault()` before the
|
||||||
|
first `await`. For a deliberately un-awaited call, assign it: `const _promise = asyncFoo()`.
|
||||||
|
|
||||||
|
## Data fetching
|
||||||
|
|
||||||
|
Use the `GET`, `POST`, `PUT`, `PATCH`, and `DELETE` wrappers from
|
||||||
|
[`web_src/js/modules/fetch.ts`](../web_src/js/modules/fetch.ts).
|
||||||
|
|
||||||
|
## DOM attributes
|
||||||
|
|
||||||
|
Avoid `node.dataset` because of its camel-casing behavior; use `node.getAttribute`
|
||||||
|
in new code. Never bind user-provided data directly onto DOM nodes.
|
||||||
|
|
||||||
|
## Showing and hiding elements
|
||||||
|
|
||||||
|
- In Vue, use `v-if` and `v-show`.
|
||||||
|
- In Go templates and plain JavaScript, use the `.tw-hidden` class together with the
|
||||||
|
`showElem()`, `hideElem()`, and `toggleElem()` helpers from
|
||||||
|
[`web_src/js/utils/dom.ts`](../web_src/js/utils/dom.ts).
|
||||||
|
|
||||||
|
## UI component gallery
|
||||||
|
|
||||||
|
When running Gitea in development mode, standardized UI components are available at
|
||||||
|
`/devtest` (for example `http://localhost:3000/devtest`). These pages are also used
|
||||||
|
by the e2e tests.
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Refactoring guidelines
|
||||||
|
|
||||||
|
This document covers expectations for refactoring work. For the general workflow see
|
||||||
|
[CONTRIBUTING.md](../CONTRIBUTING.md).
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
Gitea is a large, long-lived project. Over time the codebase has accumulated
|
||||||
|
outdated mechanisms, mixed frameworks, and legacy code that can cause bugs or slow
|
||||||
|
down new features. Refactoring keeps the codebase maintainable, but it needs to be
|
||||||
|
done carefully so it improves things without introducing regressions.
|
||||||
|
|
||||||
|
## Writing a refactoring PR
|
||||||
|
|
||||||
|
- Be forward-looking: address the root cause, not just the immediate symptom.
|
||||||
|
- Aim to reduce ambiguity and conflicts and to improve maintainability.
|
||||||
|
- Explain the rationale in the PR description: why the refactor is necessary, how it
|
||||||
|
resolves the legacy problem, and its advantages and disadvantages.
|
||||||
|
- Keep the scope tight: preserve existing behavior where feasible and avoid bundling
|
||||||
|
unrelated changes.
|
||||||
|
- Break large refactors into intermediate steps across multiple PRs so each one is
|
||||||
|
easy to review.
|
||||||
|
- Include tests that verify the behavior stays correct.
|
||||||
|
- Prefer scheduling non-bugfix refactoring early in a milestone, so any issues
|
||||||
|
surface well before a release.
|
||||||
|
- If there is disagreement about a refactor, escalate to the Technical Oversight
|
||||||
|
Committee (TOC) for a decision.
|
||||||
|
|
||||||
|
## Reviewing and merging
|
||||||
|
|
||||||
|
- Keep refactoring PRs short-lived (typically no more than 7 days) with quick review
|
||||||
|
cycles, and merge them promptly so they do not block on unrelated work.
|
||||||
|
- A non-author core member may approve and merge a refactoring PR after 7 days if the
|
||||||
|
TOC has raised no objection.
|
||||||
|
- Accept imperfect intermediate implementations as long as the final result improves
|
||||||
|
the codebase.
|
||||||
|
- A temporary regression caused by a necessary refactor is acceptable if it is fixed
|
||||||
|
promptly afterwards.
|
||||||
+151
@@ -0,0 +1,151 @@
|
|||||||
|
# Testing
|
||||||
|
|
||||||
|
Gitea has four kinds of automated tests: backend unit tests, integration tests,
|
||||||
|
end-to-end (e2e) tests, and migration tests. Local runs default to SQLite, so no
|
||||||
|
extra services are required to get started.
|
||||||
|
|
||||||
|
For prerequisites see [build-setup.md](build-setup.md); for the build workflow see
|
||||||
|
[development.md](development.md).
|
||||||
|
|
||||||
|
## Unit tests
|
||||||
|
|
||||||
|
Backend unit tests live in `*_test.go` files next to the code they cover. Set
|
||||||
|
`GITEA_TEST_LOG_SQL=1` to log all SQL statements executed during the tests.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test-backend
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a single backend test, use `go test` directly or the `#` selector:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go test -run '^TestName$' ./modulepath/
|
||||||
|
make test-backend#TestName
|
||||||
|
```
|
||||||
|
|
||||||
|
Frontend unit tests run with [Vitest](https://vitest.dev/):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test-frontend
|
||||||
|
# single file:
|
||||||
|
pnpm exec vitest <path-filter>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Integration tests
|
||||||
|
|
||||||
|
Integration tests exercise Gitea against a real database. They live in
|
||||||
|
`tests/integration/` and require [Git LFS](https://git-lfs.com/) to be installed.
|
||||||
|
The database is selected with `GITEA_TEST_DATABASE`; an empty value defaults to
|
||||||
|
SQLite, which needs no external service:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test-integration
|
||||||
|
```
|
||||||
|
|
||||||
|
Run a single integration test with the `#` selector:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test-integration#TestName
|
||||||
|
```
|
||||||
|
|
||||||
|
If you hit errors such as a mismatched database version or SSH push failures, try a
|
||||||
|
clean rebuild first:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make clean build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running against other databases
|
||||||
|
|
||||||
|
Set `GITEA_TEST_DATABASE` together with the matching `TEST_*` connection variables.
|
||||||
|
The commands below start a throwaway database container (press `Ctrl-C` to stop and
|
||||||
|
remove it) and then run the tests against it.
|
||||||
|
|
||||||
|
#### MySQL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -e "MYSQL_DATABASE=test" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" -p 3306:3306 --rm --name mysql mysql:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GITEA_TEST_DATABASE=mysql TEST_MYSQL_HOST=localhost:3306 TEST_MYSQL_DBNAME=test TEST_MYSQL_USERNAME=root TEST_MYSQL_PASSWORD='' make test-integration
|
||||||
|
```
|
||||||
|
|
||||||
|
#### PostgreSQL
|
||||||
|
|
||||||
|
PostgreSQL tests also use a MinIO container for object storage:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -e "POSTGRES_DB=test" -e "POSTGRES_USER=postgres" -e "POSTGRES_PASSWORD=postgres" -p 5432:5432 --rm --name pgsql postgres:latest
|
||||||
|
docker run --rm -p 9000:9000 -e MINIO_ROOT_USER=123456 -e MINIO_ROOT_PASSWORD=12345678 --name minio bitnamilegacy/minio:2023.8.31
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GITEA_TEST_DATABASE=pgsql TEST_MINIO_ENDPOINT=localhost:9000 TEST_PGSQL_HOST=localhost:5432 TEST_PGSQL_DBNAME=postgres TEST_PGSQL_USERNAME=postgres TEST_PGSQL_PASSWORD=postgres make test-integration
|
||||||
|
```
|
||||||
|
|
||||||
|
#### MSSQL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_PID=Standard" -e "SA_PASSWORD=MwantsaSecurePassword1" -p 1433:1433 --rm --name mssql microsoft/mssql-server-linux:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GITEA_TEST_DATABASE=mssql TEST_MSSQL_HOST=localhost:1433 TEST_MSSQL_DBNAME=gitea_test TEST_MSSQL_USERNAME=sa TEST_MSSQL_PASSWORD=MwantsaSecurePassword1 make test-integration
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running the database test workflow with Gitea Runner
|
||||||
|
|
||||||
|
The CI database test jobs can be run locally with
|
||||||
|
[Gitea Runner](https://gitea.com/gitea/runner). Running every job is
|
||||||
|
resource-intensive and not recommended:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gitea-runner exec -W ./.github/workflows/pull-db-tests.yml --event=pull_request --default-actions-url="https://github.com" -i catthehacker/ubuntu:runner-latest
|
||||||
|
```
|
||||||
|
|
||||||
|
List the available job names, then run a single one:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gitea-runner exec -W ./.github/workflows/pull-db-tests.yml --event=pull_request --default-actions-url="https://github.com" -i catthehacker/ubuntu:runner-latest -l
|
||||||
|
gitea-runner exec -W ./.github/workflows/pull-db-tests.yml --event=pull_request --default-actions-url="https://github.com" -i catthehacker/ubuntu:runner-latest -j <job_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
## End-to-end tests
|
||||||
|
|
||||||
|
End-to-end tests drive a running Gitea instance with [Playwright](https://playwright.dev/):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test-e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a single e2e test file, pass it via `GITEA_TEST_E2E_FLAGS`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GITEA_TEST_E2E_FLAGS='<filepath>' make test-e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
Useful environment variables:
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| :--- | :--- |
|
||||||
|
| `GITEA_TEST_E2E_DEBUG` | When set, show the Gitea server output. |
|
||||||
|
| `GITEA_TEST_E2E_FLAGS` | Additional flags passed to Playwright, e.g. `--ui`. |
|
||||||
|
| `GITEA_TEST_E2E_TIMEOUT_FACTOR` | Timeout multiplier (default: 4 on CI, 1 locally). |
|
||||||
|
|
||||||
|
## Migration tests
|
||||||
|
|
||||||
|
If you change a database-persisted struct under `models/` you will usually need a
|
||||||
|
new migration in `models/migrations/`. Run the migration tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test-migration
|
||||||
|
```
|
||||||
|
|
||||||
|
## Continuous integration
|
||||||
|
|
||||||
|
CI runs the unit tests, runs the integration tests against every supported database,
|
||||||
|
and tests migration from several recent Gitea versions. Please submit your pull
|
||||||
|
request with additional unit and integration tests as appropriate. Prefer unit tests
|
||||||
|
when the logic can be tested in isolation, and keep local integration and e2e tests
|
||||||
|
fast (aim for sub-2s runtime).
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
# Integration tests
|
|
||||||
|
|
||||||
Integration tests can be run with command `make test-integration`.
|
|
||||||
Environment variable `GITEA_TEST_DATABASE` can be used to specify the database type for testing.
|
|
||||||
|
|
||||||
If you encounter some errors like mismatched database version, SSH push errors, etc.,
|
|
||||||
you can try to perform a clean build by: `make clean build`.
|
|
||||||
|
|
||||||
## Run sqlite integration tests
|
|
||||||
|
|
||||||
Start tests directly (empty `GITEA_TEST_DATABASE` defaults to sqlite):
|
|
||||||
|
|
||||||
```
|
|
||||||
make test-integration
|
|
||||||
```
|
|
||||||
|
|
||||||
## Run MySQL integration tests
|
|
||||||
|
|
||||||
Set up a MySQL database inside docker:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run -e "MYSQL_DATABASE=test" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" -p 3306:3306 --rm --name mysql mysql:latest #(just ctrl-c to stop db and clean the container)
|
|
||||||
docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --rm --name elasticsearch elasticsearch:7.6.0 #(in a second terminal, just ctrl-c to stop db and clean the container)
|
|
||||||
```
|
|
||||||
|
|
||||||
Start tests based on the database container:
|
|
||||||
|
|
||||||
```
|
|
||||||
GITEA_TEST_DATABASE=mysql TEST_MYSQL_HOST=localhost:3306 TEST_MYSQL_DBNAME=test TEST_MYSQL_USERNAME=root TEST_MYSQL_PASSWORD='' make test-integration
|
|
||||||
```
|
|
||||||
|
|
||||||
## Run pgsql integration tests
|
|
||||||
|
|
||||||
Set up a pgsql database inside docker:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run -e "POSTGRES_DB=test" -e "POSTGRES_USER=postgres" -e "POSTGRES_PASSWORD=postgres" -p 5432:5432 --rm --name pgsql postgres:latest #(just ctrl-c to stop db and clean the container)
|
|
||||||
```
|
|
||||||
|
|
||||||
Set up minio inside docker:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run --rm -p 9000:9000 -e MINIO_ROOT_USER=123456 -e MINIO_ROOT_PASSWORD=12345678 --name minio bitnamilegacy/minio:2023.8.31
|
|
||||||
```
|
|
||||||
|
|
||||||
Start tests based on the database container:
|
|
||||||
|
|
||||||
```
|
|
||||||
GITEA_TEST_DATABASE=pgsql TEST_MINIO_ENDPOINT=localhost:9000 TEST_PGSQL_HOST=localhost:5432 TEST_PGSQL_DBNAME=postgres TEST_PGSQL_USERNAME=postgres TEST_PGSQL_PASSWORD=postgres make test-integration
|
|
||||||
```
|
|
||||||
|
|
||||||
## Run mssql integration tests
|
|
||||||
|
|
||||||
Set up a mssql database inside docker:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_PID=Standard" -e "SA_PASSWORD=MwantsaSecurePassword1" -p 1433:1433 --rm --name mssql microsoft/mssql-server-linux:latest #(just ctrl-c to stop db and clean the container)
|
|
||||||
```
|
|
||||||
|
|
||||||
Start tests based on the database container:
|
|
||||||
|
|
||||||
```
|
|
||||||
GITEA_TEST_DATABASE=mssql TEST_MSSQL_HOST=localhost:1433 TEST_MSSQL_DBNAME=gitea_test TEST_MSSQL_USERNAME=sa TEST_MSSQL_PASSWORD=MwantsaSecurePassword1 make test-integration
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running individual tests
|
|
||||||
|
|
||||||
Example command to run GPG test:
|
|
||||||
|
|
||||||
```
|
|
||||||
GITEA_TEST_DATABASE=... make test-integration#GPG
|
|
||||||
```
|
|
||||||
|
|
||||||
## Run Gitea Actions tests via local act_runner
|
|
||||||
|
|
||||||
### Run all jobs
|
|
||||||
|
|
||||||
```
|
|
||||||
act_runner exec -W ./.github/workflows/pull-db-tests.yml --event=pull_request --default-actions-url="https://github.com" -i catthehacker/ubuntu:runner-latest
|
|
||||||
```
|
|
||||||
|
|
||||||
Warning: This file defines many jobs, so it will be resource-intensive and therefore not recommended.
|
|
||||||
|
|
||||||
### Run single job
|
|
||||||
|
|
||||||
```SHELL
|
|
||||||
act_runner exec -W ./.github/workflows/pull-db-tests.yml --event=pull_request --default-actions-url="https://github.com" -i catthehacker/ubuntu:runner-latest -j <job_name>
|
|
||||||
```
|
|
||||||
|
|
||||||
You can list all job names via:
|
|
||||||
|
|
||||||
```SHELL
|
|
||||||
act_runner exec -W ./.github/workflows/pull-db-tests.yml --event=pull_request --default-actions-url="https://github.com" -i catthehacker/ubuntu:runner-latest -l
|
|
||||||
```
|
|
||||||
@@ -50,14 +50,8 @@ func TestAPIUpdateOrgAvatar(t *testing.T) {
|
|||||||
MakeRequest(t, req, http.StatusBadRequest)
|
MakeRequest(t, req, http.StatusBadRequest)
|
||||||
|
|
||||||
// Test what happens if you use a file that is not an image
|
// Test what happens if you use a file that is not an image
|
||||||
text, err := os.ReadFile(filepath.Join(setting.GetGiteaTestSourceRoot(), "tests/integration/README.md"))
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if err != nil {
|
|
||||||
assert.FailNow(t, "Unable to open README.md")
|
|
||||||
}
|
|
||||||
|
|
||||||
opts = api.UpdateUserAvatarOption{
|
opts = api.UpdateUserAvatarOption{
|
||||||
Image: base64.StdEncoding.EncodeToString(text),
|
Image: base64.StdEncoding.EncodeToString([]byte("This is not an image")),
|
||||||
}
|
}
|
||||||
|
|
||||||
req = NewRequestWithJSON(t, "POST", "/api/v1/orgs/org3/avatar", &opts).
|
req = NewRequestWithJSON(t, "POST", "/api/v1/orgs/org3/avatar", &opts).
|
||||||
|
|||||||
@@ -54,14 +54,8 @@ func TestAPIUpdateRepoAvatar(t *testing.T) {
|
|||||||
MakeRequest(t, req, http.StatusBadRequest)
|
MakeRequest(t, req, http.StatusBadRequest)
|
||||||
|
|
||||||
// Test what happens if you use a file that is not an image
|
// Test what happens if you use a file that is not an image
|
||||||
text, err := os.ReadFile(filepath.Join(setting.GetGiteaTestSourceRoot(), "tests/integration/README.md"))
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if err != nil {
|
|
||||||
assert.FailNow(t, "Unable to open README.md")
|
|
||||||
}
|
|
||||||
|
|
||||||
opts = api.UpdateRepoAvatarOption{
|
opts = api.UpdateRepoAvatarOption{
|
||||||
Image: base64.StdEncoding.EncodeToString(text),
|
Image: base64.StdEncoding.EncodeToString([]byte("This is not an image")),
|
||||||
}
|
}
|
||||||
|
|
||||||
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/avatar", repo.OwnerName, repo.Name), &opts).
|
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/avatar", repo.OwnerName, repo.Name), &opts).
|
||||||
|
|||||||
@@ -50,14 +50,8 @@ func TestAPIUpdateUserAvatar(t *testing.T) {
|
|||||||
MakeRequest(t, req, http.StatusBadRequest)
|
MakeRequest(t, req, http.StatusBadRequest)
|
||||||
|
|
||||||
// Test what happens if you use a file that is not an image
|
// Test what happens if you use a file that is not an image
|
||||||
text, err := os.ReadFile(filepath.Join(setting.GetGiteaTestSourceRoot(), "tests/integration/README.md"))
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if err != nil {
|
|
||||||
assert.FailNow(t, "Unable to open README.md")
|
|
||||||
}
|
|
||||||
|
|
||||||
opts = api.UpdateUserAvatarOption{
|
opts = api.UpdateUserAvatarOption{
|
||||||
Image: base64.StdEncoding.EncodeToString(text),
|
Image: base64.StdEncoding.EncodeToString([]byte("This is not an image")),
|
||||||
}
|
}
|
||||||
|
|
||||||
req = NewRequestWithJSON(t, "POST", "/api/v1/user/avatar", &opts).
|
req = NewRequestWithJSON(t, "POST", "/api/v1/user/avatar", &opts).
|
||||||
|
|||||||
Reference in New Issue
Block a user