mirror of
https://github.com/gogs/gogs.git
synced 2026-02-28 09:10:57 +01:00
Compare commits
48 Commits
v0.14.1
...
latest-com
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df467d8ff1 | ||
|
|
36d56d5525 | ||
|
|
5f17b670b3 | ||
|
|
ea682c5bbc | ||
|
|
9001a68cdd | ||
|
|
295bfba729 | ||
|
|
ac21150a53 | ||
|
|
a000f0c7a6 | ||
|
|
a976fd2f9c | ||
|
|
441c64d7bd | ||
|
|
5c67d47512 | ||
|
|
94d6e53dc2 | ||
|
|
a1fa62b270 | ||
|
|
317e28b908 | ||
|
|
069d3535d6 | ||
|
|
81ee883644 | ||
|
|
400ae7bd28 | ||
|
|
630ae0b3b0 | ||
|
|
3c358ede6d | ||
|
|
48500aa2b0 | ||
|
|
785157ba1f | ||
|
|
1c8016a27b | ||
|
|
00c36d8d8a | ||
|
|
3747cd9058 | ||
|
|
08e7cfd76c | ||
|
|
9dd3e58f7b | ||
|
|
edc1478f6b | ||
|
|
bb86d12c36 | ||
|
|
bf17cc6c69 | ||
|
|
6d56105f8f | ||
|
|
ed5d02e036 | ||
|
|
5874791a57 | ||
|
|
17ad3d3425 | ||
|
|
9b2a967e45 | ||
|
|
e80635a449 | ||
|
|
47bccf292d | ||
|
|
38def73489 | ||
|
|
6cf6422b88 | ||
|
|
8d8d66ec1d | ||
|
|
7ea2c4093f | ||
|
|
7ebfb202e4 | ||
|
|
7b8c560f15 | ||
|
|
a636dcf678 | ||
|
|
3dcb74be39 | ||
|
|
7ad425025e | ||
|
|
85abee4b9b | ||
|
|
997c3c5eab | ||
|
|
a5ddb2665e |
13
.claude/commands/ghsa.md
Normal file
13
.claude/commands/ghsa.md
Normal file
@@ -0,0 +1,13 @@
|
||||
Analyze and help fix the GitHub Security Advisory (GHSA) at: $ARGUMENTS
|
||||
|
||||
Steps:
|
||||
1. Fetch the GHSA page using `gh api repos/gogs/gogs/security-advisories` and understand the vulnerability details (description, severity, affected versions, CWE).
|
||||
2. Verify the reported vulnerability actually exists, and why.
|
||||
3. Identify the affected code in this repository.
|
||||
4. Propose a fix with a clear explanation of the root cause and how the fix addresses it. Check for prior art in the codebase to stay consistent with existing patterns.
|
||||
5. Implement the fix. Only add tests when there is something meaningful to test at our layer.
|
||||
6. Run all the usual build and test commands.
|
||||
7. If a changelog entry is warranted (user will specify), add it to CHANGELOG.md with a placeholder for the PR link.
|
||||
8. Create a branch named after the GHSA ID, commit, and push.
|
||||
9. Create a pull request with a proper title and description, do not reveal too much detail and link the GHSA.
|
||||
10. If a changelog entry was added, update it with the PR link, then commit and push again.
|
||||
6
.github/CONTRIBUTING.md
vendored
6
.github/CONTRIBUTING.md
vendored
@@ -29,7 +29,7 @@ In addition to the general guides with open source contributions, you would also
|
||||
|
||||
### Ask for help
|
||||
|
||||
Before opening an issue, please make sure the problem you're encountering isn't already addressed on the [Troubleshooting](https://gogs.io/docs/intro/troubleshooting.html) and [FAQs](https://gogs.io/docs/intro/faqs.html) pages.
|
||||
Before opening an issue, please make sure the problem you're encountering isn't already addressed on the [Troubleshooting](https://gogs.io/asking/troubleshooting) and [FAQs](https://gogs.io/asking/faq) pages.
|
||||
|
||||
### Create a new issue
|
||||
|
||||
@@ -65,12 +65,12 @@ Contributing to another codebase is not as simple as code changes, it is also ab
|
||||
|
||||
### Things we do not accept
|
||||
|
||||
1. Updates to locale files (`conf/locale_xx-XX.ini`) other than the `conf/locale_en-US.ini`. Please read the [guide for localizing Gogs](https://gogs.io/docs/features/i18n).
|
||||
1. Updates to locale files (`conf/locale_xx-XX.ini`) other than the `conf/locale_en-US.ini`. Please read the [guide for localizing Gogs](https://gogs.io/advancing/localization).
|
||||
1. Docker compose files.
|
||||
|
||||
### Coding guidelines
|
||||
|
||||
1. Please read the Sourcegraph's [Go style guide](https://docs.sourcegraph.com/dev/background-information/languages/go).
|
||||
1. Please read the Sourcegraph's [Go style guide](https://github.com/sourcegraph/sourcegraph-public-snapshot/blob/main/doc/dev/background-information/languages/go.md).
|
||||
1. **NO** direct modifications to `.css` files, `.css` files are all generated by `.less` files. You can regenerate `.css` files by executing `task less`.
|
||||
|
||||
## Your PR is merged!
|
||||
|
||||
@@ -22,16 +22,14 @@ On the `main` branch:
|
||||
|
||||
On the release branch:
|
||||
|
||||
- [ ] [Update the hard-coded version](https://github.com/gogs/gogs/commit/f17e7d5a2c36c52a1121d2315f3d75dcd8053b89) to the current release, e.g. `0.14.0+dev` -> `0.14.0`.
|
||||
- [ ] [Update the hard-coded version](https://github.com/gogs/gogs/commit/f0e3cd90f8d7695960eeef2e4e54b2e717302f6c) to the current release, e.g. `0.14.0+dev` -> `0.14.0`.
|
||||
- [ ] Wait for GitHub Actions to complete and no failed jobs.
|
||||
- [ ] Publish new RC releases (e.g. `v0.14.0-rc.1`, `v0.14.0-rc.2`) to ensure Docker and release workflows both succeed.
|
||||
- ⚠️ **Make sure the tag is created on the release branch**.
|
||||
- [ ] Publish new RC releases (e.g. `v0.14.0-rc.1`, `v0.14.0-rc.2`) ⚠️ **on the release branch** ⚠️ and ensure Docker and release workflows both succeed.
|
||||
- [ ] Pull down the Docker image and [run through application setup](https://github.com/gogs/gogs/blob/main/docker/README.md) to make sure nothing blows up.
|
||||
- [ ] Download one of the release archives and run through application setup to make sure nothing blows up.
|
||||
- [ ] Publish a new [GitHub release](https://github.com/gogs/gogs/releases) with entries from [CHANGELOG](https://github.com/gogs/gogs/blob/main/CHANGELOG.md) for the current minor release.
|
||||
- ⚠️ **Make sure the tag is created on the release branch**.
|
||||
- [ ] [Wait for a new image tag for the current release](https://github.com/gogs/gogs/actions/workflows/docker.yml?query=event%3Arelease) to be created automatically on both [Docker Hub](https://hub.docker.com/r/gogs/gogs/tags) and [GitHub Container registry](https://github.com/gogs/gogs/pkgs/container/gogs).
|
||||
- [ ] [Push a new Docker image tag](https://github.com/gogs/gogs/blob/main/docs/dev/release/release_new_version.md#update-docker-image-tag) as `<MAJOR>.<MINOR>` to both [Docker Hub](https://hub.docker.com/r/gogs/gogs/tags) and [GitHub Container registry](https://github.com/gogs/gogs/pkgs/container/gogs), e.g.:
|
||||
- [ ] Publish a new [GitHub release](https://github.com/gogs/gogs/releases) ⚠️ **on the release branch** ⚠️ with entries from [CHANGELOG](https://github.com/gogs/gogs/blob/main/CHANGELOG.md) for the current minor release.
|
||||
- [ ] [Wait for new image tags for the current release](https://github.com/gogs/gogs/actions/workflows/docker.yml?query=event%3Arelease) to be created automatically on both [Docker Hub](https://hub.docker.com/r/gogs/gogs/tags) and [GitHub Container registry](https://github.com/gogs/gogs/pkgs/container/gogs).
|
||||
- Pull down the Docker image and [run through application setup](https://github.com/gogs/gogs/blob/main/docker/README.md) to make sure nothing blows up.
|
||||
- [ ] Download all release archives and [generate SHA256 checksum](https://github.com/gogs/gogs/blob/main/docs/dev/release/sha256.sh) for all binaries to the file `checksum_sha256.txt`.
|
||||
- [ ] Upload all archives and `checksum_sha256.txt` to https://dl.gogs.io.
|
||||
|
||||
@@ -39,7 +37,6 @@ On the release branch:
|
||||
|
||||
On the `main` branch:
|
||||
|
||||
- [ ] Publish [GitHub security advisories](https://github.com/gogs/gogs/security) for security patches included in the release.
|
||||
- [ ] Update the repository mirror on [Gitee](https://gitee.com/unknwon/gogs).
|
||||
- [ ] Create a new release announcement in [Discussions](https://github.com/gogs/gogs/discussions/categories/announcements).
|
||||
- [ ] Send a tweet on the [official Twitter account](https://twitter.com/GogsHQ) for the minor release.
|
||||
|
||||
@@ -22,19 +22,16 @@ On the release branch:
|
||||
|
||||
- [ ] [Update the hard-coded version](https://github.com/gogs/gogs/commit/f0e3cd90f8d7695960eeef2e4e54b2e717302f6c) to the current release, e.g. `0.12.0` -> `0.12.1`.
|
||||
- [ ] Wait for GitHub Actions to complete and no failed jobs.
|
||||
- [ ] Publish new RC releases in [GitHub release](https://github.com/gogs/gogs/releases) (e.g. `v0.12.0-rc.1`, `v0.12.0-rc.2`) to ensure Docker workflow succeeds.
|
||||
- ⚠️ **Make sure the tag is created on the release branch**.
|
||||
- Pull down the Docker image and [run through application setup](https://github.com/gogs/gogs/blob/main/docker/README.md) to make sure nothing blows up.
|
||||
- [ ] Publish new RC releases in [GitHub release](https://github.com/gogs/gogs/releases) (e.g. `v0.12.0-rc.1`, `v0.12.0-rc.2`) ⚠️ **on the release branch** ⚠️ and ensure Docker workflow succeeds.
|
||||
- [ ] Pull down the Docker image and [run through application setup](https://github.com/gogs/gogs/blob/main/docker/README.md) to make sure nothing blows up.
|
||||
- [ ] Download one of the release archives and run through application setup to make sure nothing blows up.
|
||||
- [ ] Publish a new [GitHub release](https://github.com/gogs/gogs/releases) with entries from [CHANGELOG](https://github.com/gogs/gogs/blob/main/CHANGELOG.md) for the current patch release and all previous releases with same minor version.
|
||||
- ⚠️ **Make sure the tag is created on the release branch**.
|
||||
- [ ] Publish a new [GitHub release](https://github.com/gogs/gogs/releases) ⚠️ **on the release branch** ⚠️ with entries from [CHANGELOG](https://github.com/gogs/gogs/blob/main/CHANGELOG.md) for the current patch release and all previous releases with same minor version.
|
||||
- [ ] Update all previous GitHub releases with same minor version with the warning:
|
||||
```
|
||||
**ℹ️ Heads up! There is a new patch release [0.12.1](https://github.com/gogs/gogs/releases/tag/v0.12.1) available, we recommend directly installing or upgrading to that version.**
|
||||
```
|
||||
- [ ] [Wait for a new image tag for the current release](https://github.com/gogs/gogs/actions/workflows/docker.yml?query=event%3Arelease) to be created automatically on both [Docker Hub](https://hub.docker.com/r/gogs/gogs/tags) and [GitHub Container registry](https://github.com/gogs/gogs/pkgs/container/gogs).
|
||||
- [ ] [Wait for new image tags for the current release](https://github.com/gogs/gogs/actions/workflows/docker.yml?query=event%3Arelease) to be created automatically on both [Docker Hub](https://hub.docker.com/r/gogs/gogs/tags) and [GitHub Container registry](https://github.com/gogs/gogs/pkgs/container/gogs).
|
||||
- Pull down the Docker image and [run through application setup](https://github.com/gogs/gogs/blob/main/docker/README.md) to make sure nothing blows up.
|
||||
- [ ] [Update Docker image tag](https://www.notion.so/jcunknwon/Cheatsheet-and-playbooks-c3b053da42114411bd27285cd065b2a6?source=copy_link#1654f105c63f80958d96cd72e2f5df69) for the minor release `<MAJOR>.<MINOR>` on both [Docker Hub](https://hub.docker.com/r/gogs/gogs/tags) and [GitHub Container registry](https://github.com/gogs/gogs/pkgs/container/gogs).
|
||||
- [ ] Download all release archives and [generate SHA256 checksum](https://github.com/gogs/gogs/blob/main/docs/dev/release/sha256.sh) for all binaries to the file `checksum_sha256.txt`.
|
||||
- [ ] Upload all archives and `checksum_sha256.txt` to https://dl.gogs.io.
|
||||
|
||||
|
||||
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
|
||||
12
.github/workflows/docker.yml
vendored
12
.github/workflows/docker.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
@@ -173,7 +173,7 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
@@ -212,7 +212,7 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
@@ -274,7 +274,7 @@ jobs:
|
||||
echo "TAGS<<EOF" >> $GITHUB_ENV
|
||||
echo "$TAGS" >> $GITHUB_ENV
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
@@ -343,7 +343,7 @@ jobs:
|
||||
echo "TAGS<<EOF" >> $GITHUB_ENV
|
||||
echo "$TAGS" >> $GITHUB_ENV
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
|
||||
45
.github/workflows/go.yml
vendored
45
.github/workflows/go.yml
vendored
@@ -29,12 +29,12 @@ jobs:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: 1.25.x
|
||||
go-version: 1.26.x
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2.0.0
|
||||
with:
|
||||
@@ -61,23 +61,21 @@ jobs:
|
||||
name: Test
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 1.25.x ]
|
||||
go-version: [ 1.26.x ]
|
||||
platform: [ ubuntu-latest, macos-latest ]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Run tests with coverage
|
||||
run: go test -shuffle=on -v -race -coverprofile=coverage -covermode=atomic ./...
|
||||
- name: Upload coverage report to Codecov
|
||||
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
|
||||
with:
|
||||
file: ./coverage
|
||||
flags: unittests
|
||||
run: |
|
||||
go test -shuffle=on -v -race -coverprofile=coverage -covermode=atomic -json ./... > test-report.json
|
||||
go install github.com/mfridman/tparse@latest
|
||||
tparse -all -file=test-report.json
|
||||
- name: Send email on failure
|
||||
uses: unknwon/send-email-on-failure@89339a1bc93f4ad1d30f3b7e4911fcba985c9adb # v1
|
||||
if: ${{ failure() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
@@ -91,11 +89,11 @@ jobs:
|
||||
name: Test Windows
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 1.25.x ]
|
||||
go-version: [ 1.26.x ]
|
||||
platform: [ windows-latest ]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
@@ -103,11 +101,6 @@ jobs:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Run tests with coverage
|
||||
run: go test -shuffle=on -v -coverprofile=coverage -covermode=atomic ./...
|
||||
- name: Upload coverage report to Codecov
|
||||
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
|
||||
with:
|
||||
file: ./coverage
|
||||
flags: unittests
|
||||
- name: Send email on failure
|
||||
uses: unknwon/send-email-on-failure@89339a1bc93f4ad1d30f3b7e4911fcba985c9adb # v1
|
||||
if: ${{ failure() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
@@ -119,7 +112,7 @@ jobs:
|
||||
name: Postgres
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 1.25.x ]
|
||||
go-version: [ 1.26.x ]
|
||||
platform: [ ubuntu-latest ]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
services:
|
||||
@@ -135,14 +128,17 @@ jobs:
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Run tests with coverage
|
||||
run: go test -shuffle=on -v -race -coverprofile=coverage -covermode=atomic ./internal/database/...
|
||||
run: |
|
||||
go test -shuffle=on -v -race -coverprofile=coverage -covermode=atomic -json ./internal/database/... > test-report.json
|
||||
go install github.com/mfridman/tparse@latest
|
||||
tparse -all -file=test-report.json
|
||||
env:
|
||||
GOGS_DATABASE_TYPE: postgres
|
||||
PGPORT: 5432
|
||||
@@ -155,20 +151,23 @@ jobs:
|
||||
name: MySQL
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 1.25.x ]
|
||||
go-version: [ 1.26.x ]
|
||||
platform: [ ubuntu-22.04 ] # Use the lowest version possible for backwards compatibility
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- name: Start MySQL server
|
||||
run: sudo systemctl start mysql
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Run tests with coverage
|
||||
run: go test -shuffle=on -v -race -coverprofile=coverage -covermode=atomic ./internal/database/...
|
||||
run: |
|
||||
go test -shuffle=on -v -race -coverprofile=coverage -covermode=atomic -json ./internal/database/... > test-report.json
|
||||
go install github.com/mfridman/tparse@latest
|
||||
tparse -all -file=test-report.json
|
||||
env:
|
||||
GOGS_DATABASE_TYPE: mysql
|
||||
MYSQL_USER: root
|
||||
|
||||
16
.github/workflows/release.yml
vendored
16
.github/workflows/release.yml
vendored
@@ -40,17 +40,17 @@ jobs:
|
||||
- {goos: windows, goarch: arm64, suffix: "_mws", tags: minwinsvc}
|
||||
- {goos: windows, goarch: "386", suffix: "_mws", tags: minwinsvc}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Setup Go
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: 1.25.x
|
||||
go-version: 1.26.x
|
||||
- name: Determine version
|
||||
id: version
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "release" ]; then
|
||||
echo "version=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${{ github.event.release.tag_name }}" | sed 's/version=v/version=/' >> "$GITHUB_OUTPUT"
|
||||
echo "release_tag=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT"
|
||||
elif [ "${{ github.event_name }}" = "push" ] && [ "${{ github.ref }}" = "refs/heads/main" ]; then
|
||||
echo "version=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
|
||||
@@ -81,7 +81,7 @@ jobs:
|
||||
-X \"gogs.io/gogs/internal/conf.BuildCommit=$(git rev-parse HEAD)\"
|
||||
" \
|
||||
$TAGS_FLAG \
|
||||
-trimpath -o "$BINARY_NAME"
|
||||
-trimpath -o "$BINARY_NAME" ./cmd/gogs
|
||||
- name: Prepare archive contents
|
||||
run: |
|
||||
mkdir -p dist/gogs
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
BINARY_NAME="gogs.exe"
|
||||
fi
|
||||
cp "$BINARY_NAME" dist/gogs/
|
||||
cp LICENSE README.md README_ZH.md dist/gogs/
|
||||
cp LICENSE README.md dist/gogs/
|
||||
cp -r scripts dist/gogs/
|
||||
- name: Create archives
|
||||
working-directory: dist
|
||||
@@ -112,14 +112,14 @@ jobs:
|
||||
if [ "${{ github.event_name }}" != "release" ]; then
|
||||
git tag -f "$RELEASE_TAG"
|
||||
git push origin "$RELEASE_TAG" --force || true
|
||||
|
||||
|
||||
RELEASE_TITLE="Release Archive Testing"
|
||||
RELEASE_NOTES="Automated testing release for workflow development."
|
||||
if [ "$RELEASE_TAG" = "latest-commit-build" ]; then
|
||||
RELEASE_TITLE="Latest Commit Build"
|
||||
RELEASE_NOTES="Automated build from the latest commit on main branch. This release is updated automatically with every push to main."
|
||||
fi
|
||||
|
||||
|
||||
gh release view "$RELEASE_TAG" || gh release create "$RELEASE_TAG" --title "$RELEASE_TITLE" --notes "$RELEASE_NOTES" --prerelease
|
||||
fi
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ This applies to all texts, including but not limited to UI, documentation, code
|
||||
|
||||
- Prefer `task` command over vanilla `go` command when available. Use `--force` flag when necessary.
|
||||
- Run `task lint` after every time you finish changing code, and fix all linter errors.
|
||||
- Run `go mod tidy` after every time you change `go.mod`, do not manually edit `go.sum` file.
|
||||
|
||||
## Tool-use guidance
|
||||
|
||||
@@ -28,5 +29,5 @@ This applies to all texts, including but not limited to UI, documentation, code
|
||||
## Source code control
|
||||
|
||||
- When pushing changes to a pull request from a fork, use SSH address and do not add remote.
|
||||
- Never automatically executes commands that touches Git history even if the session does not require approvals, including but not limited to `rebase`, `commit`, `push`, `pull`, `reset`, `amend`. Exceptions are only allowed case-by-case.
|
||||
- Do not amend commits unless being explicitly asked to do so.
|
||||
- Never commit on the `main` branch directly unless being explicitly asked to do so. A single ask only grants a single commit action on the `main` branch.
|
||||
- Never amend commits unless being explicitly asked to do so.
|
||||
|
||||
15
CHANGELOG.md
15
CHANGELOG.md
@@ -4,7 +4,20 @@ All notable changes to Gogs are documented in this file.
|
||||
|
||||
## 0.15.0+dev (`main`)
|
||||
|
||||
## 0.14.0
|
||||
### Fixed
|
||||
|
||||
- _Security:_ Cross-repository LFS object overwrite via missing content hash verification. [#8166](https://github.com/gogs/gogs/pull/8166) - [GHSA-gmf8-978x-2fg2](https://github.com/gogs/gogs/security/advisories/GHSA-gmf8-978x-2fg2)
|
||||
- _Security:_ DOM-based XSS via issue meta selection on the issue page. [#8178](https://github.com/gogs/gogs/pull/8178) - [GHSA-vgjm-2cpf-4g7c](https://github.com/gogs/gogs/security/advisories/GHSA-vgjm-2cpf-4g7c)
|
||||
- Unable to update files via web editor and API. [#8184](https://github.com/gogs/gogs/pull/8184)
|
||||
|
||||
### Removed
|
||||
|
||||
- Support for passing API access tokens via URL query parameters (`token`, `access_token`). Use the `Authorization` header instead. [#8177](https://github.com/gogs/gogs/pull/8177) - [GHSA-x9p5-w45c-7ffc](https://github.com/gogs/gogs/security/advisories/GHSA-x9p5-w45c-7ffc)
|
||||
- The `gogs cert` subcommand. [#8153](https://github.com/gogs/gogs/pull/8153)
|
||||
- The `[email] DISABLE_HELO` configuration option. HELO/EHLO is now always sent during SMTP handshake. [#8164](https://github.com/gogs/gogs/pull/8164)
|
||||
- Support for MSSQL as a database backend. Stay on 0.14 for continued usage. [#8173](https://github.com/gogs/gogs/pull/8173)
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Added
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:alpine3.21 AS binarybuilder
|
||||
FROM golang:1.26-alpine3.23 AS binarybuilder
|
||||
RUN apk --no-cache --no-progress add --virtual \
|
||||
build-deps \
|
||||
build-base \
|
||||
@@ -11,7 +11,7 @@ COPY . .
|
||||
RUN ./docker/build/install-task.sh
|
||||
RUN TAGS="cert pam" task build
|
||||
|
||||
FROM alpine:3.21
|
||||
FROM alpine:3.23
|
||||
RUN apk --no-cache --no-progress add \
|
||||
bash \
|
||||
ca-certificates \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:alpine3.23 AS binarybuilder
|
||||
FROM golang:1.26-alpine3.23 AS binarybuilder
|
||||
RUN apk --no-cache --no-progress add --virtual \
|
||||
build-deps \
|
||||
build-base \
|
||||
|
||||
19
README.md
19
README.md
@@ -13,10 +13,10 @@ The Gogs (`/gɑgz/`) project aims to build a simple, stable and extensible self-
|
||||
- Please visit [our home page](https://gogs.io) for user documentation.
|
||||
- Please refer to [CHANGELOG.md](CHANGELOG.md) for list of changes in each releases.
|
||||
- Want to try it before doing anything else? Do it [online](https://try.gogs.io/gogs/gogs)!
|
||||
- Having trouble? Help yourself with [troubleshooting](https://gogs.io/docs/intro/troubleshooting.html) or ask questions in [Discussions](https://github.com/gogs/gogs/discussions).
|
||||
- Want to help with localization? Check out the [localization documentation](https://gogs.io/docs/features/i18n.html).
|
||||
- Having trouble? Help yourself with [troubleshooting](https://gogs.io/asking/troubleshooting) or ask questions in [Discussions](https://github.com/gogs/gogs/discussions).
|
||||
- Want to help with localization? Check out the [localization documentation](https://gogs.io/advancing/localization).
|
||||
- Ready to get hands dirty? Read our [contributing guide](.github/CONTRIBUTING.md).
|
||||
- Hmm... What about APIs? We have experimental support with [documentation](https://github.com/gogs/docs-api).
|
||||
- Hmm... What about APIs? We have experimental support with [documentation](https://gogs.io/api-reference).
|
||||
|
||||
## 💌 Features
|
||||
|
||||
@@ -47,15 +47,7 @@ The Gogs (`/gɑgz/`) project aims to build a simple, stable and extensible self-
|
||||
|
||||
## 📜 Installation
|
||||
|
||||
Make sure you install the [prerequisites](https://gogs.io/docs/installation) first.
|
||||
|
||||
There are 6 ways to install Gogs:
|
||||
|
||||
- [Install from binary](https://gogs.io/docs/installation/install_from_binary.html)
|
||||
- [Install from source](https://gogs.io/docs/installation/install_from_source.html)
|
||||
- [Install from packages](https://gogs.io/docs/installation/install_from_packages.html)
|
||||
- [Ship with Docker](https://github.com/gogs/gogs/tree/main/docker)
|
||||
- [Try with Vagrant](https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs)
|
||||
Please follow [the guide in our documentation](https://gogs.io/getting-started/installation).
|
||||
|
||||
### Deploy to cloud
|
||||
|
||||
@@ -94,7 +86,8 @@ There are 6 ways to install Gogs:
|
||||
Other acknowledgments:
|
||||
|
||||
- Thanks [Egon Elbre](https://twitter.com/egonelbre) for designing the original version of the logo.
|
||||
- Thanks [Crowdin](https://crowdin.com/project/gogs) for sponsoring open source translation plan.
|
||||
- Thanks [Mintlify](https://mintlify.com) for sponsoring open source documentation plan.
|
||||
- Thanks [Crowdin](https://crowdin.com) for sponsoring open source translation plan.
|
||||
- Thanks [Buildkite](https://buildkite.com) for sponsoring open source CI/CD plan.
|
||||
|
||||
## 👋 Contributors
|
||||
|
||||
102
README_ZH.md
102
README_ZH.md
@@ -1,102 +0,0 @@
|
||||
# Gogs
|
||||
|
||||
Gogs 是一款极易搭建的自助 Git 服务。
|
||||
|
||||
## 项目愿景
|
||||
|
||||
Gogs(`/gɑgz/`)项目旨在打造一个以最简便的方式搭建简单、稳定和可扩展的自助 Git 服务。使用 Go 语言开发使得 Gogs 能够通过独立的二进制分发,并且支持 Go 语言支持的 **所有平台**,包括 Linux、macOS、Windows 和基于 ARM 的操作系统。
|
||||
|
||||
## 概览
|
||||
|
||||
- 请移步[官网](https://gogs.io)查看用户使用文档
|
||||
- 请通过 [CHANGELOG.md](CHANGELOG.md) 文件查看各个版本的变更历史
|
||||
- 想要先睹为快?直接去[在线体验](https://try.gogs.io/gogs/gogs)吧!
|
||||
- 使用过程中遇到问题?尝试[故障排查](https://gogs.io/docs/intro/troubleshooting.html)或者前往[用户论坛](https://discuss.gogs.io/)获取帮助
|
||||
- 希望帮助多国语言的翻译吗?请查看[本地化文档](https://gogs.io/docs/features/i18n.html)
|
||||
- 准备搞点事情?请阅读[开发指南](docs/dev/local_development.md)配置开发环境
|
||||
- 想调用 API 吗?请查看[文档](https://github.com/gogs/docs-api)吧
|
||||
|
||||
## 主要特性
|
||||
|
||||
- 控制面板、用户页面以及活动时间线
|
||||
- 通过 SSH、HTTP 和 HTTPS 协议操作仓库
|
||||
- 管理用户、组织和仓库
|
||||
- 仓库和组织级 Webhook,包括 Slack、Discord 和钉钉
|
||||
- 仓库 Git 钩子、部署密钥和 Git LFS
|
||||
- 仓库工单(Issue)、合并请求(Pull Request)、Wiki、保护分支和多人协作
|
||||
- 从其它代码平台迁移和镜像仓库以及 Wiki
|
||||
- 在线编辑仓库文件和 Wiki
|
||||
- Jupyter Notebook 和 PDF 的渲染
|
||||
- 通过 SMTP、LDAP、反向代理、GitHub.com 和 GitHub 企业版进行用户认证
|
||||
- 开启两步验证(2FA)登录
|
||||
- 自定义 HTML 模板、静态文件和许多其它组件
|
||||
- 多样的数据库后端,包括 PostgreSQL、MySQL、SQLite3 和 [TiDB](https://github.com/pingcap/tidb)
|
||||
- 超过 [31 种语言](https://crowdin.com/project/gogs)的本地化
|
||||
|
||||
## 硬件要求
|
||||
|
||||
- 最低的系统硬件要求为一个廉价的树莓派
|
||||
- 如果用于团队项目管理,建议使用 2 核 CPU 及 512MB 内存
|
||||
- 当团队成员大量增加时,可以考虑添加 CPU 核数,内存占用保持不变
|
||||
|
||||
## 浏览器支持
|
||||
|
||||
- 请根据 [Semantic UI](https://github.com/Semantic-Org/Semantic-UI#browser-support) 查看具体支持的浏览器版本。
|
||||
- 官方支持的最小 UI 尺寸为 **1024*768**,UI 不一定会在更小尺寸的设备上被破坏,但我们无法保证且不会修复。
|
||||
|
||||
## 安装部署
|
||||
|
||||
在安装 Gogs 之前,您需要先安装 [基本环境](https://gogs.io/docs/installation)。
|
||||
|
||||
然后,您可以通过以下 6 种方式来安装 Gogs:
|
||||
|
||||
- [二进制安装](https://gogs.io/docs/installation/install_from_binary.html)
|
||||
- [源码安装](https://gogs.io/docs/installation/install_from_source.html)
|
||||
- [包管理安装](https://gogs.io/docs/installation/install_from_packages.html)
|
||||
- [采用 Docker 部署](https://github.com/gogs/gogs/tree/main/docker)
|
||||
- [通过 Vagrant 安装](https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs)
|
||||
- [通过基于 Kubernetes 的 Helm Charts](https://github.com/helm/charts/tree/master/incubator/gogs)
|
||||
|
||||
### 云端部署
|
||||
|
||||
- [OpenShift](https://github.com/tkisme/gogs-openshift)
|
||||
- [Cloudron](https://cloudron.io/appstore.html#io.gogs.cloudronapp)
|
||||
- [Scaleway](https://www.scaleway.com/imagehub/gogs/)
|
||||
- [Sandstorm](https://github.com/cem/gogs-sandstorm)
|
||||
- [sloppy.io](https://github.com/sloppyio/quickstarters/tree/master/gogs)
|
||||
- [YunoHost](https://github.com/mbugeia/gogs_ynh)
|
||||
- [DPlatform](https://github.com/j8r/DPlatform)
|
||||
- [LunaNode](https://github.com/LunaNode/launchgogs)
|
||||
|
||||
### 使用教程
|
||||
|
||||
- [使用 Gogs 搭建自己的 Git 服务器](https://blog.mynook.info/post/host-your-own-git-server-using-gogs/)
|
||||
- [阿里云上 Ubuntu 14.04 64 位安装 Gogs](http://my.oschina.net/luyao/blog/375654)
|
||||
|
||||
## 软件、服务以及产品支持
|
||||
|
||||
- [Fabric8](http://fabric8.io/)(DevOps)
|
||||
- [Jenkins](https://plugins.jenkins.io/gogs-webhook/)(CI)
|
||||
- [Taiga](https://taiga.io/)(项目管理)
|
||||
- [Puppet](https://forge.puppet.com/Siteminds/gogs)(IT)
|
||||
- [Kanboard](https://github.com/kanboard/plugin-gogs-webhook)(项目管理)
|
||||
- [BearyChat](https://bearychat.com/)(团队交流)
|
||||
- [GitPitch](https://gitpitch.com/)(Markdown 演示)
|
||||
- [Synology](https://www.synology.com)(Docker)
|
||||
- [Syncloud](https://syncloud.org/)(应用商店)
|
||||
|
||||
## 特别鸣谢
|
||||
|
||||
- 感谢 [Egon Elbre](https://twitter.com/egonelbre) 设计的 Logo。
|
||||
- 感谢 [DigitalOcean](https://www.digitalocean.com) 和 [MonoVM](https://monovm.com) 提供服务器赞助。
|
||||
- 感谢 [Crowdin](https://crowdin.com/project/gogs) 提供免费的开源项目本地化支持。
|
||||
- 感谢 [Buildkite](https://buildkite.com) 提供免费的开源项目 CI/CD 支持。
|
||||
|
||||
## 贡献成员
|
||||
|
||||
- 您可以通过查看 [贡献者页面](https://github.com/gogs/gogs/graphs/contributors) 获取 TOP 100 的贡献者列表。
|
||||
- 您可以通过查看 [TRANSLATORS](conf/locale/TRANSLATORS) 文件获取公开的翻译人员列表。
|
||||
|
||||
## 授权许可
|
||||
|
||||
本项目采用 MIT 开源授权许可证,完整的授权说明已放置在 [LICENSE](https://github.com/gogs/gogs/blob/main/LICENSE) 文件中。
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
## Supported versions
|
||||
|
||||
Only the latest minor version releases are supported (>= 0.13) for accepting vulnerability reports and patching fixes.
|
||||
Only the latest minor version releases are supported (e.g., 0.14) for patching vulnerabilities. You can find the latest minor version in the [GitHub releases](https://github.com/gogs/gogs/releases) page.
|
||||
|
||||
Existing vulnerability reports are being tracked in [GitHub Security Advisories](https://github.com/gogs/gogs/security/advisories).
|
||||
Existing vulnerability reports are being tracked in [GitHub Security Advisories](https://github.com/gogs/gogs/security/advisories). Not all accepted GHSA are published.
|
||||
|
||||
## Vulnerability lifecycle
|
||||
|
||||
|
||||
11
Taskfile.yml
11
Taskfile.yml
@@ -10,8 +10,6 @@ tasks:
|
||||
web:
|
||||
desc: Build the binary and start the web server
|
||||
deps: [build]
|
||||
env:
|
||||
GOGS_WORK_DIR: '{{.ROOT_DIR}}'
|
||||
cmds:
|
||||
- .bin/gogs web
|
||||
|
||||
@@ -24,7 +22,7 @@ tasks:
|
||||
-X "{{.PKG_PATH}}.BuildCommit={{.BUILD_COMMIT}}"
|
||||
'
|
||||
-tags '{{.TAGS}}'
|
||||
-trimpath -o .bin/gogs{{.BINARY_EXT}}
|
||||
-trimpath -o .bin/gogs{{.BINARY_EXT}} ./cmd/gogs
|
||||
vars:
|
||||
PKG_PATH: gogs.io/gogs/internal/conf
|
||||
BUILD_TIME:
|
||||
@@ -33,7 +31,7 @@ tasks:
|
||||
sh: git rev-parse HEAD
|
||||
sources:
|
||||
- go.mod
|
||||
- gogs.go
|
||||
- cmd/gogs/*.go
|
||||
- internal/**/*.go
|
||||
- conf/**/*
|
||||
- public/**/*
|
||||
@@ -94,3 +92,8 @@ tasks:
|
||||
desc: Run all linters
|
||||
cmds:
|
||||
- golangci-lint run
|
||||
|
||||
docs:
|
||||
desc: Start docs server
|
||||
cmds:
|
||||
- cd docs && mint dev --port 3333
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cmd
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,27 +7,27 @@ import (
|
||||
"runtime"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"gogs.io/gogs/internal/conf"
|
||||
"gogs.io/gogs/internal/database"
|
||||
)
|
||||
|
||||
var (
|
||||
Admin = cli.Command{
|
||||
adminCommand = cli.Command{
|
||||
Name: "admin",
|
||||
Usage: "Perform admin operations on command line",
|
||||
Description: `Allow using internal logic of Gogs without hacking into the source code
|
||||
to make automatic initialization process more smoothly`,
|
||||
Subcommands: []cli.Command{
|
||||
subcmdCreateUser,
|
||||
subcmdDeleteInactivateUsers,
|
||||
subcmdDeleteRepositoryArchives,
|
||||
subcmdDeleteMissingRepositories,
|
||||
subcmdGitGcRepos,
|
||||
subcmdRewriteAuthorizedKeys,
|
||||
subcmdSyncRepositoryHooks,
|
||||
subcmdReinitMissingRepositories,
|
||||
Commands: []*cli.Command{
|
||||
&subcmdCreateUser,
|
||||
&subcmdDeleteInactivateUsers,
|
||||
&subcmdDeleteRepositoryArchives,
|
||||
&subcmdDeleteMissingRepositories,
|
||||
&subcmdGitGcRepos,
|
||||
&subcmdRewriteAuthorizedKeys,
|
||||
&subcmdSyncRepositoryHooks,
|
||||
&subcmdReinitMissingRepositories,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -129,16 +129,16 @@ to make automatic initialization process more smoothly`,
|
||||
}
|
||||
)
|
||||
|
||||
func runCreateUser(c *cli.Context) error {
|
||||
if !c.IsSet("name") {
|
||||
func runCreateUser(ctx context.Context, cmd *cli.Command) error {
|
||||
if !cmd.IsSet("name") {
|
||||
return errors.New("Username is not specified")
|
||||
} else if !c.IsSet("password") {
|
||||
} else if !cmd.IsSet("password") {
|
||||
return errors.New("Password is not specified")
|
||||
} else if !c.IsSet("email") {
|
||||
} else if !cmd.IsSet("email") {
|
||||
return errors.New("Email is not specified")
|
||||
}
|
||||
|
||||
err := conf.Init(c.String("config"))
|
||||
err := conf.Init(configFromLineage(cmd))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "init configuration")
|
||||
}
|
||||
@@ -149,13 +149,13 @@ func runCreateUser(c *cli.Context) error {
|
||||
}
|
||||
|
||||
user, err := database.Handle.Users().Create(
|
||||
context.Background(),
|
||||
c.String("name"),
|
||||
c.String("email"),
|
||||
ctx,
|
||||
cmd.String("name"),
|
||||
cmd.String("email"),
|
||||
database.CreateUserOptions{
|
||||
Password: c.String("password"),
|
||||
Password: cmd.String("password"),
|
||||
Activated: true,
|
||||
Admin: c.Bool("admin"),
|
||||
Admin: cmd.Bool("admin"),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -166,9 +166,9 @@ func runCreateUser(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func adminDashboardOperation(operation func() error, successMessage string) func(*cli.Context) error {
|
||||
return func(c *cli.Context) error {
|
||||
err := conf.Init(c.String("config"))
|
||||
func adminDashboardOperation(operation func() error, successMessage string) func(context.Context, *cli.Command) error {
|
||||
return func(_ context.Context, cmd *cli.Command) error {
|
||||
err := conf.Init(configFromLineage(cmd))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "init configuration")
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cmd
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -11,16 +11,16 @@ import (
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/unknwon/cae/zip"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v3"
|
||||
"gopkg.in/ini.v1"
|
||||
log "unknwon.dev/clog/v2"
|
||||
|
||||
"gogs.io/gogs/internal/conf"
|
||||
"gogs.io/gogs/internal/database"
|
||||
"gogs.io/gogs/internal/osutil"
|
||||
"gogs.io/gogs/internal/osx"
|
||||
)
|
||||
|
||||
var Backup = cli.Command{
|
||||
var backupCommand = cli.Command{
|
||||
Name: "backup",
|
||||
Usage: "Backup files and database",
|
||||
Description: `Backup dumps and compresses all related files and database into zip file,
|
||||
@@ -44,10 +44,10 @@ const (
|
||||
archiveRootDir = "gogs-backup"
|
||||
)
|
||||
|
||||
func runBackup(c *cli.Context) error {
|
||||
zip.Verbose = c.Bool("verbose")
|
||||
func runBackup(ctx context.Context, cmd *cli.Command) error {
|
||||
zip.Verbose = cmd.Bool("verbose")
|
||||
|
||||
err := conf.Init(c.String("config"))
|
||||
err := conf.Init(configFromLineage(cmd))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "init configuration")
|
||||
}
|
||||
@@ -58,8 +58,8 @@ func runBackup(c *cli.Context) error {
|
||||
return errors.Wrap(err, "set engine")
|
||||
}
|
||||
|
||||
tmpDir := c.String("tempdir")
|
||||
if !osutil.Exist(tmpDir) {
|
||||
tmpDir := cmd.String("tempdir")
|
||||
if !osx.Exist(tmpDir) {
|
||||
log.Fatal("'--tempdir' does not exist: %s", tmpDir)
|
||||
}
|
||||
rootDir, err := os.MkdirTemp(tmpDir, "gogs-backup-")
|
||||
@@ -78,7 +78,7 @@ func runBackup(c *cli.Context) error {
|
||||
log.Fatal("Failed to save metadata '%s': %v", metaFile, err)
|
||||
}
|
||||
|
||||
archiveName := filepath.Join(c.String("target"), c.String("archive-name"))
|
||||
archiveName := filepath.Join(cmd.String("target"), cmd.String("archive-name"))
|
||||
log.Info("Packing backup files to: %s", archiveName)
|
||||
|
||||
z, err := zip.Create(archiveName)
|
||||
@@ -91,14 +91,14 @@ func runBackup(c *cli.Context) error {
|
||||
|
||||
// Database
|
||||
dbDir := filepath.Join(rootDir, "db")
|
||||
if err = database.DumpDatabase(context.Background(), conn, dbDir, c.Bool("verbose")); err != nil {
|
||||
if err = database.DumpDatabase(ctx, conn, dbDir, cmd.Bool("verbose")); err != nil {
|
||||
log.Fatal("Failed to dump database: %v", err)
|
||||
}
|
||||
if err = z.AddDir(archiveRootDir+"/db", dbDir); err != nil {
|
||||
log.Fatal("Failed to include 'db': %v", err)
|
||||
}
|
||||
|
||||
if !c.Bool("database-only") {
|
||||
if !cmd.Bool("database-only") {
|
||||
// Custom files
|
||||
err = addCustomDirToBackup(z)
|
||||
if err != nil {
|
||||
@@ -108,7 +108,7 @@ func runBackup(c *cli.Context) error {
|
||||
// Data files
|
||||
for _, dir := range []string{"ssh", "attachments", "avatars", "repo-avatars"} {
|
||||
dirPath := filepath.Join(conf.Server.AppDataPath, dir)
|
||||
if !osutil.IsDir(dirPath) {
|
||||
if !osx.IsDir(dirPath) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -119,10 +119,10 @@ func runBackup(c *cli.Context) error {
|
||||
}
|
||||
|
||||
// Repositories
|
||||
if !c.Bool("exclude-repos") && !c.Bool("database-only") {
|
||||
if !cmd.Bool("exclude-repos") && !cmd.Bool("database-only") {
|
||||
reposDump := filepath.Join(rootDir, "repositories.zip")
|
||||
log.Info("Dumping repositories in %q", conf.Repository.Root)
|
||||
if c.Bool("exclude-mirror-repos") {
|
||||
if cmd.Bool("exclude-mirror-repos") {
|
||||
repos, err := database.GetNonMirrorRepositories()
|
||||
if err != nil {
|
||||
log.Fatal("Failed to get non-mirror repositories: %v", err)
|
||||
43
cmd/gogs/cmd.go
Normal file
43
cmd/gogs/cmd.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func stringFlag(name, value, usage string) *cli.StringFlag {
|
||||
parts := strings.SplitN(name, ", ", 2)
|
||||
f := &cli.StringFlag{
|
||||
Name: parts[0],
|
||||
Value: value,
|
||||
Usage: usage,
|
||||
}
|
||||
if len(parts) > 1 {
|
||||
f.Aliases = []string{parts[1]}
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// configFromLineage walks the command lineage to find the --config flag value.
|
||||
// This is needed because subcommands may not directly see flags set on parent commands.
|
||||
func configFromLineage(cmd *cli.Command) string {
|
||||
for _, c := range cmd.Lineage() {
|
||||
if c.IsSet("config") {
|
||||
return c.String("config")
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func boolFlag(name, usage string) *cli.BoolFlag {
|
||||
parts := strings.SplitN(name, ", ", 2)
|
||||
f := &cli.BoolFlag{
|
||||
Name: parts[0],
|
||||
Usage: usage,
|
||||
}
|
||||
if len(parts) > 1 {
|
||||
f.Aliases = []string{parts[1]}
|
||||
}
|
||||
return f
|
||||
}
|
||||
@@ -1,18 +1,19 @@
|
||||
package cmd
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v3"
|
||||
log "unknwon.dev/clog/v2"
|
||||
|
||||
"github.com/gogs/git-module"
|
||||
@@ -21,20 +22,21 @@ import (
|
||||
"gogs.io/gogs/internal/database"
|
||||
"gogs.io/gogs/internal/email"
|
||||
"gogs.io/gogs/internal/httplib"
|
||||
"gogs.io/gogs/internal/osx"
|
||||
)
|
||||
|
||||
var (
|
||||
Hook = cli.Command{
|
||||
hookCommand = cli.Command{
|
||||
Name: "hook",
|
||||
Usage: "Delegate commands to corresponding Git hooks",
|
||||
Description: "All sub-commands should only be called by Git",
|
||||
Flags: []cli.Flag{
|
||||
stringFlag("config, c", "", "Custom configuration file path"),
|
||||
},
|
||||
Subcommands: []cli.Command{
|
||||
subcmdHookPreReceive,
|
||||
subcmdHookUpadte,
|
||||
subcmdHookPostReceive,
|
||||
Commands: []*cli.Command{
|
||||
&subcmdHookPreReceive,
|
||||
&subcmdHookUpadte,
|
||||
&subcmdHookPostReceive,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -58,11 +60,11 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func runHookPreReceive(c *cli.Context) error {
|
||||
func runHookPreReceive(_ context.Context, cmd *cli.Command) error {
|
||||
if os.Getenv("SSH_ORIGINAL_COMMAND") == "" {
|
||||
return nil
|
||||
}
|
||||
setup(c, "pre-receive.log", true)
|
||||
setup(cmd, "pre-receive.log", true)
|
||||
|
||||
isWiki := strings.Contains(os.Getenv(database.EnvRepoCustomHooksPath), ".wiki.git/")
|
||||
|
||||
@@ -85,7 +87,7 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
branchName := git.RefShortName(string(fields[2]))
|
||||
|
||||
// Branch protection
|
||||
repoID := com.StrTo(os.Getenv(database.EnvRepoID)).MustInt64()
|
||||
repoID, _ := strconv.ParseInt(os.Getenv(database.EnvRepoID), 10, 64)
|
||||
protectBranch, err := database.GetProtectBranchOfRepoByName(repoID, branchName)
|
||||
if err != nil {
|
||||
if database.IsErrBranchNotExist(err) {
|
||||
@@ -101,7 +103,7 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
bypassRequirePullRequest := false
|
||||
|
||||
// Check if user is in whitelist when enabled
|
||||
userID := com.StrTo(os.Getenv(database.EnvAuthUserID)).MustInt64()
|
||||
userID, _ := strconv.ParseInt(os.Getenv(database.EnvAuthUserID), 10, 64)
|
||||
if protectBranch.EnableWhitelist {
|
||||
if !database.IsUserInProtectBranchWhitelist(repoID, userID, branchName) {
|
||||
fail(fmt.Sprintf("Branch '%s' is protected and you are not in the push whitelist", branchName), "")
|
||||
@@ -131,7 +133,7 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
}
|
||||
|
||||
customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "pre-receive")
|
||||
if !com.IsFile(customHooksPath) {
|
||||
if !osx.IsFile(customHooksPath) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -151,13 +153,13 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runHookUpdate(c *cli.Context) error {
|
||||
func runHookUpdate(_ context.Context, cmd *cli.Command) error {
|
||||
if os.Getenv("SSH_ORIGINAL_COMMAND") == "" {
|
||||
return nil
|
||||
}
|
||||
setup(c, "update.log", false)
|
||||
setup(cmd, "update.log", false)
|
||||
|
||||
args := c.Args()
|
||||
args := cmd.Args().Slice()
|
||||
if len(args) != 3 {
|
||||
fail("Arguments received are not equal to three", "Arguments received are not equal to three")
|
||||
} else if args[0] == "" {
|
||||
@@ -165,7 +167,7 @@ func runHookUpdate(c *cli.Context) error {
|
||||
}
|
||||
|
||||
customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "update")
|
||||
if !com.IsFile(customHooksPath) {
|
||||
if !osx.IsFile(customHooksPath) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -185,11 +187,11 @@ func runHookUpdate(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runHookPostReceive(c *cli.Context) error {
|
||||
func runHookPostReceive(_ context.Context, cmd *cli.Command) error {
|
||||
if os.Getenv("SSH_ORIGINAL_COMMAND") == "" {
|
||||
return nil
|
||||
}
|
||||
setup(c, "post-receive.log", true)
|
||||
setup(cmd, "post-receive.log", true)
|
||||
|
||||
// Post-receive hook does more than just gather Git information,
|
||||
// so we need to setup additional services for email notifications.
|
||||
@@ -213,11 +215,12 @@ func runHookPostReceive(c *cli.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
pusherID, _ := strconv.ParseInt(os.Getenv(database.EnvAuthUserID), 10, 64)
|
||||
options := database.PushUpdateOptions{
|
||||
OldCommitID: string(fields[0]),
|
||||
NewCommitID: string(fields[1]),
|
||||
FullRefspec: string(fields[2]),
|
||||
PusherID: com.StrTo(os.Getenv(database.EnvAuthUserID)).MustInt64(),
|
||||
PusherID: pusherID,
|
||||
PusherName: os.Getenv(database.EnvAuthUserName),
|
||||
RepoUserName: os.Getenv(database.EnvRepoOwnerName),
|
||||
RepoName: os.Getenv(database.EnvRepoName),
|
||||
@@ -249,7 +252,7 @@ func runHookPostReceive(c *cli.Context) error {
|
||||
}
|
||||
|
||||
customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "post-receive")
|
||||
if !com.IsFile(customHooksPath) {
|
||||
if !osx.IsFile(customHooksPath) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
package cmd
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"gogs.io/gogs/internal/conf"
|
||||
"gogs.io/gogs/internal/osx"
|
||||
)
|
||||
|
||||
var (
|
||||
Import = cli.Command{
|
||||
importCommand = cli.Command{
|
||||
Name: "import",
|
||||
Usage: "Import portable data as local Gogs data",
|
||||
Description: `Allow user import data from other Gogs installations to local instance
|
||||
without manually hacking the data files`,
|
||||
Subcommands: []cli.Command{
|
||||
subcmdImportLocale,
|
||||
Commands: []*cli.Command{
|
||||
&subcmdImportLocale,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -38,19 +39,19 @@ without manually hacking the data files`,
|
||||
}
|
||||
)
|
||||
|
||||
func runImportLocale(c *cli.Context) error {
|
||||
if !c.IsSet("source") {
|
||||
func runImportLocale(_ context.Context, cmd *cli.Command) error {
|
||||
if !cmd.IsSet("source") {
|
||||
return errors.New("source directory is not specified")
|
||||
} else if !c.IsSet("target") {
|
||||
} else if !cmd.IsSet("target") {
|
||||
return errors.New("target directory is not specified")
|
||||
}
|
||||
if !com.IsDir(c.String("source")) {
|
||||
return errors.Newf("source directory %q does not exist or is not a directory", c.String("source"))
|
||||
} else if !com.IsDir(c.String("target")) {
|
||||
return errors.Newf("target directory %q does not exist or is not a directory", c.String("target"))
|
||||
if !osx.IsDir(cmd.String("source")) {
|
||||
return errors.Newf("source directory %q does not exist or is not a directory", cmd.String("source"))
|
||||
} else if !osx.IsDir(cmd.String("target")) {
|
||||
return errors.Newf("target directory %q does not exist or is not a directory", cmd.String("target"))
|
||||
}
|
||||
|
||||
err := conf.Init(c.String("config"))
|
||||
err := conf.Init(configFromLineage(cmd))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "init configuration")
|
||||
}
|
||||
@@ -64,9 +65,9 @@ func runImportLocale(c *cli.Context) error {
|
||||
// Cut out en-US.
|
||||
for _, lang := range conf.I18n.Langs[1:] {
|
||||
name := fmt.Sprintf("locale_%s.ini", lang)
|
||||
source := filepath.Join(c.String("source"), name)
|
||||
target := filepath.Join(c.String("target"), name)
|
||||
if !com.IsFile(source) {
|
||||
source := filepath.Join(cmd.String("source"), name)
|
||||
target := filepath.Join(cmd.String("target"), name)
|
||||
if !osx.IsFile(source) {
|
||||
continue
|
||||
}
|
||||
|
||||
36
cmd/gogs/main.go
Normal file
36
cmd/gogs/main.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Gogs is a painless self-hosted Git Service.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli/v3"
|
||||
log "unknwon.dev/clog/v2"
|
||||
|
||||
"gogs.io/gogs/internal/conf"
|
||||
)
|
||||
|
||||
func init() {
|
||||
conf.App.Version = "0.15.0+dev"
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd := &cli.Command{
|
||||
Name: "Gogs",
|
||||
Usage: "A painless self-hosted Git service",
|
||||
Version: conf.App.Version,
|
||||
Commands: []*cli.Command{
|
||||
&webCommand,
|
||||
&servCommand,
|
||||
&hookCommand,
|
||||
&adminCommand,
|
||||
&importCommand,
|
||||
&backupCommand,
|
||||
&restoreCommand,
|
||||
},
|
||||
}
|
||||
if err := cmd.Run(context.Background(), os.Args); err != nil {
|
||||
log.Fatal("Failed to start application: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cmd
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,17 +8,17 @@ import (
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/unknwon/cae/zip"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v3"
|
||||
"gopkg.in/ini.v1"
|
||||
log "unknwon.dev/clog/v2"
|
||||
|
||||
"gogs.io/gogs/internal/conf"
|
||||
"gogs.io/gogs/internal/database"
|
||||
"gogs.io/gogs/internal/osutil"
|
||||
"gogs.io/gogs/internal/semverutil"
|
||||
"gogs.io/gogs/internal/osx"
|
||||
"gogs.io/gogs/internal/semverx"
|
||||
)
|
||||
|
||||
var Restore = cli.Command{
|
||||
var restoreCommand = cli.Command{
|
||||
Name: "restore",
|
||||
Usage: "Restore files and database from backup",
|
||||
Description: `Restore imports all related files and database from a backup archive.
|
||||
@@ -42,11 +42,11 @@ be skipped and remain unchanged.`,
|
||||
// format that is able to import.
|
||||
var lastSupportedVersionOfFormat = map[int]string{}
|
||||
|
||||
func runRestore(c *cli.Context) error {
|
||||
zip.Verbose = c.Bool("verbose")
|
||||
func runRestore(ctx context.Context, cmd *cli.Command) error {
|
||||
zip.Verbose = cmd.Bool("verbose")
|
||||
|
||||
tmpDir := c.String("tempdir")
|
||||
if !osutil.IsDir(tmpDir) {
|
||||
tmpDir := cmd.String("tempdir")
|
||||
if !osx.IsDir(tmpDir) {
|
||||
log.Fatal("'--tempdir' does not exist: %s", tmpDir)
|
||||
}
|
||||
archivePath := path.Join(tmpDir, archiveRootDir)
|
||||
@@ -58,15 +58,15 @@ func runRestore(c *cli.Context) error {
|
||||
}
|
||||
defer func() { _ = os.RemoveAll(archivePath) }()
|
||||
|
||||
log.Info("Restoring backup from: %s", c.String("from"))
|
||||
err = zip.ExtractTo(c.String("from"), tmpDir)
|
||||
log.Info("Restoring backup from: %s", cmd.String("from"))
|
||||
err = zip.ExtractTo(cmd.String("from"), tmpDir)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to extract backup archive: %v", err)
|
||||
}
|
||||
|
||||
// Check backup version
|
||||
metaFile := filepath.Join(archivePath, "metadata.ini")
|
||||
if !osutil.IsFile(metaFile) {
|
||||
if !osx.IsFile(metaFile) {
|
||||
log.Fatal("File 'metadata.ini' is missing")
|
||||
}
|
||||
metadata, err := ini.Load(metaFile)
|
||||
@@ -74,7 +74,7 @@ func runRestore(c *cli.Context) error {
|
||||
log.Fatal("Failed to load metadata '%s': %v", metaFile, err)
|
||||
}
|
||||
backupVersion := metadata.Section("").Key("GOGS_VERSION").MustString("999.0")
|
||||
if semverutil.Compare(conf.App.Version, "<", backupVersion) {
|
||||
if semverx.Compare(conf.App.Version, "<", backupVersion) {
|
||||
log.Fatal("Current Gogs version is lower than backup version: %s < %s", conf.App.Version, backupVersion)
|
||||
}
|
||||
formatVersion := metadata.Section("").Key("VERSION").MustInt()
|
||||
@@ -90,9 +90,9 @@ func runRestore(c *cli.Context) error {
|
||||
// Otherwise, it's optional to set config file flag.
|
||||
configFile := filepath.Join(archivePath, "custom", "conf", "app.ini")
|
||||
var customConf string
|
||||
if c.IsSet("config") {
|
||||
customConf = c.String("config")
|
||||
} else if !osutil.IsFile(configFile) {
|
||||
if lineageConf := configFromLineage(cmd); lineageConf != "" {
|
||||
customConf = lineageConf
|
||||
} else if !osx.IsFile(configFile) {
|
||||
log.Fatal("'--config' is not specified and custom config file is not found in backup")
|
||||
} else {
|
||||
customConf = configFile
|
||||
@@ -111,13 +111,13 @@ func runRestore(c *cli.Context) error {
|
||||
|
||||
// Database
|
||||
dbDir := path.Join(archivePath, "db")
|
||||
if err = database.ImportDatabase(context.Background(), conn, dbDir, c.Bool("verbose")); err != nil {
|
||||
if err = database.ImportDatabase(ctx, conn, dbDir, cmd.Bool("verbose")); err != nil {
|
||||
log.Fatal("Failed to import database: %v", err)
|
||||
}
|
||||
|
||||
if !c.Bool("database-only") {
|
||||
if !cmd.Bool("database-only") {
|
||||
// Custom files
|
||||
if osutil.IsDir(conf.CustomDir()) {
|
||||
if osx.IsDir(conf.CustomDir()) {
|
||||
if err = os.Rename(conf.CustomDir(), conf.CustomDir()+".bak"); err != nil {
|
||||
log.Fatal("Failed to backup current 'custom': %v", err)
|
||||
}
|
||||
@@ -131,12 +131,12 @@ func runRestore(c *cli.Context) error {
|
||||
for _, dir := range []string{"attachments", "avatars", "repo-avatars"} {
|
||||
// Skip if backup archive does not have corresponding data
|
||||
srcPath := filepath.Join(archivePath, "data", dir)
|
||||
if !osutil.IsDir(srcPath) {
|
||||
if !osx.IsDir(srcPath) {
|
||||
continue
|
||||
}
|
||||
|
||||
dirPath := filepath.Join(conf.Server.AppDataPath, dir)
|
||||
if osutil.IsDir(dirPath) {
|
||||
if osx.IsDir(dirPath) {
|
||||
if err = os.Rename(dirPath, dirPath+".bak"); err != nil {
|
||||
log.Fatal("Failed to backup current 'data': %v", err)
|
||||
}
|
||||
@@ -149,7 +149,7 @@ func runRestore(c *cli.Context) error {
|
||||
|
||||
// Repositories
|
||||
reposPath := filepath.Join(archivePath, "repositories.zip")
|
||||
if !c.Bool("exclude-repos") && !c.Bool("database-only") && osutil.IsFile(reposPath) {
|
||||
if !cmd.Bool("exclude-repos") && !cmd.Bool("database-only") && osx.IsFile(reposPath) {
|
||||
if err := zip.ExtractTo(reposPath, filepath.Dir(conf.Repository.Root)); err != nil {
|
||||
log.Fatal("Failed to extract 'repositories.zip': %v", err)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cmd
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,11 +6,11 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v3"
|
||||
log "unknwon.dev/clog/v2"
|
||||
|
||||
"gogs.io/gogs/internal/conf"
|
||||
@@ -21,7 +21,7 @@ const (
|
||||
accessDeniedMessage = "Repository does not exist or you do not have access"
|
||||
)
|
||||
|
||||
var Serv = cli.Command{
|
||||
var servCommand = cli.Command{
|
||||
Name: "serv",
|
||||
Usage: "This command should only be called by SSH shell",
|
||||
Description: `Serv provide access auth for repositories`,
|
||||
@@ -48,15 +48,10 @@ func fail(userMessage, errMessage string, args ...any) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func setup(c *cli.Context, logFile string, connectDB bool) {
|
||||
func setup(cmd *cli.Command, logFile string, connectDB bool) {
|
||||
conf.HookMode = true
|
||||
|
||||
var customConf string
|
||||
if c.IsSet("config") {
|
||||
customConf = c.String("config")
|
||||
} else if c.GlobalIsSet("config") {
|
||||
customConf = c.GlobalString("config")
|
||||
}
|
||||
customConf := configFromLineage(cmd)
|
||||
|
||||
err := conf.Init(customConf)
|
||||
if err != nil {
|
||||
@@ -128,16 +123,15 @@ var allowedCommands = map[string]database.AccessMode{
|
||||
"git-receive-pack": database.AccessModeWrite,
|
||||
}
|
||||
|
||||
func runServ(c *cli.Context) error {
|
||||
ctx := context.Background()
|
||||
setup(c, "serv.log", true)
|
||||
func runServ(ctx context.Context, cmd *cli.Command) error {
|
||||
setup(cmd, "serv.log", true)
|
||||
|
||||
if conf.SSH.Disabled {
|
||||
println("Gogs: SSH has been disabled")
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(c.Args()) < 1 {
|
||||
if cmd.Args().Len() < 1 {
|
||||
fail("Not enough arguments", "Not enough arguments")
|
||||
}
|
||||
|
||||
@@ -188,9 +182,10 @@ func runServ(c *cli.Context) error {
|
||||
// Allow anonymous (user is nil) clone for public repositories.
|
||||
var user *database.User
|
||||
|
||||
key, err := database.GetPublicKeyByID(com.StrTo(strings.TrimPrefix(c.Args()[0], "key-")).MustInt64())
|
||||
keyID, _ := strconv.ParseInt(strings.TrimPrefix(cmd.Args().Get(0), "key-"), 10, 64)
|
||||
key, err := database.GetPublicKeyByID(keyID)
|
||||
if err != nil {
|
||||
fail("Invalid key ID", "Invalid key ID '%s': %v", c.Args()[0], err)
|
||||
fail("Invalid key ID", "Invalid key ID '%s': %v", cmd.Args().Get(0), err)
|
||||
}
|
||||
|
||||
if requestMode == database.AccessModeWrite || repo.IsPrivate {
|
||||
@@ -1,6 +1,7 @@
|
||||
package cmd
|
||||
package main
|
||||
|
||||
import (
|
||||
stdctx "context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -20,8 +21,7 @@ import (
|
||||
"github.com/go-macaron/session"
|
||||
"github.com/go-macaron/toolbox"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v3"
|
||||
"gopkg.in/macaron.v1"
|
||||
log "unknwon.dev/clog/v2"
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/database"
|
||||
"gogs.io/gogs/internal/form"
|
||||
"gogs.io/gogs/internal/osutil"
|
||||
"gogs.io/gogs/internal/osx"
|
||||
"gogs.io/gogs/internal/route"
|
||||
"gogs.io/gogs/internal/route/admin"
|
||||
apiv1 "gogs.io/gogs/internal/route/api/v1"
|
||||
@@ -45,7 +45,7 @@ import (
|
||||
"gogs.io/gogs/templates"
|
||||
)
|
||||
|
||||
var Web = cli.Command{
|
||||
var webCommand = cli.Command{
|
||||
Name: "web",
|
||||
Usage: "Start web server",
|
||||
Description: `Gogs web server is the only thing you need to run,
|
||||
@@ -53,7 +53,7 @@ and it takes care of all the other things for you`,
|
||||
Action: runWeb,
|
||||
Flags: []cli.Flag{
|
||||
stringFlag("port, p", "3000", "Temporary port number to prevent conflict"),
|
||||
stringFlag("config, c", "", "Custom configuration file path"),
|
||||
stringFlag("config, c", filepath.Join(conf.CustomDir(), "conf", "app.ini"), "Custom configuration file path"),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -159,8 +159,8 @@ func newMacaron() *macaron.Macaron {
|
||||
return m
|
||||
}
|
||||
|
||||
func runWeb(c *cli.Context) error {
|
||||
err := route.GlobalInit(c.String("config"))
|
||||
func runWeb(_ stdctx.Context, cmd *cli.Command) error {
|
||||
err := route.GlobalInit(configFromLineage(cmd))
|
||||
if err != nil {
|
||||
log.Fatal("Failed to initialize application: %v", err)
|
||||
}
|
||||
@@ -308,7 +308,7 @@ func runWeb(c *cli.Context) error {
|
||||
if err != nil {
|
||||
c.NotFoundOrError(err, "get attachment by UUID")
|
||||
return
|
||||
} else if !com.IsFile(attach.LocalPath()) {
|
||||
} else if !osx.IsFile(attach.LocalPath()) {
|
||||
c.NotFound()
|
||||
return
|
||||
}
|
||||
@@ -698,10 +698,10 @@ func runWeb(c *cli.Context) error {
|
||||
m.NotFound(route.NotFound)
|
||||
|
||||
// Flag for port number in case first time run conflict.
|
||||
if c.IsSet("port") {
|
||||
conf.Server.URL.Host = strings.Replace(conf.Server.URL.Host, ":"+conf.Server.URL.Port(), ":"+c.String("port"), 1)
|
||||
if cmd.IsSet("port") {
|
||||
conf.Server.URL.Host = strings.Replace(conf.Server.URL.Host, ":"+conf.Server.URL.Port(), ":"+cmd.String("port"), 1)
|
||||
conf.Server.ExternalURL = conf.Server.URL.String()
|
||||
conf.Server.HTTPPort = c.String("port")
|
||||
conf.Server.HTTPPort = cmd.String("port")
|
||||
}
|
||||
|
||||
var listenAddr string
|
||||
@@ -750,7 +750,7 @@ func runWeb(c *cli.Context) error {
|
||||
err = fcgi.Serve(nil, m)
|
||||
|
||||
case "unix":
|
||||
if osutil.Exist(listenAddr) {
|
||||
if osx.Exist(listenAddr) {
|
||||
err = os.Remove(listenAddr)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to remove existing Unix domain socket: %v", err)
|
||||
16
codecov.yml
16
codecov.yml
@@ -1,16 +0,0 @@
|
||||
coverage:
|
||||
range: "60...95"
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
threshold: 1%
|
||||
informational: true
|
||||
patch:
|
||||
default:
|
||||
only_pulls: true
|
||||
informational: true
|
||||
|
||||
comment:
|
||||
layout: 'diff'
|
||||
|
||||
github_checks: false
|
||||
@@ -141,8 +141,7 @@ FILE_MAX_SIZE = 3
|
||||
MAX_FILES = 5
|
||||
|
||||
[database]
|
||||
; The database backend, either "postgres", "mysql" "sqlite3" or "mssql".
|
||||
; You can connect to TiDB with MySQL protocol.
|
||||
; The database backend, either "postgres", "mysql" or "sqlite3".
|
||||
TYPE = postgres
|
||||
HOST = 127.0.0.1:5432
|
||||
NAME = gogs
|
||||
@@ -197,8 +196,6 @@ USER = noreply@gogs.localhost
|
||||
; The login password.
|
||||
PASSWORD =
|
||||
|
||||
; Whether to disable HELO operation when the hostname is different.
|
||||
DISABLE_HELO =
|
||||
; The custom hostname for HELO operation, default is from system.
|
||||
HELO_HOSTNAME =
|
||||
|
||||
@@ -279,6 +276,8 @@ ACCESS_CONTROL_ALLOW_ORIGIN =
|
||||
STORAGE = local
|
||||
; The root path to store LFS objects on local file system.
|
||||
OBJECTS_PATH = data/lfs-objects
|
||||
; The path to temporarily store LFS objects during upload verification.
|
||||
OBJECTS_TEMP_PATH = data/tmp/lfs-objects
|
||||
|
||||
[attachment]
|
||||
; Whether to enabled upload attachments in general.
|
||||
|
||||
@@ -120,7 +120,6 @@ confirm_password = Confirm Password
|
||||
admin_email = Admin Email
|
||||
install_gogs = Install Gogs
|
||||
test_git_failed = Failed to test 'git' command: %v
|
||||
sqlite3_not_available = Your release version does not support SQLite3, please download the official binary version from %s, NOT the gobuild version.
|
||||
invalid_db_setting = Database setting is not correct: %v
|
||||
invalid_repo_path = Repository root path is invalid: %v
|
||||
run_user_not_match = Run user isn't the current user: %s -> %s
|
||||
@@ -1263,7 +1262,6 @@ config.email.subject_prefix = Subject prefix
|
||||
config.email.host = Host
|
||||
config.email.from = From
|
||||
config.email.user = User
|
||||
config.email.disable_helo = Disable HELO
|
||||
config.email.helo_hostname = HELO hostname
|
||||
config.email.skip_verify = Skip certificate verify
|
||||
config.email.use_certificate = Use custom certificate
|
||||
|
||||
26
docs/README.md
Normal file
26
docs/README.md
Normal file
@@ -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)
|
||||
@@ -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
|
||||
```
|
||||
@@ -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.
|
||||
270
docs/advancing/authentication.mdx
Normal file
270
docs/advancing/authentication.mdx
Normal file
@@ -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.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="When to use Bind DN">
|
||||
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.
|
||||
</Tab>
|
||||
<Tab title="When to use Simple Auth">
|
||||
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.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 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` |
|
||||
|
||||
<Tip>
|
||||
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)))
|
||||
```
|
||||
</Tip>
|
||||
|
||||
### 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. | -- |
|
||||
|
||||
<Warning>
|
||||
The Bind Password is stored in plaintext on the server. Ensure that your Bind DN has the minimum privileges necessary.
|
||||
</Warning>
|
||||
|
||||
### 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`.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Bind DN">
|
||||
```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 =
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Simple Auth">
|
||||
```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 =
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 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.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="FreeIPA with Simple Auth">
|
||||
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
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="FreeIPA with Bind DN">
|
||||
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.
|
||||
|
||||
<Info>
|
||||
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.
|
||||
</Info>
|
||||
|
||||
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.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## PAM
|
||||
|
||||
To configure PAM authentication, set the **PAM Service Name** to a filename in `/etc/pam.d/`.
|
||||
|
||||
<Warning>
|
||||
If you want PAM authentication to work with normal Linux passwords, the user running Gogs must have read access to `/etc/shadow`.
|
||||
</Warning>
|
||||
|
||||
### 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.
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
</Warning>
|
||||
67
docs/advancing/cli-reference.mdx
Normal file
67
docs/advancing/cli-reference.mdx
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: "CLI reference"
|
||||
description: "Discover all the commands available in the gogs binary"
|
||||
icon: "terminal"
|
||||
---
|
||||
|
||||
Most people know `gogs web` for starting the server, but the `gogs` binary ships with several other commands that help you manage your instance from the command line.
|
||||
|
||||
Run `gogs --help` at any time to see the full list of available commands, and `gogs <command> --help` for details on a specific command.
|
||||
|
||||
<Tip>
|
||||
Every command accepts a `--config` (`-c`) flag to specify a custom configuration file path. The default is `custom/conf/app.ini`.
|
||||
</Tip>
|
||||
|
||||
## Starting the server
|
||||
|
||||
```bash
|
||||
gogs web
|
||||
```
|
||||
|
||||
The `web` command starts the HTTP server that powers the web UI, the REST API, and Git HTTP operations. Use the `--port` (`-p`) flag to override the default listening port.
|
||||
|
||||
## Administration
|
||||
|
||||
```bash
|
||||
gogs admin <subcommand>
|
||||
```
|
||||
|
||||
The `admin` command lets you perform maintenance tasks without going through the web interface. Available subcommands include:
|
||||
|
||||
| Subcommand | Purpose |
|
||||
|---|---|
|
||||
| `create-user` | Create a new user account (with optional `--admin` flag). |
|
||||
| `delete-inactive-users` | Remove user accounts that were never activated. |
|
||||
| `delete-repository-archives` | Clean up generated repository archive files. |
|
||||
| `delete-missing-repositories` | Remove database records for repositories whose Git data is missing on disk. |
|
||||
| `collect-garbage` | Run `git gc` across all repositories. |
|
||||
| `rewrite-authorized-keys` | Regenerate the SSH `authorized_keys` file from the database. |
|
||||
| `resync-hooks` | Re-write Git server-side hooks for all repositories. |
|
||||
| `reinit-missing-repositories` | Re-initialize bare Git repositories that are missing on disk. |
|
||||
|
||||
<Warning>
|
||||
`rewrite-authorized-keys` replaces the entire `authorized_keys` file. Any non-Gogs keys in that file will be lost.
|
||||
</Warning>
|
||||
|
||||
## Importing data
|
||||
|
||||
```bash
|
||||
gogs import locale --source <dir> --target <dir>
|
||||
```
|
||||
|
||||
The `import` command helps you bring portable data from other Gogs installations into your local instance. Currently the only subcommand is `locale`, which merges locale files from a source directory into a target directory.
|
||||
|
||||
## Backup and restore
|
||||
|
||||
```bash
|
||||
gogs backup
|
||||
gogs restore --from <archive>
|
||||
```
|
||||
|
||||
`backup` dumps the database, repositories, and related files into a single zip archive. `restore` imports everything back from an archive, which is useful for migrating Gogs to another server or switching database engines.
|
||||
|
||||
Both commands support `--database-only` and `--exclude-repos` flags to narrow the scope. `backup` additionally supports `--exclude-mirror-repos` and `--target` to control where the archive is saved.
|
||||
|
||||
## Internal commands
|
||||
|
||||
The `serv` and `hook` commands are used internally by the SSH and Git subsystems. You generally do not need to invoke them directly, but they are the reason Gogs can handle SSH authentication and server-side Git hooks without any external tooling.
|
||||
100
docs/advancing/custom-templates.mdx
Normal file
100
docs/advancing/custom-templates.mdx
Normal file
@@ -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.
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
</Warning>
|
||||
|
||||
## Override HTML templates
|
||||
|
||||
You can replace any HTML template (including email templates) by placing a customized version under the `custom/templates/` directory.
|
||||
|
||||
<Steps>
|
||||
<Step title="Find the original template">
|
||||
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`.
|
||||
</Step>
|
||||
<Step title="Copy and edit">
|
||||
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
|
||||
```
|
||||
</Step>
|
||||
<Step title="Restart Gogs">
|
||||
Edits to custom HTML templates **require restarting Gogs** to take effect.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
</Warning>
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
<Tip>
|
||||
Edits to custom static files **do not** require restarting Gogs. Changes take effect immediately.
|
||||
</Tip>
|
||||
|
||||
## 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 `<head>` | Add stylesheets, meta tags, analytics scripts |
|
||||
| `custom/templates/inject/footer.tmpl` | Before `</body>` | 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:
|
||||
|
||||
<Steps>
|
||||
<Step title="Create the CSS file">
|
||||
Create a file named `custom.css` under the `custom/public/css/` directory:
|
||||
|
||||
```
|
||||
custom/public/css/custom.css
|
||||
```
|
||||
</Step>
|
||||
<Step title="Add your CSS rules">
|
||||
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;
|
||||
}
|
||||
```
|
||||
</Step>
|
||||
<Step title="Link the stylesheet">
|
||||
Edit the file `custom/templates/inject/head.tmpl` and add a link to your CSS file:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="/css/custom.css">
|
||||
```
|
||||
</Step>
|
||||
<Step title="Restart Gogs">
|
||||
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.
|
||||
</Step>
|
||||
</Steps>
|
||||
102
docs/advancing/git-lfs.mdx
Normal file
102
docs/advancing/git-lfs.mdx
Normal file
@@ -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.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install Git LFS">
|
||||
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
|
||||
```
|
||||
</Step>
|
||||
<Step title="Track large files">
|
||||
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"
|
||||
```
|
||||
</Step>
|
||||
<Step title="Push as usual">
|
||||
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
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
For a complete walkthrough, see the official [Git LFS Tutorial](https://github.com/git-lfs/git-lfs/wiki/Tutorial).
|
||||
|
||||
## Known limitations
|
||||
|
||||
<Warning>
|
||||
Be aware of the following limitations when using Git LFS with Gogs.
|
||||
</Warning>
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="No S3 or object storage support">
|
||||
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).
|
||||
</Accordion>
|
||||
<Accordion title="SSH remotes use HTTP for LFS transfers">
|
||||
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.
|
||||
</Accordion>
|
||||
<Accordion title="No file locking support">
|
||||
File locking is not supported. This feature is being tracked in [gogs/gogs#6064](https://github.com/gogs/gogs/issues/6064).
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
78
docs/advancing/localization.mdx
Normal file
78
docs/advancing/localization.mdx
Normal file
@@ -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`. |
|
||||
|
||||
<Tip>
|
||||
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.
|
||||
</Tip>
|
||||
|
||||
## Contributing translations
|
||||
|
||||
Translations are managed through Crowdin. To contribute:
|
||||
|
||||
<Steps>
|
||||
<Step title="Sign up">
|
||||
Create an account on the [Gogs Crowdin project](https://crowdin.gogs.io/).
|
||||
</Step>
|
||||
<Step title="Translate">
|
||||
Browse the available strings and fill in untranslated entries for your language.
|
||||
</Step>
|
||||
<Step title="Review">
|
||||
Review existing translations and suggest improvements where needed.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Info>
|
||||
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.
|
||||
</Info>
|
||||
|
||||
### 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/<file>
|
||||
```
|
||||
|
||||
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_<lang>.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.
|
||||
|
||||
<Note>
|
||||
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.
|
||||
</Note>
|
||||
130
docs/advancing/webhooks.mdx
Normal file
130
docs/advancing/webhooks.mdx
Normal file
@@ -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...` |
|
||||
|
||||
<Tip>
|
||||
Always verify the `X-Gogs-Signature` header in your webhook receiver to ensure the request genuinely originated from your Gogs instance.
|
||||
</Tip>
|
||||
|
||||
## 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. |
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Add or update team repository"
|
||||
openapi: "PUT /admin/teams/{teamid}/repos/{reponame}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Add team membership"
|
||||
openapi: "PUT /admin/teams/{teamid}/members/{username}"
|
||||
---
|
||||
4
docs/api-reference/administration/create-a-new-user.mdx
Normal file
4
docs/api-reference/administration/create-a-new-user.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create a new user"
|
||||
openapi: "POST /admin/users"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create a public key for a user"
|
||||
openapi: "POST /admin/users/{username}/keys"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create a repository for a user"
|
||||
openapi: "POST /admin/users/{username}/repos"
|
||||
---
|
||||
4
docs/api-reference/administration/create-a-team.mdx
Normal file
4
docs/api-reference/administration/create-a-team.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create a team"
|
||||
openapi: "POST /admin/orgs/{orgname}/teams"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create an organization"
|
||||
openapi: "POST /admin/users/{username}/orgs"
|
||||
---
|
||||
4
docs/api-reference/administration/delete-a-user.mdx
Normal file
4
docs/api-reference/administration/delete-a-user.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Delete a user"
|
||||
openapi: "DELETE /admin/users/{username}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Edit an existing user"
|
||||
openapi: "PATCH /admin/users/{username}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List all members of a team"
|
||||
openapi: "GET /admin/teams/{teamid}/members"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Remove team membership"
|
||||
openapi: "DELETE /admin/teams/{teamid}/members/{username}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Remove team repository"
|
||||
openapi: "DELETE /admin/teams/{teamid}/repos/{reponame}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Add a collaborator"
|
||||
openapi: "PUT /repos/{owner}/{repo}/collaborators/{collaborator}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Add a deploy key"
|
||||
openapi: "POST /repos/{owner}/{repo}/keys"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Check if a user is a collaborator"
|
||||
openapi: "GET /repos/{owner}/{repo}/collaborators/{collaborator}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get a deploy key"
|
||||
openapi: "GET /repos/{owner}/{repo}/keys/{id}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List collaborators"
|
||||
openapi: "GET /repos/{owner}/{repo}/collaborators"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List deploy keys"
|
||||
openapi: "GET /repos/{owner}/{repo}/keys"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Remove a collaborator"
|
||||
openapi: "DELETE /repos/{owner}/{repo}/collaborators/{collaborator}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Remove a deploy key"
|
||||
openapi: "DELETE /repos/{owner}/{repo}/keys/{id}"
|
||||
---
|
||||
104
docs/api-reference/introduction.mdx
Normal file
104
docs/api-reference/introduction.mdx
Normal file
@@ -0,0 +1,104 @@
|
||||
---
|
||||
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/).
|
||||
|
||||
<Info>
|
||||
The API is bundled with every Gogs installation. No additional setup is required.
|
||||
</Info>
|
||||
|
||||
<Warning>
|
||||
The API is still in its early stages. Content and endpoints are subject to change.
|
||||
</Warning>
|
||||
|
||||
## 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.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Basic authentication">
|
||||
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
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Basic authentication should only be used to generate access tokens. Do not use it for regular API requests.
|
||||
</Warning>
|
||||
</Tab>
|
||||
<Tab title="Access token">
|
||||
Personal access tokens must be sent via the `Authorization` request header.
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: token {YOUR_ACCESS_TOKEN}" https://gogs.example.com/api/v1/user/repos
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 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: <https://gogs.example.com/api/v1/repos/alice/hello/issues?page=3>; rel="next",
|
||||
<https://gogs.example.com/api/v1/repos/alice/hello/issues?page=50>; 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. |
|
||||
|
||||
<Tip>
|
||||
Always use the Link header values to navigate between pages rather than constructing URLs manually.
|
||||
</Tip>
|
||||
|
||||
## SDKs
|
||||
|
||||
The following best-effort-maintained SDKs are available:
|
||||
|
||||
| Language | Repository |
|
||||
|---|---|
|
||||
| Go | [gogs/go-gogs-client](https://github.com/gogs/go-gogs-client) |
|
||||
4
docs/api-reference/issues/add-labels-to-an-issue.mdx
Normal file
4
docs/api-reference/issues/add-labels-to-an-issue.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Add labels to an issue"
|
||||
openapi: "POST /repos/{owner}/{repo}/issues/{index}/labels"
|
||||
---
|
||||
4
docs/api-reference/issues/create-a-comment.mdx
Normal file
4
docs/api-reference/issues/create-a-comment.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create a comment"
|
||||
openapi: "POST /repos/{owner}/{repo}/issues/{index}/comments"
|
||||
---
|
||||
4
docs/api-reference/issues/create-a-label.mdx
Normal file
4
docs/api-reference/issues/create-a-label.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create a label"
|
||||
openapi: "POST /repos/{owner}/{repo}/labels"
|
||||
---
|
||||
4
docs/api-reference/issues/create-a-milestone.mdx
Normal file
4
docs/api-reference/issues/create-a-milestone.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create a milestone"
|
||||
openapi: "POST /repos/{owner}/{repo}/milestones"
|
||||
---
|
||||
4
docs/api-reference/issues/create-an-issue.mdx
Normal file
4
docs/api-reference/issues/create-an-issue.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create an issue"
|
||||
openapi: "POST /repos/{owner}/{repo}/issues"
|
||||
---
|
||||
4
docs/api-reference/issues/delete-a-comment.mdx
Normal file
4
docs/api-reference/issues/delete-a-comment.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Delete a comment"
|
||||
openapi: "DELETE /repos/{owner}/{repo}/issues/{index}/comments/{id}"
|
||||
---
|
||||
4
docs/api-reference/issues/delete-a-label.mdx
Normal file
4
docs/api-reference/issues/delete-a-label.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Delete a label"
|
||||
openapi: "DELETE /repos/{owner}/{repo}/labels/{id}"
|
||||
---
|
||||
4
docs/api-reference/issues/delete-a-milestone.mdx
Normal file
4
docs/api-reference/issues/delete-a-milestone.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Delete a milestone"
|
||||
openapi: "DELETE /repos/{owner}/{repo}/milestones/{id}"
|
||||
---
|
||||
4
docs/api-reference/issues/edit-a-comment.mdx
Normal file
4
docs/api-reference/issues/edit-a-comment.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Edit a comment"
|
||||
openapi: "PATCH /repos/{owner}/{repo}/issues/{index}/comments/{id}"
|
||||
---
|
||||
4
docs/api-reference/issues/edit-a-milestone.mdx
Normal file
4
docs/api-reference/issues/edit-a-milestone.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Edit a milestone"
|
||||
openapi: "PATCH /repos/{owner}/{repo}/milestones/{id}"
|
||||
---
|
||||
4
docs/api-reference/issues/edit-an-issue.mdx
Normal file
4
docs/api-reference/issues/edit-an-issue.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Edit an issue"
|
||||
openapi: "PATCH /repos/{owner}/{repo}/issues/{index}"
|
||||
---
|
||||
4
docs/api-reference/issues/get-a-single-issue.mdx
Normal file
4
docs/api-reference/issues/get-a-single-issue.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get a single issue"
|
||||
openapi: "GET /repos/{owner}/{repo}/issues/{index}"
|
||||
---
|
||||
4
docs/api-reference/issues/get-a-single-label.mdx
Normal file
4
docs/api-reference/issues/get-a-single-label.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get a single label"
|
||||
openapi: "GET /repos/{owner}/{repo}/labels/{id}"
|
||||
---
|
||||
4
docs/api-reference/issues/get-a-single-milestone.mdx
Normal file
4
docs/api-reference/issues/get-a-single-milestone.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get a single milestone"
|
||||
openapi: "GET /repos/{owner}/{repo}/milestones/{id}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List all labels for a repository"
|
||||
openapi: "GET /repos/{owner}/{repo}/labels"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List comments in a repository"
|
||||
openapi: "GET /repos/{owner}/{repo}/issues/comments"
|
||||
---
|
||||
4
docs/api-reference/issues/list-comments-on-an-issue.mdx
Normal file
4
docs/api-reference/issues/list-comments-on-an-issue.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List comments on an issue"
|
||||
openapi: "GET /repos/{owner}/{repo}/issues/{index}/comments"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List issues for a repository"
|
||||
openapi: "GET /repos/{owner}/{repo}/issues"
|
||||
---
|
||||
4
docs/api-reference/issues/list-labels-on-an-issue.mdx
Normal file
4
docs/api-reference/issues/list-labels-on-an-issue.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List labels on an issue"
|
||||
openapi: "GET /repos/{owner}/{repo}/issues/{index}/labels"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List milestones for a repository"
|
||||
openapi: "GET /repos/{owner}/{repo}/milestones"
|
||||
---
|
||||
4
docs/api-reference/issues/list-user-issues.mdx
Normal file
4
docs/api-reference/issues/list-user-issues.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List user issues"
|
||||
openapi: "GET /user/issues"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Remove a label from an issue"
|
||||
openapi: "DELETE /repos/{owner}/{repo}/issues/{index}/labels/{id}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Remove all labels from an issue"
|
||||
openapi: "DELETE /repos/{owner}/{repo}/issues/{index}/labels"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Replace all labels for an issue"
|
||||
openapi: "PUT /repos/{owner}/{repo}/issues/{index}/labels"
|
||||
---
|
||||
4
docs/api-reference/issues/update-a-label.mdx
Normal file
4
docs/api-reference/issues/update-a-label.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Update a label"
|
||||
openapi: "PATCH /repos/{owner}/{repo}/labels/{id}"
|
||||
---
|
||||
4
docs/api-reference/miscellaneous/get-a-git-blob.mdx
Normal file
4
docs/api-reference/miscellaneous/get-a-git-blob.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get a git blob"
|
||||
openapi: "GET /repos/{owner}/{repo}/git/blobs/{sha}"
|
||||
---
|
||||
4
docs/api-reference/miscellaneous/get-a-tree.mdx
Normal file
4
docs/api-reference/miscellaneous/get-a-tree.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get a tree"
|
||||
openapi: "GET /repos/{owner}/{repo}/git/trees/{sha}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Render a Markdown document in raw mode"
|
||||
openapi: "POST /markdown/raw"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Render a Markdown document"
|
||||
openapi: "POST /markdown"
|
||||
---
|
||||
6262
docs/api-reference/openapi.json
Normal file
6262
docs/api-reference/openapi.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create an organization"
|
||||
openapi: "POST /user/orgs"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Edit an organization"
|
||||
openapi: "PATCH /orgs/{orgname}"
|
||||
---
|
||||
4
docs/api-reference/organizations/get-an-organization.mdx
Normal file
4
docs/api-reference/organizations/get-an-organization.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Get an organization"
|
||||
openapi: "GET /orgs/{orgname}"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List teams of an organization"
|
||||
openapi: "GET /orgs/{orgname}/teams"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List user organizations"
|
||||
openapi: "GET /users/{username}/orgs"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List your organizations"
|
||||
openapi: "GET /user/orgs"
|
||||
---
|
||||
4
docs/api-reference/releases/list-releases.mdx
Normal file
4
docs/api-reference/releases/list-releases.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "List releases"
|
||||
openapi: "GET /repos/{owner}/{repo}/releases"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create a repository in an organization"
|
||||
openapi: "POST /org/{org}/repos"
|
||||
---
|
||||
4
docs/api-reference/repositories/create-a-repository.mdx
Normal file
4
docs/api-reference/repositories/create-a-repository.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create a repository"
|
||||
openapi: "POST /user/repos"
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Create or update a file"
|
||||
openapi: "PUT /repos/{owner}/{repo}/contents/{path}"
|
||||
---
|
||||
4
docs/api-reference/repositories/delete-a-repository.mdx
Normal file
4
docs/api-reference/repositories/delete-a-repository.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Delete a repository"
|
||||
openapi: "DELETE /repos/{owner}/{repo}"
|
||||
---
|
||||
4
docs/api-reference/repositories/download-archive.mdx
Normal file
4
docs/api-reference/repositories/download-archive.mdx
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: "Download archive"
|
||||
openapi: "GET /repos/{owner}/{repo}/archive/{archive}"
|
||||
---
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user