diff --git a/Taskfile.yml b/Taskfile.yml index 63d2db404..cc75065fb 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -94,3 +94,8 @@ tasks: desc: Run all linters cmds: - golangci-lint run + + docs: + desc: Start docs server + cmds: + - cd docs && mint dev --port 3333 diff --git a/docs-old/admin/lfs.md b/docs-old/admin/lfs.md deleted file mode 100644 index 143552ecb..000000000 --- a/docs-old/admin/lfs.md +++ /dev/null @@ -1,21 +0,0 @@ -# Configuring Git Large File Storage (LFS) - -> NOTE: Git LFS is supported in Gogs starting with version 0.12. - -Git LFS works out of box with default configuration for any supported versions. - -## Known limitations - -- Only local storage is supported (i.e. all LFS objects are stored on the same server where Gogs runs), support of Object Storage Service like Amazon S3 is being tracked in [#6065](https://github.com/gogs/gogs/issues/6065). - -## Configuration - -All configuration options for Git LFS are located in [`[lfs]` section](https://github.com/gogs/gogs/blob/44ea9604ed7440c2cf1105d965c2429ee225e8f6/conf/app.ini#L266-L270): - -```ini -[lfs] -; The storage backend for uploading new objects. -STORAGE = local -; The root path to store LFS objects on local file system. -OBJECTS_PATH = data/lfs-objects -``` diff --git a/docs-old/admin/release_strategy.md b/docs-old/admin/release_strategy.md deleted file mode 100644 index ba7e8174c..000000000 --- a/docs-old/admin/release_strategy.md +++ /dev/null @@ -1,33 +0,0 @@ -# Release strategy - -## Semantic versioning - -Starting 0.12.0, Gogs uses [semantic versioning](https://semver.org/) for publishing releases. For example: - -- `0.12.0` is a minor version release. -- `0.12.1` is the first patch release of `0.12`. -- `0.12` indicates a series of releases for a minor version and its patch releases. - -Each minor release has its own release branch with prefix `release/`, e.g. `release/0.12` is the release branch for minor version 0.12.0 and all its patch releases (`0.12.1`, `0.12.2`, etc.). - -## Backwards compatibility - -### Before 0.12 - -If you're running Gogs with any version below 0.12, please upgrade to 0.12 to run necessary migrations. - -### Since 0.12 - -We maintain one minor version backwards compatibility, patch releases are disregarded. - -For example, you should: - -- Upgrade from `0.12.0` to `0.13.0`. -- Upgrade from `0.12.1` to `0.13.4`. -- NOT upgrade from `0.12.4` to `0.14.0`. - -Therefore, we recommend upgrade one minor version at a time. - -### Running source builds - -If you're running Gogs with building from source code, we recommend you update at least weekly to be not fall behind and potentially miss migrations. diff --git a/docs-old/user/lfs.md b/docs-old/user/lfs.md deleted file mode 100644 index f89730b67..000000000 --- a/docs-old/user/lfs.md +++ /dev/null @@ -1,28 +0,0 @@ -# Git Large File Storage (LFS) - -> This document is driven from https://docs.gitlab.com/ee/topics/git/lfs/. - -Managing large binaries in Git repositories is challenging, that is why Git LFS was developed for, to manage large files. - -## How it works - -Git LFS client talks with the Gogs server over HTTP/HTTPS. It uses HTTP Basic Authentication to authorize client requests. Once the request is authorized, Git LFS client receives instructions from where to fetch or where to push the large file. - -## Server configuration - -Please refer to [Configuring Git Large File Storage (LFS)](../admin/lfs.md). - -## Requirements - -- Git LFS is supported in Gogs starting with version 0.12. -- [Git LFS client](https://git-lfs.github.com/) version 1.0.1 and up. - -## Known limitations - -- When SSH is set as a remote, Git LFS objects still go through HTTP/HTTPS. -- Any Git LFS request will ask for HTTP/HTTPS credentials to be provided so a good Git credentials store is recommended. -- File locking is not supported, and is being tracked in [#6064](https://github.com/gogs/gogs/issues/6064). - -## Using Git LFS - -Git LFS endpoints in a Gogs server can be automatically discovered by the Git LFS client, therefore you do not need to configure anything upfront for using it. Please walk through official [Git LFS Tutorial](https://github.com/git-lfs/git-lfs/wiki/Tutorial) to get started. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..65cff2638 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,26 @@ +## Development + +Install the [Mintlify CLI](https://www.npmjs.com/package/mint) to preview your documentation changes locally. To install, use the following command: + +``` +pnpm i -g mint +``` + +Run the following command at the root of your documentation, where your `docs.json` is located: + +``` +mint dev +``` + +View your local preview at `http://localhost:3000`. + +## Need help? + +### Troubleshooting + +- If your dev environment isn't running: Run `mint update` to ensure you have the most recent version of the CLI. +- If a page loads as a 404: Make sure you are running in a folder with a valid `docs.json`. + +### Resources + +- [Mintlify documentation](https://mintlify.com/docs) diff --git a/docs/advancing/authentication.mdx b/docs/advancing/authentication.mdx new file mode 100644 index 000000000..a53d17cdf --- /dev/null +++ b/docs/advancing/authentication.mdx @@ -0,0 +1,270 @@ +--- +title: "Authentication" +description: "Integrate with your existing IAM system" +icon: "key" +--- + +Gogs supports authentication through various external sources. Currently supported backends are **LDAP**, **SMTP**, **PAM**, and **HTTP header**. Authentication sources can be configured in two ways: + +- **Admin Panel**: Navigate to **Admin Panel > Authentication Sources** +- **Configuration files**: Place `.conf` files in the `custom/conf/auth.d/` directory. Each file describes one source using INI format. Files are loaded once at startup and keyed by `id`. See the "Configuration file" subsection under each backend below for examples. + +## LDAP + +Gogs supports two variants of LDAP authentication: **Simple Auth** and **Bind DN**. In both cases, authentication is performed by attempting to bind to the LDAP server with the User DN and password. The difference is that with Bind DN, a preliminary query is performed (using the Bind DN credentials) to find the User DN first. + + + + The Bind DN mechanism has these advantages: + + - It may be more secure than blindly attempting to bind with a possibly non-existent User DN. + - It supports login with attributes such as email address or phone number. The preliminary search can look up the User DN using `mail` or `mobile` attributes. + - It is required when the LDAP does not allow the User DN to query its own attributes or group memberships. + + The downside is that, unless the LDAP allows anonymous queries, it requires a bind DN to be defined and Gogs needs to store its credentials. Gogs currently does not encrypt these credentials. + + + In the ideal situation where you know the exact DN template for your users and the LDAP allows the User DN to query its own attributes, Simple Auth is the simpler option. It requires no separate bind account and no stored credentials beyond what the user provides at login. + + + +### Shared fields + +The following fields are shared between both **Bind DN** and **Simple Auth** configurations: + +| Field | Required | Description | Example | +|---|---|---|---| +| **Authentication Name** | Yes | A friendly name for the authentication source. | `My LDAP` | +| **Security Protocol** | Yes | Connection security: Unencrypted, LDAPS, or StartTLS. | `LDAPS` | +| **Host** | Yes | The address of the LDAP server. | `ldap.mydomain.com` | +| **Port** | Yes | The port for the LDAP connection. Usually `389` for LDAP/StartTLS, `636` for LDAPS. | `389` | +| **User Filter** | Yes | An LDAP filter declaring which users can log in. The `%s` parameter is substituted with the login name. | `(&(objectClass=posixAccount)(uid=%s))` | +| **Email Attribute** | Yes | The LDAP attribute containing the user's email address. | `mail` | +| **Admin Filter** | No | An LDAP filter applied to the User DN context to determine Gogs administrator privileges. | `(memberOf=cn=admins,cn=groups,dc=mydomain,dc=com)` | +| **Username Attribute** | No | The LDAP attribute containing the username. Used for the Gogs account name after first sign-in. Leave empty to use the login name from the sign-in form. | `uid` | +| **First Name Attribute** | No | The LDAP attribute containing the user's first name. | `givenName` | +| **Surname Attribute** | No | The LDAP attribute containing the user's last name. | `sn` | + + + The **User Filter** field can be used to filter on group membership if the User DN object has `memberOf` attributes. For example: + ``` + (&(objectClass=posixAccount)(uid=%s)(memberOf=cn=gogs_users,cn=groups,dc=mydomain,dc=com)) + ``` + In the Bind DN authenticator, the User Filter can also match against multiple user attributes: + ``` + (&(objectClass=Person)(|(uid=%s)(mail=%s)(mobile=%s))) + ``` + + +### Simple Auth fields + +LDAP via Simple Auth adds the following field: + +| Field | Required | Description | Example | +|---|---|---|---| +| **User DN** | Yes | A template for the user's DN. The `%s` parameter is substituted with the login name. | `cn=%s,ou=Users,dc=mydomain,dc=com` or `uid=%s,ou=Users,dc=mydomain,dc=com` | + +### Bind DN fields + +LDAP via Bind DN adds the following fields: + +| Field | Required | Description | Example | +|---|---|---|---| +| **Bind DN** | No | The DN used to bind to the LDAP server when searching for the user. Leave blank for anonymous search. | `cn=Search,dc=mydomain,dc=com` | +| **Bind Password** | No | The password for the Bind DN specified above. | -- | +| **User Search Base** | Yes | The LDAP base below which user accounts will be searched. | `ou=Users,dc=mydomain,dc=com` | +| **Fetch Attributes in Bind DN Context** | No | When enabled, user attributes are retrieved while bound as the Bind DN instead of the User DN. | -- | + + + The Bind Password is stored in plaintext on the server. Ensure that your Bind DN has the minimum privileges necessary. + + +### Group membership verification + +You can optionally verify LDAP group membership using the following fields: + +| Field | Required | Description | Example | +|---|---|---|---| +| **Group Search Base DN** | No | The LDAP base below which groups will be searched. | `ou=group,dc=mydomain,dc=com` | +| **Group Filter** | No | An LDAP filter declaring the groups that grant access. | `(\|(cn=gogs_users)(cn=admins))` | +| **Group Attribute Containing List of Users** | No | The multi-valued attribute containing the group's members. | `memberUid` or `member` | +| **User Attribute Listed in Group** | No | The user attribute referenced in the group membership attributes. | `uid` or `dn` | + +### Configuration files + +LDAP sources can also be defined as `.conf` files in `custom/conf/auth.d/` instead of through the admin panel. Files are loaded at startup and keyed by `id`. + + + + ```ini + id = 101 + type = ldap_bind_dn + name = LDAP BindDN + is_activated = true + + [config] + host = mydomain.com + port = 636 + # 0 - Unencrypted, 1 - LDAPS, 2 - StartTLS + security_protocol = 0 + skip_verify = false + bind_dn = + bind_password = + user_base = ou=Users,dc=mydomain,dc=com + attribute_username = + attribute_name = + attribute_surname = + attribute_mail = mail + attributes_in_bind = false + filter = (&(objectClass=posixAccount)(cn=%s)) + admin_filter = + group_enabled = false + group_dn = + group_filter = + group_member_uid = + user_uid = + ``` + + + ```ini + id = 102 + type = ldap_simple_auth + name = LDAP Simple Auth + is_activated = true + + [config] + host = mydomain.com + port = 636 + # 0 - Unencrypted, 1 - LDAPS, 2 - StartTLS + security_protocol = 0 + skip_verify = false + bind_dn = + bind_password = + user_base = + user_dn = cn=%s,ou=Users,dc=mydomain,dc=com + attribute_username = + attribute_name = + attribute_surname = + attribute_mail = mail + attributes_in_bind = false + filter = (&(objectClass=posixAccount)(cn=%s)) + admin_filter = + group_enabled = false + group_dn = + group_filter = + group_member_uid = + user_uid = + ``` + + + +### FreeIPA examples + +It is possible to use either Bind DN or Simple Auth with FreeIPA. The examples below assume your domain is `domain.com` and that users must be a member of the `gogs_users` group to get access. + + + + Setting up access using Simple Auth is straightforward: + + ```ini + user_dn = uid=%s,cn=users,cn=accounts,dc=domain,dc=com + filter = (&(objectClass=posixAccount)(memberOf=cn=gogs_users,cn=groups,cn=accounts,dc=domain,dc=com)) + attribute_username = uid + attribute_name = givenName + attribute_surname = sn + attribute_mail = mail + admin_filter = (memberOf=cn=admins,cn=groups,cn=accounts,dc=domain,dc=com) + group_enabled = false + ``` + + + If you want to allow login by email address, note that FreeIPA by default does not grant anonymous search access to the `mail` attribute. This can be changed in IPA: + + ```bash + ipa permission-mod --includedattrs=mail 'System: Read User Standard Attributes' + ``` + + Alternatively, you can ask your LDAP administrators for a dedicated bind user account. + + + Allowing email-based login via Bind DN may no longer be necessary. Gogs translates email logins to the corresponding user ID before making the authentication call to the backend LDAP. The only requirement is that the user's **first login** is with their user ID. After that, they can use either user ID or email address. + + + More precisely, Gogs maps the login name onto the user's "Authentication Login Name", which administrators can edit on the user's **Edit Account** page. + + + +## PAM + +To configure PAM authentication, set the **PAM Service Name** to a filename in `/etc/pam.d/`. + + + If you want PAM authentication to work with normal Linux passwords, the user running Gogs must have read access to `/etc/shadow`. + + +### Configuration file + +```ini +id = 104 +type = pam +name = System Auth +is_activated = true + +[config] +service_name = system-auth +``` + +## SMTP + +SMTP authentication allows Gogs to log in to your SMTP host to verify user credentials. Configure the following fields: + +| Field | Required | Description | Example | +|---|---|---|---| +| **Authentication Name** | Yes | A name for this authentication source. | `Company SMTP` | +| **SMTP Authentication Type** | Yes | The authentication type: `PLAIN` or `LOGIN`. | `PLAIN` | +| **Host** | Yes | The address of the SMTP server. | `smtp.mydomain.com` | +| **Port** | Yes | The port for the SMTP connection. | `587` | +| **Allowed Domains** | No | Restrict login to specific email domains. Separate multiple domains with commas. | `gogs.io,mydomain.com` | +| **Enable TLS Encryption** | No | Enable TLS encryption for the authentication connection. | -- | +| **Skip TLS Verify** | No | Disable TLS certificate verification. | -- | +| **This Authentication is Activated** | No | Enable or disable this authentication method. | -- | + +### Configuration file + +```ini +id = 103 +type = smtp +name = GMail +is_activated = true + +[config] +# Either "PLAIN" or "LOGIN" +auth = PLAIN +host = smtp.gmail.com +port = 587 +allowed_domains = +tls = true +skip_verify = false +``` + +## HTTP header + +If your reverse proxy already handles user authentication (e.g. via SSO, OAuth, or client certificates), Gogs can trust the authenticated username from an HTTP header. This is configured in `custom/conf/app.ini` under `[auth]`: + +```ini +[auth] +ENABLE_REVERSE_PROXY_AUTHENTICATION = true +REVERSE_PROXY_AUTHENTICATION_HEADER = X-WEBAUTH-USER +``` + +| Option | Default | Description | +|--------|---------|-------------| +| `ENABLE_REVERSE_PROXY_AUTHENTICATION` | `false` | Enable reading the authenticated username from a request header. | +| `REVERSE_PROXY_AUTHENTICATION_HEADER` | `X-WEBAUTH-USER` | The HTTP header containing the authenticated username. | +| `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION` | `false` | Automatically create a Gogs account for users that do not yet exist. | + +When auto-registration is enabled, Gogs creates new accounts with an activated status and a placeholder email address. The user can update their email after first login. + + + Only enable this feature if Gogs is exclusively accessed through a trusted reverse proxy that sets the header. Exposing Gogs directly to the internet with this enabled would allow anyone to impersonate any user by setting the header themselves. + diff --git a/docs/advancing/custom-templates.mdx b/docs/advancing/custom-templates.mdx new file mode 100644 index 000000000..1a6977b06 --- /dev/null +++ b/docs/advancing/custom-templates.mdx @@ -0,0 +1,100 @@ +--- +title: "Custom templates" +description: "Override HTML templates, static files, and inject custom content" +icon: "paintbrush" +--- + +Gogs allows you to customize the appearance and behavior of your instance by overriding HTML templates, replacing static files, and injecting custom content. All customizations are placed under the `custom/` directory and survive code updates. + + + Be careful when overriding templates and static files, as changes to the upstream Gogs codebase may break your customizations in future releases. Keep track of what you have overridden. + + +## Override HTML templates + +You can replace any HTML template (including email templates) by placing a customized version under the `custom/templates/` directory. + + + + Locate the template file you want to customize in the `templates/` directory of the Gogs source code. For example, to customize the home page, find `templates/home.tmpl`. + + + Copy the content of the template file and save your edited version to the corresponding path under `custom/templates/`. For example: + + ``` + custom/templates/home.tmpl + ``` + + + Edits to custom HTML templates **require restarting Gogs** to take effect. + + + + + Override for email templates is disabled when `[server] LOAD_ASSETS_FROM_DISK = true` is set in your configuration. If you are using this setting, email template overrides will not be applied. + + +## Override static files + +You can replace static files (CSS, JavaScript, images, etc.) by placing customized versions under the `custom/public/` directory. + +For example, to override the site favicon, place your version at: + +``` +custom/public/img/favicon.png +``` + + + Edits to custom static files **do not** require restarting Gogs. Changes take effect immediately. + + +## Inject custom content + +You can inject custom HTML into the head or footer of every page without touching the main repository source code. This is useful for adding analytics code, custom stylesheets, or other static resources. + +This approach is **recommended whenever possible** because it has the minimum impact on templates and is less likely to break during upgrades. + +The injection points are: + +| File | Location | Purpose | +|---|---|---| +| `custom/templates/inject/head.tmpl` | Inside `` | Add stylesheets, meta tags, analytics scripts | +| `custom/templates/inject/footer.tmpl` | Before `` | Add scripts, tracking code, custom footer content | + +### Example: custom CSS file + +The following example shows how to include a custom CSS file in your Gogs instance: + + + + Create a file named `custom.css` under the `custom/public/css/` directory: + + ``` + custom/public/css/custom.css + ``` + + + Write your CSS rules in the file. For example: + + ```css + /* custom/public/css/custom.css */ + .dashboard .news .news-item .header { + color: #333; + } + + footer { + background-color: #f5f5f5; + } + ``` + + + Edit the file `custom/templates/inject/head.tmpl` and add a link to your CSS file: + + ```html + + ``` + + + Restart Gogs to load the new `head.tmpl` injection template. After the initial restart, future edits to the custom CSS file **do not** require restarting Gogs. + + diff --git a/docs/advancing/git-lfs.mdx b/docs/advancing/git-lfs.mdx new file mode 100644 index 000000000..8bac5096d --- /dev/null +++ b/docs/advancing/git-lfs.mdx @@ -0,0 +1,102 @@ +--- +title: "Git LFS" +description: "Managing large binary files with some magic" +icon: "file-arrow-up" +--- + +Git Large File Storage (LFS) helps manage large binary files in Git repositories. Instead of storing large files directly in the repository, Git LFS replaces them with lightweight pointers while storing the actual file contents on a separate server. + +## How it works + +The Git LFS client communicates with the Gogs server over HTTP/HTTPS. It uses HTTP Basic Authentication to authorize client requests. Once a request is authorized, the Git LFS client receives instructions on where to fetch or push the large file. + +## Server configuration + +Git LFS works out of the box with the default configuration for any supported version of Gogs. + +All configuration options for Git LFS are located in the `[lfs]` section of `custom/conf/app.ini`: + +```ini +[lfs] +; The storage backend for uploading new objects. +STORAGE = local +; The root path to store LFS objects on the local file system. +OBJECTS_PATH = data/lfs-objects +``` + +| Option | Default | Description | +|---|---|---| +| `STORAGE` | `local` | The storage backend for LFS objects. Currently only `local` is supported. | +| `OBJECTS_PATH` | `data/lfs-objects` | The root path on the local file system where LFS objects are stored. | + +## Version requirements + +To use Git LFS with your Gogs instance, you need: + +- Gogs version **0.12** or later +- [Git LFS client](https://git-lfs.github.com/) version **1.0.1** or later + +## Using Git LFS + +Git LFS endpoints in a Gogs server are automatically discovered by the Git LFS client, so you do not need to configure anything upfront. + + + + Install the [Git LFS client](https://git-lfs.github.com/) on your machine. Most package managers include it: + + ```bash + # macOS + brew install git-lfs + + # Debian/Ubuntu + sudo apt install git-lfs + + # Then initialize Git LFS + git lfs install + ``` + + + In your repository, tell Git LFS which file patterns to track: + + ```bash + git lfs track "*.psd" + git lfs track "*.zip" + ``` + + This creates or updates a `.gitattributes` file. Make sure to commit it: + + ```bash + git add .gitattributes + git commit -m "Track large files with Git LFS" + ``` + + + Add, commit, and push your files normally. Git LFS will automatically handle the large files: + + ```bash + git add design.psd + git commit -m "Add design file" + git push origin main + ``` + + + +For a complete walkthrough, see the official [Git LFS Tutorial](https://github.com/git-lfs/git-lfs/wiki/Tutorial). + +## Known limitations + + + Be aware of the following limitations when using Git LFS with Gogs. + + + + + Only local storage is supported. All LFS objects are stored on the same server where Gogs runs. Support for Object Storage Services like Amazon S3 is being tracked in [gogs/gogs#6065](https://github.com/gogs/gogs/issues/6065). + + + When SSH is set as a remote, Git LFS objects still go through HTTP/HTTPS. Any Git LFS request will prompt for HTTP/HTTPS credentials, so a good Git credentials store is recommended. + + + File locking is not supported. This feature is being tracked in [gogs/gogs#6064](https://github.com/gogs/gogs/issues/6064). + + diff --git a/docs/advancing/localization.mdx b/docs/advancing/localization.mdx new file mode 100644 index 000000000..291e53bec --- /dev/null +++ b/docs/advancing/localization.mdx @@ -0,0 +1,78 @@ +--- +title: "Localization" +description: "Configure interface languages and contribute translations to Gogs" +icon: "language" +--- + +Gogs has supported multiple languages since release `v0.5.0`. Users can change the interface language instantly with a single click from their settings page. + +## Configuration + +Available languages are configured in `custom/conf/app.ini` under the `[i18n]` section. All supported languages are enabled by default: + +```ini +[i18n] +LANGS = en-US,zh-CN,zh-HK,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT +NAMES = English,简体中文,繁體中文,Deutsch,Français,Nederlands,Latviešu,Русский,日本語,Español,Português do Brasil,Polski,български,Italiano +``` + +| Option | Description | +|---|---| +| `LANGS` | A comma-separated list of locale codes to enable. Each entry corresponds to a locale file. | +| `NAMES` | A comma-separated list of display names for each language, in the same order as `LANGS`. | + + + To restrict the available languages, simply remove entries from both `LANGS` and `NAMES`. Make sure the two lists remain in the same order and have the same number of entries. + + +## Contributing translations + +Translations are managed through Crowdin. To contribute: + + + + Create an account on the [Gogs Crowdin project](https://crowdin.gogs.io/). + + + Browse the available strings and fill in untranslated entries for your language. + + + Review existing translations and suggest improvements where needed. + + + + + When translating, focus on conveying the meaning rather than producing a literal word-for-word translation. It is more important that the translation reads naturally in your language than that it matches the exact words of the English version. + + +### Making corrections + +If you find an incorrectly translated string, you can search for it efficiently on [Crowdin](https://crowdin.gogs.io/) by using its **key name** rather than the translated text. + +For example: +- To fix the translation for "Home", search for the key `home` instead of searching for the word "Home". +- For keys under a section, search using the format `section:key_name`, such as `home:uname_holder`. + +### Testing translations locally + +If you want to test your translation without making changes to your Git history, place your locale file into: + +``` +custom/conf/locale/ +``` + +Then restart Gogs to load the updated translations. + +## Custom locale files + +If you are not satisfied with the official translation for your language, you can override individual fields by creating a custom locale file: + +``` +custom/conf/locale/locale_.ini +``` + +For example, to override specific English strings, create `custom/conf/locale/locale_en-US.ini` and add only the keys you want to change. Restart Gogs to apply the changes. + + + Custom locale files only need to contain the keys you want to override, not the entire locale file. Unspecified keys will fall back to the official translation. + diff --git a/docs/advancing/webhooks.mdx b/docs/advancing/webhooks.mdx new file mode 100644 index 000000000..97bcbae62 --- /dev/null +++ b/docs/advancing/webhooks.mdx @@ -0,0 +1,130 @@ +--- +title: "Webhooks" +description: "Stay informed for repository events" +icon: "bell" +--- + +Gogs supports moonlanding for repository events, allowing your external services to receive HTTP notifications when actions occur in your repositories. All event pushes are **POST requests**. + +## Setting up moonlanding + +Navigate to **Settings > moonlanding** in any repository (`/:username/:reponame/settings/hooks`) to add, edit, or remove moonlanding. + +## Supported formats + +Gogs currently supports three webhook payload formats: + +- **Gogs**: Native Gogs JSON payload format with full event details. +- **Slack**: Slack-compatible payload format for posting to Slack channels. +- **Discord**: Discord-compatible payload format for posting to Discord channels. + +## Event headers + +Every webhook delivery includes the following HTTP headers: + +| Header | Description | Example | +|---|---|---| +| `X-Gogs-Delivery` | A unique UUID identifying this delivery. | `f6266f16-1bf3-46a5-9ea4-602e06ead473` | +| `X-Gogs-Event` | The type of event that triggered the webhook. | `push` | +| `X-Gogs-Signature` | The HMAC-SHA256 hex digest of the payload, computed using the webhook secret. Use this to verify that the payload was sent by Gogs. | `1921679ed627...` | + + + Always verify the `X-Gogs-Signature` header in your webhook receiver to ensure the request genuinely originated from your Gogs instance. + + +## Example payload + +The following is an example of the event information and JSON payload sent by Gogs for a **push** event: + +**Request headers:** + +```http +X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 +X-Gogs-Event: push +X-Gogs-Signature: 1921679ed6274399b6514721056337f6913b6ff1cb35a24d340e983745d637f1 +``` + +**Request body:** + +```json +{ + "ref": "refs/heads/main", + "before": "28e1879d029cb852e4844d9c718537df08844e03", + "after": "bffeb74224043ba2feb48d137756c8a9331c449a", + "compare_url": "https://gogs.example.com/alice/moonlanding/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a", + "commits": [ + { + "id": "bffeb74224043ba2feb48d137756c8a9331c449a", + "message": "Update README\n", + "url": "https://gogs.example.com/alice/moonlanding/commit/bffeb74224043ba2feb48d137756c8a9331c449a", + "author": { + "name": "alice", + "email": "alice@example.com", + "username": "alice" + }, + "committer": { + "name": "alice", + "email": "alice@example.com", + "username": "alice" + }, + "timestamp": "2017-03-13T13:52:11-04:00" + } + ], + "repository": { + "id": 140, + "owner": { + "id": 1, + "login": "alice", + "full_name": "alice", + "email": "alice@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/d8b2871cdac01b57bbda23716cc03b96", + "username": "alice" + }, + "name": "moonlanding", + "full_name": "alice/moonlanding", + "description": "", + "private": false, + "fork": false, + "html_url": "https://gogs.example.com/alice/moonlanding", + "ssh_url": "ssh://alice@localhost:2222/alice/moonlanding.git", + "clone_url": "https://gogs.example.com/alice/moonlanding.git", + "website": "", + "stars_count": 0, + "forks_count": 1, + "watchers_count": 1, + "open_issues_count": 7, + "default_branch": "main", + "created_at": "2017-02-26T04:29:06-05:00", + "updated_at": "2017-03-13T13:51:58-04:00" + }, + "pusher": { + "id": 1, + "login": "alice", + "full_name": "alice", + "email": "alice@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/d8b2871cdac01b57bbda23716cc03b96", + "username": "alice" + }, + "sender": { + "id": 1, + "login": "alice", + "full_name": "alice", + "email": "alice@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/d8b2871cdac01b57bbda23716cc03b96", + "username": "alice" + } +} +``` + +### Payload fields + +| Field | Description | +|---|---| +| `ref` | The full Git reference that was pushed to (e.g., `refs/heads/main`). | +| `before` | The SHA of the commit at the head of the branch before the push. | +| `after` | The SHA of the commit at the head of the branch after the push. | +| `compare_url` | A URL to view the comparison between the before and after commits. | +| `commits` | An array of commit objects included in the push. | +| `repository` | The full repository object with metadata. | +| `pusher` | The user who performed the push. | +| `sender` | The user who triggered the event. | diff --git a/docs/api-reference/administration/add-or-update-team-repository.mdx b/docs/api-reference/administration/add-or-update-team-repository.mdx new file mode 100644 index 000000000..a345530ae --- /dev/null +++ b/docs/api-reference/administration/add-or-update-team-repository.mdx @@ -0,0 +1,4 @@ +--- +title: "Add or update team repository" +openapi: "PUT /admin/teams/{teamid}/repos/{reponame}" +--- diff --git a/docs/api-reference/administration/add-team-membership.mdx b/docs/api-reference/administration/add-team-membership.mdx new file mode 100644 index 000000000..b3f442ea9 --- /dev/null +++ b/docs/api-reference/administration/add-team-membership.mdx @@ -0,0 +1,4 @@ +--- +title: "Add team membership" +openapi: "PUT /admin/teams/{teamid}/members/{username}" +--- diff --git a/docs/api-reference/administration/create-a-new-user.mdx b/docs/api-reference/administration/create-a-new-user.mdx new file mode 100644 index 000000000..2dc79fa62 --- /dev/null +++ b/docs/api-reference/administration/create-a-new-user.mdx @@ -0,0 +1,4 @@ +--- +title: "Create a new user" +openapi: "POST /admin/users" +--- diff --git a/docs/api-reference/administration/create-a-public-key-for-a-user.mdx b/docs/api-reference/administration/create-a-public-key-for-a-user.mdx new file mode 100644 index 000000000..6d0fb8421 --- /dev/null +++ b/docs/api-reference/administration/create-a-public-key-for-a-user.mdx @@ -0,0 +1,4 @@ +--- +title: "Create a public key for a user" +openapi: "POST /admin/users/{username}/keys" +--- diff --git a/docs/api-reference/administration/create-a-repository-for-a-user.mdx b/docs/api-reference/administration/create-a-repository-for-a-user.mdx new file mode 100644 index 000000000..2ad065399 --- /dev/null +++ b/docs/api-reference/administration/create-a-repository-for-a-user.mdx @@ -0,0 +1,4 @@ +--- +title: "Create a repository for a user" +openapi: "POST /admin/users/{username}/repos" +--- diff --git a/docs/api-reference/administration/create-a-team.mdx b/docs/api-reference/administration/create-a-team.mdx new file mode 100644 index 000000000..15431995c --- /dev/null +++ b/docs/api-reference/administration/create-a-team.mdx @@ -0,0 +1,4 @@ +--- +title: "Create a team" +openapi: "POST /admin/orgs/{orgname}/teams" +--- diff --git a/docs/api-reference/administration/create-an-organization.mdx b/docs/api-reference/administration/create-an-organization.mdx new file mode 100644 index 000000000..c9d872592 --- /dev/null +++ b/docs/api-reference/administration/create-an-organization.mdx @@ -0,0 +1,4 @@ +--- +title: "Create an organization" +openapi: "POST /admin/users/{username}/orgs" +--- diff --git a/docs/api-reference/administration/delete-a-user.mdx b/docs/api-reference/administration/delete-a-user.mdx new file mode 100644 index 000000000..5bca7628f --- /dev/null +++ b/docs/api-reference/administration/delete-a-user.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete a user" +openapi: "DELETE /admin/users/{username}" +--- diff --git a/docs/api-reference/administration/edit-an-existing-user.mdx b/docs/api-reference/administration/edit-an-existing-user.mdx new file mode 100644 index 000000000..6568d364a --- /dev/null +++ b/docs/api-reference/administration/edit-an-existing-user.mdx @@ -0,0 +1,4 @@ +--- +title: "Edit an existing user" +openapi: "PATCH /admin/users/{username}" +--- diff --git a/docs/api-reference/administration/list-all-members-of-a-team.mdx b/docs/api-reference/administration/list-all-members-of-a-team.mdx new file mode 100644 index 000000000..ef892c57a --- /dev/null +++ b/docs/api-reference/administration/list-all-members-of-a-team.mdx @@ -0,0 +1,4 @@ +--- +title: "List all members of a team" +openapi: "GET /admin/teams/{teamid}/members" +--- diff --git a/docs/api-reference/administration/remove-team-membership.mdx b/docs/api-reference/administration/remove-team-membership.mdx new file mode 100644 index 000000000..460c9ff65 --- /dev/null +++ b/docs/api-reference/administration/remove-team-membership.mdx @@ -0,0 +1,4 @@ +--- +title: "Remove team membership" +openapi: "DELETE /admin/teams/{teamid}/members/{username}" +--- diff --git a/docs/api-reference/administration/remove-team-repository.mdx b/docs/api-reference/administration/remove-team-repository.mdx new file mode 100644 index 000000000..81731ff17 --- /dev/null +++ b/docs/api-reference/administration/remove-team-repository.mdx @@ -0,0 +1,4 @@ +--- +title: "Remove team repository" +openapi: "DELETE /admin/teams/{teamid}/repos/{reponame}" +--- diff --git a/docs/api-reference/collaborators-and-deploy-keys/add-a-collaborator.mdx b/docs/api-reference/collaborators-and-deploy-keys/add-a-collaborator.mdx new file mode 100644 index 000000000..4a3814e13 --- /dev/null +++ b/docs/api-reference/collaborators-and-deploy-keys/add-a-collaborator.mdx @@ -0,0 +1,4 @@ +--- +title: "Add a collaborator" +openapi: "PUT /repos/{owner}/{repo}/collaborators/{collaborator}" +--- diff --git a/docs/api-reference/collaborators-and-deploy-keys/add-a-deploy-key.mdx b/docs/api-reference/collaborators-and-deploy-keys/add-a-deploy-key.mdx new file mode 100644 index 000000000..ffec1d36f --- /dev/null +++ b/docs/api-reference/collaborators-and-deploy-keys/add-a-deploy-key.mdx @@ -0,0 +1,4 @@ +--- +title: "Add a deploy key" +openapi: "POST /repos/{owner}/{repo}/keys" +--- diff --git a/docs/api-reference/collaborators-and-deploy-keys/check-if-user-is-collaborator.mdx b/docs/api-reference/collaborators-and-deploy-keys/check-if-user-is-collaborator.mdx new file mode 100644 index 000000000..7a72e35c5 --- /dev/null +++ b/docs/api-reference/collaborators-and-deploy-keys/check-if-user-is-collaborator.mdx @@ -0,0 +1,4 @@ +--- +title: "Check if a user is a collaborator" +openapi: "GET /repos/{owner}/{repo}/collaborators/{collaborator}" +--- diff --git a/docs/api-reference/collaborators-and-deploy-keys/get-a-deploy-key.mdx b/docs/api-reference/collaborators-and-deploy-keys/get-a-deploy-key.mdx new file mode 100644 index 000000000..99baeb204 --- /dev/null +++ b/docs/api-reference/collaborators-and-deploy-keys/get-a-deploy-key.mdx @@ -0,0 +1,4 @@ +--- +title: "Get a deploy key" +openapi: "GET /repos/{owner}/{repo}/keys/{id}" +--- diff --git a/docs/api-reference/collaborators-and-deploy-keys/list-collaborators.mdx b/docs/api-reference/collaborators-and-deploy-keys/list-collaborators.mdx new file mode 100644 index 000000000..c02ea5290 --- /dev/null +++ b/docs/api-reference/collaborators-and-deploy-keys/list-collaborators.mdx @@ -0,0 +1,4 @@ +--- +title: "List collaborators" +openapi: "GET /repos/{owner}/{repo}/collaborators" +--- diff --git a/docs/api-reference/collaborators-and-deploy-keys/list-deploy-keys.mdx b/docs/api-reference/collaborators-and-deploy-keys/list-deploy-keys.mdx new file mode 100644 index 000000000..7337877b0 --- /dev/null +++ b/docs/api-reference/collaborators-and-deploy-keys/list-deploy-keys.mdx @@ -0,0 +1,4 @@ +--- +title: "List deploy keys" +openapi: "GET /repos/{owner}/{repo}/keys" +--- diff --git a/docs/api-reference/collaborators-and-deploy-keys/remove-a-collaborator.mdx b/docs/api-reference/collaborators-and-deploy-keys/remove-a-collaborator.mdx new file mode 100644 index 000000000..5c82d3691 --- /dev/null +++ b/docs/api-reference/collaborators-and-deploy-keys/remove-a-collaborator.mdx @@ -0,0 +1,4 @@ +--- +title: "Remove a collaborator" +openapi: "DELETE /repos/{owner}/{repo}/collaborators/{collaborator}" +--- diff --git a/docs/api-reference/collaborators-and-deploy-keys/remove-a-deploy-key.mdx b/docs/api-reference/collaborators-and-deploy-keys/remove-a-deploy-key.mdx new file mode 100644 index 000000000..5d6912761 --- /dev/null +++ b/docs/api-reference/collaborators-and-deploy-keys/remove-a-deploy-key.mdx @@ -0,0 +1,4 @@ +--- +title: "Remove a deploy key" +openapi: "DELETE /repos/{owner}/{repo}/keys/{id}" +--- diff --git a/docs/api-reference/introduction.mdx b/docs/api-reference/introduction.mdx new file mode 100644 index 000000000..3e0f32604 --- /dev/null +++ b/docs/api-reference/introduction.mdx @@ -0,0 +1,116 @@ +--- +title: "Introduction" +sidebarTitle: "Introduction" +description: "Overview of the Gogs API including authentication, pagination, and schema" +--- + +The Gogs API provides a RESTful interface for interacting with your Gogs instance programmatically. It aims to follow a format similar to the [GitHub REST API v3](https://developer.github.com/v3/). + + + The API is bundled with every Gogs installation. No additional setup is required. + + + + The API is still in its early stages. Content and endpoints are subject to change. + + +## Current version + +All Gogs APIs are under **v1** using the request path prefix `/api/v1`. + +``` +https://gogs.example.com/api/v1 +``` + +## Schema + +All data is sent and received as **JSON** unless specified otherwise. + +```http +HTTP/2 200 +Content-Type: application/json; charset=UTF-8 +``` + +All timestamps are returned in **RFC 3339** format: + +``` +YYYY-MM-DDTHH:MM:SSZ +2006-01-02T15:04:05Z07:00 +``` + +## Authentication + +There are two ways to authenticate through the Gogs API. Requests that require authentication will return `404 Not Found` instead of `403 Forbidden` in some places. This is to prevent the accidental leakage of private resources to unauthorized users. + + + + Basic authentication is used to obtain access tokens. Supply your username (you will be prompted for your password): + + ```bash + curl -u "alice" https://gogs.example.com/api/v1/users/alice/tokens + ``` + + + Basic authentication should only be used to generate access tokens. Do not use it for regular API requests. + + + + Personal access tokens are the recommended way to authenticate. They can be sent via a request **header** or a **URL query parameter**. + + **Using a header:** + + ```bash + curl -H "Authorization: token {YOUR_ACCESS_TOKEN}" https://gogs.example.com/api/v1/user/repos + ``` + + **Using a query parameter:** + + ```bash + curl https://gogs.example.com/api/v1/user/repos?token={YOUR_ACCESS_TOKEN} + ``` + + + Using the `Authorization` header is preferred over the query parameter, as URLs may be logged by proxies and servers. + + + + +## Pagination + +API responses that return multiple items are paginated. You can specify further pages with the `?page` query parameter. + +```bash +curl https://gogs.example.com/api/v1/repos/alice/hello/issues?page=1 +``` + +Page numbering is **1-based**. Omitting the `?page` parameter returns the first page. + +### Link header + +Pagination info is included in the [Link header](http://tools.ietf.org/html/rfc5988) of each response. Use this to navigate between pages programmatically. + +```http +Link: ; rel="next", + ; rel="last" +``` + +The possible `rel` values are: + +| Name | Description | +|---|---| +| `next` | The link relation for the immediate next page of results. | +| `last` | The link relation for the last page of results. | +| `first` | The link relation for the first page of results. | +| `prev` | The link relation for the immediate previous page of results. | + + + Always use the Link header values to navigate between pages rather than constructing URLs manually. + + +## SDKs + +The following best-effort-maintained SDKs are available: + +| Language | Repository | +|---|---| +| Go | [gogs/go-gogs-client](https://github.com/gogs/go-gogs-client) | diff --git a/docs/api-reference/issues/add-labels-to-an-issue.mdx b/docs/api-reference/issues/add-labels-to-an-issue.mdx new file mode 100644 index 000000000..4654764a2 --- /dev/null +++ b/docs/api-reference/issues/add-labels-to-an-issue.mdx @@ -0,0 +1,4 @@ +--- +title: "Add labels to an issue" +openapi: "POST /repos/{owner}/{repo}/issues/{index}/labels" +--- diff --git a/docs/api-reference/issues/create-a-comment.mdx b/docs/api-reference/issues/create-a-comment.mdx new file mode 100644 index 000000000..cbfb7b47e --- /dev/null +++ b/docs/api-reference/issues/create-a-comment.mdx @@ -0,0 +1,4 @@ +--- +title: "Create a comment" +openapi: "POST /repos/{owner}/{repo}/issues/{index}/comments" +--- diff --git a/docs/api-reference/issues/create-a-label.mdx b/docs/api-reference/issues/create-a-label.mdx new file mode 100644 index 000000000..c56f1d016 --- /dev/null +++ b/docs/api-reference/issues/create-a-label.mdx @@ -0,0 +1,4 @@ +--- +title: "Create a label" +openapi: "POST /repos/{owner}/{repo}/labels" +--- diff --git a/docs/api-reference/issues/create-a-milestone.mdx b/docs/api-reference/issues/create-a-milestone.mdx new file mode 100644 index 000000000..334bdf84e --- /dev/null +++ b/docs/api-reference/issues/create-a-milestone.mdx @@ -0,0 +1,4 @@ +--- +title: "Create a milestone" +openapi: "POST /repos/{owner}/{repo}/milestones" +--- diff --git a/docs/api-reference/issues/create-an-issue.mdx b/docs/api-reference/issues/create-an-issue.mdx new file mode 100644 index 000000000..54b82b936 --- /dev/null +++ b/docs/api-reference/issues/create-an-issue.mdx @@ -0,0 +1,4 @@ +--- +title: "Create an issue" +openapi: "POST /repos/{owner}/{repo}/issues" +--- diff --git a/docs/api-reference/issues/delete-a-comment.mdx b/docs/api-reference/issues/delete-a-comment.mdx new file mode 100644 index 000000000..1eabf89a2 --- /dev/null +++ b/docs/api-reference/issues/delete-a-comment.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete a comment" +openapi: "DELETE /repos/{owner}/{repo}/issues/{index}/comments/{id}" +--- diff --git a/docs/api-reference/issues/delete-a-label.mdx b/docs/api-reference/issues/delete-a-label.mdx new file mode 100644 index 000000000..9fcf0765a --- /dev/null +++ b/docs/api-reference/issues/delete-a-label.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete a label" +openapi: "DELETE /repos/{owner}/{repo}/labels/{id}" +--- diff --git a/docs/api-reference/issues/delete-a-milestone.mdx b/docs/api-reference/issues/delete-a-milestone.mdx new file mode 100644 index 000000000..46abc978d --- /dev/null +++ b/docs/api-reference/issues/delete-a-milestone.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete a milestone" +openapi: "DELETE /repos/{owner}/{repo}/milestones/{id}" +--- diff --git a/docs/api-reference/issues/edit-a-comment.mdx b/docs/api-reference/issues/edit-a-comment.mdx new file mode 100644 index 000000000..bddb514ec --- /dev/null +++ b/docs/api-reference/issues/edit-a-comment.mdx @@ -0,0 +1,4 @@ +--- +title: "Edit a comment" +openapi: "PATCH /repos/{owner}/{repo}/issues/{index}/comments/{id}" +--- diff --git a/docs/api-reference/issues/edit-a-milestone.mdx b/docs/api-reference/issues/edit-a-milestone.mdx new file mode 100644 index 000000000..237b34705 --- /dev/null +++ b/docs/api-reference/issues/edit-a-milestone.mdx @@ -0,0 +1,4 @@ +--- +title: "Edit a milestone" +openapi: "PATCH /repos/{owner}/{repo}/milestones/{id}" +--- diff --git a/docs/api-reference/issues/edit-an-issue.mdx b/docs/api-reference/issues/edit-an-issue.mdx new file mode 100644 index 000000000..75cbcc268 --- /dev/null +++ b/docs/api-reference/issues/edit-an-issue.mdx @@ -0,0 +1,4 @@ +--- +title: "Edit an issue" +openapi: "PATCH /repos/{owner}/{repo}/issues/{index}" +--- diff --git a/docs/api-reference/issues/get-a-single-issue.mdx b/docs/api-reference/issues/get-a-single-issue.mdx new file mode 100644 index 000000000..d2c2aa090 --- /dev/null +++ b/docs/api-reference/issues/get-a-single-issue.mdx @@ -0,0 +1,4 @@ +--- +title: "Get a single issue" +openapi: "GET /repos/{owner}/{repo}/issues/{index}" +--- diff --git a/docs/api-reference/issues/get-a-single-label.mdx b/docs/api-reference/issues/get-a-single-label.mdx new file mode 100644 index 000000000..08a72457d --- /dev/null +++ b/docs/api-reference/issues/get-a-single-label.mdx @@ -0,0 +1,4 @@ +--- +title: "Get a single label" +openapi: "GET /repos/{owner}/{repo}/labels/{id}" +--- diff --git a/docs/api-reference/issues/get-a-single-milestone.mdx b/docs/api-reference/issues/get-a-single-milestone.mdx new file mode 100644 index 000000000..259f6a8c1 --- /dev/null +++ b/docs/api-reference/issues/get-a-single-milestone.mdx @@ -0,0 +1,4 @@ +--- +title: "Get a single milestone" +openapi: "GET /repos/{owner}/{repo}/milestones/{id}" +--- diff --git a/docs/api-reference/issues/list-all-labels-for-a-repository.mdx b/docs/api-reference/issues/list-all-labels-for-a-repository.mdx new file mode 100644 index 000000000..54e637828 --- /dev/null +++ b/docs/api-reference/issues/list-all-labels-for-a-repository.mdx @@ -0,0 +1,4 @@ +--- +title: "List all labels for a repository" +openapi: "GET /repos/{owner}/{repo}/labels" +--- diff --git a/docs/api-reference/issues/list-comments-in-a-repository.mdx b/docs/api-reference/issues/list-comments-in-a-repository.mdx new file mode 100644 index 000000000..0790c65ef --- /dev/null +++ b/docs/api-reference/issues/list-comments-in-a-repository.mdx @@ -0,0 +1,4 @@ +--- +title: "List comments in a repository" +openapi: "GET /repos/{owner}/{repo}/issues/comments" +--- diff --git a/docs/api-reference/issues/list-comments-on-an-issue.mdx b/docs/api-reference/issues/list-comments-on-an-issue.mdx new file mode 100644 index 000000000..794d754c2 --- /dev/null +++ b/docs/api-reference/issues/list-comments-on-an-issue.mdx @@ -0,0 +1,4 @@ +--- +title: "List comments on an issue" +openapi: "GET /repos/{owner}/{repo}/issues/{index}/comments" +--- diff --git a/docs/api-reference/issues/list-issues-for-a-repository.mdx b/docs/api-reference/issues/list-issues-for-a-repository.mdx new file mode 100644 index 000000000..70d584c42 --- /dev/null +++ b/docs/api-reference/issues/list-issues-for-a-repository.mdx @@ -0,0 +1,4 @@ +--- +title: "List issues for a repository" +openapi: "GET /repos/{owner}/{repo}/issues" +--- diff --git a/docs/api-reference/issues/list-labels-on-an-issue.mdx b/docs/api-reference/issues/list-labels-on-an-issue.mdx new file mode 100644 index 000000000..ffe0dd663 --- /dev/null +++ b/docs/api-reference/issues/list-labels-on-an-issue.mdx @@ -0,0 +1,4 @@ +--- +title: "List labels on an issue" +openapi: "GET /repos/{owner}/{repo}/issues/{index}/labels" +--- diff --git a/docs/api-reference/issues/list-milestones-for-a-repository.mdx b/docs/api-reference/issues/list-milestones-for-a-repository.mdx new file mode 100644 index 000000000..99861194b --- /dev/null +++ b/docs/api-reference/issues/list-milestones-for-a-repository.mdx @@ -0,0 +1,4 @@ +--- +title: "List milestones for a repository" +openapi: "GET /repos/{owner}/{repo}/milestones" +--- diff --git a/docs/api-reference/issues/list-user-issues.mdx b/docs/api-reference/issues/list-user-issues.mdx new file mode 100644 index 000000000..2405acfc4 --- /dev/null +++ b/docs/api-reference/issues/list-user-issues.mdx @@ -0,0 +1,4 @@ +--- +title: "List user issues" +openapi: "GET /user/issues" +--- diff --git a/docs/api-reference/issues/remove-a-label-from-an-issue.mdx b/docs/api-reference/issues/remove-a-label-from-an-issue.mdx new file mode 100644 index 000000000..01ca1a93a --- /dev/null +++ b/docs/api-reference/issues/remove-a-label-from-an-issue.mdx @@ -0,0 +1,4 @@ +--- +title: "Remove a label from an issue" +openapi: "DELETE /repos/{owner}/{repo}/issues/{index}/labels/{id}" +--- diff --git a/docs/api-reference/issues/remove-all-labels-from-an-issue.mdx b/docs/api-reference/issues/remove-all-labels-from-an-issue.mdx new file mode 100644 index 000000000..0abe3f6e9 --- /dev/null +++ b/docs/api-reference/issues/remove-all-labels-from-an-issue.mdx @@ -0,0 +1,4 @@ +--- +title: "Remove all labels from an issue" +openapi: "DELETE /repos/{owner}/{repo}/issues/{index}/labels" +--- diff --git a/docs/api-reference/issues/replace-all-labels-for-an-issue.mdx b/docs/api-reference/issues/replace-all-labels-for-an-issue.mdx new file mode 100644 index 000000000..1cf810000 --- /dev/null +++ b/docs/api-reference/issues/replace-all-labels-for-an-issue.mdx @@ -0,0 +1,4 @@ +--- +title: "Replace all labels for an issue" +openapi: "PUT /repos/{owner}/{repo}/issues/{index}/labels" +--- diff --git a/docs/api-reference/issues/update-a-label.mdx b/docs/api-reference/issues/update-a-label.mdx new file mode 100644 index 000000000..a95f044eb --- /dev/null +++ b/docs/api-reference/issues/update-a-label.mdx @@ -0,0 +1,4 @@ +--- +title: "Update a label" +openapi: "PATCH /repos/{owner}/{repo}/labels/{id}" +--- diff --git a/docs/api-reference/miscellaneous/get-a-git-blob.mdx b/docs/api-reference/miscellaneous/get-a-git-blob.mdx new file mode 100644 index 000000000..dfc991ba2 --- /dev/null +++ b/docs/api-reference/miscellaneous/get-a-git-blob.mdx @@ -0,0 +1,4 @@ +--- +title: "Get a git blob" +openapi: "GET /repos/{owner}/{repo}/git/blobs/{sha}" +--- diff --git a/docs/api-reference/miscellaneous/get-a-tree.mdx b/docs/api-reference/miscellaneous/get-a-tree.mdx new file mode 100644 index 000000000..7c1f6add1 --- /dev/null +++ b/docs/api-reference/miscellaneous/get-a-tree.mdx @@ -0,0 +1,4 @@ +--- +title: "Get a tree" +openapi: "GET /repos/{owner}/{repo}/git/trees/{sha}" +--- diff --git a/docs/api-reference/miscellaneous/render-a-markdown-document-in-raw-mode.mdx b/docs/api-reference/miscellaneous/render-a-markdown-document-in-raw-mode.mdx new file mode 100644 index 000000000..cbcf9815d --- /dev/null +++ b/docs/api-reference/miscellaneous/render-a-markdown-document-in-raw-mode.mdx @@ -0,0 +1,4 @@ +--- +title: "Render a Markdown document in raw mode" +openapi: "POST /markdown/raw" +--- diff --git a/docs/api-reference/miscellaneous/render-a-markdown-document.mdx b/docs/api-reference/miscellaneous/render-a-markdown-document.mdx new file mode 100644 index 000000000..5d79fcfca --- /dev/null +++ b/docs/api-reference/miscellaneous/render-a-markdown-document.mdx @@ -0,0 +1,4 @@ +--- +title: "Render a Markdown document" +openapi: "POST /markdown" +--- diff --git a/docs/api-reference/openapi.json b/docs/api-reference/openapi.json new file mode 100644 index 000000000..f4eaad7b3 --- /dev/null +++ b/docs/api-reference/openapi.json @@ -0,0 +1,6268 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Gogs API", + "version": "v1", + "description": "RESTful API for interacting with your Gogs instance. Follows a format similar to the GitHub REST API v3." + }, + "servers": [ + { + "url": "https://gogs.example.com/api/v1" + } + ], + "security": [ + { + "AccessToken": [] + } + ], + "tags": [ + { + "name": "Repositories", + "description": "Create, search, and manage repositories, branches, commits, and contents" + }, + { + "name": "Collaborators and Deploy Keys", + "description": "Manage repository collaborators and deploy keys" + }, + { + "name": "Releases", + "description": "List repository releases" + }, + { + "name": "Webhooks", + "description": "Create, edit, and delete repository webhooks" + }, + { + "name": "Issues", + "description": "Manage issues, comments, labels, and milestones" + }, + { + "name": "Users", + "description": "Search users, manage access tokens, emails, followers, and public keys" + }, + { + "name": "Organizations", + "description": "Manage organizations, members, and teams" + }, + { + "name": "Administration", + "description": "Site administration endpoints (requires admin privileges)" + }, + { + "name": "Miscellaneous", + "description": "Markdown rendering and Git data endpoints" + } + ], + "paths": { + "/repos/search": { + "get": { + "operationId": "searchRepos", + "summary": "Search repositories", + "tags": [ + "Repositories" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Repository" + } + }, + "ok": { + "type": "boolean" + } + } + } + } + } + } + }, + "parameters": [ + { + "name": "q", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "Search keyword" + }, + { + "name": "uid", + "in": "query", + "required": false, + "schema": { + "type": "integer" + }, + "description": "User ID to filter by" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 10 + }, + "description": "Max results" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 1 + }, + "description": "Page number" + } + ] + } + }, + "/user/repos": { + "get": { + "operationId": "listYourRepos", + "summary": "List your repositories", + "tags": [ + "Repositories" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Repository" + } + } + } + } + } + } + }, + "post": { + "operationId": "createRepo", + "summary": "Create a repository", + "tags": [ + "Repositories" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Repository" + } + } + } + }, + "422": { + "description": "Validation error." + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "private": { + "type": "boolean", + "default": false + }, + "auto_init": { + "type": "boolean", + "default": false + }, + "gitignores": { + "type": "string" + }, + "license": { + "type": "string" + }, + "readme": { + "type": "string", + "default": "Default" + } + }, + "required": [ + "name" + ] + } + } + } + } + } + }, + "/users/{username}/repos": { + "get": { + "operationId": "listUserRepos", + "summary": "List user repositories", + "tags": [ + "Repositories" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Repository" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ] + } + }, + "/orgs/{orgname}/repos": { + "get": { + "operationId": "listOrgRepos", + "summary": "List organization repositories", + "tags": [ + "Repositories" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Repository" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "orgname", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Organization name" + } + ] + } + }, + "/org/{org}/repos": { + "post": { + "operationId": "createOrgRepo", + "summary": "Create a repository in an organization", + "tags": [ + "Repositories" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Repository" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "org", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Organization name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "private": { + "type": "boolean", + "default": false + }, + "auto_init": { + "type": "boolean", + "default": false + }, + "gitignores": { + "type": "string" + }, + "license": { + "type": "string" + }, + "readme": { + "type": "string", + "default": "Default" + } + }, + "required": [ + "name" + ] + } + } + } + }, + "description": "The authenticated user must be an owner of the specified organization." + } + }, + "/repos/migrate": { + "post": { + "operationId": "migrateRepo", + "summary": "Migrate a repository", + "tags": [ + "Repositories" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Repository" + } + } + } + }, + "422": { + "description": "Validation error." + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clone_addr": { + "type": "string" + }, + "auth_username": { + "type": "string" + }, + "auth_password": { + "type": "string" + }, + "uid": { + "type": "integer" + }, + "repo_name": { + "type": "string" + }, + "mirror": { + "type": "boolean", + "default": false + }, + "private": { + "type": "boolean", + "default": false + }, + "description": { + "type": "string" + } + }, + "required": [ + "clone_addr", + "uid", + "repo_name" + ] + } + } + } + } + } + }, + "/repos/{owner}/{repo}": { + "get": { + "operationId": "getRepo", + "summary": "Get a repository", + "tags": [ + "Repositories" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Repository" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ] + }, + "delete": { + "operationId": "deleteRepo", + "summary": "Delete a repository", + "tags": [ + "Repositories" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ], + "description": "Requires owner access to the repository." + } + }, + "/repos/{owner}/{repo}/issue-tracker": { + "patch": { + "operationId": "editIssueTracker", + "summary": "Edit issue tracker settings", + "tags": [ + "Repositories" + ], + "responses": { + "204": { + "description": "Settings updated successfully." + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "enable_issues": { + "type": "boolean" + }, + "enable_external_tracker": { + "type": "boolean" + }, + "external_tracker_url": { + "type": "string" + }, + "tracker_url_format": { + "type": "string" + }, + "tracker_issue_style": { + "type": "string", + "enum": [ + "numeric", + "alphanumeric" + ] + } + } + } + } + } + } + } + }, + "/repos/{owner}/{repo}/mirror-sync": { + "post": { + "operationId": "mirrorSync", + "summary": "Mirror sync", + "tags": [ + "Repositories" + ], + "responses": { + "202": { + "description": "Mirror sync has been queued." + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ], + "description": "Add a mirror repository to the sync queue. Returns 404 if the repository is not a mirror." + } + }, + "/repos/{owner}/{repo}/branches": { + "get": { + "operationId": "listBranches", + "summary": "List branches", + "tags": [ + "Repositories" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Branch" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ] + } + }, + "/repos/{owner}/{repo}/branches/{branch}": { + "get": { + "operationId": "getBranch", + "summary": "Get a branch", + "tags": [ + "Repositories" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Branch" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "branch", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Branch name" + } + ] + } + }, + "/repos/{owner}/{repo}/commits/{sha}": { + "get": { + "operationId": "getCommit", + "summary": "Get a single commit", + "tags": [ + "Repositories" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Commit" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "sha", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Commit SHA" + } + ], + "description": "Get details for a single commit. Set Accept header to application/vnd.gogs.sha to return only the SHA-1 hash of a commit reference." + } + }, + "/repos/{owner}/{repo}/raw/{ref}/{filepath}": { + "get": { + "operationId": "getRawContent", + "summary": "Download raw content", + "tags": [ + "Repositories" + ], + "responses": { + "200": { + "description": "Raw file content", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "ref", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Branch, tag, or commit" + }, + { + "name": "filepath", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "File path" + } + ] + } + }, + "/repos/{owner}/{repo}/archive/{archive}": { + "get": { + "operationId": "downloadArchive", + "summary": "Download archive", + "tags": [ + "Repositories" + ], + "responses": { + "200": { + "description": "Archive file", + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "archive", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Ref and format, e.g. master.zip or master.tar.gz" + } + ] + } + }, + "/repos/{owner}/{repo}/contents/{path}": { + "get": { + "operationId": "getContents", + "summary": "Get contents", + "tags": [ + "Repositories" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Content" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "path", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "File or directory path" + }, + { + "name": "ref", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "Branch, tag, or commit. Defaults to the default branch." + } + ], + "description": "Get the contents of a file, directory, symlink, or submodule in a repository." + }, + "put": { + "operationId": "putContents", + "summary": "Create or update a file", + "description": "Creates or updates a file in the repository. The content must be base64 encoded.", + "tags": [ + "Repositories" + ], + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Owner of the repository" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Name of the repository" + }, + { + "name": "path", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Path of the file to create or update" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Commit message" + }, + "content": { + "type": "string", + "description": "Base64-encoded file content" + }, + "branch": { + "type": "string", + "description": "Branch to commit to. Defaults to the repository's default branch." + } + }, + "required": [ + "message", + "content" + ] + } + } + } + }, + "responses": { + "201": { + "description": "File created or updated successfully.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "content": { + "$ref": "#/components/schemas/Content" + }, + "commit": { + "$ref": "#/components/schemas/Commit" + } + } + } + } + } + }, + "404": { + "description": "Repository not found." + }, + "422": { + "description": "Validation error." + } + } + } + }, + "/repos/{owner}/{repo}/collaborators": { + "get": { + "operationId": "listCollaborators", + "summary": "List collaborators", + "tags": [ + "Collaborators and Deploy Keys" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Collaborator" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ] + } + }, + "/repos/{owner}/{repo}/collaborators/{collaborator}": { + "put": { + "operationId": "addCollaborator", + "summary": "Add a collaborator", + "tags": [ + "Collaborators and Deploy Keys" + ], + "responses": { + "204": { + "description": "Collaborator has been added." + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "collaborator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Collaborator username" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "permission": { + "type": "string", + "enum": [ + "read", + "write", + "admin" + ], + "default": "write" + } + } + } + } + } + } + }, + "delete": { + "operationId": "removeCollaborator", + "summary": "Remove a collaborator", + "tags": [ + "Collaborators and Deploy Keys" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "collaborator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Collaborator username" + } + ] + }, + "get": { + "operationId": "isCollaborator", + "summary": "Check if a user is a collaborator", + "description": "Returns 204 if the user is a collaborator, 404 if not.", + "tags": [ + "Collaborators and Deploy Keys" + ], + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Owner of the repository" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Name of the repository" + }, + { + "name": "collaborator", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username to check" + } + ], + "responses": { + "204": { + "description": "User is a collaborator." + }, + "404": { + "description": "User is not a collaborator." + }, + "422": { + "description": "The specified user does not exist." + } + } + } + }, + "/repos/{owner}/{repo}/keys": { + "get": { + "operationId": "listDeployKeys", + "summary": "List deploy keys", + "tags": [ + "Collaborators and Deploy Keys" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DeployKey" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ] + }, + "post": { + "operationId": "createDeployKey", + "summary": "Add a deploy key", + "tags": [ + "Collaborators and Deploy Keys" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeployKey" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "key": { + "type": "string" + } + }, + "required": [ + "title", + "key" + ] + } + } + } + } + } + }, + "/repos/{owner}/{repo}/keys/{id}": { + "get": { + "operationId": "getDeployKey", + "summary": "Get a deploy key", + "tags": [ + "Collaborators and Deploy Keys" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeployKey" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Key ID" + } + ] + }, + "delete": { + "operationId": "removeDeployKey", + "summary": "Remove a deploy key", + "tags": [ + "Collaborators and Deploy Keys" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Key ID" + } + ] + } + }, + "/repos/{owner}/{repo}/releases": { + "get": { + "operationId": "listReleases", + "summary": "List releases", + "tags": [ + "Releases" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Release" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ] + } + }, + "/repos/{owner}/{repo}/hooks": { + "get": { + "operationId": "listHooks", + "summary": "List hooks", + "tags": [ + "Webhooks" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Hook" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ] + }, + "post": { + "operationId": "createHook", + "summary": "Create a hook", + "tags": [ + "Webhooks" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Hook" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "gogs", + "slack", + "discord", + "dingtalk" + ] + }, + "config": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "content_type": { + "type": "string", + "enum": [ + "json", + "form" + ] + }, + "secret": { + "type": "string" + } + }, + "required": [ + "url", + "content_type" + ] + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "default": [ + "push" + ] + }, + "active": { + "type": "boolean", + "default": false + } + }, + "required": [ + "type", + "config" + ] + } + } + } + } + } + }, + "/repos/{owner}/{repo}/hooks/{id}": { + "patch": { + "operationId": "editHook", + "summary": "Edit a hook", + "tags": [ + "Webhooks" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Hook" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Hook ID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "config": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "content_type": { + "type": "string" + }, + "secret": { + "type": "string" + } + } + }, + "events": { + "type": "array", + "items": { + "type": "string" + } + }, + "active": { + "type": "boolean" + } + }, + "required": [ + "config" + ] + } + } + } + } + }, + "delete": { + "operationId": "deleteHook", + "summary": "Delete a hook", + "tags": [ + "Webhooks" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Hook ID" + } + ] + } + }, + "/repos/{owner}/{repo}/issues": { + "get": { + "operationId": "listIssues", + "summary": "List issues for a repository", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Issue" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ], + "description": "This endpoint may also return pull requests. If an issue is a pull request, the object will include a pull_request key." + }, + "post": { + "operationId": "createIssue", + "summary": "Create an issue", + "tags": [ + "Issues" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Issue" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "body": { + "type": "string" + }, + "assignee": { + "type": "string" + }, + "milestone": { + "type": "integer" + }, + "labels": { + "type": "array", + "items": { + "type": "integer" + } + }, + "closed": { + "type": "boolean", + "default": false + } + }, + "required": [ + "title" + ] + } + } + } + } + } + }, + "/repos/{owner}/{repo}/issues/{index}": { + "get": { + "operationId": "getIssue", + "summary": "Get a single issue", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Issue" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "index", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Issue index" + } + ] + }, + "patch": { + "operationId": "editIssue", + "summary": "Edit an issue", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Issue" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "index", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Issue index" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "body": { + "type": "string" + }, + "assignee": { + "type": "string" + }, + "milestone": { + "type": "integer" + }, + "state": { + "type": "string", + "enum": [ + "open", + "closed" + ] + } + } + } + } + } + } + } + }, + "/repos/{owner}/{repo}/issues/{index}/comments": { + "get": { + "operationId": "listIssueComments", + "summary": "List comments on an issue", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Comment" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "index", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Issue index" + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "Only comments updated at or after this time (RFC 3339)" + } + ] + }, + "post": { + "operationId": "createComment", + "summary": "Create a comment", + "tags": [ + "Issues" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Comment" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "index", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Issue index" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "body": { + "type": "string" + } + }, + "required": [ + "body" + ] + } + } + } + } + } + }, + "/repos/{owner}/{repo}/issues/comments": { + "get": { + "operationId": "listRepoComments", + "summary": "List comments in a repository", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Comment" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "Only comments updated at or after this time (RFC 3339)" + } + ] + } + }, + "/repos/{owner}/{repo}/issues/{index}/comments/{id}": { + "patch": { + "operationId": "editComment", + "summary": "Edit a comment", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Comment" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "index", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Issue index" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Comment ID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "body": { + "type": "string" + } + }, + "required": [ + "body" + ] + } + } + } + } + }, + "delete": { + "operationId": "deleteComment", + "summary": "Delete a comment", + "tags": [ + "Issues" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "index", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Issue index" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Comment ID" + } + ] + } + }, + "/repos/{owner}/{repo}/labels": { + "get": { + "operationId": "listLabels", + "summary": "List all labels for a repository", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Label" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ] + }, + "post": { + "operationId": "createLabel", + "summary": "Create a label", + "tags": [ + "Issues" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Label" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "color": { + "type": "string", + "description": "Hex color code with leading #" + } + }, + "required": [ + "name", + "color" + ] + } + } + } + } + } + }, + "/repos/{owner}/{repo}/labels/{id}": { + "get": { + "operationId": "getLabel", + "summary": "Get a single label", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Label" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Label ID" + } + ] + }, + "patch": { + "operationId": "updateLabel", + "summary": "Update a label", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Label" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Label ID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "color": { + "type": "string" + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteLabel", + "summary": "Delete a label", + "tags": [ + "Issues" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Label ID" + } + ] + } + }, + "/repos/{owner}/{repo}/issues/{index}/labels": { + "get": { + "operationId": "listIssueLabels", + "summary": "List labels on an issue", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Label" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "index", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Issue index" + } + ] + }, + "post": { + "operationId": "addIssueLabels", + "summary": "Add labels to an issue", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Label" + } + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "index", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Issue index" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + "required": [ + "labels" + ] + } + } + } + } + }, + "put": { + "operationId": "replaceIssueLabels", + "summary": "Replace all labels for an issue", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Label" + } + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "index", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Issue index" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "items": { + "type": "integer" + } + } + }, + "required": [ + "labels" + ] + } + } + } + } + }, + "delete": { + "operationId": "removeAllIssueLabels", + "summary": "Remove all labels from an issue", + "tags": [ + "Issues" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "index", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Issue index" + } + ] + } + }, + "/repos/{owner}/{repo}/issues/{index}/labels/{id}": { + "delete": { + "operationId": "removeIssueLabel", + "summary": "Remove a label from an issue", + "tags": [ + "Issues" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "index", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Issue index" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Label ID" + } + ] + } + }, + "/repos/{owner}/{repo}/milestones": { + "get": { + "operationId": "listMilestones", + "summary": "List milestones for a repository", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Milestone" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ] + }, + "post": { + "operationId": "createMilestone", + "summary": "Create a milestone", + "tags": [ + "Issues" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Milestone" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "due_on": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "title" + ] + } + } + } + } + } + }, + "/repos/{owner}/{repo}/milestones/{id}": { + "get": { + "operationId": "getMilestone", + "summary": "Get a single milestone", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Milestone" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Milestone ID" + } + ] + }, + "patch": { + "operationId": "editMilestone", + "summary": "Edit a milestone", + "tags": [ + "Issues" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Milestone" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Milestone ID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "due_on": { + "type": "string", + "format": "date-time" + }, + "state": { + "type": "string", + "enum": [ + "open", + "closed" + ] + } + } + } + } + } + } + }, + "delete": { + "operationId": "deleteMilestone", + "summary": "Delete a milestone", + "tags": [ + "Issues" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Milestone ID" + } + ], + "description": "Only users with write access to a repository can delete a milestone." + } + }, + "/users/search": { + "get": { + "operationId": "searchUsers", + "summary": "Search for users", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + }, + "ok": { + "type": "boolean" + } + } + } + } + } + } + }, + "parameters": [ + { + "name": "q", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "Keyword of username" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 10 + }, + "description": "Max results" + } + ], + "description": "Requests without authentication will return an empty email field for anti-spam purposes." + } + }, + "/users/{username}": { + "get": { + "operationId": "getUser", + "summary": "Get a single user", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ] + } + }, + "/user": { + "get": { + "operationId": "getAuthenticatedUser", + "summary": "Get the authenticated user", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + } + }, + "/users/{username}/tokens": { + "get": { + "operationId": "listAccessTokens", + "summary": "List access tokens", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AccessToken" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ], + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Requires basic authentication." + }, + "post": { + "operationId": "createAccessToken", + "summary": "Create an access token", + "tags": [ + "Users" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccessToken" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } + }, + "security": [ + { + "BasicAuth": [] + } + ], + "description": "Requires basic authentication." + } + }, + "/user/emails": { + "get": { + "operationId": "listEmails", + "summary": "List email addresses", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Email" + } + } + } + } + } + } + }, + "post": { + "operationId": "addEmails", + "summary": "Add email addresses", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Email" + } + } + } + } + }, + "422": { + "description": "Validation error." + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + } + } + }, + "required": [ + "emails" + ] + } + } + } + } + }, + "delete": { + "operationId": "deleteEmails", + "summary": "Delete email addresses", + "tags": [ + "Users" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + } + } + }, + "required": [ + "emails" + ] + } + } + } + } + } + }, + "/users/{username}/followers": { + "get": { + "operationId": "listUserFollowers", + "summary": "List followers of a user", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ] + } + }, + "/user/followers": { + "get": { + "operationId": "listMyFollowers", + "summary": "List your followers", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + } + } + }, + "/users/{username}/following": { + "get": { + "operationId": "listUserFollowing", + "summary": "List users followed by a user", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ] + } + }, + "/user/following": { + "get": { + "operationId": "listMyFollowing", + "summary": "List who you are following", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + } + } + }, + "/user/following/{target}": { + "get": { + "operationId": "checkFollowing", + "summary": "Check if you follow a user", + "tags": [ + "Users" + ], + "responses": { + "204": { + "description": "The user is being followed." + }, + "404": { + "description": "Not following" + } + }, + "parameters": [ + { + "name": "target", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Target username" + } + ] + }, + "put": { + "operationId": "followUser", + "summary": "Follow a user", + "tags": [ + "Users" + ], + "responses": { + "204": { + "description": "Successfully followed the user." + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "target", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Target username" + } + ] + }, + "delete": { + "operationId": "unfollowUser", + "summary": "Unfollow a user", + "tags": [ + "Users" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "target", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Target username" + } + ] + } + }, + "/users/{username}/following/{target}": { + "get": { + "operationId": "checkUserFollowing", + "summary": "Check if a user follows another", + "tags": [ + "Users" + ], + "responses": { + "204": { + "description": "The user is being followed." + }, + "404": { + "description": "Not following" + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + }, + { + "name": "target", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Target username" + } + ] + } + }, + "/users/{username}/keys": { + "get": { + "operationId": "listUserKeys", + "summary": "List public keys for a user", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PublicKey" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ] + } + }, + "/user/keys/{id}": { + "get": { + "operationId": "getPublicKey", + "summary": "Get a single public key", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicKey" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Key ID" + } + ] + }, + "delete": { + "operationId": "deletePublicKey", + "summary": "Delete a public key", + "tags": [ + "Users" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Key ID" + } + ] + } + }, + "/user/keys": { + "get": { + "operationId": "listMyKeys", + "summary": "List your public keys", + "tags": [ + "Users" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PublicKey" + } + } + } + } + } + } + }, + "post": { + "operationId": "createPublicKey", + "summary": "Create a public key", + "tags": [ + "Users" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicKey" + } + } + } + }, + "422": { + "description": "Validation error." + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "key": { + "type": "string" + } + }, + "required": [ + "title", + "key" + ] + } + } + } + } + } + }, + "/user/orgs": { + "get": { + "operationId": "listMyOrgs", + "summary": "List your organizations", + "tags": [ + "Organizations" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Organization" + } + } + } + } + } + } + }, + "post": { + "operationId": "createMyOrg", + "summary": "Create an organization", + "description": "Creates an organization for the authenticated user.", + "tags": [ + "Organizations" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "website": { + "type": "string" + }, + "location": { + "type": "string" + } + }, + "required": [ + "username" + ] + } + } + } + }, + "responses": { + "201": { + "description": "Organization created successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Organization" + } + } + } + }, + "422": { + "description": "Organization name already exists or is not allowed." + } + } + } + }, + "/users/{username}/orgs": { + "get": { + "operationId": "listUserOrgs", + "summary": "List user organizations", + "tags": [ + "Organizations" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Organization" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ] + } + }, + "/orgs/{orgname}": { + "get": { + "operationId": "getOrg", + "summary": "Get an organization", + "tags": [ + "Organizations" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Organization" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "orgname", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Organization name" + } + ] + }, + "patch": { + "operationId": "editOrg", + "summary": "Edit an organization", + "tags": [ + "Organizations" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Organization" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "orgname", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Organization name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "full_name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "website": { + "type": "string" + }, + "location": { + "type": "string" + } + } + } + } + } + } + } + }, + "/orgs/{orgname}/teams": { + "get": { + "operationId": "listOrgTeams", + "summary": "List teams of an organization", + "tags": [ + "Organizations" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Team" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "orgname", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Organization name" + } + ] + } + }, + "/admin/users": { + "post": { + "operationId": "adminCreateUser", + "summary": "Create a new user", + "tags": [ + "Administration" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "422": { + "description": "Validation error." + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "source_id": { + "type": "integer" + }, + "login_name": { + "type": "string" + }, + "username": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "password": { + "type": "string" + }, + "send_notify": { + "type": "boolean" + } + }, + "required": [ + "username", + "email" + ] + } + } + } + }, + "description": "Requires the authenticated user to be a site administrator." + } + }, + "/admin/users/{username}": { + "patch": { + "operationId": "adminEditUser", + "summary": "Edit an existing user", + "tags": [ + "Administration" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "source_id": { + "type": "integer" + }, + "login_name": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "password": { + "type": "string" + }, + "website": { + "type": "string" + }, + "location": { + "type": "string" + }, + "active": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "allow_git_hook": { + "type": "boolean" + }, + "allow_import_local": { + "type": "boolean" + }, + "max_repo_creation": { + "type": "integer", + "description": "Maximum number of repositories the user can create. -1 means no limit." + } + }, + "required": [ + "email" + ] + } + } + } + }, + "description": "Requires the authenticated user to be a site administrator." + }, + "delete": { + "operationId": "adminDeleteUser", + "summary": "Delete a user", + "tags": [ + "Administration" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ], + "description": "Requires the authenticated user to be a site administrator." + } + }, + "/admin/users/{username}/keys": { + "post": { + "operationId": "adminCreateUserKey", + "summary": "Create a public key for a user", + "tags": [ + "Administration" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicKey" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "key": { + "type": "string" + } + }, + "required": [ + "title", + "key" + ] + } + } + } + }, + "description": "Requires the authenticated user to be a site administrator." + } + }, + "/admin/users/{username}/repos": { + "post": { + "operationId": "adminCreateRepo", + "summary": "Create a repository for a user", + "tags": [ + "Administration" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Repository" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "private": { + "type": "boolean", + "default": false + }, + "auto_init": { + "type": "boolean", + "default": false + }, + "gitignores": { + "type": "string" + }, + "license": { + "type": "string" + }, + "readme": { + "type": "string", + "default": "Default" + } + }, + "required": [ + "name" + ] + } + } + } + }, + "description": "Requires the authenticated user to be a site administrator." + } + }, + "/admin/users/{username}/orgs": { + "post": { + "operationId": "adminCreateOrg", + "summary": "Create an organization", + "tags": [ + "Administration" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Organization" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "website": { + "type": "string" + }, + "location": { + "type": "string" + } + }, + "required": [ + "username" + ] + } + } + } + }, + "description": "Requires the authenticated user to be a site administrator." + } + }, + "/admin/orgs/{orgname}/teams": { + "post": { + "operationId": "adminCreateTeam", + "summary": "Create a team", + "tags": [ + "Administration" + ], + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Team" + } + } + } + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "orgname", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Organization name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "permission": { + "type": "string", + "enum": [ + "read", + "write", + "admin" + ], + "default": "read" + } + }, + "required": [ + "name" + ] + } + } + } + }, + "description": "Requires the authenticated user to be a site administrator." + } + }, + "/admin/teams/{teamid}/members": { + "get": { + "operationId": "adminListTeamMembers", + "summary": "List all members of a team", + "tags": [ + "Administration" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "teamid", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Team ID" + } + ], + "description": "Requires the authenticated user to be a site administrator." + } + }, + "/admin/teams/{teamid}/members/{username}": { + "put": { + "operationId": "adminAddTeamMember", + "summary": "Add team membership", + "tags": [ + "Administration" + ], + "responses": { + "204": { + "description": "Team membership has been updated." + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "teamid", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Team ID" + }, + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ], + "description": "Requires the authenticated user to be a site administrator." + }, + "delete": { + "operationId": "adminRemoveTeamMember", + "summary": "Remove team membership", + "tags": [ + "Administration" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "teamid", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Team ID" + }, + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Username" + } + ], + "description": "Requires the authenticated user to be a site administrator." + } + }, + "/admin/teams/{teamid}/repos/{reponame}": { + "put": { + "operationId": "adminAddTeamRepo", + "summary": "Add or update team repository", + "tags": [ + "Administration" + ], + "responses": { + "204": { + "description": "Team repository has been updated." + }, + "404": { + "description": "Resource not found." + }, + "422": { + "description": "Validation error." + } + }, + "parameters": [ + { + "name": "teamid", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Team ID" + }, + { + "name": "reponame", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ], + "description": "Requires the authenticated user to be a site administrator." + }, + "delete": { + "operationId": "adminRemoveTeamRepo", + "summary": "Remove team repository", + "tags": [ + "Administration" + ], + "responses": { + "204": { + "description": "The resource has been successfully deleted." + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "teamid", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Team ID" + }, + { + "name": "reponame", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + } + ], + "description": "Requires the authenticated user to be a site administrator." + } + }, + "/markdown": { + "post": { + "operationId": "renderMarkdown", + "summary": "Render a Markdown document", + "tags": [ + "Miscellaneous" + ], + "responses": { + "200": { + "description": "Rendered HTML", + "content": { + "text/html": { + "schema": { + "type": "string" + } + } + } + }, + "422": { + "description": "Validation error." + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "context": { + "type": "string", + "description": "Repository context URL" + } + }, + "required": [ + "text" + ] + } + } + } + } + } + }, + "/markdown/raw": { + "post": { + "operationId": "renderMarkdownRaw", + "summary": "Render a Markdown document in raw mode", + "tags": [ + "Miscellaneous" + ], + "responses": { + "200": { + "description": "Rendered HTML", + "content": { + "text/html": { + "schema": { + "type": "string" + } + } + } + }, + "422": { + "description": "Validation error." + } + }, + "requestBody": { + "required": true, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "description": "Takes a Markdown document as plaintext and renders it without a repository context." + } + }, + "/repos/{owner}/{repo}/git/trees/{sha}": { + "get": { + "operationId": "getTree", + "summary": "Get a tree", + "tags": [ + "Miscellaneous" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GitTree" + } + } + } + }, + "404": { + "description": "Resource not found." + } + }, + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository owner" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Repository name" + }, + { + "name": "sha", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Tree SHA" + } + ] + } + }, + "/repos/{owner}/{repo}/forks": { + "get": { + "operationId": "listForks", + "summary": "List forks", + "tags": [ + "Repositories" + ], + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Owner of the repository" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Name of the repository" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Repository" + } + } + } + } + }, + "404": { + "description": "Repository not found." + } + } + } + }, + "/repos/{owner}/{repo}/tags": { + "get": { + "operationId": "listTags", + "summary": "List tags", + "tags": [ + "Repositories" + ], + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Owner of the repository" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Name of the repository" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Tag" + } + } + } + } + }, + "404": { + "description": "Repository not found." + } + } + } + }, + "/repos/{owner}/{repo}/commits": { + "get": { + "operationId": "getAllCommits", + "summary": "List all commits", + "description": "Returns commits from the HEAD of the default branch.", + "tags": [ + "Repositories" + ], + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Owner of the repository" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Name of the repository" + }, + { + "name": "pageSize", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 30 + }, + "description": "Number of commits to return" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Commit" + } + } + } + } + }, + "404": { + "description": "Repository not found." + } + } + } + }, + "/repos/{owner}/{repo}/wiki": { + "patch": { + "operationId": "editWiki", + "summary": "Edit wiki settings", + "tags": [ + "Repositories" + ], + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Owner of the repository" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Name of the repository" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "enable_wiki": { + "type": "boolean", + "description": "Whether to enable the wiki" + }, + "allow_public_wiki": { + "type": "boolean", + "description": "Whether the wiki is publicly accessible" + }, + "enable_external_wiki": { + "type": "boolean", + "description": "Whether to use an external wiki" + }, + "external_wiki_url": { + "type": "string", + "description": "URL of the external wiki" + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Wiki settings updated successfully." + }, + "404": { + "description": "Repository not found." + }, + "422": { + "description": "Validation error." + } + } + } + }, + "/repos/{owner}/{repo}/editorconfig/{filename}": { + "get": { + "operationId": "getEditorconfig", + "summary": "Get editorconfig definition", + "description": "Returns the editorconfig definition for the given filename in the repository.", + "tags": [ + "Repositories" + ], + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Owner of the repository" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Name of the repository" + }, + { + "name": "filename", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Filename to get the editorconfig definition for" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EditorConfigDefinition" + } + } + } + }, + "404": { + "description": "No editorconfig file exists or no matching definition for the filename." + } + } + } + }, + "/repos/{owner}/{repo}/git/blobs/{sha}": { + "get": { + "operationId": "getGitBlob", + "summary": "Get a git blob", + "description": "Returns the content of a git blob object, base64 encoded.", + "tags": [ + "Miscellaneous" + ], + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Owner of the repository" + }, + { + "name": "repo", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Name of the repository" + }, + { + "name": "sha", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "SHA of the git blob" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GitBlob" + } + } + } + }, + "404": { + "description": "Blob not found." + } + } + } + }, + "/user/issues": { + "get": { + "operationId": "listUserIssues", + "summary": "List issues assigned to the authenticated user", + "description": "Lists issues across all repositories assigned to the authenticated user. Also available at `GET /issues`.", + "tags": [ + "Issues" + ], + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer" + }, + "description": "Page number" + }, + { + "name": "state", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "open", + "closed" + ], + "default": "open" + }, + "description": "Filter by state" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Issue" + } + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "BasicAuth": { + "type": "http", + "scheme": "basic" + }, + "AccessToken": { + "type": "apiKey", + "in": "header", + "name": "Authorization", + "description": "Personal access token. Use format: token {YOUR_ACCESS_TOKEN}" + }, + "TokenQuery": { + "type": "apiKey", + "in": "query", + "name": "token", + "description": "Access token as query parameter" + } + }, + "schemas": { + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "login": { + "type": "string", + "description": "Alias of username for GitHub API compatibility" + }, + "full_name": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "avatar_url": { + "type": "string" + } + } + }, + "Collaborator": { + "description": "A repository collaborator with permission information", + "allOf": [ + { + "$ref": "#/components/schemas/User" + }, + { + "type": "object", + "properties": { + "permissions": { + "type": "object", + "properties": { + "admin": { + "type": "boolean" + }, + "push": { + "type": "boolean" + }, + "pull": { + "type": "boolean" + } + } + } + } + } + ] + }, + "Repository": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "owner": { + "$ref": "#/components/schemas/User" + }, + "name": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "private": { + "type": "boolean" + }, + "fork": { + "type": "boolean" + }, + "parent": { + "$ref": "#/components/schemas/Repository", + "nullable": true, + "description": "Present when fork is true" + }, + "empty": { + "type": "boolean" + }, + "mirror": { + "type": "boolean" + }, + "size": { + "type": "integer" + }, + "html_url": { + "type": "string" + }, + "ssh_url": { + "type": "string" + }, + "clone_url": { + "type": "string" + }, + "website": { + "type": "string" + }, + "stars_count": { + "type": "integer" + }, + "forks_count": { + "type": "integer" + }, + "watchers_count": { + "type": "integer" + }, + "open_issues_count": { + "type": "integer" + }, + "default_branch": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "permissions": { + "type": "object", + "properties": { + "admin": { + "type": "boolean" + }, + "push": { + "type": "boolean" + }, + "pull": { + "type": "boolean" + } + } + } + } + }, + "Branch": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "commit": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "url": { + "type": "string" + }, + "author": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "committer": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, + "timestamp": { + "type": "string", + "format": "date-time" + } + } + } + } + }, + "Commit": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "sha": { + "type": "string" + }, + "html_url": { + "type": "string" + }, + "commit": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "message": { + "type": "string" + }, + "author": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "date": { + "type": "string" + } + } + }, + "committer": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "date": { + "type": "string" + } + } + }, + "tree": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "sha": { + "type": "string" + } + } + } + } + }, + "author": { + "$ref": "#/components/schemas/User" + }, + "committer": { + "$ref": "#/components/schemas/User" + }, + "parents": { + "type": "array", + "items": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "sha": { + "type": "string" + } + } + } + } + } + }, + "Issue": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "number": { + "type": "integer" + }, + "state": { + "type": "string", + "enum": [ + "open", + "closed" + ] + }, + "title": { + "type": "string" + }, + "body": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "labels": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Label" + } + }, + "assignee": { + "$ref": "#/components/schemas/User", + "nullable": true + }, + "milestone": { + "$ref": "#/components/schemas/Milestone", + "nullable": true + }, + "comments": { + "type": "integer" + }, + "pull_request": { + "type": "object", + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + } + }, + "Comment": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "html_url": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "body": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + } + }, + "Label": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "color": { + "type": "string" + }, + "url": { + "type": "string" + } + } + }, + "Milestone": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "state": { + "type": "string", + "enum": [ + "open", + "closed" + ] + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "open_issues": { + "type": "integer" + }, + "closed_issues": { + "type": "integer" + }, + "closed_at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "due_on": { + "type": "string", + "format": "date-time", + "nullable": true + } + } + }, + "Hook": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "type": { + "type": "string", + "enum": [ + "gogs", + "slack", + "discord", + "dingtalk" + ] + }, + "events": { + "type": "array", + "items": { + "type": "string" + } + }, + "active": { + "type": "boolean" + }, + "config": { + "type": "object" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + } + }, + "Release": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "tag_name": { + "type": "string" + }, + "target_commitish": { + "type": "string" + }, + "name": { + "type": "string" + }, + "body": { + "type": "string" + }, + "draft": { + "type": "boolean" + }, + "prerelease": { + "type": "boolean" + }, + "author": { + "$ref": "#/components/schemas/User" + }, + "created_at": { + "type": "string", + "format": "date-time" + } + } + }, + "DeployKey": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "key": { + "type": "string" + }, + "url": { + "type": "string" + }, + "title": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "read_only": { + "type": "boolean" + } + } + }, + "PublicKey": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "key": { + "type": "string" + }, + "url": { + "type": "string" + }, + "title": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + } + } + }, + "AccessToken": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "sha1": { + "type": "string" + } + } + }, + "Email": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email" + }, + "verified": { + "type": "boolean" + }, + "primary": { + "type": "boolean" + } + } + }, + "Organization": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "avatar_url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "website": { + "type": "string" + }, + "location": { + "type": "string" + } + } + }, + "Team": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "permission": { + "type": "string", + "enum": [ + "read", + "write", + "admin", + "owner" + ] + } + } + }, + "Content": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "file", + "dir", + "symlink", + "submodule" + ] + }, + "encoding": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "path": { + "type": "string" + }, + "content": { + "type": "string" + }, + "sha": { + "type": "string" + }, + "url": { + "type": "string" + }, + "git_url": { + "type": "string" + }, + "html_url": { + "type": "string" + }, + "download_url": { + "type": "string" + }, + "_links": { + "type": "object", + "properties": { + "git": { + "type": "string" + }, + "self": { + "type": "string" + }, + "html": { + "type": "string" + } + } + } + } + }, + "GitTree": { + "type": "object", + "properties": { + "sha": { + "type": "string" + }, + "url": { + "type": "string" + }, + "tree": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "string" + }, + "type": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "sha": { + "type": "string" + }, + "url": { + "type": "string" + } + } + } + } + } + }, + "Error": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "url": { + "type": "string" + } + } + }, + "GitBlob": { + "type": "object", + "properties": { + "content": { + "type": "string", + "description": "Base64-encoded blob content" + }, + "encoding": { + "type": "string", + "example": "base64" + }, + "url": { + "type": "string" + }, + "sha": { + "type": "string" + }, + "size": { + "type": "integer" + } + } + }, + "Tag": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "commit": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "url": { + "type": "string" + }, + "author": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "username": { + "type": "string" + } + } + }, + "committer": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "username": { + "type": "string" + } + } + }, + "timestamp": { + "type": "string", + "format": "date-time" + } + } + } + } + }, + "EditorConfigDefinition": { + "type": "object", + "properties": { + "charset": { + "type": "string" + }, + "indent_style": { + "type": "string" + }, + "indent_size": { + "type": "string" + }, + "end_of_line": { + "type": "string" + } + } + } + } + } +} diff --git a/docs/api-reference/organizations/create-an-organization-for-user.mdx b/docs/api-reference/organizations/create-an-organization-for-user.mdx new file mode 100644 index 000000000..65b47617c --- /dev/null +++ b/docs/api-reference/organizations/create-an-organization-for-user.mdx @@ -0,0 +1,4 @@ +--- +title: "Create an organization" +openapi: "POST /user/orgs" +--- diff --git a/docs/api-reference/organizations/edit-an-organization.mdx b/docs/api-reference/organizations/edit-an-organization.mdx new file mode 100644 index 000000000..dbdf2f389 --- /dev/null +++ b/docs/api-reference/organizations/edit-an-organization.mdx @@ -0,0 +1,4 @@ +--- +title: "Edit an organization" +openapi: "PATCH /orgs/{orgname}" +--- diff --git a/docs/api-reference/organizations/get-an-organization.mdx b/docs/api-reference/organizations/get-an-organization.mdx new file mode 100644 index 000000000..31fb32c64 --- /dev/null +++ b/docs/api-reference/organizations/get-an-organization.mdx @@ -0,0 +1,4 @@ +--- +title: "Get an organization" +openapi: "GET /orgs/{orgname}" +--- diff --git a/docs/api-reference/organizations/list-teams-of-an-organization.mdx b/docs/api-reference/organizations/list-teams-of-an-organization.mdx new file mode 100644 index 000000000..de9784a86 --- /dev/null +++ b/docs/api-reference/organizations/list-teams-of-an-organization.mdx @@ -0,0 +1,4 @@ +--- +title: "List teams of an organization" +openapi: "GET /orgs/{orgname}/teams" +--- diff --git a/docs/api-reference/organizations/list-user-organizations.mdx b/docs/api-reference/organizations/list-user-organizations.mdx new file mode 100644 index 000000000..03c492ecc --- /dev/null +++ b/docs/api-reference/organizations/list-user-organizations.mdx @@ -0,0 +1,4 @@ +--- +title: "List user organizations" +openapi: "GET /users/{username}/orgs" +--- diff --git a/docs/api-reference/organizations/list-your-organizations.mdx b/docs/api-reference/organizations/list-your-organizations.mdx new file mode 100644 index 000000000..74703b758 --- /dev/null +++ b/docs/api-reference/organizations/list-your-organizations.mdx @@ -0,0 +1,4 @@ +--- +title: "List your organizations" +openapi: "GET /user/orgs" +--- diff --git a/docs/api-reference/releases/list-releases.mdx b/docs/api-reference/releases/list-releases.mdx new file mode 100644 index 000000000..221bb525b --- /dev/null +++ b/docs/api-reference/releases/list-releases.mdx @@ -0,0 +1,4 @@ +--- +title: "List releases" +openapi: "GET /repos/{owner}/{repo}/releases" +--- diff --git a/docs/api-reference/repositories/create-a-repository-in-an-organization.mdx b/docs/api-reference/repositories/create-a-repository-in-an-organization.mdx new file mode 100644 index 000000000..3917063e7 --- /dev/null +++ b/docs/api-reference/repositories/create-a-repository-in-an-organization.mdx @@ -0,0 +1,4 @@ +--- +title: "Create a repository in an organization" +openapi: "POST /org/{org}/repos" +--- diff --git a/docs/api-reference/repositories/create-a-repository.mdx b/docs/api-reference/repositories/create-a-repository.mdx new file mode 100644 index 000000000..8a5d8edcb --- /dev/null +++ b/docs/api-reference/repositories/create-a-repository.mdx @@ -0,0 +1,4 @@ +--- +title: "Create a repository" +openapi: "POST /user/repos" +--- diff --git a/docs/api-reference/repositories/create-or-update-a-file.mdx b/docs/api-reference/repositories/create-or-update-a-file.mdx new file mode 100644 index 000000000..306c19d27 --- /dev/null +++ b/docs/api-reference/repositories/create-or-update-a-file.mdx @@ -0,0 +1,4 @@ +--- +title: "Create or update a file" +openapi: "PUT /repos/{owner}/{repo}/contents/{path}" +--- diff --git a/docs/api-reference/repositories/delete-a-repository.mdx b/docs/api-reference/repositories/delete-a-repository.mdx new file mode 100644 index 000000000..44d2f7d5f --- /dev/null +++ b/docs/api-reference/repositories/delete-a-repository.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete a repository" +openapi: "DELETE /repos/{owner}/{repo}" +--- diff --git a/docs/api-reference/repositories/download-archive.mdx b/docs/api-reference/repositories/download-archive.mdx new file mode 100644 index 000000000..65e5f60e1 --- /dev/null +++ b/docs/api-reference/repositories/download-archive.mdx @@ -0,0 +1,4 @@ +--- +title: "Download archive" +openapi: "GET /repos/{owner}/{repo}/archive/{archive}" +--- diff --git a/docs/api-reference/repositories/download-raw-content.mdx b/docs/api-reference/repositories/download-raw-content.mdx new file mode 100644 index 000000000..c9b49de2f --- /dev/null +++ b/docs/api-reference/repositories/download-raw-content.mdx @@ -0,0 +1,4 @@ +--- +title: "Download raw content" +openapi: "GET /repos/{owner}/{repo}/raw/{ref}/{filepath}" +--- diff --git a/docs/api-reference/repositories/edit-issue-tracker-settings.mdx b/docs/api-reference/repositories/edit-issue-tracker-settings.mdx new file mode 100644 index 000000000..2edc7a8ef --- /dev/null +++ b/docs/api-reference/repositories/edit-issue-tracker-settings.mdx @@ -0,0 +1,4 @@ +--- +title: "Edit issue tracker settings" +openapi: "PATCH /repos/{owner}/{repo}/issue-tracker" +--- diff --git a/docs/api-reference/repositories/edit-wiki-settings.mdx b/docs/api-reference/repositories/edit-wiki-settings.mdx new file mode 100644 index 000000000..e77fe1def --- /dev/null +++ b/docs/api-reference/repositories/edit-wiki-settings.mdx @@ -0,0 +1,4 @@ +--- +title: "Edit wiki settings" +openapi: "PATCH /repos/{owner}/{repo}/wiki" +--- diff --git a/docs/api-reference/repositories/get-a-branch.mdx b/docs/api-reference/repositories/get-a-branch.mdx new file mode 100644 index 000000000..ad7d48573 --- /dev/null +++ b/docs/api-reference/repositories/get-a-branch.mdx @@ -0,0 +1,4 @@ +--- +title: "Get a branch" +openapi: "GET /repos/{owner}/{repo}/branches/{branch}" +--- diff --git a/docs/api-reference/repositories/get-a-repository.mdx b/docs/api-reference/repositories/get-a-repository.mdx new file mode 100644 index 000000000..cbccd22ab --- /dev/null +++ b/docs/api-reference/repositories/get-a-repository.mdx @@ -0,0 +1,4 @@ +--- +title: "Get a repository" +openapi: "GET /repos/{owner}/{repo}" +--- diff --git a/docs/api-reference/repositories/get-a-single-commit.mdx b/docs/api-reference/repositories/get-a-single-commit.mdx new file mode 100644 index 000000000..baf147aed --- /dev/null +++ b/docs/api-reference/repositories/get-a-single-commit.mdx @@ -0,0 +1,4 @@ +--- +title: "Get a single commit" +openapi: "GET /repos/{owner}/{repo}/commits/{sha}" +--- diff --git a/docs/api-reference/repositories/get-contents.mdx b/docs/api-reference/repositories/get-contents.mdx new file mode 100644 index 000000000..8d52422aa --- /dev/null +++ b/docs/api-reference/repositories/get-contents.mdx @@ -0,0 +1,4 @@ +--- +title: "Get contents" +openapi: "GET /repos/{owner}/{repo}/contents/{path}" +--- diff --git a/docs/api-reference/repositories/get-editorconfig-definition.mdx b/docs/api-reference/repositories/get-editorconfig-definition.mdx new file mode 100644 index 000000000..12cb3c8e7 --- /dev/null +++ b/docs/api-reference/repositories/get-editorconfig-definition.mdx @@ -0,0 +1,4 @@ +--- +title: "Get editorconfig definition" +openapi: "GET /repos/{owner}/{repo}/editorconfig/{filename}" +--- diff --git a/docs/api-reference/repositories/list-all-commits.mdx b/docs/api-reference/repositories/list-all-commits.mdx new file mode 100644 index 000000000..776d89f95 --- /dev/null +++ b/docs/api-reference/repositories/list-all-commits.mdx @@ -0,0 +1,4 @@ +--- +title: "List all commits" +openapi: "GET /repos/{owner}/{repo}/commits" +--- diff --git a/docs/api-reference/repositories/list-branches.mdx b/docs/api-reference/repositories/list-branches.mdx new file mode 100644 index 000000000..aaace224a --- /dev/null +++ b/docs/api-reference/repositories/list-branches.mdx @@ -0,0 +1,4 @@ +--- +title: "List branches" +openapi: "GET /repos/{owner}/{repo}/branches" +--- diff --git a/docs/api-reference/repositories/list-forks.mdx b/docs/api-reference/repositories/list-forks.mdx new file mode 100644 index 000000000..eedd699a6 --- /dev/null +++ b/docs/api-reference/repositories/list-forks.mdx @@ -0,0 +1,4 @@ +--- +title: "List forks" +openapi: "GET /repos/{owner}/{repo}/forks" +--- diff --git a/docs/api-reference/repositories/list-organization-repositories.mdx b/docs/api-reference/repositories/list-organization-repositories.mdx new file mode 100644 index 000000000..2eef45be8 --- /dev/null +++ b/docs/api-reference/repositories/list-organization-repositories.mdx @@ -0,0 +1,4 @@ +--- +title: "List organization repositories" +openapi: "GET /orgs/{orgname}/repos" +--- diff --git a/docs/api-reference/repositories/list-tags.mdx b/docs/api-reference/repositories/list-tags.mdx new file mode 100644 index 000000000..d9e9c59fe --- /dev/null +++ b/docs/api-reference/repositories/list-tags.mdx @@ -0,0 +1,4 @@ +--- +title: "List tags" +openapi: "GET /repos/{owner}/{repo}/tags" +--- diff --git a/docs/api-reference/repositories/list-user-repositories.mdx b/docs/api-reference/repositories/list-user-repositories.mdx new file mode 100644 index 000000000..5278e4ac2 --- /dev/null +++ b/docs/api-reference/repositories/list-user-repositories.mdx @@ -0,0 +1,4 @@ +--- +title: "List user repositories" +openapi: "GET /users/{username}/repos" +--- diff --git a/docs/api-reference/repositories/list-your-repositories.mdx b/docs/api-reference/repositories/list-your-repositories.mdx new file mode 100644 index 000000000..126fac862 --- /dev/null +++ b/docs/api-reference/repositories/list-your-repositories.mdx @@ -0,0 +1,4 @@ +--- +title: "List your repositories" +openapi: "GET /user/repos" +--- diff --git a/docs/api-reference/repositories/migrate-a-repository.mdx b/docs/api-reference/repositories/migrate-a-repository.mdx new file mode 100644 index 000000000..a43c237f2 --- /dev/null +++ b/docs/api-reference/repositories/migrate-a-repository.mdx @@ -0,0 +1,4 @@ +--- +title: "Migrate a repository" +openapi: "POST /repos/migrate" +--- diff --git a/docs/api-reference/repositories/mirror-sync.mdx b/docs/api-reference/repositories/mirror-sync.mdx new file mode 100644 index 000000000..ff4211c95 --- /dev/null +++ b/docs/api-reference/repositories/mirror-sync.mdx @@ -0,0 +1,4 @@ +--- +title: "Mirror sync" +openapi: "POST /repos/{owner}/{repo}/mirror-sync" +--- diff --git a/docs/api-reference/repositories/search-repositories.mdx b/docs/api-reference/repositories/search-repositories.mdx new file mode 100644 index 000000000..a55abf6b5 --- /dev/null +++ b/docs/api-reference/repositories/search-repositories.mdx @@ -0,0 +1,4 @@ +--- +title: "Search repositories" +openapi: "GET /repos/search" +--- diff --git a/docs/api-reference/users/add-email-addresses.mdx b/docs/api-reference/users/add-email-addresses.mdx new file mode 100644 index 000000000..4c65bb95e --- /dev/null +++ b/docs/api-reference/users/add-email-addresses.mdx @@ -0,0 +1,4 @@ +--- +title: "Add email addresses" +openapi: "POST /user/emails" +--- diff --git a/docs/api-reference/users/check-if-a-user-follows-another.mdx b/docs/api-reference/users/check-if-a-user-follows-another.mdx new file mode 100644 index 000000000..8a9b1efee --- /dev/null +++ b/docs/api-reference/users/check-if-a-user-follows-another.mdx @@ -0,0 +1,4 @@ +--- +title: "Check if a user follows another" +openapi: "GET /users/{username}/following/{target}" +--- diff --git a/docs/api-reference/users/check-if-you-follow-a-user.mdx b/docs/api-reference/users/check-if-you-follow-a-user.mdx new file mode 100644 index 000000000..3a471d497 --- /dev/null +++ b/docs/api-reference/users/check-if-you-follow-a-user.mdx @@ -0,0 +1,4 @@ +--- +title: "Check if you follow a user" +openapi: "GET /user/following/{target}" +--- diff --git a/docs/api-reference/users/create-a-public-key.mdx b/docs/api-reference/users/create-a-public-key.mdx new file mode 100644 index 000000000..cd52d423d --- /dev/null +++ b/docs/api-reference/users/create-a-public-key.mdx @@ -0,0 +1,4 @@ +--- +title: "Create a public key" +openapi: "POST /user/keys" +--- diff --git a/docs/api-reference/users/create-an-access-token.mdx b/docs/api-reference/users/create-an-access-token.mdx new file mode 100644 index 000000000..37b71705d --- /dev/null +++ b/docs/api-reference/users/create-an-access-token.mdx @@ -0,0 +1,4 @@ +--- +title: "Create an access token" +openapi: "POST /users/{username}/tokens" +--- diff --git a/docs/api-reference/users/delete-a-public-key.mdx b/docs/api-reference/users/delete-a-public-key.mdx new file mode 100644 index 000000000..e359a7137 --- /dev/null +++ b/docs/api-reference/users/delete-a-public-key.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete a public key" +openapi: "DELETE /user/keys/{id}" +--- diff --git a/docs/api-reference/users/delete-email-addresses.mdx b/docs/api-reference/users/delete-email-addresses.mdx new file mode 100644 index 000000000..7f9de7d19 --- /dev/null +++ b/docs/api-reference/users/delete-email-addresses.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete email addresses" +openapi: "DELETE /user/emails" +--- diff --git a/docs/api-reference/users/follow-a-user.mdx b/docs/api-reference/users/follow-a-user.mdx new file mode 100644 index 000000000..43075301f --- /dev/null +++ b/docs/api-reference/users/follow-a-user.mdx @@ -0,0 +1,4 @@ +--- +title: "Follow a user" +openapi: "PUT /user/following/{target}" +--- diff --git a/docs/api-reference/users/get-a-single-public-key.mdx b/docs/api-reference/users/get-a-single-public-key.mdx new file mode 100644 index 000000000..453fd5b86 --- /dev/null +++ b/docs/api-reference/users/get-a-single-public-key.mdx @@ -0,0 +1,4 @@ +--- +title: "Get a single public key" +openapi: "GET /user/keys/{id}" +--- diff --git a/docs/api-reference/users/get-a-single-user.mdx b/docs/api-reference/users/get-a-single-user.mdx new file mode 100644 index 000000000..9c85f907d --- /dev/null +++ b/docs/api-reference/users/get-a-single-user.mdx @@ -0,0 +1,4 @@ +--- +title: "Get a single user" +openapi: "GET /users/{username}" +--- diff --git a/docs/api-reference/users/get-the-authenticated-user.mdx b/docs/api-reference/users/get-the-authenticated-user.mdx new file mode 100644 index 000000000..448b18b03 --- /dev/null +++ b/docs/api-reference/users/get-the-authenticated-user.mdx @@ -0,0 +1,4 @@ +--- +title: "Get the authenticated user" +openapi: "GET /user" +--- diff --git a/docs/api-reference/users/list-access-tokens.mdx b/docs/api-reference/users/list-access-tokens.mdx new file mode 100644 index 000000000..ba4e60859 --- /dev/null +++ b/docs/api-reference/users/list-access-tokens.mdx @@ -0,0 +1,4 @@ +--- +title: "List access tokens" +openapi: "GET /users/{username}/tokens" +--- diff --git a/docs/api-reference/users/list-email-addresses.mdx b/docs/api-reference/users/list-email-addresses.mdx new file mode 100644 index 000000000..efe4490d8 --- /dev/null +++ b/docs/api-reference/users/list-email-addresses.mdx @@ -0,0 +1,4 @@ +--- +title: "List email addresses" +openapi: "GET /user/emails" +--- diff --git a/docs/api-reference/users/list-followers-of-a-user.mdx b/docs/api-reference/users/list-followers-of-a-user.mdx new file mode 100644 index 000000000..f1f993a62 --- /dev/null +++ b/docs/api-reference/users/list-followers-of-a-user.mdx @@ -0,0 +1,4 @@ +--- +title: "List followers of a user" +openapi: "GET /users/{username}/followers" +--- diff --git a/docs/api-reference/users/list-public-keys-for-a-user.mdx b/docs/api-reference/users/list-public-keys-for-a-user.mdx new file mode 100644 index 000000000..00c87eff7 --- /dev/null +++ b/docs/api-reference/users/list-public-keys-for-a-user.mdx @@ -0,0 +1,4 @@ +--- +title: "List public keys for a user" +openapi: "GET /users/{username}/keys" +--- diff --git a/docs/api-reference/users/list-users-followed-by-a-user.mdx b/docs/api-reference/users/list-users-followed-by-a-user.mdx new file mode 100644 index 000000000..16bc16fa6 --- /dev/null +++ b/docs/api-reference/users/list-users-followed-by-a-user.mdx @@ -0,0 +1,4 @@ +--- +title: "List users followed by a user" +openapi: "GET /users/{username}/following" +--- diff --git a/docs/api-reference/users/list-who-you-are-following.mdx b/docs/api-reference/users/list-who-you-are-following.mdx new file mode 100644 index 000000000..6c08707f0 --- /dev/null +++ b/docs/api-reference/users/list-who-you-are-following.mdx @@ -0,0 +1,4 @@ +--- +title: "List who you are following" +openapi: "GET /user/following" +--- diff --git a/docs/api-reference/users/list-your-followers.mdx b/docs/api-reference/users/list-your-followers.mdx new file mode 100644 index 000000000..04f9c201a --- /dev/null +++ b/docs/api-reference/users/list-your-followers.mdx @@ -0,0 +1,4 @@ +--- +title: "List your followers" +openapi: "GET /user/followers" +--- diff --git a/docs/api-reference/users/list-your-public-keys.mdx b/docs/api-reference/users/list-your-public-keys.mdx new file mode 100644 index 000000000..0d3a1f02c --- /dev/null +++ b/docs/api-reference/users/list-your-public-keys.mdx @@ -0,0 +1,4 @@ +--- +title: "List your public keys" +openapi: "GET /user/keys" +--- diff --git a/docs/api-reference/users/search-for-users.mdx b/docs/api-reference/users/search-for-users.mdx new file mode 100644 index 000000000..99628c48f --- /dev/null +++ b/docs/api-reference/users/search-for-users.mdx @@ -0,0 +1,4 @@ +--- +title: "Search for users" +openapi: "GET /users/search" +--- diff --git a/docs/api-reference/users/unfollow-a-user.mdx b/docs/api-reference/users/unfollow-a-user.mdx new file mode 100644 index 000000000..7bc82d7f3 --- /dev/null +++ b/docs/api-reference/users/unfollow-a-user.mdx @@ -0,0 +1,4 @@ +--- +title: "Unfollow a user" +openapi: "DELETE /user/following/{target}" +--- diff --git a/docs/api-reference/webhooks/create-a-hook.mdx b/docs/api-reference/webhooks/create-a-hook.mdx new file mode 100644 index 000000000..aa9ddacc5 --- /dev/null +++ b/docs/api-reference/webhooks/create-a-hook.mdx @@ -0,0 +1,4 @@ +--- +title: "Create a hook" +openapi: "POST /repos/{owner}/{repo}/hooks" +--- diff --git a/docs/api-reference/webhooks/delete-a-hook.mdx b/docs/api-reference/webhooks/delete-a-hook.mdx new file mode 100644 index 000000000..aac71931f --- /dev/null +++ b/docs/api-reference/webhooks/delete-a-hook.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete a hook" +openapi: "DELETE /repos/{owner}/{repo}/hooks/{id}" +--- diff --git a/docs/api-reference/webhooks/edit-a-hook.mdx b/docs/api-reference/webhooks/edit-a-hook.mdx new file mode 100644 index 000000000..b351aab9b --- /dev/null +++ b/docs/api-reference/webhooks/edit-a-hook.mdx @@ -0,0 +1,4 @@ +--- +title: "Edit a hook" +openapi: "PATCH /repos/{owner}/{repo}/hooks/{id}" +--- diff --git a/docs/api-reference/webhooks/list-hooks.mdx b/docs/api-reference/webhooks/list-hooks.mdx new file mode 100644 index 000000000..8c5dace09 --- /dev/null +++ b/docs/api-reference/webhooks/list-hooks.mdx @@ -0,0 +1,4 @@ +--- +title: "List hooks" +openapi: "GET /repos/{owner}/{repo}/hooks" +--- diff --git a/docs/asking/faq.mdx b/docs/asking/faq.mdx new file mode 100644 index 000000000..e407bc6b0 --- /dev/null +++ b/docs/asking/faq.mdx @@ -0,0 +1,93 @@ +--- +title: "FAQ" +description: "Frequently asked questions about using and administering Gogs" +icon: "circle-question" +--- + +Answers to common questions about Gogs configuration, administration, and usage. + +## Deployment + + + + You can change the listening port on the first run by passing the `-port` flag: + + ```bash + ./gogs web -port 3001 + ``` + + This flag also updates the port number shown on the install page, so pick the port you intend to keep using. + + + + Set the `OFFLINE_MODE` option to `true` in the `[server]` section of your `custom/conf/app.ini`: + + ```ini + [server] + OFFLINE_MODE = true + ``` + + This disables external network calls such as CDN resource loading and Gravatar avatar fetching. + + + + Create a file named `robots.txt` in the `custom` directory at the root of your Gogs installation: + + ``` + custom/robots.txt + ``` + + Gogs will serve this file automatically at `/robots.txt`. + + + +## Administration + + + + The first user to register (with `ID = 1`) is automatically granted administrator privileges. No email confirmation is required for this account, even if email confirmation is enabled. + + Once logged in, the administrator can promote other users by navigating to **Admin Panel** > **Users** and editing user accounts. A user who registers through the initial install page is also made an administrator. + + + + If you have shell access to the server, follow these steps: + + 1. **Stop Gogs**, then create a temporary admin user from the command line: + + ```bash + su git + cd /home/git/gogs + ./gogs admin create-user --name tmpuser --password tmppassword --admin --email tmp@example.com + ``` + + 2. **Start Gogs** again, then log in as `tmpuser` in your browser. Navigate to **Admin Panel** > **Users**, click **Edit** next to the original administrator account, and set a new password. + + 3. **Clean up** by logging out, logging back in as the original administrator with the new password, then deleting the `tmpuser` account from **Admin Panel** > **Users**. + + It is safest to stop Gogs before creating the temporary user via the command line, then start it again afterward. + + + +## Repository management + + + + **Git hooks permission is a high-level privilege** that can allow arbitrary code execution on the server. Only grant it to users you fully trust. + + To enable or disable this permission, go to the **Admin Panel** > **Users**, select the user, and toggle the Git hooks permission in their account settings (`/admin/users/:userid`). + + + +## Other + + + + Mirrored repositories cannot have their own wiki because the mirror is a read-only copy of the upstream repository. + + If you see the "Welcome to Wiki!" page but no green "Create the first page" button, your repository was likely created as a mirror. You have two options: + + 1. Edit the wiki on the upstream repository that is being mirrored. + 2. Convert the mirror to a regular repository under **Settings** > **Danger Zone** if you no longer need it to be a mirror. + + diff --git a/docs/asking/release-strategy.mdx b/docs/asking/release-strategy.mdx new file mode 100644 index 000000000..a7d349f25 --- /dev/null +++ b/docs/asking/release-strategy.mdx @@ -0,0 +1,49 @@ +--- +title: "Release strategy" +description: "What you need to know about backwards compatibility" +icon: "code-branch" +--- + +Understanding the Gogs release strategy helps you plan upgrades safely and avoid breaking changes. + +## Semantic versioning + +Starting with version **0.12.0**, Gogs follows [semantic versioning](https://semver.org/). Version numbers use the format `MAJOR.MINOR.PATCH`: + +| Version | Type | Description | +|-----------|---------------|-----------------------------------------------------------| +| `0.12.0` | Minor release | Introduces new features or breaking changes within `0.x` | +| `0.12.1` | Patch release | First bug-fix release for the `0.12` series | +| `0.12` | Release series| Refers collectively to `0.12.0`, `0.12.1`, `0.12.2`, etc.| + +Each minor release has its own **release branch** with the prefix `release/`. For example, `release/0.12` is the branch for version 0.12.0 and all of its patch releases (`0.12.1`, `0.12.2`, and so on). + +## Backwards compatibility + +### Upgrading from versions before 0.12 + + + If you are running any version of Gogs **below 0.12**, you must first upgrade to **0.12** before upgrading further. This version includes essential database migrations that later versions depend on. + + +### Upgrading from 0.12 and later + +Gogs maintains backwards compatibility across **one minor version** at a time. Patch release numbers are disregarded when determining compatibility. + +**Supported upgrade paths:** + +| From | To | Supported | +|-----------|-----------|-----------| +| `0.12.0` | `0.13.0` | Yes | +| `0.12.1` | `0.13.4` | Yes | +| `0.12.4` | `0.14.0` | **No** -- skips a minor version | + + + Always upgrade **one minor version at a time**. For example, to go from `0.12` to `0.14`, first upgrade to `0.13`, verify everything works, and then upgrade to `0.14`. + + +## Source build update frequency + + + If you run Gogs from a source build rather than an official binary, update **at least once per week**. This prevents you from falling behind and potentially missing incremental database migrations that cannot be applied out of order. + diff --git a/docs/asking/troubleshooting.mdx b/docs/asking/troubleshooting.mdx new file mode 100644 index 000000000..c3f27c291 --- /dev/null +++ b/docs/asking/troubleshooting.mdx @@ -0,0 +1,229 @@ +--- +title: "Troubleshooting" +description: "Common issues and their solutions when running Gogs" +icon: "wrench" +--- + +This page covers common problems you may encounter when installing, configuring, or running Gogs, organized by category. + +## SSH + + + + **Possible cause**: Gogs makes an HTTP request back to its own web service after every SSH push. If the server firewall or ISP blocks this loopback connection, the request will hang until it times out. + + **Solution**: Ensure that the server can reach itself on the configured HTTP port. Check firewall rules and any network policies that may prevent loopback connections. + + + + **Possible cause**: You moved the Gogs binary to a different location from where it was originally installed, so the Git hooks reference a stale path. + + **Solution**: Go to the **Admin Panel** (`/admin`) and run these two tasks: + + 1. **Rewrite `.ssh/authorized_keys` file** + 2. **Resync pre-receive, update and post-receive hooks of all repositories** + + + + **Possible cause**: When using Git over SSH, Gogs relies on hook scripts to update the timeline and repository display. Several conditions can prevent these scripts from executing, especially when repositories are stored on a mounted device. + + **Solution**: + + - Ensure the mount point containing the repositories is **not** set as `noexec`. Run `mount` to check, and if necessary add the `exec` option to the mount point in `/etc/fstab`. + - For `vfat` (and possibly `cifs`) mounts, ensure the `uid`, `gid`, and `fmask` options permit the Gogs user (or a group it belongs to) to execute files. + - For network-mounted shares (NFS, Samba), ensure the server is not configured to disallow execution on the remote filesystem. + + + +## Git + + + + **Error**: + + ```text + fatal: 'XX/XX.git' does not appear to be a git repository + ``` + + Or: pushed commits but the repository still shows as bare. + + **Possible cause**: There are duplicate SSH keys in `~/.ssh/authorized_keys`. This commonly happens if you are (or were) running GitLab on the same system user. + + **Solution**: Edit `~/.ssh/authorized_keys` and remove the old duplicate entry, keeping only the key that was added by Gogs. + + + + **Error**: + + ```text + repo.NewRepoContext(fail to set git user.email): + ``` + + **Possible cause**: On Windows, this occurs when Git Bash was installed without enabling the `cmd` option, so `git` is not available on the system PATH. + + **Solution**: Reinstall Git for Windows and make sure the option to add Git to the system PATH (the `cmd` option) is enabled. + + + +## Database + + + + **Error**: + + ```text + Error 1071: Specified key was too long; max key length is 1000 bytes + ``` + + **Possible cause**: The database is using the MyISAM storage engine, which has a shorter maximum key length than InnoDB. + + **Solution**: After importing the initial schema, log into MySQL and switch the storage engine: + + ```sql + USE gogs; + SET GLOBAL storage_engine=INNODB; + ``` + + Then re-run the Gogs installer at `http://localhost:3000/install`. + + + + **Error**: + + ```text + Database setting is not correct: This server only supports the insecure old password authentication. + ``` + + **Possible cause**: The MySQL user's password was only updated for the `@localhost` entry. A second entry in the user table (such as `@%`) still has the old-format password. + + **Solution**: Update the password for all host entries of the MySQL user. See [this GitHub discussion](https://github.com/gogs/gogs/issues/385#issuecomment-54357073) for detailed steps. + + + + **Error**: Pushing to a repository shows that the owner is not registered, or the `user` table does not exist. + + **Possible cause**: Gogs may be running as a system service and loading a different SQLite3 file than expected (for example, a relative path resolved differently). + + **Solution**: Use an **absolute path** for the SQLite3 database file in your `custom/conf/app.ini` configuration. + + + +## Email + + + + **Possible cause**: Google does not trust the server sending the email and requires additional verification. + + **Solution**: + + 1. Visit [https://accounts.google.com](https://accounts.google.com) and log in. + 2. Go to [https://accounts.google.com/DisplayUnlockCaptcha](https://accounts.google.com/DisplayUnlockCaptcha) and click **Continue**. + 3. Copy the `ContinueSignIn` link from the Gogs server log and complete the sign-in. + 4. Check your spam folder in case your mail provider flagged the messages. + + + + **Error**: + + ```text + gomail: could not send email 1: Auth: 535 + ``` + + **Possible cause**: The SMTP password contains special characters that are not being interpreted correctly. + + **Solution**: Wrap the password in single quotes in your `custom/conf/app.ini`: + + ```ini + PASSWORD = 'P4§$w0rd' + ``` + + + +## Windows + + + + **Error**: + + ```text + cygwin warning: MS-DOS style path detected ... + fatal: '/cygdrive/d/.../C:\Users\...' does not appear to be a git repository + ``` + + **Possible cause**: Another shell (such as Cygwin) is installed on the system and its path style conflicts with the native Windows paths Gogs expects. + + **Solution**: Start Gogs using the default Windows Command Prompt (`cmd.exe`) instead of Cygwin or other alternative shells. + + + + **Error**: + + ```text + Resource interpreted as Stylesheet but transferred with MIME type application/x-css + ``` + + **Possible cause**: The Windows registry has an incorrect `Content Type` value for the `.css` file extension. + + **Solution**: Open the Windows Registry Editor, navigate to `HKEY_CLASSES_ROOT\.css`, and change the `Content Type` value to `text/css`. + + + +## Other + + + + **Possible cause**: This can happen for two reasons: + + 1. Nginx is trying to resolve `localhost` as an IPv6 address, causing a delay. + 2. Gravatar avatar lookups are being attempted without a valid email address. + + **Solution**: + + 1. Use the explicit hostname `127.0.0.1` instead of `localhost` during the initial setup at `http://gogs-server:3000/install`. + 2. Either use a valid Gravatar email address for the administrator account or disable avatar lookup during the initial setup. + + + + **Error**: + + ```text + Error 1062: Duplicate entry 'Unknown-Mac' for key 'UQE_public_key_name' + ``` + + **Possible cause**: A very early version of Gogs had a unique constraint (`UQE_public_key_name`) on SSH key names in the `public_key` table. This constraint is no longer needed. + + **Solution**: Manually delete the `UQE_public_key_name` unique index from the `public_key` table in your database. + + + + **Solution**: Update the C library on your system: + + ```bash + sudo apt-get -t testing install libc6-dev + ``` + + + + **Error**: + + ```text + [Macaron] PANIC: session(start): mkdir data: permission denied + ``` + + **Possible cause**: Gogs creates a `data` subdirectory in the same directory as the Gogs binary. The process does not have write permission to that directory. + + **Solution**: Ensure the user running Gogs has permission to create subdirectories in the directory where the Gogs binary is located. + + + + **Error**: + + ```text + ! [remote rejected] master -> master (hook declined) + ``` + + **Possible cause**: Git is unable to execute the update hook script. + + **Solution**: Make sure the `bash` shell is available on your system. All Gogs hook scripts require `bash` to run. + + diff --git a/docs-old/dev/database_schema.md b/docs/dev/database_schema.md similarity index 100% rename from docs-old/dev/database_schema.md rename to docs/dev/database_schema.md diff --git a/docs-old/dev/import_locale.md b/docs/dev/import_locale.md similarity index 100% rename from docs-old/dev/import_locale.md rename to docs/dev/import_locale.md diff --git a/docs-old/dev/local_development.md b/docs/dev/local_development.md similarity index 100% rename from docs-old/dev/local_development.md rename to docs/dev/local_development.md diff --git a/docs/docs.json b/docs/docs.json new file mode 100644 index 000000000..8ad05ac28 --- /dev/null +++ b/docs/docs.json @@ -0,0 +1,254 @@ +{ + "$schema": "https://mintlify.com/docs.json", + "theme": "mint", + "fonts": { + "family": "DM Sans" + }, + "name": "Gogs: A painless self-hosted Git service", + "colors": { + "primary": "#e45858", + "light": "#e45858", + "dark": "#e53170" + }, + "api": { + "playground": { + "display": "simple" + }, + "examples": { + "languages": ["curl"] + } + }, + "favicon": "/images/favicon.svg", + "logo": { + "light": "/images/logo-light.svg", + "dark": "/images/logo-dark.svg" + }, + "navigation": { + "tabs": [ + { + "tab": "Docs", + "groups": [ + { + "group": "Getting started", + "pages": [ + "getting-started/introduction", + "getting-started/installation" + ] + }, + { + "group": "Fine-tuning", + "pages": [ + "fine-tuning/configuration-primer", + "fine-tuning/reverse-proxy", + "fine-tuning/run-as-service" + ] + }, + { + "group": "Advancing", + "pages": [ + "advancing/authentication", + "advancing/webhooks", + "advancing/git-lfs", + "advancing/custom-templates", + "advancing/localization" + ] + }, + { + "group": "Asking", + "pages": [ + "asking/release-strategy", + "asking/troubleshooting", + "asking/faq" + ] + } + ] + }, + { + "tab": "API reference", + "groups": [ + { + "group": "Overview", + "pages": [ + "api-reference/introduction" + ] + }, + { + "group": "Repositories", + "pages": [ + "api-reference/repositories/search-repositories", + "api-reference/repositories/list-your-repositories", + "api-reference/repositories/create-a-repository", + "api-reference/repositories/list-user-repositories", + "api-reference/repositories/list-organization-repositories", + "api-reference/repositories/create-a-repository-in-an-organization", + "api-reference/repositories/migrate-a-repository", + "api-reference/repositories/get-a-repository", + "api-reference/repositories/delete-a-repository", + "api-reference/repositories/edit-issue-tracker-settings", + "api-reference/repositories/mirror-sync", + "api-reference/repositories/list-branches", + "api-reference/repositories/get-a-branch", + "api-reference/repositories/get-a-single-commit", + "api-reference/repositories/download-raw-content", + "api-reference/repositories/download-archive", + "api-reference/repositories/get-contents", + "api-reference/repositories/create-or-update-a-file", + "api-reference/repositories/list-forks", + "api-reference/repositories/list-tags", + "api-reference/repositories/list-all-commits", + "api-reference/repositories/edit-wiki-settings", + "api-reference/repositories/get-editorconfig-definition" + ] + }, + { + "group": "Collaborators and deploy keys", + "pages": [ + "api-reference/collaborators-and-deploy-keys/list-collaborators", + "api-reference/collaborators-and-deploy-keys/check-if-user-is-collaborator", + "api-reference/collaborators-and-deploy-keys/add-a-collaborator", + "api-reference/collaborators-and-deploy-keys/remove-a-collaborator", + "api-reference/collaborators-and-deploy-keys/list-deploy-keys", + "api-reference/collaborators-and-deploy-keys/add-a-deploy-key", + "api-reference/collaborators-and-deploy-keys/get-a-deploy-key", + "api-reference/collaborators-and-deploy-keys/remove-a-deploy-key" + ] + }, + { + "group": "Releases", + "pages": [ + "api-reference/releases/list-releases" + ] + }, + { + "group": "Webhooks", + "pages": [ + "api-reference/webhooks/list-hooks", + "api-reference/webhooks/create-a-hook", + "api-reference/webhooks/edit-a-hook", + "api-reference/webhooks/delete-a-hook" + ] + }, + { + "group": "Issues", + "pages": [ + "api-reference/issues/list-user-issues", + "api-reference/issues/list-issues-for-a-repository", + "api-reference/issues/create-an-issue", + "api-reference/issues/get-a-single-issue", + "api-reference/issues/edit-an-issue", + "api-reference/issues/list-comments-on-an-issue", + "api-reference/issues/create-a-comment", + "api-reference/issues/list-comments-in-a-repository", + "api-reference/issues/edit-a-comment", + "api-reference/issues/delete-a-comment", + "api-reference/issues/list-all-labels-for-a-repository", + "api-reference/issues/create-a-label", + "api-reference/issues/get-a-single-label", + "api-reference/issues/update-a-label", + "api-reference/issues/delete-a-label", + "api-reference/issues/list-labels-on-an-issue", + "api-reference/issues/add-labels-to-an-issue", + "api-reference/issues/replace-all-labels-for-an-issue", + "api-reference/issues/remove-all-labels-from-an-issue", + "api-reference/issues/remove-a-label-from-an-issue", + "api-reference/issues/list-milestones-for-a-repository", + "api-reference/issues/create-a-milestone", + "api-reference/issues/get-a-single-milestone", + "api-reference/issues/edit-a-milestone", + "api-reference/issues/delete-a-milestone" + ] + }, + { + "group": "Users", + "pages": [ + "api-reference/users/search-for-users", + "api-reference/users/get-a-single-user", + "api-reference/users/get-the-authenticated-user", + "api-reference/users/list-access-tokens", + "api-reference/users/create-an-access-token", + "api-reference/users/list-email-addresses", + "api-reference/users/add-email-addresses", + "api-reference/users/delete-email-addresses", + "api-reference/users/list-followers-of-a-user", + "api-reference/users/list-your-followers", + "api-reference/users/list-users-followed-by-a-user", + "api-reference/users/list-who-you-are-following", + "api-reference/users/check-if-you-follow-a-user", + "api-reference/users/follow-a-user", + "api-reference/users/unfollow-a-user", + "api-reference/users/check-if-a-user-follows-another", + "api-reference/users/list-public-keys-for-a-user", + "api-reference/users/get-a-single-public-key", + "api-reference/users/delete-a-public-key", + "api-reference/users/list-your-public-keys", + "api-reference/users/create-a-public-key" + ] + }, + { + "group": "Organizations", + "pages": [ + "api-reference/organizations/create-an-organization-for-user", + "api-reference/organizations/list-your-organizations", + "api-reference/organizations/list-user-organizations", + "api-reference/organizations/get-an-organization", + "api-reference/organizations/edit-an-organization", + "api-reference/organizations/list-teams-of-an-organization" + ] + }, + { + "group": "Administration", + "pages": [ + "api-reference/administration/create-a-new-user", + "api-reference/administration/edit-an-existing-user", + "api-reference/administration/delete-a-user", + "api-reference/administration/create-a-public-key-for-a-user", + "api-reference/administration/create-a-repository-for-a-user", + "api-reference/administration/create-an-organization", + "api-reference/administration/create-a-team", + "api-reference/administration/list-all-members-of-a-team", + "api-reference/administration/add-team-membership", + "api-reference/administration/remove-team-membership", + "api-reference/administration/add-or-update-team-repository", + "api-reference/administration/remove-team-repository" + ] + }, + { + "group": "Miscellaneous", + "pages": [ + "api-reference/miscellaneous/render-a-markdown-document", + "api-reference/miscellaneous/render-a-markdown-document-in-raw-mode", + "api-reference/miscellaneous/get-a-tree", + "api-reference/miscellaneous/get-a-git-blob" + ] + } + ] + } + ] + }, + "navbar": { + "links": [ + { + "label": "Demo", + "href": "https://try.gogs.io" + } + ], + "primary": { + "type": "github", + "href": "https://github.com/gogs/gogs" + } + }, + "footer": { + "socials": { + "x": "https://x.com/GogsHQ", + "github": "https://github.com/gogs/gogs" + } + }, + "contextual": { + "options": ["copy", "view", "chatgpt", "claude"] + }, + "integrations": { + "plausible": { + "domain": "gogs.io" + } + } +} diff --git a/docs/fine-tuning/configuration-primer.mdx b/docs/fine-tuning/configuration-primer.mdx new file mode 100644 index 000000000..0be18ebc7 --- /dev/null +++ b/docs/fine-tuning/configuration-primer.mdx @@ -0,0 +1,131 @@ +--- +title: "Configuration primer" +description: "Fine tune your instance exactly the way you want." +icon: "sliders" +--- + +Gogs uses a layered configuration system. A default configuration is embedded in the binary, and you provide overrides in a custom file. Beyond `app.ini`, the `custom/` directory lets you override templates, static assets, locale files, and more. + +## Two-layer configuration + +Gogs reads configuration from two sources, in order: + +1. **Embedded defaults**: The [`conf/app.ini`](https://github.com/gogs/gogs/blob/main/conf/app.ini) file is compiled into the binary. You should never edit this file directly. +2. **Custom overrides**: Your `custom/conf/app.ini` file. Any value you set here takes precedence over the embedded default. + +This separation means binary users can upgrade without losing their settings, and source installers benefit from `custom/` being in `.gitignore`. + + + The embedded [`conf/app.ini`](https://github.com/gogs/gogs/blob/main/conf/app.ini) contains every available option with detailed inline comments. Use it as your canonical reference. + + +### Overriding a value + +You only need to include the values you want to change. For example, to set a custom repository storage path and switch to production mode: + +```ini +RUN_MODE = prod + +[repository] +ROOT = /home/git/gogs-repositories +``` + +Values support INI variable interpolation with the `%(KEY)s` syntax. The embedded defaults use this extensively, for example: + +```ini +EXTERNAL_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/ +``` + +Values also support environment variable expansion, so you can reference system environment variables directly in your configuration: + +```ini +[database] +PASSWORD = ${DATABASE_PASSWORD} +``` + + + If a password or value contains special characters (like backticks or `#`), wrap it in backticks, e.g., PASSWORD = \`p@ss#word!\`. + + + + Gogs uses [go-ini/ini](https://ini.unknwon.io/) as the configuration library, please refer to its documentation for the full syntax specification including multi-line values, key/value separators, and section handling. + + +## The `custom/` directory + +The `custom/` directory is Gogs' extension point. It sits alongside the binary by default, and contains much more than just `app.ini`. + +### Finding the path + +Run `gogs web --help` to see the custom directory path in the output. You can also override it: + +| Method | Example | +|--------|---------| +| Default | The `custom/` subdirectory next to the binary | +| Environment variable | `GOGS_CUSTOM=/etc/gogs` | + +The work directory (parent of `custom/`) can also be overridden with `GOGS_WORK_DIR`. + +### Specifying a custom config path + +Every Gogs subcommand accepts `-c, --config` to point to a configuration file at a non-default location: + +```bash +./gogs web --config /etc/gogs/app.ini +``` + +### What lives in `custom/` + +``` +custom/ +├── conf/ +│ ├── app.ini # Your configuration overrides +│ ├── auth.d/ # Authentication source files +│ │ └── *.conf +│ ├── gitignore/ # Custom .gitignore templates +│ ├── license/ # Custom license templates +│ ├── readme/ # Custom README templates +│ ├── label/ # Custom issue label sets +│ └── locale/ # Translation overrides +│ └── locale_*.ini +├── templates/ # HTML template overrides +├── public/ # Static asset overrides (CSS, JS, images) +└── robots.txt # Search engine crawling rules +``` + +All of these are optional. Gogs falls back to embedded defaults when a custom file does not exist. + +## Repository templates + +Gogs ships with embedded templates used when creating new repositories: + +| Template type | Embedded location | +|---------------|-------------------| +| `.gitignore` | `conf/gitignore/` | +| License | `conf/license/` | +| README | `conf/readme/` | +| Issue labels | `conf/label/` | + +You can add your own by placing files in the corresponding `custom/conf/` subdirectory. Custom files take priority over embedded ones with the same name, so you can also override built-in templates. + +For example, to add a custom `.gitignore` template that appears in the repository creation form: + +``` +custom/conf/gitignore/MyFramework +``` + +The `[repository] PREFERRED_LICENSES` option controls which licenses appear at the top of the selection list. The names must match filenames in `conf/license/` or `custom/conf/license/`. + +## Custom templates and static assets + +You can override any of Gogs' HTML templates or static assets by mirroring the file structure under `custom/`. + +**Templates** -- Place files in `custom/templates/` matching the path of the [embedded template](https://github.com/gogs/gogs/tree/main/templates) you want to override. See [Custom templates](/advancing/custom-templates) for details. + +**Static assets** -- Place files in `custom/public/` to override CSS, JavaScript, or images. Custom public files are served with higher priority than embedded ones. + +**Locale overrides** -- Place `locale_*.ini` files in `custom/conf/locale/` to override translation strings for any supported language. + +## Loading assets from disk + +By default, Gogs serves templates, locale files, and public assets from the binary's embedded data. If you set `LOAD_ASSETS_FROM_DISK = true` in `[server]`, Gogs will load them from the work directory instead. This is mainly useful during development. diff --git a/docs/fine-tuning/reverse-proxy.mdx b/docs/fine-tuning/reverse-proxy.mdx new file mode 100644 index 000000000..4358928d5 --- /dev/null +++ b/docs/fine-tuning/reverse-proxy.mdx @@ -0,0 +1,373 @@ +--- +title: "Reverse proxy" +description: "Host-sharing your Git service with HTTPS" +icon: "shield-halved" +--- + +Running Gogs behind a reverse proxy allows you to serve it on standard ports (80/443) with a clean and nice URL in the browser address bar, add TLS termination, and integrate with existing web server infrastructure. + + + Make sure the `EXTERNAL_URL` in your `custom/conf/app.ini` matches the actual URL users will access. When using a reverse proxy for TLS termination, keep `PROTOCOL = http` in Gogs and set `EXTERNAL_URL` to `https://`. The reverse proxy handles the encryption, and Gogs communicates with it over plain HTTP on the local network. + + +## Caddy + + + + Add the following server block to your `Caddyfile` and reload: + + ```caddy + gogs.example.com { + proxy / http://localhost:3000 + } + ``` + + Set the matching external URL in `custom/conf/app.ini`: + + ```ini + [server] + EXTERNAL_URL = https://gogs.example.com/ + ``` + + + Caddy automatically provisions TLS certificates via Let's Encrypt when you use a domain name. + + + + To serve Gogs under a subpath, note the trailing `/`: + + ```caddy + example.com { + proxy /gogs/ http://localhost:3000 + } + ``` + + Set the matching external URL in `custom/conf/app.ini`: + + ```ini + [server] + EXTERNAL_URL = https://example.com/gogs/ + ``` + + + +## NGINX + + + + Add the following `server` block inside the `http` section of your `nginx.conf` (or in a file under `sites-available`), then reload the NGINX configuration: + + ```nginx + server { + listen 80; + server_name gogs.example.com; + + location / { + proxy_pass http://localhost:3000; + } + } + ``` + + Set the matching external URL in `custom/conf/app.ini`: + + ```ini + [server] + EXTERNAL_URL = http://gogs.example.com/ + ``` + + + To serve Gogs under a subpath, note the trailing `/` on both the `location` and `proxy_pass` directives: + + ```nginx + server { + listen 80; + server_name example.com; + + location /gogs/ { + proxy_pass http://localhost:3000/; + } + } + ``` + + Set the matching external URL in `custom/conf/app.ini`: + + ```ini + [server] + EXTERNAL_URL = http://example.com/gogs/ + ``` + + + Install [Certbot](https://certbot.eff.org/) and obtain a [Let's Encrypt](https://letsencrypt.org/) certificate: + + ```bash + sudo apt install certbot python3-certbot-nginx + sudo certbot --nginx -d gogs.example.com + ``` + + Certbot will automatically modify your Nginx configuration to use HTTPS. Your Nginx server block will look similar to: + + ```nginx + server { + listen 443 ssl; + server_name gogs.example.com; + + ssl_certificate /etc/letsencrypt/live/gogs.example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/gogs.example.com/privkey.pem; + + location / { + proxy_pass http://localhost:3000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + } + + server { + listen 80; + server_name gogs.example.com; + return 301 https://$host$request_uri; + } + ``` + + Set the matching external URL in `custom/conf/app.ini`: + + ```ini + [server] + EXTERNAL_URL = https://gogs.example.com/ + ``` + + Certbot sets up automatic renewal via a cron job or systemd timer. Verify with: + + ```bash + sudo certbot renew --dry-run + ``` + + + +### Large file uploads + +If you encounter HTTP `413 Request Entity Too Large` errors when pushing large files through NGINX, add `client_max_body_size` to your server block: + +```nginx +server { + listen 80; + server_name gogs.example.com; + + client_max_body_size 50m; + + location / { + proxy_pass http://localhost:3000; + } +} +``` + + + Adjust the `client_max_body_size` value to match or exceed the maximum file size you expect users to push. The default NGINX limit is only 1 MB. + + +## Apache 2 + + + + Create or edit your virtual host configuration file (e.g. `/etc/apache2/vhost.d/gogs.conf`): + + ```apache + + ServerName gogs.example.com + + ProxyPreserveHost On + ProxyRequests off + ProxyPass / http://127.0.0.1:3000 + ProxyPassReverse / http://127.0.0.1:3000 + + ``` + + Set the matching external URL in `custom/conf/app.ini`: + + ```ini + [server] + EXTERNAL_URL = http://gogs.example.com/ + ``` + + + To serve Gogs under a subpath, omit the trailing slash after the port number in the `ProxyPass` directives: + + ```apache + + ServerName example.com + + + Order allow,deny + Allow from all + + + ProxyPass /gogs http://127.0.0.1:3000 + ProxyPassReverse /gogs http://127.0.0.1:3000 + + ``` + + Set the matching external URL in `custom/conf/app.ini`: + + ```ini + [server] + EXTERNAL_URL = http://example.com/gogs/ + ``` + + + Enable the `ssl` module in addition to the proxy modules: + + ```bash + sudo a2enmod proxy proxy_http ssl + sudo systemctl restart apache2 + ``` + + Apache virtual host configuration: + + ```apache + + ServerName gogs.example.com + + SSLEngine on + SSLCertificateFile /path/to/cert.pem + SSLCertificateKeyFile /path/to/key.pem + + ProxyPreserveHost On + ProxyRequests off + ProxyPass / http://127.0.0.1:3000/ + ProxyPassReverse / http://127.0.0.1:3000/ + + + # Redirect HTTP to HTTPS + + ServerName gogs.example.com + Redirect permanent / https://gogs.example.com/ + + ``` + + Set the matching external URL in `custom/conf/app.ini`: + + ```ini + [server] + EXTERNAL_URL = https://gogs.example.com/ + ``` + + + +## lighttpd + + + + Add the following to your lighttpd configuration: + + ```lighttpd + server.modules += ( "mod_proxy" ) + + $HTTP["host"] == "gogs.example.com" { + proxy.server = ( "" => ( ( "host" => "127.0.0.1", "port" => "3000" ) ) ) + } + ``` + + Set the matching external URL in `custom/conf/app.ini`: + + ```ini + [server] + EXTERNAL_URL = http://gogs.example.com/ + ``` + + + To serve Gogs under a subpath, requires lighttpd **1.4.46 or later** for the `proxy.header` directive: + + ```lighttpd + server.modules += ( "mod_proxy" ) + + $HTTP["url"] =~ "^/gogs/" { + proxy.server = ( "" => ( ( "host" => "localhost", "port" => "3000" ) ) ) + proxy.header = ( "map-urlpath" => ( "/gogs/" => "/" ) ) + } + ``` + + Set the matching external URL in `custom/conf/app.ini`: + + ```ini + [server] + EXTERNAL_URL = http://example.com/gogs/ + ``` + + + +## IIS + +Create a new website in IIS and use the following `web.config` file. + + + If you do not need HTTPS handled by IIS, remove the entire `RedirectToHttps` rule section from the configuration below. + + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +Then set the matching external URL in `custom/conf/app.ini`: + +```ini +[server] +EXTERNAL_URL = https://gogs.example.com/ +``` + +## Native HTTPS + +If you are not using a reverse proxy, Gogs can serve HTTPS directly. Update the `[server]` section of `custom/conf/app.ini`: + +```ini +[server] +PROTOCOL = https +EXTERNAL_URL = https://gogs.example.com/ +CERT_FILE = custom/https/cert.pem +KEY_FILE = custom/https/key.pem +``` + +| Option | Description | Default | +|--------|-------------|---------| +| `PROTOCOL` | Set to `https` to enable native TLS. | `http` | +| `CERT_FILE` | Path to the TLS certificate file (PEM format). | `custom/https/cert.pem` | +| `KEY_FILE` | Path to the TLS private key file (PEM format). | `custom/https/key.pem` | +| `TLS_MIN_VERSION` | Minimum TLS version. Options: `TLS10`, `TLS11`, `TLS12`, `TLS13`. | `TLS12` | diff --git a/docs/fine-tuning/run-as-service.mdx b/docs/fine-tuning/run-as-service.mdx new file mode 100644 index 000000000..df58699e1 --- /dev/null +++ b/docs/fine-tuning/run-as-service.mdx @@ -0,0 +1,356 @@ +--- +title: "Run as service" +description: "Configure Gogs to start automatically as a system service on Linux, macOS, and Windows" +icon: "server" +--- + +Running Gogs as a system service ensures it starts automatically on boot and restarts if it crashes. Choose the init system or service manager that matches your operating system. + +## Linux + + + + Systemd is the default init system on most modern Linux distributions (Ubuntu 16.04+, Debian 8+, CentOS 7+, Fedora, Arch Linux, etc.). + + Gogs ships with a [systemd service template](https://github.com/gogs/gogs/blob/main/scripts/systemd/gogs.service) at `scripts/systemd/gogs.service` in the installation directory. + + ### 1. Customize the service file + + Copy the template and edit it to match your installation: + + ```bash + sudo cp /home/git/gogs/scripts/systemd/gogs.service /etc/systemd/system/gogs.service + sudo vim /etc/systemd/system/gogs.service + ``` + + Here is the default service file for reference: + + ```ini + [Unit] + Description=Gogs + After=network.target + After=mariadb.service mysql.service mysqld.service postgresql.service memcached.service redis.service + + [Service] + # Uncomment the following if you have repos with lots of files + # and get an HTTP 500 error because of that + #LimitMEMLOCK=infinity + #LimitNOFILE=65535 + Type=simple + User=git + Group=git + WorkingDirectory=/home/git/gogs + ExecStart=/home/git/gogs/gogs web + Restart=always + RestartSec=2s + Environment=USER=git HOME=/home/git + + # Hardening directives (comment out if not supported by your systemd version) + ProtectSystem=full + PrivateDevices=yes + PrivateTmp=yes + NoNewPrivileges=true + + [Install] + WantedBy=multi-user.target + ``` + + Update the following values to match your environment: + - `User` and `Group` -- the system user running Gogs + - `WorkingDirectory` -- the Gogs installation directory + - `ExecStart` -- the full path to the Gogs binary + - `Environment` -- ensure `USER` and `HOME` match the Gogs user + + + If you use MySQL/MariaDB, PostgreSQL, Redis, or Memcached, the `After=` lines ensure Gogs starts after those services. Uncomment or add lines as needed for your database. + + + ### 2. Enable and start the service + + ```bash + sudo systemctl enable gogs + sudo systemctl start gogs + ``` + + ### 3. Verify the service + + ```bash + # Check status + sudo systemctl status gogs -l + + # View logs + sudo journalctl -b -u gogs + ``` + + + If you have repositories with a large number of files and encounter HTTP 500 errors, uncomment the `LimitMEMLOCK=infinity` and `LimitNOFILE=65535` directives in the service file. + + + + For Debian-based systems that do not use systemd, Gogs provides an init.d script at `scripts/init/debian/gogs`. + + ### 1. Copy and customize the script + + ```bash + sudo cp /home/git/gogs/scripts/init/debian/gogs /etc/init.d/gogs + sudo chmod +x /etc/init.d/gogs + sudo vim /etc/init.d/gogs + ``` + + Verify or update the following variables in the script: + + ```bash + WORKINGDIR=/home/git/gogs + DAEMON=$WORKINGDIR/$NAME + DAEMON_ARGS="web" + USER=git + ``` + + If you run Gogs alongside Nginx and PostgreSQL, update the init dependencies at the top of the script: + + ```bash + # Required-Start: $syslog $network $local_fs nginx postgresql + # Required-Stop: $syslog $local_fs + ``` + + ### 2. Register and start the service + + ```bash + sudo update-rc.d gogs defaults 30 70 + sudo service gogs start + ``` + + ### 3. Verify + + Visit your Gogs URL in a browser to confirm it is running. You can also check: + + ```bash + sudo service gogs status + ``` + + + For CentOS/RHEL systems, Gogs provides an init.d script at `scripts/init/centos/gogs`. + + ### 1. Copy and customize the script + + ```bash + sudo cp /home/git/gogs/scripts/init/centos/gogs /etc/rc.d/init.d/gogs + sudo chmod +x /etc/rc.d/init.d/gogs + sudo vim /etc/rc.d/init.d/gogs + ``` + + Verify or update the following variables: + + ```bash + NAME=gogs + GOGS_HOME=/home/git/gogs + GOGS_PATH=${GOGS_HOME}/$NAME + GOGS_USER=git + LOGPATH=${GOGS_HOME}/log + ``` + + + You can override these defaults by creating `/etc/sysconfig/gogs` with your custom values. + + + ### 2. Register and start the service + + ```bash + sudo chkconfig gogs on + sudo service gogs start + ``` + + ### 3. Verify + + ```bash + sudo service gogs status + ``` + + + For Gentoo and other distributions using OpenRC, create a service script at `/etc/init.d/gogs`: + + ```bash + #!/sbin/openrc-run + + description="Gogs - A painless self-hosted Git service" + command="/home/git/gogs/gogs" + command_args="web" + command_user="git" + command_background=true + pidfile="/var/run/gogs.pid" + directory="/home/git/gogs" + + depend() { + need net + after mysql postgresql + } + ``` + + Make it executable and enable it: + + ```bash + sudo chmod +x /etc/init.d/gogs + sudo rc-update add gogs default + sudo rc-service gogs start + ``` + + + +## Windows + +On Windows, Gogs can run as a native Windows service using either the builtin `minwinsvc` support or the third-party NSSM tool. + + + + Gogs binaries built with the `minwinsvc` tag (release archive name that contains `mws`) support running as a native Windows service. + + ### 1. Configure Gogs for Windows + + Edit `C:\gogs\custom\conf\app.ini`: + + ```ini + RUN_USER = COMPUTERNAME$ + ``` + + Replace `COMPUTERNAME` with the output of `echo %COMPUTERNAME%` in a command prompt. For example, if the computer name is `USER-PC`, set `RUN_USER = USER-PC$`. + + Configure the server section: + + ```ini + [server] + DOMAIN = gogs + PROTOCOL = http + HTTP_ADDR = 127.0.1.1 + HTTP_PORT = 80 + OFFLINE_MODE = true + EXTERNAL_URL = http://gogs/ + ``` + + + Using an address in the `127.x.x.x` range (other than `127.0.0.1`) prevents port conflicts with other local services while keeping traffic local. Any address from `127.0.0.2` to `127.254.254.254` works. + + + ### 2. Add a hosts entry + + Open Notepad as Administrator and edit `C:\Windows\System32\drivers\etc\hosts`: + + ```text + # Gogs local HTTPd + 127.0.1.1 gogs + ``` + + ### 3. Create and start the service + + Open a command prompt as Administrator: + + ```cmd + sc create gogs start= auto binPath= "\"C:\gogs\gogs.exe\" web --config \"C:\gogs\custom\conf\app.ini\"" + ``` + + + There must be a space after each `=` in the `sc create` command. This is a Windows `sc.exe` syntax requirement. + + + Start the service: + + ```cmd + net start gogs + ``` + + You should see: + + ```text + The gogs service is starting. + The gogs service was started successfully. + ``` + + + Windows services run from `%WINDIR%\System32` by default. Always use **absolute paths** in `app.ini` for data directories and database files: + + ```ini + [server] + APP_DATA_PATH = c:/gogs/data + + [database] + PATH = c:/gogs/data/gogs.db + ``` + + Use forward slashes (`/`) in paths to avoid escape character issues. + + + + [NSSM (Non-Sucking Service Manager)](https://nssm.cc/) provides more control over service configuration and automatic restart behavior. + + ### 1. Install NSSM + + Download [nssm.exe](https://nssm.cc/download) for your architecture (32-bit or 64-bit) and place it in a directory on your `PATH`. + + ### 2. Install the Gogs service + + Open a command prompt as Administrator: + + ```cmd + nssm install gogs + ``` + + The NSSM service installer GUI will appear. Configure the following tabs: + + **Application tab:** + - **Path:** `C:\gogs\gogs.exe` + - **Startup directory:** `C:\gogs` + - **Arguments:** `web` + + **Details tab:** + - **Display name:** `Gogs` + - **Description:** `Gogs is a painless self-hosted Git service.` + - **Startup type:** `Automatic (Delayed Start)` + + + Delayed start means the service will begin approximately two minutes after non-delayed services, reducing impact on boot time. + + + **I/O tab:** + - **Output (stdout):** `C:\gogs\log\gogs-nssm.txt` + - **Error (stderr):** `C:\gogs\log\gogs-nssm.txt` + + **File rotation tab:** + - Check **Rotate files** + - **Restrict rotation to files bigger than:** `1000000` bytes + + **Environment tab:** + - **Environment variables:** `PATH=%PATH%;C:\gogs;C:\Program Files (x86)\Git\bin` + + + The environment variable ensures both `gogs.exe` and `git.exe` are available on the service's PATH at runtime. + + + Click **Install service** to complete the setup. + + ### 3. Start and manage the service + + ```cmd + nssm start gogs + ``` + + You should see: + + ```text + gogs: START: The operation completed successfully. + ``` + + Verify by checking `C:\gogs\log\gogs-nssm.txt` for Gogs startup output, ending with lines like: + + ```text + [I] Run Mode: Production + [I] Listen: http://127.0.1.1:80 + ``` + + To restart after configuration changes: + + ```cmd + nssm restart gogs + ``` + + NSSM will automatically attempt to restart Gogs if it crashes. + + diff --git a/docs/getting-started/installation.mdx b/docs/getting-started/installation.mdx new file mode 100644 index 000000000..694af3b8d --- /dev/null +++ b/docs/getting-started/installation.mdx @@ -0,0 +1,77 @@ +--- +title: "Installation" +description: "Get your own Git service up and running in minutes" +icon: "download" +--- + +## Prerequisites + +1. Gogs requires use of one of the following database backends: + - MySQL, >= 5.7 + - PostgreSQL, >= 9.6 + - SQLite 3 +1. Git, >= 1.8.3, on both server and client side +1. SSH server + - Only required when enable Git over SSH, e.g., `git clone git@gogs.example.com:...` + - Builtin SSH server is also available + + +**For Windows users:** + +- When using builtin SSH server, you still need to have `ssh-keygen` installed and available via the `%PATH%` environment variable. +- Use [OpenSSH](https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse) on Windows 10 or newer. +- [Cygwin OpenSSH](http://docs.oracle.com/cd/E24628_01/install.121/e22624/preinstall_req_cygwin_ssh.htm) or [Copssh](https://www.itefix.net/copssh) are available on older versions of Windows. + + +## Initialize database + +If you choose to use MySQL or PostgreSQL as your database backend, you need to first complete the initial database creation. + + + + Create a database user and database: + + ```bash + psql -c "CREATE USER gogs WITH PASSWORD '{YOUR_PASSWORD}';" + psql -c "CREATE DATABASE gogs OWNER gogs ENCODING 'UTF8';" + ``` + + + Use the [bundled script](https://github.com/gogs/gogs/blob/main/scripts/mysql.sql) to create the database with proper encoding: + + ```zsh + mysql -u root -p < scripts/mysql.sql + ``` + + + +## Installation methods + + + + All release archives containing pre-built binaries are available in [dl.gogs.io](https://dl.gogs.io) and [GitHub releases](https://github.com/gogs/gogs/releases). + + + **For Windows users:** + + Release archives containing `mws` come with built-in Windows service support. If you prefer to manage the service using [NSSM](https://nssm.cc), download the standard version instead. + + + Once extracted the archive, run `./gogs web` to start the server. Use `./gogs web --help` to see all available options. + + + Two types of Docker images are provided: + 1. [docker-next](https://github.com/gogs/gogs/blob/main/docker-next/README.md): The modern, non-root, and cloud-native version, but with no container options. + 1. [docker](https://github.com/gogs/gogs/blob/main/docker/README.md): The traditional, root-privileged version, with extensive container options. + + + + All packages listed below are packaged by third-party maintainers. Use at your own risk. + + + |Source| Description | Note| + |------|------------------------------------------|-----| + |Packager.io ([link](https://packager.io/gh/gogs/gogs))|Every commit of `main`|After installation, place custom configuration in `/etc/default/gogs`.| + |Arch User Repository ([link](https://aur.archlinux.org/packages/gogs/))| Stable releases | Detailed instructions available in the [Arch Linux Wiki entry](https://wiki.archlinux.org/title/Gogs). | + + diff --git a/docs/getting-started/introduction.mdx b/docs/getting-started/introduction.mdx new file mode 100644 index 000000000..05bd7753f --- /dev/null +++ b/docs/getting-started/introduction.mdx @@ -0,0 +1,128 @@ +--- +title: "Introduction" +sidebarTitle: "Introduction" +description: "The painless way to host your own Git service" +icon: "book-open" +--- + + + + + +## Vision + +The Gogs project aims to build a simple, stable and extensible self-hosted Git service that can be set up in the most painless way. With Go, this can be done with an independent binary distribution across all platforms that Go supports, including Linux, macOS, Windows and ARM-based systems. + +## Core values + +- **Simple to install**: Run the binary, or run as a Docker container. +- **Cross-platform**: Runs on every platform that Go toolchain supports. +- **Lightweight**: Unrealistically low resource consumption to get started. Only got 64 MiB of RAM and a quarter of vCPU? No problem! +- **Open source**: MIT-licensed since 2014, all source code available in public. + +## Sponsors + +The growth of the Gogs project wasn't possible without our world-class sponsors! + + + + + + + + + + + + + + + + + + + + + + + +## Quickstart + + + + Get your own Git service up and running in minutes. + + + Fine tune your instance exactly the way you want. + + + Discover powerful and advanced features. + + + Keep up the version and energy. + + diff --git a/docs/images/favicon.svg b/docs/images/favicon.svg new file mode 100644 index 000000000..d94c66ddd --- /dev/null +++ b/docs/images/favicon.svg @@ -0,0 +1,28 @@ + + + + 编组 7 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/images/logo-dark.svg b/docs/images/logo-dark.svg new file mode 100644 index 000000000..81c617ae2 --- /dev/null +++ b/docs/images/logo-dark.svg @@ -0,0 +1,22 @@ + + + logo组合-反白-1 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/images/logo-light.svg b/docs/images/logo-light.svg new file mode 100644 index 000000000..1df64b9bc --- /dev/null +++ b/docs/images/logo-light.svg @@ -0,0 +1,22 @@ + + + logo组合-normal + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/images/sponsors/buildkite-dark.svg b/docs/images/sponsors/buildkite-dark.svg new file mode 100644 index 000000000..af5c99ec9 --- /dev/null +++ b/docs/images/sponsors/buildkite-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/images/sponsors/buildkite-light.svg b/docs/images/sponsors/buildkite-light.svg new file mode 100644 index 000000000..8df8e5e3f --- /dev/null +++ b/docs/images/sponsors/buildkite-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/images/sponsors/crowdin-dark.svg b/docs/images/sponsors/crowdin-dark.svg new file mode 100644 index 000000000..c4c15b7b1 --- /dev/null +++ b/docs/images/sponsors/crowdin-dark.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/docs/images/sponsors/crowdin-light.svg b/docs/images/sponsors/crowdin-light.svg new file mode 100644 index 000000000..f8813752a --- /dev/null +++ b/docs/images/sponsors/crowdin-light.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/docs/images/sponsors/digitalocean-dark.png b/docs/images/sponsors/digitalocean-dark.png new file mode 100755 index 000000000..8898df7f9 Binary files /dev/null and b/docs/images/sponsors/digitalocean-dark.png differ diff --git a/docs/images/sponsors/digitalocean-light.png b/docs/images/sponsors/digitalocean-light.png new file mode 100755 index 000000000..ee98b493e Binary files /dev/null and b/docs/images/sponsors/digitalocean-light.png differ diff --git a/docs/images/sponsors/mintlify-dark.svg b/docs/images/sponsors/mintlify-dark.svg new file mode 100644 index 000000000..4553d4141 --- /dev/null +++ b/docs/images/sponsors/mintlify-dark.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/images/sponsors/mintlify-light.svg b/docs/images/sponsors/mintlify-light.svg new file mode 100644 index 000000000..744eb7722 --- /dev/null +++ b/docs/images/sponsors/mintlify-light.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/scripts/ads.js b/docs/scripts/ads.js new file mode 100644 index 000000000..4ee448198 --- /dev/null +++ b/docs/scripts/ads.js @@ -0,0 +1,68 @@ +// wwads.cn: above table of contents. Carbon Ads: below table of contents. +(function () { + "use strict"; + + var CARBON_ID = "gogs-carbon-ad"; + var WWADS_ID = "gogs-wwads"; + + // Load the wwads.cn global script (skipped on localhost — ad unit + // 97 is registered for gogs.io and the API rejects other origins). + var isProduction = location.hostname !== "localhost"; + if (isProduction) { + var wwScript = document.createElement("script"); + wwScript.src = "https://cdn.wwads.cn/js/makemoney.js"; + wwScript.async = true; + document.head.appendChild(wwScript); + } + + function injectCarbonAd() { + if (document.getElementById(CARBON_ID)) return; + + var toc = document.getElementById("table-of-contents"); + if (!toc) return; + + var container = document.createElement("div"); + container.id = CARBON_ID; + + var carbon = document.createElement("script"); + carbon.async = true; + carbon.type = "text/javascript"; + carbon.src = + "//cdn.carbonads.com/carbon.js?serve=CKYILK3U&placement=gogsio"; + carbon.id = "_carbonads_js"; + container.appendChild(carbon); + + toc.appendChild(container); + } + + function injectWwads() { + if (document.getElementById(WWADS_ID)) return; + + var toc = document.getElementById("table-of-contents"); + if (!toc) return; + + var container = document.createElement("div"); + container.id = WWADS_ID; + + var wwads = document.createElement("div"); + wwads.className = "wwads-cn wwads-horizontal"; + wwads.setAttribute("data-id", "97"); + container.appendChild(wwads); + + toc.insertBefore(container, toc.firstChild); + } + + function injectAds() { + injectCarbonAd(); + injectWwads(); + } + + // Re-inject when the content is replaced during SPA navigation. + var debounce; + new MutationObserver(function () { + clearTimeout(debounce); + debounce = setTimeout(injectAds, 200); + }).observe(document.documentElement, { childList: true, subtree: true }); + + injectAds(); +})(); diff --git a/docs/scripts/title.js b/docs/scripts/title.js new file mode 100644 index 000000000..26bb21e7f --- /dev/null +++ b/docs/scripts/title.js @@ -0,0 +1,15 @@ +// Fix landing page tab title: "Introduction - ..." → "Gogs - ..." +(function () { + var old = "Introduction - Gogs"; + var fix = function () { + if (document.title.startsWith(old)) { + document.title = document.title.replace(old, "Gogs"); + } + }; + new MutationObserver(fix).observe( + document.querySelector("title") || document.head, + { childList: true, subtree: true, characterData: true } + ); + fix(); + setTimeout(fix, 100); +})(); diff --git a/docs/styles/style.css b/docs/styles/style.css new file mode 100644 index 000000000..a497da92d --- /dev/null +++ b/docs/styles/style.css @@ -0,0 +1,48 @@ +/* Fix sidebar HTTP method badge overflow for PATCH (5-char badge exceeds the default 32px container) */ +.method-nav-pill { + width: 2.5rem !important; +} + +/* Carbon Ads — below table of contents */ +#gogs-carbon-ad { + margin-top: 1rem; + border-top: 1px solid hsl(0 0% 90%); +} +.dark #gogs-carbon-ad { + border-top-color: hsl(0 0% 22%); +} +#carbonads { + margin-top: 1.5rem; + display: block; + padding: 0.75rem; + border-radius: 6px; + background: hsl(0 0% 98%); + font-size: 0.8125rem; + line-height: 1.4; +} +.dark #carbonads { + color: darkgray; + background: hsl(0 0% 12%); +} +#carbonads .carbon-img { + display: flex; + justify-content: center; + margin-bottom: 0.5rem; +} +#carbonads .carbon-img img { + max-width: 100%; + border-radius: 4px; +} + +/* wwads — above table of contents */ +#gogs-wwads { + margin-top: -1.5rem; + margin-bottom: 1.5rem; + padding-bottom: 1.5rem; + border-bottom: 1px solid hsl(0 0% 90%); +} +.dark #gogs-wwads { + color: darkgray; + background: hsl(0 0% 12%); + border-bottom-color: hsl(0 0% 22%); +}