Compare commits
29 commits
forgejo
...
forgejo-ci
Author | SHA1 | Date | |
---|---|---|---|
|
ca1a0256b4 | ||
|
006f064416 | ||
|
f4a21a873c | ||
|
2a4b3a2a43 | ||
|
22d8ed2544 | ||
|
644f7cb733 | ||
|
f5f5eb53fa | ||
|
fd0ebd1a65 | ||
|
fe783424e1 | ||
|
7499661326 | ||
|
f1c5e86d83 | ||
|
92c084fd2c | ||
|
209bbbf1fd | ||
|
314ae5e183 | ||
|
41001442e3 | ||
|
7a1b3fef59 | ||
|
82afc7c30b | ||
|
acde52ddb6 | ||
|
df23f83545 | ||
|
dd42a30d6a | ||
|
6ba6f62c7e | ||
|
1c39bae3ec | ||
|
fbe2fb5861 | ||
|
cf05ec745a | ||
|
59a797db40 | ||
|
8871d1aac7 | ||
|
cf054a0461 | ||
|
dc6d291b71 | ||
|
299da907a0 |
65 changed files with 1719 additions and 1594 deletions
21
.forgejo/cascading-pr-end-to-end
Executable file
21
.forgejo/cascading-pr-end-to-end
Executable file
|
@ -0,0 +1,21 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
end_to_end=$1
|
||||||
|
end_to_end_pr=$2
|
||||||
|
forgejo=$3
|
||||||
|
forgejo_pr=$4
|
||||||
|
|
||||||
|
head_url=$(jq --raw-output .head.repo.html_url < $forgejo_pr)
|
||||||
|
test "$head_url" != null
|
||||||
|
branch=$(jq --raw-output .head.ref < $forgejo_pr)
|
||||||
|
test "$branch" != null
|
||||||
|
cd $end_to_end
|
||||||
|
echo $head_url $branch 7.0.0+0-gitea-1.22.0 > forgejo/sources/1.22
|
||||||
|
date > last-upgrade
|
||||||
|
|
||||||
|
base_url=$(jq --raw-output .base.repo.html_url < $forgejo_pr)
|
||||||
|
test "$base_url" != null
|
||||||
|
test "$GITHUB_RUN_NUMBER"
|
||||||
|
echo $base_url/actions/runs/$GITHUB_RUN_NUMBER/artifacts/forgejo > forgejo/binary-url
|
12
.forgejo/cascading-release-end-to-end
Executable file
12
.forgejo/cascading-release-end-to-end
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
end_to_end=$1
|
||||||
|
end_to_end_pr=$2
|
||||||
|
forgejo=$3
|
||||||
|
forgejo_ref=$4
|
||||||
|
|
||||||
|
cd $end_to_end
|
||||||
|
date > last-upgrade
|
||||||
|
echo $FORGEJO_BINARY > forgejo/binary-url
|
3
.forgejo/testdata/build-release/Dockerfile
vendored
Normal file
3
.forgejo/testdata/build-release/Dockerfile
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
FROM public.ecr.aws/docker/library/alpine:3.18
|
||||||
|
RUN mkdir -p /app/gitea
|
||||||
|
RUN ( echo '#!/bin/sh' ; echo "echo forgejo v1.2.3" ) > /app/gitea/gitea ; chmod +x /app/gitea/gitea
|
5
.forgejo/testdata/build-release/Makefile
vendored
Normal file
5
.forgejo/testdata/build-release/Makefile
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
VERSION ?= $(shell cat VERSION 2>/dev/null)
|
||||||
|
sources-tarbal:
|
||||||
|
mkdir -p dist/release
|
||||||
|
echo $(VERSION) > VERSION
|
||||||
|
sources=forgejo-src-$(VERSION).tar.gz ; tar --transform 's|^./|forgejo-src-$(VERSION)/|' -czf dist/release/forgejo-src-$(VERSION).tar.gz . ; cd dist/release ; shasum -a 256 $$sources > $$sources.sha256
|
0
.forgejo/testdata/build-release/modules/public/bindata.go
vendored
Normal file
0
.forgejo/testdata/build-release/modules/public/bindata.go
vendored
Normal file
0
.forgejo/testdata/build-release/public/assets/css/placeholder
vendored
Normal file
0
.forgejo/testdata/build-release/public/assets/css/placeholder
vendored
Normal file
0
.forgejo/testdata/build-release/public/assets/fonts/placeholder
vendored
Normal file
0
.forgejo/testdata/build-release/public/assets/fonts/placeholder
vendored
Normal file
0
.forgejo/testdata/build-release/public/assets/js/placeholder
vendored
Normal file
0
.forgejo/testdata/build-release/public/assets/js/placeholder
vendored
Normal file
107
.forgejo/workflows/build-release-integration.yml
Normal file
107
.forgejo/workflows/build-release-integration.yml
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
name: Integration tests for the release process
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- Makefile
|
||||||
|
- Dockerfile
|
||||||
|
- Dockerfile.rootless
|
||||||
|
- docker/**
|
||||||
|
- .forgejo/workflows/build-release.yml
|
||||||
|
- .forgejo/workflows/build-release-integration.yml
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- Makefile
|
||||||
|
- Dockerfile
|
||||||
|
- Dockerfile.rootless
|
||||||
|
- docker/**
|
||||||
|
- .forgejo/workflows/build-release.yml
|
||||||
|
- .forgejo/workflows/build-release-integration.yml
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release-simulation:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- id: forgejo
|
||||||
|
uses: https://code.forgejo.org/actions/setup-forgejo@v1
|
||||||
|
with:
|
||||||
|
user: root
|
||||||
|
password: admin1234
|
||||||
|
image-version: 1.21
|
||||||
|
lxc-ip-prefix: 10.0.9
|
||||||
|
|
||||||
|
- name: publish the forgejo release
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
|
||||||
|
version=1.2.3
|
||||||
|
cat > /etc/docker/daemon.json <<EOF
|
||||||
|
{
|
||||||
|
"insecure-registries" : ["${{ steps.forgejo.outputs.host-port }}"]
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
systemctl restart docker
|
||||||
|
|
||||||
|
apt-get install -qq -y xz-utils
|
||||||
|
|
||||||
|
dir=$(mktemp -d)
|
||||||
|
trap "rm -fr $dir" EXIT
|
||||||
|
|
||||||
|
url=http://root:admin1234@${{ steps.forgejo.outputs.host-port }}
|
||||||
|
export FORGEJO_RUNNER_LOGS="${{ steps.forgejo.outputs.runner-logs }}"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create a new project with a fake forgejo and the release workflow only
|
||||||
|
#
|
||||||
|
cp -a .forgejo/testdata/build-release/* $dir
|
||||||
|
mkdir -p $dir/.forgejo/workflows
|
||||||
|
cp .forgejo/workflows/build-release.yml $dir/.forgejo/workflows
|
||||||
|
cp $dir/Dockerfile $dir/Dockerfile.rootless
|
||||||
|
|
||||||
|
forgejo-test-helper.sh push $dir $url root forgejo
|
||||||
|
sha=$(forgejo-test-helper.sh branch_tip $url root/forgejo main)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Push a tag to trigger the release workflow and wait for it to complete
|
||||||
|
#
|
||||||
|
forgejo-curl.sh api_json --data-raw '{"tag_name": "v'$version'", "target": "'$sha'"}' $url/api/v1/repos/root/forgejo/tags
|
||||||
|
forgejo-curl.sh api_json -X PUT --data-raw '{"data":"${{ steps.forgejo.outputs.token }}"}' $url/api/v1/repos/root/forgejo/actions/secrets/TOKEN
|
||||||
|
forgejo-curl.sh api_json -X PUT --data-raw '{"data":"root"}' $url/api/v1/repos/root/forgejo/actions/secrets/DOER
|
||||||
|
LOOPS=180 forgejo-test-helper.sh wait_success "$url" root/forgejo $sha
|
||||||
|
|
||||||
|
#
|
||||||
|
# uncomment to see the logs even when everything is reported to be working ok
|
||||||
|
#
|
||||||
|
#cat $FORGEJO_RUNNER_LOGS
|
||||||
|
|
||||||
|
#
|
||||||
|
# Minimal sanity checks. e2e test is for the setup-forgejo
|
||||||
|
# action and the infrastructure playbook. Since the binary
|
||||||
|
# is a script shell it does not test the sanity of the cross
|
||||||
|
# build, only the sanity of the naming of the binaries.
|
||||||
|
#
|
||||||
|
for arch in amd64 arm64 arm-6 ; do
|
||||||
|
binary=forgejo-$version-linux-$arch
|
||||||
|
for suffix in '' '.xz' ; do
|
||||||
|
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$binary$suffix > $binary$suffix
|
||||||
|
if test "$suffix" = .xz ; then
|
||||||
|
unxz --keep $binary$suffix
|
||||||
|
fi
|
||||||
|
chmod +x $binary
|
||||||
|
./$binary --version | grep $version
|
||||||
|
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$binary$suffix.sha256 > $binary$suffix.sha256
|
||||||
|
shasum -a 256 --check $binary$suffix.sha256
|
||||||
|
rm $binary$suffix
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
sources=forgejo-src-$version.tar.gz
|
||||||
|
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$sources > $sources
|
||||||
|
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$sources.sha256 > $sources.sha256
|
||||||
|
shasum -a 256 --check $sources.sha256
|
||||||
|
|
||||||
|
docker pull ${{ steps.forgejo.outputs.host-port }}/root/forgejo:$version
|
||||||
|
docker pull ${{ steps.forgejo.outputs.host-port }}/root/forgejo:$version-rootless
|
169
.forgejo/workflows/build-release.yml
Normal file
169
.forgejo/workflows/build-release.yml
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
#
|
||||||
|
# See also https://forgejo.org/docs/next/developer/RELEASE/#release-process
|
||||||
|
#
|
||||||
|
# https://codeberg.org/forgejo-integration/forgejo
|
||||||
|
#
|
||||||
|
# Builds a release from a codeberg.org/forgejo-integration tag
|
||||||
|
#
|
||||||
|
# vars.ROLE: forgejo-integration
|
||||||
|
#
|
||||||
|
# secrets.DOER: forgejo-experimental-ci
|
||||||
|
# secrets.TOKEN: <generated from codeberg.org/forgejo-experimental-ci> scope read:user, write:repository, write:package
|
||||||
|
#
|
||||||
|
# secrets.CASCADE_ORIGIN_TOKEN: <generated from codeberg.org/forgejo-experimental-ci> scope read:user, write:repository, write:issue
|
||||||
|
# secrets.CASCADE_DESTINATION_TOKEN: <generated from code.forgejo.org/forgejo-ci> scope read:user, write:repository, write:issue
|
||||||
|
# vars.CASCADE_DESTINATION_DOER: forgejo-ci
|
||||||
|
#
|
||||||
|
name: Build release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: self-hosted
|
||||||
|
# root is used for testing, allow it
|
||||||
|
if: vars.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Sanitize the name of the repository
|
||||||
|
id: repository
|
||||||
|
run: |
|
||||||
|
repository="${{ github.repository }}"
|
||||||
|
echo "value=${repository##*/}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: ">=1.21"
|
||||||
|
check-latest: true
|
||||||
|
|
||||||
|
- name: version from ref_name
|
||||||
|
id: tag-version
|
||||||
|
run: |
|
||||||
|
version="${{ github.ref_name }}"
|
||||||
|
version=${version##*v}
|
||||||
|
echo "value=$version" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: release notes
|
||||||
|
id: release-notes
|
||||||
|
run: |
|
||||||
|
anchor=${{ steps.tag-version.outputs.value }}
|
||||||
|
anchor=${anchor//./-}
|
||||||
|
cat >> "$GITHUB_OUTPUT" <<EOF
|
||||||
|
value<<ENDVAR
|
||||||
|
See https://codeberg.org/forgejo/forgejo/src/branch/forgejo/RELEASE-NOTES.md#$anchor
|
||||||
|
ENDVAR
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Build sources
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
apt-get -qq install -y make
|
||||||
|
version=${{ steps.tag-version.outputs.value }}
|
||||||
|
#
|
||||||
|
# Make sure all files are owned by the current user.
|
||||||
|
# When run as root `npx webpack` will assume the identity
|
||||||
|
# of the owner of the current working directory and may
|
||||||
|
# fail to create files if some sub-directories are not owned
|
||||||
|
# by the same user.
|
||||||
|
#
|
||||||
|
# Binaries:
|
||||||
|
# Node: 18.17.0 - /usr/local/node-v18.17.0-linux-x64/bin/node
|
||||||
|
# npm: 9.6.7 - /usr/local/node-v18.17.0-linux-x64/bin/npm
|
||||||
|
# Packages:
|
||||||
|
# add-asset-webpack-plugin: 2.0.1 => 2.0.1
|
||||||
|
# css-loader: 6.8.1 => 6.8.1
|
||||||
|
# esbuild-loader: 3.0.1 => 3.0.1
|
||||||
|
# license-checker-webpack-plugin: 0.2.1 => 0.2.1
|
||||||
|
# monaco-editor-webpack-plugin: 7.0.1 => 7.0.1
|
||||||
|
# vue-loader: 17.2.2 => 17.2.2
|
||||||
|
# webpack: 5.87.0 => 5.87.0
|
||||||
|
# webpack-cli: 5.1.4 => 5.1.4
|
||||||
|
#
|
||||||
|
chown -R $(id -u) .
|
||||||
|
make VERSION=$version TAGS=bindata sources-tarbal
|
||||||
|
mv dist/release release
|
||||||
|
|
||||||
|
(
|
||||||
|
tmp=$(mktemp -d)
|
||||||
|
tar --directory $tmp -zxvf release/*$version*.tar.gz
|
||||||
|
cd $tmp/*
|
||||||
|
#
|
||||||
|
# Verify `make frontend` files are available
|
||||||
|
#
|
||||||
|
test -d public/assets/css
|
||||||
|
test -d public/assets/fonts
|
||||||
|
test -d public/assets/js
|
||||||
|
#
|
||||||
|
# Verify `make generate` files are available
|
||||||
|
#
|
||||||
|
test -f modules/public/bindata.go
|
||||||
|
#
|
||||||
|
# Sanity check to verify that the source tarbal knows the
|
||||||
|
# version and is able to rebuild itself from it.
|
||||||
|
#
|
||||||
|
# When in sources the version is determined with git.
|
||||||
|
# When in the tarbal the version is determined from a VERSION file.
|
||||||
|
#
|
||||||
|
make sources-tarbal
|
||||||
|
tarbal=$(echo dist/release/*$version*.tar.gz)
|
||||||
|
if ! test -f $tarbal ; then
|
||||||
|
echo $tarbal does not exist
|
||||||
|
find dist release
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
|
||||||
|
- name: build container & release
|
||||||
|
if: ${{ secrets.TOKEN != '' }}
|
||||||
|
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v1
|
||||||
|
with:
|
||||||
|
forgejo: "${{ env.GITHUB_SERVER_URL }}"
|
||||||
|
owner: "${{ env.GITHUB_REPOSITORY_OWNER }}"
|
||||||
|
repository: "${{ steps.repository.outputs.value }}"
|
||||||
|
doer: "${{ secrets.DOER }}"
|
||||||
|
tag-version: "${{ steps.tag-version.outputs.value }}"
|
||||||
|
token: "${{ secrets.TOKEN }}"
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
||||||
|
release-notes: "${{ steps.release-notes.outputs.value }}"
|
||||||
|
binary-name: forgejo
|
||||||
|
binary-path: /app/gitea/gitea
|
||||||
|
verbose: ${{ vars.VERBOSE || 'false' }}
|
||||||
|
|
||||||
|
- name: build rootless container
|
||||||
|
if: ${{ secrets.TOKEN != '' }}
|
||||||
|
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v1
|
||||||
|
with:
|
||||||
|
forgejo: "${{ env.GITHUB_SERVER_URL }}"
|
||||||
|
owner: "${{ env.GITHUB_REPOSITORY_OWNER }}"
|
||||||
|
repository: "${{ steps.repository.outputs.value }}"
|
||||||
|
doer: "${{ secrets.DOER }}"
|
||||||
|
tag-version: "${{ steps.tag-version.outputs.value }}"
|
||||||
|
token: "${{ secrets.TOKEN }}"
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
||||||
|
suffix: -rootless
|
||||||
|
dockerfile: Dockerfile.rootless
|
||||||
|
verbose: ${{ vars.VERBOSE || 'false' }}
|
||||||
|
|
||||||
|
- name: end-to-end tests
|
||||||
|
if: ${{ secrets.TOKEN != '' && vars.ROLE == 'forgejo-integration' }}
|
||||||
|
uses: https://code.forgejo.org/actions/cascading-pr@v1
|
||||||
|
with:
|
||||||
|
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||||
|
origin-repo: ${{ github.repository }}
|
||||||
|
origin-token: ${{ secrets.CASCADE_ORIGIN_TOKEN }}
|
||||||
|
origin-ref: refs/heads/forgejo
|
||||||
|
destination-url: https://code.forgejo.org
|
||||||
|
destination-fork-repo: ${{ vars.CASCADE_DESTINATION_DOER }}/end-to-end
|
||||||
|
destination-repo: forgejo/end-to-end
|
||||||
|
destination-branch: forgejo-pr
|
||||||
|
destination-token: ${{ secrets.CASCADE_DESTINATION_TOKEN }}
|
||||||
|
update: .forgejo/cascading-release-end-to-end
|
||||||
|
env:
|
||||||
|
FORGEJO_BINARY: "${{ env.GITHUB_SERVER_URL }}/${{ github.repository }}/releases/download/v${{ steps.tag-version.outputs.value }}/forgejo-${{ steps.tag-version.outputs.value }}-linux-amd64"
|
83
.forgejo/workflows/cascade-setup-end-to-end.yml
Normal file
83
.forgejo/workflows/cascade-setup-end-to-end.yml
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types:
|
||||||
|
- labeled
|
||||||
|
|
||||||
|
env:
|
||||||
|
FEATURE_BRANCHES: "privacy i18n moderation branding dependency"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
info:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: node:20-bookworm
|
||||||
|
steps:
|
||||||
|
- name: event
|
||||||
|
run: |
|
||||||
|
echo github.event.pull_request.head.repo.fork = ${{ github.event.pull_request.head.repo.fork }}
|
||||||
|
echo github.event.action = ${{ github.event.action }}
|
||||||
|
echo github.event.pull_request.merged = ${{ github.event.pull_request.merged }}
|
||||||
|
echo github.event.pull_request.labels.*.name
|
||||||
|
cat <<'EOF'
|
||||||
|
${{ toJSON(github.event.pull_request.labels.*.name) }}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
build:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') && github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'run-end-to-end-tests') }}
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: 'docker.io/node:20-bookworm'
|
||||||
|
steps:
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: '0'
|
||||||
|
show-progress: 'false'
|
||||||
|
- name: adduser forgejo
|
||||||
|
run: |
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
git config user.email "you@example.com"
|
||||||
|
git config user.name "Your Name"
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- name: merge feature branches
|
||||||
|
run: |
|
||||||
|
su forgejo -c 'set -ex ; for b in ${{ env.FEATURE_BRANCHES }} ; do git merge -m $b origin/forgejo-$b ; done'
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: ">=1.21"
|
||||||
|
- name: make deps-backend
|
||||||
|
run: |
|
||||||
|
su forgejo -c 'make deps-backend'
|
||||||
|
- name: make forgejo
|
||||||
|
run: |
|
||||||
|
su forgejo -c 'make generate-backend static-executable && ln gitea forgejo'
|
||||||
|
env:
|
||||||
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: forgejo
|
||||||
|
path: forgejo
|
||||||
|
|
||||||
|
cascade:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') && github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'run-end-to-end-tests') }}
|
||||||
|
needs: [build]
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: node:20-bookworm
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/cascading-pr@v1
|
||||||
|
with:
|
||||||
|
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||||
|
origin-repo: ${{ github.repository }}
|
||||||
|
origin-token: ${{ secrets.END_TO_END_CASCADING_PR_ORIGIN }}
|
||||||
|
origin-pr: ${{ github.event.pull_request.number }}
|
||||||
|
destination-url: https://code.forgejo.org
|
||||||
|
destination-fork-repo: cascading-pr/end-to-end
|
||||||
|
destination-repo: forgejo/end-to-end
|
||||||
|
destination-branch: forgejo-pr
|
||||||
|
destination-token: ${{ secrets.END_TO_END_CASCADING_PR_DESTINATION }}
|
||||||
|
close-merge: true
|
||||||
|
update: .forgejo/cascading-pr-end-to-end
|
37
.forgejo/workflows/e2e.yml
Normal file
37
.forgejo/workflows/e2e.yml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
name: e2e
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- Makefile
|
||||||
|
- .forgejo/workflows/e2e.yml
|
||||||
|
- tests/e2e/**
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-e2e:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: 'docker.io/node:20-bookworm'
|
||||||
|
steps:
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: "~1.21"
|
||||||
|
check-latest: true
|
||||||
|
- run: |
|
||||||
|
apt-get -qq update
|
||||||
|
apt-get -qq install -q sudo
|
||||||
|
sed -i -e 's/%sudo.*/%sudo ALL=(ALL:ALL) NOPASSWD:ALL/' /etc/sudoers
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
adduser forgejo sudo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make deps-frontend frontend deps-backend'
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make generate test-e2e-sqlite'
|
||||||
|
timeout-minutes: 40
|
||||||
|
env:
|
||||||
|
DEPS_PLAYWRIGHT: 1
|
||||||
|
USE_REPO_TEST_DIR: 1
|
27
.forgejo/workflows/mirror.yml
Normal file
27
.forgejo/workflows/mirror.yml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
name: mirror
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'forgejo'
|
||||||
|
- 'v*/forgejo'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
mirror:
|
||||||
|
if: ${{ secrets.MIRROR_TOKEN != '' }}
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: 'docker.io/node:20-bookworm'
|
||||||
|
steps:
|
||||||
|
- name: git push {v*/,}forgejo
|
||||||
|
run: |
|
||||||
|
git init --bare .
|
||||||
|
git remote add origin ${{ env.GITHUB_SERVER_URL }}/${{ env.GITHUB_REPOSITORY }}
|
||||||
|
git fetch origin refs/heads/forgejo:refs/mirror/forgejo
|
||||||
|
git ls-remote origin refs/heads/v*/forgejo | while read sha full_ref ; do
|
||||||
|
ref=${full_ref#refs/heads/}
|
||||||
|
echo git fetch origin $full_ref:refs/mirror/$ref
|
||||||
|
git fetch origin $full_ref:refs/mirror/$ref
|
||||||
|
done
|
||||||
|
echo git push --force https://${{ vars.MIRROR_DESTINATION }} refs/mirror/*:refs/heads/*
|
||||||
|
git push --force https://any:${{ secrets.MIRROR_TOKEN }}@${{ vars.MIRROR_DESTINATION }} refs/mirror/*:refs/heads/*
|
76
.forgejo/workflows/publish-release.yml
Normal file
76
.forgejo/workflows/publish-release.yml
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
#
|
||||||
|
# See also https://forgejo.org/docs/next/developer/RELEASE/#release-process
|
||||||
|
#
|
||||||
|
# https://codeberg.org/forgejo-experimental/forgejo
|
||||||
|
#
|
||||||
|
# Copies a release from codeberg.org/forgejo-integration to codeberg.org/forgejo-experimental
|
||||||
|
#
|
||||||
|
# vars.ROLE: forgejo-experimental
|
||||||
|
# vars.FORGEJO: https://codeberg.org
|
||||||
|
# vars.FROM_OWNER: forgejo-integration
|
||||||
|
# vars.TO_OWNER: forgejo-experimental
|
||||||
|
# vars.REPO: forgejo
|
||||||
|
# vars.DOER: forgejo-experimental-ci
|
||||||
|
# secrets.TOKEN: <generated from codeberg.org/forgejo-experimental-ci>
|
||||||
|
#
|
||||||
|
# http://private.forgejo.org/forgejo/forgejo
|
||||||
|
#
|
||||||
|
# Copies & sign a release from codeberg.org/forgejo-integration to codeberg.org/forgejo
|
||||||
|
#
|
||||||
|
# vars.ROLE: forgejo-release
|
||||||
|
# vars.FORGEJO: https://codeberg.org
|
||||||
|
# vars.FROM_OWNER: forgejo-integration
|
||||||
|
# vars.TO_OWNER: forgejo
|
||||||
|
# vars.REPO: forgejo
|
||||||
|
# vars.DOER: release-team
|
||||||
|
# secrets.TOKEN: <generated from codeberg.org/release-team>
|
||||||
|
# secrets.GPG_PRIVATE_KEY: <XYZ>
|
||||||
|
# secrets.GPG_PASSPHRASE: <ABC>
|
||||||
|
#
|
||||||
|
name: Pubish release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: self-hosted
|
||||||
|
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: copy & sign
|
||||||
|
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v1
|
||||||
|
with:
|
||||||
|
forgejo: ${{ vars.FORGEJO }}
|
||||||
|
from-owner: ${{ vars.FROM_OWNER }}
|
||||||
|
to-owner: ${{ vars.TO_OWNER }}
|
||||||
|
repo: ${{ vars.REPO }}
|
||||||
|
ref-name: ${{ github.ref_name }}
|
||||||
|
release-notes: "See https://codeberg.org/forgejo/forgejo/src/branch/forgejo/RELEASE-NOTES.md#{ANCHOR}"
|
||||||
|
doer: ${{ vars.DOER }}
|
||||||
|
token: ${{ secrets.TOKEN }}
|
||||||
|
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||||
|
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
|
verbose: ${{ vars.VERBOSE }}
|
||||||
|
|
||||||
|
|
||||||
|
- name: set up go for the DNS update below
|
||||||
|
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
||||||
|
uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: ">=1.21"
|
||||||
|
check-latest: true
|
||||||
|
- name: update the _release.experimental DNS record
|
||||||
|
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
||||||
|
uses: https://code.forgejo.org/actions/ovh-dns-update@v1
|
||||||
|
with:
|
||||||
|
subdomain: _release.experimental
|
||||||
|
domain: forgejo.com # there is a CNAME from .org to .com (for security reasons)
|
||||||
|
record-id: 5283602601
|
||||||
|
value: v=${{ github.ref_name }}
|
||||||
|
ovh-app-key: ${{ secrets.OVH_APP_KEY }}
|
||||||
|
ovh-app-secret: ${{ secrets.OVH_APP_SECRET }}
|
||||||
|
ovh-consumer-key: ${{ secrets.OVH_CON_KEY }}
|
211
.forgejo/workflows/testing.yml
Normal file
211
.forgejo/workflows/testing.yml
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
name: testing
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'forgejo*'
|
||||||
|
- 'v*/forgejo*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-backend:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: 'docker.io/node:20-bookworm'
|
||||||
|
steps:
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: ">=1.21"
|
||||||
|
check-latest: true
|
||||||
|
- run: make deps-backend deps-tools
|
||||||
|
- run: make lint-backend
|
||||||
|
env:
|
||||||
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
|
checks-backend:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: 'docker.io/node:20-bookworm'
|
||||||
|
steps:
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: ">=1.21"
|
||||||
|
check-latest: true
|
||||||
|
- run: make deps-backend deps-tools
|
||||||
|
- run: make --always-make checks-backend # ensure the "go-licenses" make target runs
|
||||||
|
test-unit:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
|
runs-on: docker
|
||||||
|
needs: [lint-backend, checks-backend]
|
||||||
|
container:
|
||||||
|
image: 'docker.io/node:20-bookworm'
|
||||||
|
services:
|
||||||
|
minio:
|
||||||
|
image: 'docker.io/bitnami/minio:2023.8.31'
|
||||||
|
env:
|
||||||
|
MINIO_ROOT_USER: 123456
|
||||||
|
MINIO_ROOT_PASSWORD: 12345678
|
||||||
|
steps:
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: ">=1.21"
|
||||||
|
- run: |
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- name: install git >= 2.42
|
||||||
|
run: |
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get -q install -qq -y git
|
||||||
|
rm /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make deps-backend'
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make backend'
|
||||||
|
env:
|
||||||
|
TAGS: bindata
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make test-backend test-check'
|
||||||
|
timeout-minutes: 50
|
||||||
|
env:
|
||||||
|
RACE_ENABLED: 'true'
|
||||||
|
TAGS: bindata
|
||||||
|
test-mysql:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
|
runs-on: docker
|
||||||
|
needs: [lint-backend, checks-backend]
|
||||||
|
container:
|
||||||
|
image: 'docker.io/node:20-bookworm'
|
||||||
|
services:
|
||||||
|
mysql:
|
||||||
|
image: 'docker.io/mysql:8-debian'
|
||||||
|
env:
|
||||||
|
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||||
|
MYSQL_DATABASE: testgitea
|
||||||
|
#
|
||||||
|
# See also https://codeberg.org/forgejo/forgejo/issues/976
|
||||||
|
#
|
||||||
|
cmd: ['mysqld', '--innodb-adaptive-flushing=OFF', '--innodb-buffer-pool-size=4G', '--innodb-log-buffer-size=128M', '--innodb-flush-log-at-trx-commit=0', '--innodb-flush-log-at-timeout=30', '--innodb-flush-method=nosync', '--innodb-fsync-threshold=1000000000']
|
||||||
|
steps:
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: "1.21"
|
||||||
|
- name: install dependencies & git >= 2.42
|
||||||
|
run: |
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install --no-install-recommends -qq -y git git-lfs
|
||||||
|
rm /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
- name: setup user and permissions
|
||||||
|
run: |
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make deps-backend'
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make backend'
|
||||||
|
env:
|
||||||
|
TAGS: bindata
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make test-mysql-migration test-mysql'
|
||||||
|
timeout-minutes: 50
|
||||||
|
env:
|
||||||
|
TAGS: bindata
|
||||||
|
USE_REPO_TEST_DIR: 1
|
||||||
|
test-pgsql:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
|
runs-on: docker
|
||||||
|
needs: [lint-backend, checks-backend]
|
||||||
|
container:
|
||||||
|
image: 'docker.io/node:20-bookworm'
|
||||||
|
services:
|
||||||
|
minio:
|
||||||
|
image: bitnami/minio:2021.3.17
|
||||||
|
env:
|
||||||
|
MINIO_ACCESS_KEY: 123456
|
||||||
|
MINIO_SECRET_KEY: 12345678
|
||||||
|
pgsql:
|
||||||
|
image: 'docker.io/postgres:15'
|
||||||
|
env:
|
||||||
|
POSTGRES_DB: test
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
steps:
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: "1.21"
|
||||||
|
- name: install dependencies & git >= 2.42
|
||||||
|
run: |
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install --no-install-recommends -qq -y git git-lfs
|
||||||
|
rm /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
- name: setup user and permissions
|
||||||
|
run: |
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make deps-backend'
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make backend'
|
||||||
|
env:
|
||||||
|
TAGS: bindata
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make test-pgsql-migration test-pgsql'
|
||||||
|
timeout-minutes: 50
|
||||||
|
env:
|
||||||
|
TAGS: bindata
|
||||||
|
RACE_ENABLED: true
|
||||||
|
USE_REPO_TEST_DIR: 1
|
||||||
|
test-sqlite:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
|
runs-on: docker
|
||||||
|
needs: [lint-backend, checks-backend]
|
||||||
|
container:
|
||||||
|
image: 'docker.io/node:20-bookworm'
|
||||||
|
steps:
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: "1.21"
|
||||||
|
- name: install dependencies & git >= 2.42
|
||||||
|
run: |
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install --no-install-recommends -qq -y git git-lfs
|
||||||
|
rm /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
- name: setup user and permissions
|
||||||
|
run: |
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make deps-backend'
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make backend'
|
||||||
|
env:
|
||||||
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make test-sqlite-migration test-sqlite'
|
||||||
|
timeout-minutes: 50
|
||||||
|
env:
|
||||||
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
|
RACE_ENABLED: true
|
||||||
|
TEST_TAGS: sqlite sqlite_unlock_notify
|
||||||
|
USE_REPO_TEST_DIR: 1
|
|
@ -1,42 +0,0 @@
|
||||||
<!-- NOTE: If your issue is a security concern, please send an email to security@gitea.io instead of opening a public issue -->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
1. Please speak English, this is the language all maintainers can speak and write.
|
|
||||||
2. Please ask questions or configuration/deploy problems on our Discord
|
|
||||||
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
|
|
||||||
3. Please take a moment to check that your issue doesn't already exist.
|
|
||||||
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.com/help/faq)
|
|
||||||
5. Please give all relevant information below for bug reports, because
|
|
||||||
incomplete details will be handled as an invalid report.
|
|
||||||
-->
|
|
||||||
|
|
||||||
- Gitea version (or commit ref):
|
|
||||||
- Git version:
|
|
||||||
- Operating system:
|
|
||||||
<!-- Please include information on whether you built gitea yourself, used one of our downloads or are using some other package -->
|
|
||||||
<!-- Please also tell us how you are running gitea, e.g. if it is being run from docker, a command-line, systemd etc. --->
|
|
||||||
<!-- If you are using a package or systemd tell us what distribution you are using -->
|
|
||||||
- Database (use `[x]`):
|
|
||||||
- [ ] PostgreSQL
|
|
||||||
- [ ] MySQL
|
|
||||||
- [ ] MSSQL
|
|
||||||
- [ ] SQLite
|
|
||||||
- Can you reproduce the bug at https://try.gitea.io:
|
|
||||||
- [ ] Yes (provide example URL)
|
|
||||||
- [ ] No
|
|
||||||
- Log gist:
|
|
||||||
<!-- It really is important to provide pertinent logs -->
|
|
||||||
<!-- Please read https://docs.gitea.com/administration/logging-config#collecting-logs-for-help -->
|
|
||||||
<!-- In addition, if your problem relates to git commands set `RUN_MODE=dev` at the top of app.ini -->
|
|
||||||
|
|
||||||
## Description
|
|
||||||
<!-- If using a proxy or a CDN (e.g. CloudFlare) in front of gitea, please
|
|
||||||
disable the proxy/CDN fully and connect to gitea directly to confirm
|
|
||||||
the issue still persists without those services. -->
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
## Screenshots
|
|
||||||
|
|
||||||
<!-- **If this issue involves the Web Interface, please include a screenshot** -->
|
|
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
|
@ -1,2 +0,0 @@
|
||||||
open_collective: gitea
|
|
||||||
custom: https://www.bountysource.com/teams/gitea
|
|
91
.github/ISSUE_TEMPLATE/bug-report.yaml
vendored
91
.github/ISSUE_TEMPLATE/bug-report.yaml
vendored
|
@ -1,91 +0,0 @@
|
||||||
name: Bug Report
|
|
||||||
description: Found something you weren't expecting? Report it here!
|
|
||||||
labels: ["type/bug"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
NOTE: If your issue is a security concern, please send an email to security@gitea.io instead of opening a public issue.
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
1. Please speak English, this is the language all maintainers can speak and write.
|
|
||||||
2. Please ask questions or configuration/deploy problems on our Discord
|
|
||||||
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
|
|
||||||
3. Make sure you are using the latest release and
|
|
||||||
take a moment to check that your issue hasn't been reported before.
|
|
||||||
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.com/help/faq)
|
|
||||||
5. It's really important to provide pertinent details and logs (https://docs.gitea.com/help/support),
|
|
||||||
incomplete details will be handled as an invalid report.
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: Description
|
|
||||||
description: |
|
|
||||||
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see below)
|
|
||||||
If you are using a proxy or a CDN (e.g. Cloudflare) in front of Gitea, please disable the proxy/CDN fully and access Gitea directly to confirm the issue still persists without those services.
|
|
||||||
- type: input
|
|
||||||
id: gitea-ver
|
|
||||||
attributes:
|
|
||||||
label: Gitea Version
|
|
||||||
description: Gitea version (or commit reference) of your instance
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: can-reproduce
|
|
||||||
attributes:
|
|
||||||
label: Can you reproduce the bug on the Gitea demo site?
|
|
||||||
description: |
|
|
||||||
If so, please provide a URL in the Description field
|
|
||||||
URL of Gitea demo: https://try.gitea.io
|
|
||||||
options:
|
|
||||||
- "Yes"
|
|
||||||
- "No"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
It's really important to provide pertinent logs
|
|
||||||
Please read https://docs.gitea.com/administration/logging-config#collecting-logs-for-help
|
|
||||||
In addition, if your problem relates to git commands set `RUN_MODE=dev` at the top of app.ini
|
|
||||||
- type: input
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Log Gist
|
|
||||||
description: Please provide a gist URL of your logs, with any sensitive information (e.g. API keys) removed/hidden
|
|
||||||
- type: textarea
|
|
||||||
id: screenshots
|
|
||||||
attributes:
|
|
||||||
label: Screenshots
|
|
||||||
description: If this issue involves the Web Interface, please provide one or more screenshots
|
|
||||||
- type: input
|
|
||||||
id: git-ver
|
|
||||||
attributes:
|
|
||||||
label: Git Version
|
|
||||||
description: The version of git running on the server
|
|
||||||
- type: input
|
|
||||||
id: os-ver
|
|
||||||
attributes:
|
|
||||||
label: Operating System
|
|
||||||
description: The operating system you are using to run Gitea
|
|
||||||
- type: textarea
|
|
||||||
id: run-info
|
|
||||||
attributes:
|
|
||||||
label: How are you running Gitea?
|
|
||||||
description: |
|
|
||||||
Please include information on whether you built Gitea yourself, used one of our downloads, are using https://try.gitea.io or are using some other package
|
|
||||||
Please also tell us how you are running Gitea, e.g. if it is being run from docker, a command-line, systemd etc.
|
|
||||||
If you are using a package or systemd tell us what distribution you are using
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: database
|
|
||||||
attributes:
|
|
||||||
label: Database
|
|
||||||
description: What database system are you running?
|
|
||||||
options:
|
|
||||||
- PostgreSQL
|
|
||||||
- MySQL/MariaDB
|
|
||||||
- MSSQL
|
|
||||||
- SQLite
|
|
17
.github/ISSUE_TEMPLATE/config.yml
vendored
17
.github/ISSUE_TEMPLATE/config.yml
vendored
|
@ -1,17 +0,0 @@
|
||||||
blank_issues_enabled: false
|
|
||||||
contact_links:
|
|
||||||
- name: Security Concern
|
|
||||||
url: https://tinyurl.com/security-gitea
|
|
||||||
about: For security concerns, please send a mail to security@gitea.io instead of opening a public issue.
|
|
||||||
- name: Discord Server
|
|
||||||
url: https://discord.gg/Gitea
|
|
||||||
about: Please ask questions and discuss configuration or deployment problems here.
|
|
||||||
- name: Discourse Forum
|
|
||||||
url: https://discourse.gitea.io
|
|
||||||
about: Questions and configuration or deployment problems can also be discussed on our forum.
|
|
||||||
- name: Frequently Asked Questions
|
|
||||||
url: https://docs.gitea.com/help/faq
|
|
||||||
about: Please check if your question isn't mentioned here.
|
|
||||||
- name: Crowdin Translations
|
|
||||||
url: https://crowdin.com/project/gitea
|
|
||||||
about: Translations are managed here.
|
|
24
.github/ISSUE_TEMPLATE/feature-request.yaml
vendored
24
.github/ISSUE_TEMPLATE/feature-request.yaml
vendored
|
@ -1,24 +0,0 @@
|
||||||
name: Feature Request
|
|
||||||
description: Got an idea for a feature that Gitea doesn't have currently? Submit your idea here!
|
|
||||||
labels: ["type/proposal"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
1. Please speak English, this is the language all maintainers can speak and write.
|
|
||||||
2. Please ask questions or configuration/deploy problems on our Discord
|
|
||||||
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
|
|
||||||
3. Please take a moment to check that your feature hasn't already been suggested.
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: Feature Description
|
|
||||||
placeholder: |
|
|
||||||
I think it would be great if Gitea had...
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: screenshots
|
|
||||||
attributes:
|
|
||||||
label: Screenshots
|
|
||||||
description: If you can, provide screenshots of an implementation on another site e.g. GitHub
|
|
66
.github/ISSUE_TEMPLATE/ui.bug-report.yaml
vendored
66
.github/ISSUE_TEMPLATE/ui.bug-report.yaml
vendored
|
@ -1,66 +0,0 @@
|
||||||
name: Web Interface Bug Report
|
|
||||||
description: Something doesn't look quite as it should? Report it here!
|
|
||||||
labels: ["type/bug", "topic/ui"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
NOTE: If your issue is a security concern, please send an email to security@gitea.io instead of opening a public issue.
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
1. Please speak English, this is the language all maintainers can speak and write.
|
|
||||||
2. Please ask questions or configuration/deploy problems on our Discord
|
|
||||||
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
|
|
||||||
3. Please take a moment to check that your issue doesn't already exist.
|
|
||||||
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.com/help/faq)
|
|
||||||
5. Please give all relevant information below for bug reports, because
|
|
||||||
incomplete details will be handled as an invalid report.
|
|
||||||
6. In particular it's really important to provide pertinent logs. If you are certain that this is a javascript
|
|
||||||
error, show us the javascript console. If the error appears to relate to Gitea the server you must also give us
|
|
||||||
DEBUG level logs. (See https://docs.gitea.com/administration/logging-config#collecting-logs-for-help)
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: Description
|
|
||||||
description: |
|
|
||||||
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see below)
|
|
||||||
If using a proxy or a CDN (e.g. CloudFlare) in front of gitea, please disable the proxy/CDN fully and connect to gitea directly to confirm the issue still persists without those services.
|
|
||||||
- type: textarea
|
|
||||||
id: screenshots
|
|
||||||
attributes:
|
|
||||||
label: Screenshots
|
|
||||||
description: Please provide at least 1 screenshot showing the issue.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
id: gitea-ver
|
|
||||||
attributes:
|
|
||||||
label: Gitea Version
|
|
||||||
description: Gitea version (or commit reference) your instance is running
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: can-reproduce
|
|
||||||
attributes:
|
|
||||||
label: Can you reproduce the bug on the Gitea demo site?
|
|
||||||
description: |
|
|
||||||
If so, please provide a URL in the Description field
|
|
||||||
URL of Gitea demo: https://try.gitea.io
|
|
||||||
options:
|
|
||||||
- "Yes"
|
|
||||||
- "No"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
id: os-ver
|
|
||||||
attributes:
|
|
||||||
label: Operating System
|
|
||||||
description: The operating system you are using to access Gitea
|
|
||||||
- type: input
|
|
||||||
id: browser-ver
|
|
||||||
attributes:
|
|
||||||
label: Browser Version
|
|
||||||
description: The browser and version that you are using to access Gitea
|
|
||||||
validations:
|
|
||||||
required: true
|
|
5
.github/actionlint.yaml
vendored
5
.github/actionlint.yaml
vendored
|
@ -1,5 +0,0 @@
|
||||||
self-hosted-runner:
|
|
||||||
labels:
|
|
||||||
- actuated-4cpu-8gb
|
|
||||||
- actuated-4cpu-16gb
|
|
||||||
- nscloud
|
|
36
.github/labeler.yml
vendored
36
.github/labeler.yml
vendored
|
@ -1,36 +0,0 @@
|
||||||
modifies/docs:
|
|
||||||
- "**/*.md"
|
|
||||||
- "docs/**"
|
|
||||||
|
|
||||||
modifies/frontend:
|
|
||||||
- "web_src/**/*"
|
|
||||||
|
|
||||||
modifies/templates:
|
|
||||||
- all: ["templates/**", "!templates/swagger/v1_json.tmpl"]
|
|
||||||
|
|
||||||
modifies/api:
|
|
||||||
- "routers/api/**"
|
|
||||||
- "templates/swagger/v1_json.tmpl"
|
|
||||||
|
|
||||||
modifies/cli:
|
|
||||||
- "cmd/**"
|
|
||||||
|
|
||||||
modifies/translation:
|
|
||||||
- "options/locale/*.ini"
|
|
||||||
|
|
||||||
modifies/migrations:
|
|
||||||
- "models/migrations/**/*"
|
|
||||||
|
|
||||||
modifies/internal:
|
|
||||||
- "Makefile"
|
|
||||||
- "Dockerfile"
|
|
||||||
- "Dockerfile.rootless"
|
|
||||||
- "docker/**"
|
|
||||||
- "webpack.config.js"
|
|
||||||
- ".eslintrc.yaml"
|
|
||||||
- ".golangci.yml"
|
|
||||||
- ".markdownlint.yaml"
|
|
||||||
- ".spectral.yaml"
|
|
||||||
- ".stylelintrc.yaml"
|
|
||||||
- ".yamllint.yaml"
|
|
||||||
- ".github/**"
|
|
9
.github/pull_request_template.md
vendored
9
.github/pull_request_template.md
vendored
|
@ -1,9 +0,0 @@
|
||||||
<!-- start tips -->
|
|
||||||
Please check the following:
|
|
||||||
1. Make sure you are targeting the `main` branch, pull requests on release branches are only allowed for backports.
|
|
||||||
2. Make sure you have read contributing guidelines: https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md .
|
|
||||||
3. Describe what your pull request does and which issue you're targeting (if any).
|
|
||||||
4. It is recommended to enable "Allow edits by maintainers", so maintainers can help more easily.
|
|
||||||
5. Your input here will be included in the commit message when this PR has been merged. If you don't want some content to be included, please separate them with a line like `---`.
|
|
||||||
6. Delete all these tips before posting.
|
|
||||||
<!-- end tips -->
|
|
29
.github/workflows/cron-licenses.yml
vendored
29
.github/workflows/cron-licenses.yml
vendored
|
@ -1,29 +0,0 @@
|
||||||
name: cron-licenses
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "7 0 * * 1" # every Monday at 00:07 UTC
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cron-licenses:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'go-gitea/gitea'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- run: make generate-license generate-gitignore
|
|
||||||
timeout-minutes: 40
|
|
||||||
- name: push translations to repo
|
|
||||||
uses: appleboy/git-push-action@v0.0.3
|
|
||||||
with:
|
|
||||||
author_email: "teabot@gitea.io"
|
|
||||||
author_name: GiteaBot
|
|
||||||
branch: main
|
|
||||||
commit: true
|
|
||||||
commit_message: "[skip ci] Updated licenses and gitignores"
|
|
||||||
remote: "git@github.com:go-gitea/gitea.git"
|
|
||||||
ssh_key: ${{ secrets.DEPLOY_KEY }}
|
|
22
.github/workflows/cron-lock.yml
vendored
22
.github/workflows/cron-lock.yml
vendored
|
@ -1,22 +0,0 @@
|
||||||
name: cron-lock
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * *" # every day at 00:00 UTC
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: lock
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
action:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'go-gitea/gitea'
|
|
||||||
steps:
|
|
||||||
- uses: dessant/lock-threads@v5
|
|
||||||
with:
|
|
||||||
issue-inactive-days: 45
|
|
49
.github/workflows/cron-translations.yml
vendored
49
.github/workflows/cron-translations.yml
vendored
|
@ -1,49 +0,0 @@
|
||||||
name: cron-translations
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "7 0 * * *" # every day at 00:07 UTC
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
crowdin-pull:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'go-gitea/gitea'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: download from crowdin
|
|
||||||
uses: docker://jonasfranz/crowdin
|
|
||||||
env:
|
|
||||||
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
|
|
||||||
PLUGIN_DOWNLOAD: true
|
|
||||||
PLUGIN_EXPORT_DIR: options/locale/
|
|
||||||
PLUGIN_IGNORE_BRANCH: true
|
|
||||||
PLUGIN_PROJECT_IDENTIFIER: gitea
|
|
||||||
- name: update locales
|
|
||||||
run: ./build/update-locales.sh
|
|
||||||
- name: push translations to repo
|
|
||||||
uses: appleboy/git-push-action@v0.0.3
|
|
||||||
with:
|
|
||||||
author_email: "teabot@gitea.io"
|
|
||||||
author_name: GiteaBot
|
|
||||||
branch: main
|
|
||||||
commit: true
|
|
||||||
commit_message: "[skip ci] Updated translations via Crowdin"
|
|
||||||
remote: "git@github.com:go-gitea/gitea.git"
|
|
||||||
ssh_key: ${{ secrets.DEPLOY_KEY }}
|
|
||||||
crowdin-push:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'go-gitea/gitea'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: push translations to crowdin
|
|
||||||
uses: docker://jonasfranz/crowdin
|
|
||||||
env:
|
|
||||||
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
|
|
||||||
PLUGIN_UPLOAD: true
|
|
||||||
PLUGIN_EXPORT_DIR: options/locale/
|
|
||||||
PLUGIN_IGNORE_BRANCH: true
|
|
||||||
PLUGIN_PROJECT_IDENTIFIER: gitea
|
|
||||||
PLUGIN_FILES: |
|
|
||||||
locale_en-US.ini: options/locale/locale_en-US.ini
|
|
||||||
PLUGIN_BRANCH: main
|
|
25
.github/workflows/disk-clean.yml
vendored
25
.github/workflows/disk-clean.yml
vendored
|
@ -1,25 +0,0 @@
|
||||||
name: disk-clean
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
triage:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Free Disk Space (Ubuntu)
|
|
||||||
uses: jlumbroso/free-disk-space@main
|
|
||||||
with:
|
|
||||||
# this might remove tools that are actually needed,
|
|
||||||
# if set to "true" but frees about 6 GB
|
|
||||||
tool-cache: false
|
|
||||||
|
|
||||||
# all of these default to true, but feel free to set to
|
|
||||||
# "false" if necessary for your workflow
|
|
||||||
android: true
|
|
||||||
dotnet: true
|
|
||||||
haskell: true
|
|
||||||
large-packages: false
|
|
||||||
docker-images: false
|
|
||||||
swap-storage: true
|
|
97
.github/workflows/files-changed.yml
vendored
97
.github/workflows/files-changed.yml
vendored
|
@ -1,97 +0,0 @@
|
||||||
name: files-changed
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
outputs:
|
|
||||||
backend:
|
|
||||||
value: ${{ jobs.detect.outputs.backend }}
|
|
||||||
frontend:
|
|
||||||
value: ${{ jobs.detect.outputs.frontend }}
|
|
||||||
docs:
|
|
||||||
value: ${{ jobs.detect.outputs.docs }}
|
|
||||||
actions:
|
|
||||||
value: ${{ jobs.detect.outputs.actions }}
|
|
||||||
templates:
|
|
||||||
value: ${{ jobs.detect.outputs.templates }}
|
|
||||||
docker:
|
|
||||||
value: ${{ jobs.detect.outputs.docker }}
|
|
||||||
swagger:
|
|
||||||
value: ${{ jobs.detect.outputs.swagger }}
|
|
||||||
yaml:
|
|
||||||
value: ${{ jobs.detect.outputs.yaml }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
detect:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 3
|
|
||||||
outputs:
|
|
||||||
backend: ${{ steps.changes.outputs.backend }}
|
|
||||||
frontend: ${{ steps.changes.outputs.frontend }}
|
|
||||||
docs: ${{ steps.changes.outputs.docs }}
|
|
||||||
actions: ${{ steps.changes.outputs.actions }}
|
|
||||||
templates: ${{ steps.changes.outputs.templates }}
|
|
||||||
docker: ${{ steps.changes.outputs.docker }}
|
|
||||||
swagger: ${{ steps.changes.outputs.swagger }}
|
|
||||||
yaml: ${{ steps.changes.outputs.yaml }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: dorny/paths-filter@v2
|
|
||||||
id: changes
|
|
||||||
with:
|
|
||||||
filters: |
|
|
||||||
backend:
|
|
||||||
- "**/*.go"
|
|
||||||
- "templates/**/*.tmpl"
|
|
||||||
- "assets/emoji.json"
|
|
||||||
- "go.mod"
|
|
||||||
- "go.sum"
|
|
||||||
- "Makefile"
|
|
||||||
- ".golangci.yml"
|
|
||||||
- ".editorconfig"
|
|
||||||
|
|
||||||
frontend:
|
|
||||||
- "**/*.js"
|
|
||||||
- "web_src/**"
|
|
||||||
- "assets/emoji.json"
|
|
||||||
- "package.json"
|
|
||||||
- "package-lock.json"
|
|
||||||
- "Makefile"
|
|
||||||
- ".eslintrc.yaml"
|
|
||||||
- ".stylelintrc.yaml"
|
|
||||||
- ".npmrc"
|
|
||||||
|
|
||||||
docs:
|
|
||||||
- "**/*.md"
|
|
||||||
- "docs/**"
|
|
||||||
- ".markdownlint.yaml"
|
|
||||||
- "package.json"
|
|
||||||
- "package-lock.json"
|
|
||||||
|
|
||||||
actions:
|
|
||||||
- ".github/workflows/*"
|
|
||||||
- "Makefile"
|
|
||||||
|
|
||||||
templates:
|
|
||||||
- "templates/**/*.tmpl"
|
|
||||||
- "pyproject.toml"
|
|
||||||
- "poetry.lock"
|
|
||||||
|
|
||||||
docker:
|
|
||||||
- "Dockerfile"
|
|
||||||
- "Dockerfile.rootless"
|
|
||||||
- "docker/**"
|
|
||||||
- "Makefile"
|
|
||||||
|
|
||||||
swagger:
|
|
||||||
- "templates/swagger/v1_json.tmpl"
|
|
||||||
- "Makefile"
|
|
||||||
- "package.json"
|
|
||||||
- "package-lock.json"
|
|
||||||
- ".spectral.yaml"
|
|
||||||
|
|
||||||
yaml:
|
|
||||||
- "**/*.yml"
|
|
||||||
- "**/*.yaml"
|
|
||||||
- ".yamllint.yaml"
|
|
||||||
- "pyproject.toml"
|
|
||||||
- "poetry.lock"
|
|
182
.github/workflows/pull-compliance.yml
vendored
182
.github/workflows/pull-compliance.yml
vendored
|
@ -1,182 +0,0 @@
|
||||||
name: compliance
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
files-changed:
|
|
||||||
uses: ./.github/workflows/files-changed.yml
|
|
||||||
|
|
||||||
lint-backend:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- run: make deps-backend deps-tools
|
|
||||||
- run: make lint-backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
|
||||||
|
|
||||||
lint-templates:
|
|
||||||
if: needs.files-changed.outputs.templates == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
- run: pip install poetry
|
|
||||||
- run: make deps-py
|
|
||||||
- run: make lint-templates
|
|
||||||
|
|
||||||
lint-yaml:
|
|
||||||
if: needs.files-changed.outputs.yaml == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
- run: pip install poetry
|
|
||||||
- run: make deps-py
|
|
||||||
- run: make lint-yaml
|
|
||||||
|
|
||||||
lint-swagger:
|
|
||||||
if: needs.files-changed.outputs.swagger == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
- run: make deps-frontend
|
|
||||||
- run: make lint-swagger
|
|
||||||
|
|
||||||
lint-go-windows:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- run: make deps-backend deps-tools
|
|
||||||
- run: make lint-go-windows lint-go-vet
|
|
||||||
env:
|
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
|
||||||
GOOS: windows
|
|
||||||
GOARCH: amd64
|
|
||||||
|
|
||||||
lint-go-gogit:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- run: make deps-backend deps-tools
|
|
||||||
- run: make lint-go
|
|
||||||
env:
|
|
||||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
|
||||||
|
|
||||||
checks-backend:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- run: make deps-backend deps-tools
|
|
||||||
- run: make --always-make checks-backend # ensure the "go-licenses" make target runs
|
|
||||||
|
|
||||||
frontend:
|
|
||||||
if: needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
- run: make deps-frontend
|
|
||||||
- run: make lint-frontend
|
|
||||||
- run: make checks-frontend
|
|
||||||
- run: make test-frontend
|
|
||||||
- run: make frontend
|
|
||||||
|
|
||||||
backend:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
# no frontend build here as backend should be able to build
|
|
||||||
# even without any frontend files
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
|
|
||||||
- name: build-backend-arm64
|
|
||||||
run: make backend # test cross compile
|
|
||||||
env:
|
|
||||||
GOOS: linux
|
|
||||||
GOARCH: arm64
|
|
||||||
TAGS: bindata gogit
|
|
||||||
- name: build-backend-windows
|
|
||||||
run: go build -o gitea_windows
|
|
||||||
env:
|
|
||||||
GOOS: windows
|
|
||||||
GOARCH: amd64
|
|
||||||
TAGS: bindata gogit
|
|
||||||
- name: build-backend-386
|
|
||||||
run: go build -o gitea_linux_386 # test if compatible with 32 bit
|
|
||||||
env:
|
|
||||||
GOOS: linux
|
|
||||||
GOARCH: 386
|
|
||||||
|
|
||||||
docs:
|
|
||||||
if: needs.files-changed.outputs.docs == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
- run: make deps-frontend
|
|
||||||
- run: make lint-md
|
|
||||||
- run: make docs
|
|
||||||
|
|
||||||
actions:
|
|
||||||
if: needs.files-changed.outputs.actions == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- run: make lint-actions
|
|
215
.github/workflows/pull-db-tests.yml
vendored
215
.github/workflows/pull-db-tests.yml
vendored
|
@ -1,215 +0,0 @@
|
||||||
name: db-tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
files-changed:
|
|
||||||
uses: ./.github/workflows/files-changed.yml
|
|
||||||
|
|
||||||
test-pgsql:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
pgsql:
|
|
||||||
image: postgres:12
|
|
||||||
env:
|
|
||||||
POSTGRES_DB: test
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
ldap:
|
|
||||||
image: gitea/test-openldap:latest
|
|
||||||
ports:
|
|
||||||
- "389:389"
|
|
||||||
- "636:636"
|
|
||||||
minio:
|
|
||||||
# as github actions doesn't support "entrypoint", we need to use a non-official image
|
|
||||||
# that has a custom entrypoint set to "minio server /data"
|
|
||||||
image: bitnami/minio:2023.8.31
|
|
||||||
env:
|
|
||||||
MINIO_ROOT_USER: 123456
|
|
||||||
MINIO_ROOT_PASSWORD: 12345678
|
|
||||||
ports:
|
|
||||||
- "9000:9000"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- name: Add hosts to /etc/hosts
|
|
||||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 pgsql ldap minio" | sudo tee -a /etc/hosts'
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: make backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- run: make test-pgsql-migration test-pgsql
|
|
||||||
timeout-minutes: 50
|
|
||||||
env:
|
|
||||||
TAGS: bindata gogit
|
|
||||||
RACE_ENABLED: true
|
|
||||||
TEST_TAGS: gogit
|
|
||||||
TEST_LDAP: 1
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
|
|
||||||
test-sqlite:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: make backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
|
||||||
- run: make test-sqlite-migration test-sqlite
|
|
||||||
timeout-minutes: 50
|
|
||||||
env:
|
|
||||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
|
||||||
RACE_ENABLED: true
|
|
||||||
TEST_TAGS: gogit sqlite sqlite_unlock_notify
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
|
|
||||||
test-unit:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
elasticsearch:
|
|
||||||
image: elasticsearch:7.5.0
|
|
||||||
env:
|
|
||||||
discovery.type: single-node
|
|
||||||
ports:
|
|
||||||
- "9200:9200"
|
|
||||||
meilisearch:
|
|
||||||
image: getmeili/meilisearch:v1.2.0
|
|
||||||
env:
|
|
||||||
MEILI_ENV: development # disable auth
|
|
||||||
ports:
|
|
||||||
- "7700:7700"
|
|
||||||
redis:
|
|
||||||
image: redis
|
|
||||||
options: >- # wait until redis has started
|
|
||||||
--health-cmd "redis-cli ping"
|
|
||||||
--health-interval 5s
|
|
||||||
--health-timeout 3s
|
|
||||||
--health-retries 10
|
|
||||||
ports:
|
|
||||||
- 6379:6379
|
|
||||||
minio:
|
|
||||||
image: bitnami/minio:2021.3.17
|
|
||||||
env:
|
|
||||||
MINIO_ACCESS_KEY: 123456
|
|
||||||
MINIO_SECRET_KEY: 12345678
|
|
||||||
ports:
|
|
||||||
- "9000:9000"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- name: Add hosts to /etc/hosts
|
|
||||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql elasticsearch meilisearch smtpimap" | sudo tee -a /etc/hosts'
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: make backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- name: unit-tests
|
|
||||||
run: make unit-test-coverage test-check
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
RACE_ENABLED: true
|
|
||||||
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
|
|
||||||
- name: unit-tests-gogit
|
|
||||||
run: make unit-test-coverage test-check
|
|
||||||
env:
|
|
||||||
TAGS: bindata gogit
|
|
||||||
RACE_ENABLED: true
|
|
||||||
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
|
|
||||||
|
|
||||||
test-mysql:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
mysql:
|
|
||||||
image: mysql:8.0
|
|
||||||
env:
|
|
||||||
MYSQL_ALLOW_EMPTY_PASSWORD: true
|
|
||||||
MYSQL_DATABASE: testgitea
|
|
||||||
ports:
|
|
||||||
- "3306:3306"
|
|
||||||
elasticsearch:
|
|
||||||
image: elasticsearch:7.5.0
|
|
||||||
env:
|
|
||||||
discovery.type: single-node
|
|
||||||
ports:
|
|
||||||
- "9200:9200"
|
|
||||||
smtpimap:
|
|
||||||
image: tabascoterrier/docker-imap-devel:latest
|
|
||||||
ports:
|
|
||||||
- "25:25"
|
|
||||||
- "143:143"
|
|
||||||
- "587:587"
|
|
||||||
- "993:993"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- name: Add hosts to /etc/hosts
|
|
||||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql elasticsearch smtpimap" | sudo tee -a /etc/hosts'
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: make backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- name: run tests
|
|
||||||
run: make test-mysql-migration integration-test-coverage
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
RACE_ENABLED: true
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
|
|
||||||
|
|
||||||
test-mssql:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
mssql:
|
|
||||||
image: mcr.microsoft.com/mssql/server:2017-latest
|
|
||||||
env:
|
|
||||||
ACCEPT_EULA: Y
|
|
||||||
MSSQL_PID: Standard
|
|
||||||
SA_PASSWORD: MwantsaSecurePassword1
|
|
||||||
ports:
|
|
||||||
- "1433:1433"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- name: Add hosts to /etc/hosts
|
|
||||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mssql" | sudo tee -a /etc/hosts'
|
|
||||||
- run: make deps-backend
|
|
||||||
- run: make backend
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- run: make test-mssql-migration test-mssql
|
|
||||||
timeout-minutes: 50
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
35
.github/workflows/pull-docker-dryrun.yml
vendored
35
.github/workflows/pull-docker-dryrun.yml
vendored
|
@ -1,35 +0,0 @@
|
||||||
name: docker-dryrun
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
files-changed:
|
|
||||||
uses: ./.github/workflows/files-changed.yml
|
|
||||||
|
|
||||||
regular:
|
|
||||||
if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
push: false
|
|
||||||
tags: gitea/gitea:linux-amd64
|
|
||||||
|
|
||||||
rootless:
|
|
||||||
if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
push: false
|
|
||||||
file: Dockerfile.rootless
|
|
||||||
tags: gitea/gitea:linux-amd64
|
|
32
.github/workflows/pull-e2e-tests.yml
vendored
32
.github/workflows/pull-e2e-tests.yml
vendored
|
@ -1,32 +0,0 @@
|
||||||
name: e2e-tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
files-changed:
|
|
||||||
uses: ./.github/workflows/files-changed.yml
|
|
||||||
|
|
||||||
test-e2e:
|
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
- run: make deps-frontend frontend deps-backend
|
|
||||||
- run: npx playwright install --with-deps
|
|
||||||
- run: make test-e2e-sqlite
|
|
||||||
timeout-minutes: 40
|
|
||||||
env:
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
20
.github/workflows/pull-labeler.yml
vendored
20
.github/workflows/pull-labeler.yml
vendored
|
@ -1,20 +0,0 @@
|
||||||
name: labeler
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
label:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/labeler@v4
|
|
||||||
with:
|
|
||||||
dot: true
|
|
134
.github/workflows/release-nightly.yml
vendored
134
.github/workflows/release-nightly.yml
vendored
|
@ -1,134 +0,0 @@
|
||||||
name: release-nightly
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, release/v*]
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
disk-clean:
|
|
||||||
uses: ./.github/workflows/disk-clean.yml
|
|
||||||
nightly-binary:
|
|
||||||
runs-on: nscloud
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
|
||||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
|
||||||
- run: git fetch --unshallow --quiet --tags --force
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
- run: make deps-frontend deps-backend
|
|
||||||
# xgo build
|
|
||||||
- run: make release
|
|
||||||
env:
|
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
|
||||||
- name: import gpg key
|
|
||||||
id: import_gpg
|
|
||||||
uses: crazy-max/ghaction-import-gpg@v6
|
|
||||||
with:
|
|
||||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
|
||||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
|
||||||
- name: sign binaries
|
|
||||||
run: |
|
|
||||||
for f in dist/release/*; do
|
|
||||||
echo '${{ secrets.GPGSIGN_PASSPHRASE }}' | gpg --pinentry-mode loopback --passphrase-fd 0 --batch --yes --detach-sign -u ${{ steps.import_gpg.outputs.fingerprint }} --output "$f.asc" "$f"
|
|
||||||
done
|
|
||||||
# clean branch name to get the folder name in S3
|
|
||||||
- name: Get cleaned branch name
|
|
||||||
id: clean_name
|
|
||||||
run: |
|
|
||||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
|
||||||
echo "Cleaned name is ${REF_NAME}"
|
|
||||||
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
|
||||||
- name: configure aws
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: ${{ secrets.AWS_REGION }}
|
|
||||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
||||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
||||||
- name: upload binaries to s3
|
|
||||||
run: |
|
|
||||||
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
|
||||||
nightly-docker-rootful:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
|
||||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
|
||||||
- run: git fetch --unshallow --quiet --tags --force
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: docker/setup-qemu-action@v3
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- name: Get cleaned branch name
|
|
||||||
id: clean_name
|
|
||||||
run: |
|
|
||||||
# if main then say nightly otherwise cleanup name
|
|
||||||
if [ "${{ github.ref }}" = "refs/heads/main" ]; then
|
|
||||||
echo "branch=nightly" >> "$GITHUB_OUTPUT"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
|
||||||
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: fetch go modules
|
|
||||||
run: make vendor
|
|
||||||
- name: build rootful docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: gitea/gitea:${{ steps.clean_name.outputs.branch }}
|
|
||||||
nightly-docker-rootless:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
|
||||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
|
||||||
- run: git fetch --unshallow --quiet --tags --force
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: docker/setup-qemu-action@v3
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- name: Get cleaned branch name
|
|
||||||
id: clean_name
|
|
||||||
run: |
|
|
||||||
# if main then say nightly otherwise cleanup name
|
|
||||||
if [ "${{ github.ref }}" = "refs/heads/main" ]; then
|
|
||||||
echo "branch=nightly" >> "$GITHUB_OUTPUT"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
|
||||||
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: fetch go modules
|
|
||||||
run: make vendor
|
|
||||||
- name: build rootless docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
file: Dockerfile.rootless
|
|
||||||
tags: gitea/gitea:${{ steps.clean_name.outputs.branch }}-rootless
|
|
132
.github/workflows/release-tag-rc.yml
vendored
132
.github/workflows/release-tag-rc.yml
vendored
|
@ -1,132 +0,0 @@
|
||||||
name: release-tag-rc
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "v1*-rc*"
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
binary:
|
|
||||||
runs-on: nscloud
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
|
||||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
|
||||||
- run: git fetch --unshallow --quiet --tags --force
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
- run: make deps-frontend deps-backend
|
|
||||||
# xgo build
|
|
||||||
- run: make release
|
|
||||||
env:
|
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
|
||||||
- name: import gpg key
|
|
||||||
id: import_gpg
|
|
||||||
uses: crazy-max/ghaction-import-gpg@v6
|
|
||||||
with:
|
|
||||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
|
||||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
|
||||||
- name: sign binaries
|
|
||||||
run: |
|
|
||||||
for f in dist/release/*; do
|
|
||||||
echo '${{ secrets.GPGSIGN_PASSPHRASE }}' | gpg --pinentry-mode loopback --passphrase-fd 0 --batch --yes --detach-sign -u ${{ steps.import_gpg.outputs.fingerprint }} --output "$f.asc" "$f"
|
|
||||||
done
|
|
||||||
# clean branch name to get the folder name in S3
|
|
||||||
- name: Get cleaned branch name
|
|
||||||
id: clean_name
|
|
||||||
run: |
|
|
||||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\/v//' -e 's/release\/v//')
|
|
||||||
echo "Cleaned name is ${REF_NAME}"
|
|
||||||
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
|
||||||
- name: configure aws
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: ${{ secrets.AWS_REGION }}
|
|
||||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
||||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
||||||
- name: upload binaries to s3
|
|
||||||
run: |
|
|
||||||
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
|
||||||
- name: Install GH CLI
|
|
||||||
uses: dev-hanz-ops/install-gh-cli-action@v0.1.0
|
|
||||||
with:
|
|
||||||
gh-cli-version: 2.39.1
|
|
||||||
- name: create github release
|
|
||||||
run: |
|
|
||||||
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --draft --notes-from-tag dist/release/*
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
||||||
docker-rootful:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
|
||||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
|
||||||
- run: git fetch --unshallow --quiet --tags --force
|
|
||||||
- uses: docker/setup-qemu-action@v3
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- uses: docker/metadata-action@v5
|
|
||||||
id: meta
|
|
||||||
with:
|
|
||||||
images: gitea/gitea
|
|
||||||
flavor: |
|
|
||||||
latest=false
|
|
||||||
# 1.2.3-rc0
|
|
||||||
tags: |
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: build rootful docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
docker-rootless:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
|
||||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
|
||||||
- run: git fetch --unshallow --quiet --tags --force
|
|
||||||
- uses: docker/setup-qemu-action@v3
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- uses: docker/metadata-action@v5
|
|
||||||
id: meta
|
|
||||||
with:
|
|
||||||
images: gitea/gitea
|
|
||||||
# each tag below will have the suffix of -rootless
|
|
||||||
flavor: |
|
|
||||||
latest=false
|
|
||||||
suffix=-rootless
|
|
||||||
# 1.2.3-rc0
|
|
||||||
tags: |
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: build rootless docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
file: Dockerfile.rootless
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
143
.github/workflows/release-tag-version.yml
vendored
143
.github/workflows/release-tag-version.yml
vendored
|
@ -1,143 +0,0 @@
|
||||||
name: release-tag-version
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "v1.*"
|
|
||||||
- "!v1*-rc*"
|
|
||||||
- "!v1*-dev"
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
binary:
|
|
||||||
runs-on: nscloud
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
|
||||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
|
||||||
- run: git fetch --unshallow --quiet --tags --force
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
- run: make deps-frontend deps-backend
|
|
||||||
# xgo build
|
|
||||||
- run: make release
|
|
||||||
env:
|
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
|
||||||
- name: import gpg key
|
|
||||||
id: import_gpg
|
|
||||||
uses: crazy-max/ghaction-import-gpg@v6
|
|
||||||
with:
|
|
||||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
|
||||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
|
||||||
- name: sign binaries
|
|
||||||
run: |
|
|
||||||
for f in dist/release/*; do
|
|
||||||
echo '${{ secrets.GPGSIGN_PASSPHRASE }}' | gpg --pinentry-mode loopback --passphrase-fd 0 --batch --yes --detach-sign -u ${{ steps.import_gpg.outputs.fingerprint }} --output "$f.asc" "$f"
|
|
||||||
done
|
|
||||||
# clean branch name to get the folder name in S3
|
|
||||||
- name: Get cleaned branch name
|
|
||||||
id: clean_name
|
|
||||||
run: |
|
|
||||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\/v//' -e 's/release\/v//')
|
|
||||||
echo "Cleaned name is ${REF_NAME}"
|
|
||||||
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
|
||||||
- name: configure aws
|
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
aws-region: ${{ secrets.AWS_REGION }}
|
|
||||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
||||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
||||||
- name: upload binaries to s3
|
|
||||||
run: |
|
|
||||||
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
|
||||||
- name: Install GH CLI
|
|
||||||
uses: dev-hanz-ops/install-gh-cli-action@v0.1.0
|
|
||||||
with:
|
|
||||||
gh-cli-version: 2.39.1
|
|
||||||
- name: create github release
|
|
||||||
run: |
|
|
||||||
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --notes-from-tag dist/release/*
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
||||||
docker-rootful:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
|
||||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
|
||||||
- run: git fetch --unshallow --quiet --tags --force
|
|
||||||
- uses: docker/setup-qemu-action@v3
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- uses: docker/metadata-action@v5
|
|
||||||
id: meta
|
|
||||||
with:
|
|
||||||
images: gitea/gitea
|
|
||||||
# this will generate tags in the following format:
|
|
||||||
# latest
|
|
||||||
# 1
|
|
||||||
# 1.2
|
|
||||||
# 1.2.3
|
|
||||||
tags: |
|
|
||||||
type=semver,pattern={{major}}
|
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: build rootful docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
docker-rootless:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
|
||||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
|
||||||
- run: git fetch --unshallow --quiet --tags --force
|
|
||||||
- uses: docker/setup-qemu-action@v3
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- uses: docker/metadata-action@v5
|
|
||||||
id: meta
|
|
||||||
with:
|
|
||||||
images: gitea/gitea
|
|
||||||
# each tag below will have the suffix of -rootless
|
|
||||||
flavor: |
|
|
||||||
suffix=-rootless,onlatest=true
|
|
||||||
# this will generate tags in the following format (with -rootless suffix added):
|
|
||||||
# latest
|
|
||||||
# 1
|
|
||||||
# 1.2
|
|
||||||
# 1.2.3
|
|
||||||
tags: |
|
|
||||||
type=semver,pattern={{major}}
|
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: build rootless docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
file: Dockerfile.rootless
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,3 +1,6 @@
|
||||||
|
# Emacs
|
||||||
|
*~
|
||||||
|
|
||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
|
|
45
Dockerfile
45
Dockerfile
|
@ -1,5 +1,6 @@
|
||||||
# Build stage
|
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
||||||
FROM docker.io/library/golang:1.21-alpine3.19 AS build-env
|
|
||||||
|
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21-alpine3.19 as build-env
|
||||||
|
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
ENV GOPROXY ${GOPROXY:-direct}
|
ENV GOPROXY ${GOPROXY:-direct}
|
||||||
|
@ -9,24 +10,33 @@ ARG TAGS="sqlite sqlite_unlock_notify"
|
||||||
ENV TAGS "bindata timetzdata $TAGS"
|
ENV TAGS "bindata timetzdata $TAGS"
|
||||||
ARG CGO_EXTRA_CFLAGS
|
ARG CGO_EXTRA_CFLAGS
|
||||||
|
|
||||||
# Build deps
|
#
|
||||||
RUN apk --no-cache add \
|
# Transparently cross compile for the target platform
|
||||||
build-base \
|
#
|
||||||
git \
|
COPY --from=xx / /
|
||||||
nodejs \
|
ARG TARGETPLATFORM
|
||||||
npm \
|
RUN apk --no-cache add clang lld
|
||||||
&& rm -rf /var/cache/apk/*
|
RUN xx-apk --no-cache add gcc musl-dev
|
||||||
|
ENV CGO_ENABLED=1
|
||||||
|
RUN xx-go --wrap
|
||||||
|
#
|
||||||
|
# for go generate and binfmt to find
|
||||||
|
# without it the generate phase will fail with
|
||||||
|
# #19 25.04 modules/public/public_bindata.go:8: running "go": exit status 1
|
||||||
|
# #19 25.39 aarch64-binfmt-P: Could not open '/lib/ld-musl-aarch64.so.1': No such file or directory
|
||||||
|
# why exactly is it needed? where is binfmt involved?
|
||||||
|
#
|
||||||
|
RUN cp /*-alpine-linux-musl*/lib/ld-musl-*.so.1 /lib || true
|
||||||
|
|
||||||
|
RUN apk --no-cache add build-base git nodejs npm
|
||||||
|
|
||||||
# Setup repo
|
|
||||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
||||||
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||||
|
|
||||||
# Checkout version if set
|
RUN make clean-all
|
||||||
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
RUN make frontend
|
||||||
&& make clean-all build
|
RUN go build contrib/environment-to-ini/environment-to-ini.go && xx-verify environment-to-ini
|
||||||
|
RUN make go-check generate-backend static-executable && xx-verify gitea
|
||||||
# Begin env-to-ini build
|
|
||||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
|
||||||
|
|
||||||
# Copy local files
|
# Copy local files
|
||||||
COPY docker/root /tmp/local
|
COPY docker/root /tmp/local
|
||||||
|
@ -42,7 +52,7 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
||||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||||
|
|
||||||
FROM docker.io/library/alpine:3.19
|
FROM docker.io/library/alpine:3.19
|
||||||
LABEL maintainer="maintainers@gitea.io"
|
LABEL maintainer="contact@forgejo.org"
|
||||||
|
|
||||||
EXPOSE 22 3000
|
EXPOSE 22 3000
|
||||||
|
|
||||||
|
@ -81,6 +91,7 @@ ENTRYPOINT ["/usr/bin/entrypoint"]
|
||||||
CMD ["/bin/s6-svscan", "/etc/s6"]
|
CMD ["/bin/s6-svscan", "/etc/s6"]
|
||||||
|
|
||||||
COPY --from=build-env /tmp/local /
|
COPY --from=build-env /tmp/local /
|
||||||
|
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
COPY --from=build-env /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Build stage
|
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
||||||
FROM docker.io/library/golang:1.21-alpine3.19 AS build-env
|
|
||||||
|
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21-alpine3.19 as build-env
|
||||||
|
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
ENV GOPROXY ${GOPROXY:-direct}
|
ENV GOPROXY ${GOPROXY:-direct}
|
||||||
|
@ -9,24 +10,33 @@ ARG TAGS="sqlite sqlite_unlock_notify"
|
||||||
ENV TAGS "bindata timetzdata $TAGS"
|
ENV TAGS "bindata timetzdata $TAGS"
|
||||||
ARG CGO_EXTRA_CFLAGS
|
ARG CGO_EXTRA_CFLAGS
|
||||||
|
|
||||||
#Build deps
|
#
|
||||||
RUN apk --no-cache add \
|
# Transparently cross compile for the target platform
|
||||||
build-base \
|
#
|
||||||
git \
|
COPY --from=xx / /
|
||||||
nodejs \
|
ARG TARGETPLATFORM
|
||||||
npm \
|
RUN apk --no-cache add clang lld
|
||||||
&& rm -rf /var/cache/apk/*
|
RUN xx-apk --no-cache add gcc musl-dev
|
||||||
|
ENV CGO_ENABLED=1
|
||||||
|
RUN xx-go --wrap
|
||||||
|
#
|
||||||
|
# for go generate and binfmt to find
|
||||||
|
# without it the generate phase will fail with
|
||||||
|
# #19 25.04 modules/public/public_bindata.go:8: running "go": exit status 1
|
||||||
|
# #19 25.39 aarch64-binfmt-P: Could not open '/lib/ld-musl-aarch64.so.1': No such file or directory
|
||||||
|
# why exactly is it needed? where is binfmt involved?
|
||||||
|
#
|
||||||
|
RUN cp /*-alpine-linux-musl*/lib/ld-musl-*.so.1 /lib || true
|
||||||
|
|
||||||
|
RUN apk --no-cache add build-base git nodejs npm
|
||||||
|
|
||||||
# Setup repo
|
|
||||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
||||||
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||||
|
|
||||||
# Checkout version if set
|
RUN make clean-all
|
||||||
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
RUN make frontend
|
||||||
&& make clean-all build
|
RUN go build contrib/environment-to-ini/environment-to-ini.go && xx-verify environment-to-ini
|
||||||
|
RUN make go-check generate-backend static-executable && xx-verify gitea
|
||||||
# Begin env-to-ini build
|
|
||||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
|
||||||
|
|
||||||
# Copy local files
|
# Copy local files
|
||||||
COPY docker/rootless /tmp/local
|
COPY docker/rootless /tmp/local
|
||||||
|
@ -40,7 +50,7 @@ RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
|
||||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||||
|
|
||||||
FROM docker.io/library/alpine:3.19
|
FROM docker.io/library/alpine:3.19
|
||||||
LABEL maintainer="maintainers@gitea.io"
|
LABEL maintainer="contact@forgejo.org"
|
||||||
|
|
||||||
EXPOSE 2222 3000
|
EXPOSE 2222 3000
|
||||||
|
|
||||||
|
@ -69,18 +79,19 @@ RUN mkdir -p /var/lib/gitea /etc/gitea
|
||||||
RUN chown git:git /var/lib/gitea /etc/gitea
|
RUN chown git:git /var/lib/gitea /etc/gitea
|
||||||
|
|
||||||
COPY --from=build-env /tmp/local /
|
COPY --from=build-env /tmp/local /
|
||||||
|
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
||||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
||||||
|
|
||||||
# git:git
|
#git:git
|
||||||
USER 1000:1000
|
USER 1000:1000
|
||||||
ENV GITEA_WORK_DIR /var/lib/gitea
|
ENV GITEA_WORK_DIR /var/lib/gitea
|
||||||
ENV GITEA_CUSTOM /var/lib/gitea/custom
|
ENV GITEA_CUSTOM /var/lib/gitea/custom
|
||||||
ENV GITEA_TEMP /tmp/gitea
|
ENV GITEA_TEMP /tmp/gitea
|
||||||
ENV TMPDIR /tmp/gitea
|
ENV TMPDIR /tmp/gitea
|
||||||
|
|
||||||
# TODO add to docs the ability to define the ini to load (useful to test and revert a config)
|
#TODO add to docs the ability to define the ini to load (useful to test and revert a config)
|
||||||
ENV GITEA_APP_INI /etc/gitea/app.ini
|
ENV GITEA_APP_INI /etc/gitea/app.ini
|
||||||
ENV HOME "/var/lib/gitea/git"
|
ENV HOME "/var/lib/gitea/git"
|
||||||
VOLUME ["/var/lib/gitea", "/etc/gitea"]
|
VOLUME ["/var/lib/gitea", "/etc/gitea"]
|
||||||
|
@ -88,3 +99,4 @@ WORKDIR /var/lib/gitea
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
||||||
CMD []
|
CMD []
|
||||||
|
|
||||||
|
|
65
Makefile
65
Makefile
|
@ -83,31 +83,14 @@ endif
|
||||||
STORED_VERSION_FILE := VERSION
|
STORED_VERSION_FILE := VERSION
|
||||||
HUGO_VERSION ?= 0.111.3
|
HUGO_VERSION ?= 0.111.3
|
||||||
|
|
||||||
GITHUB_REF_TYPE ?= branch
|
|
||||||
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
|
||||||
|
|
||||||
ifneq ($(GITHUB_REF_TYPE),branch)
|
STORED_VERSION=$(shell cat $(STORED_VERSION_FILE) 2>/dev/null)
|
||||||
VERSION ?= $(subst v,,$(GITHUB_REF_NAME))
|
ifneq ($(STORED_VERSION),)
|
||||||
GITEA_VERSION ?= $(VERSION)
|
|
||||||
else
|
|
||||||
ifneq ($(GITHUB_REF_NAME),)
|
|
||||||
VERSION ?= $(subst release/v,,$(GITHUB_REF_NAME))
|
|
||||||
else
|
|
||||||
VERSION ?= main
|
|
||||||
endif
|
|
||||||
|
|
||||||
STORED_VERSION=$(shell cat $(STORED_VERSION_FILE) 2>/dev/null)
|
|
||||||
ifneq ($(STORED_VERSION),)
|
|
||||||
GITEA_VERSION ?= $(STORED_VERSION)
|
GITEA_VERSION ?= $(STORED_VERSION)
|
||||||
else
|
else
|
||||||
GITEA_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
GITEA_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
# if version = "main" then update version to "nightly"
|
|
||||||
ifeq ($(VERSION),main)
|
|
||||||
VERSION := main-nightly
|
|
||||||
endif
|
endif
|
||||||
|
VERSION = ${GITEA_VERSION}
|
||||||
|
|
||||||
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
||||||
|
|
||||||
|
@ -151,6 +134,8 @@ GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/optio
|
||||||
GO_SOURCES += $(GENERATED_GO_DEST)
|
GO_SOURCES += $(GENERATED_GO_DEST)
|
||||||
GO_SOURCES_NO_BINDATA := $(GO_SOURCES)
|
GO_SOURCES_NO_BINDATA := $(GO_SOURCES)
|
||||||
|
|
||||||
|
MIGRATION_PACKAGES := $(shell $(GO) list code.gitea.io/gitea/models/migrations/...)
|
||||||
|
|
||||||
ifeq ($(filter $(TAGS_SPLIT),bindata),bindata)
|
ifeq ($(filter $(TAGS_SPLIT),bindata),bindata)
|
||||||
GO_SOURCES += $(BINDATA_DEST)
|
GO_SOURCES += $(BINDATA_DEST)
|
||||||
GENERATED_GO_DEST += $(BINDATA_DEST)
|
GENERATED_GO_DEST += $(BINDATA_DEST)
|
||||||
|
@ -413,12 +398,11 @@ lint-go-windows:
|
||||||
.PHONY: lint-go-vet
|
.PHONY: lint-go-vet
|
||||||
lint-go-vet:
|
lint-go-vet:
|
||||||
@echo "Running go vet..."
|
@echo "Running go vet..."
|
||||||
@GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet
|
@$(GO) vet $(GO_PACKAGES)
|
||||||
@$(GO) vet -vettool=gitea-vet $(GO_PACKAGES)
|
|
||||||
|
|
||||||
.PHONY: lint-editorconfig
|
.PHONY: lint-editorconfig
|
||||||
lint-editorconfig:
|
lint-editorconfig:
|
||||||
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates .github/workflows
|
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates .forgejo/workflows
|
||||||
|
|
||||||
.PHONY: lint-actions
|
.PHONY: lint-actions
|
||||||
lint-actions:
|
lint-actions:
|
||||||
|
@ -702,8 +686,8 @@ migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
||||||
|
|
||||||
.PHONY: migrations.individual.mysql.test
|
.PHONY: migrations.individual.mysql.test
|
||||||
migrations.individual.mysql.test: $(GO_SOURCES)
|
migrations.individual.mysql.test: $(GO_SOURCES)
|
||||||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
|
for pkg in $(MIGRATION_PACKAGES); do \
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
|
||||||
done
|
done
|
||||||
|
|
||||||
.PHONY: migrations.individual.sqlite.test\#%
|
.PHONY: migrations.individual.sqlite.test\#%
|
||||||
|
@ -712,8 +696,8 @@ migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
||||||
|
|
||||||
.PHONY: migrations.individual.pgsql.test
|
.PHONY: migrations.individual.pgsql.test
|
||||||
migrations.individual.pgsql.test: $(GO_SOURCES)
|
migrations.individual.pgsql.test: $(GO_SOURCES)
|
||||||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
|
for pkg in $(MIGRATION_PACKAGES); do \
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1;\
|
||||||
done
|
done
|
||||||
|
|
||||||
.PHONY: migrations.individual.pgsql.test\#%
|
.PHONY: migrations.individual.pgsql.test\#%
|
||||||
|
@ -723,8 +707,8 @@ migrations.individual.pgsql.test\#%: $(GO_SOURCES) generate-ini-pgsql
|
||||||
|
|
||||||
.PHONY: migrations.individual.mssql.test
|
.PHONY: migrations.individual.mssql.test
|
||||||
migrations.individual.mssql.test: $(GO_SOURCES) generate-ini-mssql
|
migrations.individual.mssql.test: $(GO_SOURCES) generate-ini-mssql
|
||||||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
|
for pkg in $(MIGRATION_PACKAGES); do \
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg -test.failfast; \
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' -test.failfast $$pkg || exit 1; \
|
||||||
done
|
done
|
||||||
|
|
||||||
.PHONY: migrations.individual.mssql.test\#%
|
.PHONY: migrations.individual.mssql.test\#%
|
||||||
|
@ -733,8 +717,8 @@ migrations.individual.mssql.test\#%: $(GO_SOURCES) generate-ini-mssql
|
||||||
|
|
||||||
.PHONY: migrations.individual.sqlite.test
|
.PHONY: migrations.individual.sqlite.test
|
||||||
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
||||||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
|
for pkg in $(MIGRATION_PACKAGES); do \
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
|
||||||
done
|
done
|
||||||
|
|
||||||
.PHONY: migrations.individual.sqlite.test\#%
|
.PHONY: migrations.individual.sqlite.test\#%
|
||||||
|
@ -788,8 +772,14 @@ security-check:
|
||||||
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||||
|
|
||||||
|
static-executable: $(GO_SOURCES) $(TAGS_PREREQ)
|
||||||
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w -linkmode external -extldflags "-static" $(LDFLAGS)' -o $(EXECUTABLE)
|
||||||
|
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
release: frontend generate release-windows release-linux release-darwin release-freebsd release-copy release-compress vendor release-sources release-docs release-check
|
release: frontend generate release-linux release-copy release-compress vendor release-sources release-check
|
||||||
|
|
||||||
|
# just the sources, with all assets builtin and frontend resources generated
|
||||||
|
sources-tarbal: frontend generate vendor release-sources release-check
|
||||||
|
|
||||||
$(DIST_DIRS):
|
$(DIST_DIRS):
|
||||||
mkdir -p $(DIST_DIRS)
|
mkdir -p $(DIST_DIRS)
|
||||||
|
@ -803,7 +793,10 @@ endif
|
||||||
|
|
||||||
.PHONY: release-linux
|
.PHONY: release-linux
|
||||||
release-linux: | $(DIST_DIRS)
|
release-linux: | $(DIST_DIRS)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(LINUX_ARCHS)' -out gitea-$(VERSION) .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(LINUX_ARCHS)' -out forgejo-$(VERSION) .
|
||||||
|
ifeq ($(CI),true)
|
||||||
|
cp /build/* $(DIST)/binaries
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: release-darwin
|
.PHONY: release-darwin
|
||||||
release-darwin: | $(DIST_DIRS)
|
release-darwin: | $(DIST_DIRS)
|
||||||
|
@ -831,8 +824,8 @@ release-sources: | $(DIST_DIRS)
|
||||||
# bsdtar needs a ^ to prevent matching subdirectories
|
# bsdtar needs a ^ to prevent matching subdirectories
|
||||||
$(eval EXCL := --exclude=$(shell tar --help | grep -q bsdtar && echo "^")./)
|
$(eval EXCL := --exclude=$(shell tar --help | grep -q bsdtar && echo "^")./)
|
||||||
# use transform to a add a release-folder prefix; in bsdtar the transform parameter equivalent is -s
|
# use transform to a add a release-folder prefix; in bsdtar the transform parameter equivalent is -s
|
||||||
$(eval TRANSFORM := $(shell tar --help | grep -q bsdtar && echo "-s '/^./gitea-src-$(VERSION)/'" || echo "--transform 's|^./|gitea-src-$(VERSION)/|'"))
|
$(eval TRANSFORM := $(shell tar --help | grep -q bsdtar && echo "-s '/^./forgejo-src-$(VERSION)/'" || echo "--transform 's|^./|forgejo-src-$(VERSION)/|'"))
|
||||||
tar $(addprefix $(EXCL),$(TAR_EXCLUDES)) $(TRANSFORM) -czf $(DIST)/release/gitea-src-$(VERSION).tar.gz .
|
tar $(addprefix $(EXCL),$(TAR_EXCLUDES)) $(TRANSFORM) -czf $(DIST)/release/forgejo-src-$(VERSION).tar.gz .
|
||||||
rm -f $(STORED_VERSION_FILE)
|
rm -f $(STORED_VERSION_FILE)
|
||||||
|
|
||||||
.PHONY: release-docs
|
.PHONY: release-docs
|
||||||
|
|
243
cmd/forgejo/actions.go
Normal file
243
cmd/forgejo/actions.go
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
// Copyright The Forgejo Authors.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package forgejo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
actions_model "code.gitea.io/gitea/models/actions"
|
||||||
|
"code.gitea.io/gitea/modules/private"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
private_routers "code.gitea.io/gitea/routers/private"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CmdActions(ctx context.Context) *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Name: "actions",
|
||||||
|
Usage: "Commands for managing Forgejo Actions",
|
||||||
|
Subcommands: []*cli.Command{
|
||||||
|
SubcmdActionsGenerateRunnerToken(ctx),
|
||||||
|
SubcmdActionsGenerateRunnerSecret(ctx),
|
||||||
|
SubcmdActionsRegister(ctx),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SubcmdActionsGenerateRunnerToken(ctx context.Context) *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Name: "generate-runner-token",
|
||||||
|
Usage: "Generate a new token for a runner to use to register with the server",
|
||||||
|
Action: prepareWorkPathAndCustomConf(ctx, func(cliCtx *cli.Context) error { return RunGenerateActionsRunnerToken(ctx, cliCtx) }),
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "scope",
|
||||||
|
Aliases: []string{"s"},
|
||||||
|
Value: "",
|
||||||
|
Usage: "{owner}[/{repo}] - leave empty for a global runner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SubcmdActionsGenerateRunnerSecret(ctx context.Context) *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Name: "generate-secret",
|
||||||
|
Usage: "Generate a secret suitable for input to the register subcommand",
|
||||||
|
Action: func(cliCtx *cli.Context) error { return RunGenerateSecret(ctx, cliCtx) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SubcmdActionsRegister(ctx context.Context) *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Name: "register",
|
||||||
|
Usage: "Idempotent registration of a runner using a shared secret",
|
||||||
|
Action: prepareWorkPathAndCustomConf(ctx, func(cliCtx *cli.Context) error { return RunRegister(ctx, cliCtx) }),
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "secret",
|
||||||
|
Usage: "the secret the runner will use to connect as a 40 character hexadecimal string",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "secret-stdin",
|
||||||
|
Usage: "the secret the runner will use to connect as a 40 character hexadecimal string, read from stdin",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "secret-file",
|
||||||
|
Usage: "path to the file containing the secret the runner will use to connect as a 40 character hexadecimal string",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "scope",
|
||||||
|
Aliases: []string{"s"},
|
||||||
|
Value: "",
|
||||||
|
Usage: "{owner}[/{repo}] - leave empty for a global runner",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "labels",
|
||||||
|
Value: "",
|
||||||
|
Usage: "comma separated list of labels supported by the runner (e.g. docker,ubuntu-latest,self-hosted) (not required since v1.21)",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "name",
|
||||||
|
Value: "runner",
|
||||||
|
Usage: "name of the runner (default runner)",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "version",
|
||||||
|
Value: "",
|
||||||
|
Usage: "version of the runner (not required since v1.21)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readSecret(ctx context.Context, cliCtx *cli.Context) (string, error) {
|
||||||
|
if cliCtx.IsSet("secret") {
|
||||||
|
return cliCtx.String("secret"), nil
|
||||||
|
}
|
||||||
|
if cliCtx.IsSet("secret-stdin") {
|
||||||
|
buf, err := io.ReadAll(ContextGetStdin(ctx))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(buf), nil
|
||||||
|
}
|
||||||
|
if cliCtx.IsSet("secret-file") {
|
||||||
|
path := cliCtx.String("secret-file")
|
||||||
|
buf, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(buf), nil
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("at least one of the --secret, --secret-stdin, --secret-file options is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateSecret(secret string) error {
|
||||||
|
secretLen := len(secret)
|
||||||
|
if secretLen != 40 {
|
||||||
|
return fmt.Errorf("the secret must be exactly 40 characters long, not %d: generate-secret can provide a secret matching the requirements", secretLen)
|
||||||
|
}
|
||||||
|
if _, err := hex.DecodeString(secret); err != nil {
|
||||||
|
return fmt.Errorf("the secret must be an hexadecimal string: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunRegister(ctx context.Context, cliCtx *cli.Context) error {
|
||||||
|
if !ContextGetNoInit(ctx) {
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
ctx, cancel = installSignals(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if err := initDB(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setting.MustInstalled()
|
||||||
|
|
||||||
|
secret, err := readSecret(ctx, cliCtx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := validateSecret(secret); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
scope := cliCtx.String("scope")
|
||||||
|
labels := cliCtx.String("labels")
|
||||||
|
name := cliCtx.String("name")
|
||||||
|
version := cliCtx.String("version")
|
||||||
|
|
||||||
|
//
|
||||||
|
// There are two kinds of tokens
|
||||||
|
//
|
||||||
|
// - "registration token" only used when a runner interacts to
|
||||||
|
// register
|
||||||
|
//
|
||||||
|
// - "token" obtained after a successful registration and stored by
|
||||||
|
// the runner to authenticate
|
||||||
|
//
|
||||||
|
// The register subcommand does not need a "registration token", it
|
||||||
|
// needs a "token". Using the same name is confusing and secret is
|
||||||
|
// preferred for this reason in the cli.
|
||||||
|
//
|
||||||
|
// The ActionsRunnerRegister argument is token to be consistent with
|
||||||
|
// the internal naming. It is still confusing to the developer but
|
||||||
|
// not to the user.
|
||||||
|
//
|
||||||
|
owner, repo, err := private_routers.ParseScope(ctx, scope)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
runner, err := actions_model.RegisterRunner(ctx, owner, repo, secret, strings.Split(labels, ","), name, version)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error while registering runner: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := fmt.Fprintf(ContextGetStdout(ctx), "%s", runner.UUID); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunGenerateSecret(ctx context.Context, cliCtx *cli.Context) error {
|
||||||
|
runner := actions_model.ActionRunner{}
|
||||||
|
if err := runner.GenerateToken(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := fmt.Fprintf(ContextGetStdout(ctx), "%s", runner.Token); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunGenerateActionsRunnerToken(ctx context.Context, cliCtx *cli.Context) error {
|
||||||
|
if !ContextGetNoInit(ctx) {
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
ctx, cancel = installSignals(ctx)
|
||||||
|
defer cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
setting.MustInstalled()
|
||||||
|
|
||||||
|
scope := cliCtx.String("scope")
|
||||||
|
|
||||||
|
respText, extra := private.GenerateActionsRunnerToken(ctx, scope)
|
||||||
|
if extra.HasError() {
|
||||||
|
return handleCliResponseExtra(ctx, extra)
|
||||||
|
}
|
||||||
|
if _, err := fmt.Fprintf(ContextGetStdout(ctx), "%s", respText.Text); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareWorkPathAndCustomConf(ctx context.Context, action cli.ActionFunc) func(cliCtx *cli.Context) error {
|
||||||
|
return func(cliCtx *cli.Context) error {
|
||||||
|
if !ContextGetNoInit(ctx) {
|
||||||
|
var args setting.ArgWorkPathAndCustomConf
|
||||||
|
// from children to parent, check the global flags
|
||||||
|
for _, curCtx := range cliCtx.Lineage() {
|
||||||
|
if curCtx.IsSet("work-path") && args.WorkPath == "" {
|
||||||
|
args.WorkPath = curCtx.String("work-path")
|
||||||
|
}
|
||||||
|
if curCtx.IsSet("custom-path") && args.CustomPath == "" {
|
||||||
|
args.CustomPath = curCtx.String("custom-path")
|
||||||
|
}
|
||||||
|
if curCtx.IsSet("config") && args.CustomConf == "" {
|
||||||
|
args.CustomConf = curCtx.String("config")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setting.InitWorkPathAndCommonConfig(os.Getenv, args)
|
||||||
|
}
|
||||||
|
return action(cliCtx)
|
||||||
|
}
|
||||||
|
}
|
147
cmd/forgejo/forgejo.go
Normal file
147
cmd/forgejo/forgejo.go
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
// Copyright The Forgejo Authors.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package forgejo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/private"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type key int
|
||||||
|
|
||||||
|
const (
|
||||||
|
noInitKey key = iota + 1
|
||||||
|
noExitKey
|
||||||
|
stdoutKey
|
||||||
|
stderrKey
|
||||||
|
stdinKey
|
||||||
|
)
|
||||||
|
|
||||||
|
func CmdForgejo(ctx context.Context) *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Name: "forgejo-cli",
|
||||||
|
Usage: "Forgejo CLI",
|
||||||
|
Flags: []cli.Flag{},
|
||||||
|
Subcommands: []*cli.Command{
|
||||||
|
CmdActions(ctx),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextSetNoInit(ctx context.Context, value bool) context.Context {
|
||||||
|
return context.WithValue(ctx, noInitKey, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextGetNoInit(ctx context.Context) bool {
|
||||||
|
value, ok := ctx.Value(noInitKey).(bool)
|
||||||
|
return ok && value
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextSetNoExit(ctx context.Context, value bool) context.Context {
|
||||||
|
return context.WithValue(ctx, noExitKey, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextGetNoExit(ctx context.Context) bool {
|
||||||
|
value, ok := ctx.Value(noExitKey).(bool)
|
||||||
|
return ok && value
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextSetStderr(ctx context.Context, value io.Writer) context.Context {
|
||||||
|
return context.WithValue(ctx, stderrKey, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextGetStderr(ctx context.Context) io.Writer {
|
||||||
|
value, ok := ctx.Value(stderrKey).(io.Writer)
|
||||||
|
if !ok {
|
||||||
|
return os.Stderr
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextSetStdout(ctx context.Context, value io.Writer) context.Context {
|
||||||
|
return context.WithValue(ctx, stdoutKey, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextGetStdout(ctx context.Context) io.Writer {
|
||||||
|
value, ok := ctx.Value(stderrKey).(io.Writer)
|
||||||
|
if !ok {
|
||||||
|
return os.Stdout
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextSetStdin(ctx context.Context, value io.Reader) context.Context {
|
||||||
|
return context.WithValue(ctx, stdinKey, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextGetStdin(ctx context.Context) io.Reader {
|
||||||
|
value, ok := ctx.Value(stdinKey).(io.Reader)
|
||||||
|
if !ok {
|
||||||
|
return os.Stdin
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// copied from ../cmd.go
|
||||||
|
func initDB(ctx context.Context) error {
|
||||||
|
setting.MustInstalled()
|
||||||
|
setting.LoadDBSetting()
|
||||||
|
setting.InitSQLLoggersForCli(log.INFO)
|
||||||
|
|
||||||
|
if setting.Database.Type == "" {
|
||||||
|
log.Fatal(`Database settings are missing from the configuration file: %q.
|
||||||
|
Ensure you are running in the correct environment or set the correct configuration file with -c.
|
||||||
|
If this is the intended configuration file complete the [database] section.`, setting.CustomConf)
|
||||||
|
}
|
||||||
|
if err := db.InitEngine(ctx); err != nil {
|
||||||
|
return fmt.Errorf("unable to initialize the database using the configuration in %q. Error: %w", setting.CustomConf, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// copied from ../cmd.go
|
||||||
|
func installSignals(ctx context.Context) (context.Context, context.CancelFunc) {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
go func() {
|
||||||
|
// install notify
|
||||||
|
signalChannel := make(chan os.Signal, 1)
|
||||||
|
|
||||||
|
signal.Notify(
|
||||||
|
signalChannel,
|
||||||
|
syscall.SIGINT,
|
||||||
|
syscall.SIGTERM,
|
||||||
|
)
|
||||||
|
select {
|
||||||
|
case <-signalChannel:
|
||||||
|
case <-ctx.Done():
|
||||||
|
}
|
||||||
|
cancel()
|
||||||
|
signal.Reset()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return ctx, cancel
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleCliResponseExtra(ctx context.Context, extra private.ResponseExtra) error {
|
||||||
|
if false && extra.UserMsg != "" {
|
||||||
|
if _, err := fmt.Fprintf(ContextGetStdout(ctx), "%s", extra.UserMsg); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ContextGetNoExit(ctx) {
|
||||||
|
return extra.Error
|
||||||
|
}
|
||||||
|
return cli.Exit(extra.Error, 1)
|
||||||
|
}
|
37
cmd/main.go
37
cmd/main.go
|
@ -4,10 +4,13 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/cmd/forgejo"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
@ -113,6 +116,36 @@ func prepareWorkPathAndCustomConf(action cli.ActionFunc) func(ctx *cli.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMainApp(version, versionExtra string) *cli.App {
|
func NewMainApp(version, versionExtra string) *cli.App {
|
||||||
|
path, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
executable := filepath.Base(path)
|
||||||
|
|
||||||
|
var subCmdsStandalone []*cli.Command = make([]*cli.Command, 0, 10)
|
||||||
|
var subCmdWithConfig []*cli.Command = make([]*cli.Command, 0, 10)
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the executable is forgejo-cli, provide a Forgejo specific CLI
|
||||||
|
// that is NOT compatible with Gitea.
|
||||||
|
//
|
||||||
|
if executable == "forgejo-cli" {
|
||||||
|
subCmdsStandalone = append(subCmdsStandalone, forgejo.CmdActions(context.Background()))
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Otherwise provide a Gitea compatible CLI which includes Forgejo
|
||||||
|
// specific additions under the forgejo-cli subcommand. It allows
|
||||||
|
// admins to migration from Gitea to Forgejo by replacing the gitea
|
||||||
|
// binary and rename it to forgejo if they want.
|
||||||
|
//
|
||||||
|
subCmdsStandalone = append(subCmdsStandalone, forgejo.CmdForgejo(context.Background()))
|
||||||
|
subCmdWithConfig = append(subCmdWithConfig, CmdActions)
|
||||||
|
}
|
||||||
|
|
||||||
|
return innerNewMainApp(version, versionExtra, subCmdsStandalone, subCmdWithConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func innerNewMainApp(version, versionExtra string, subCmdsStandaloneArgs, subCmdWithConfigArgs []*cli.Command) *cli.App {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "Gitea"
|
app.Name = "Gitea"
|
||||||
app.HelpName = "gitea"
|
app.HelpName = "gitea"
|
||||||
|
@ -137,15 +170,17 @@ func NewMainApp(version, versionExtra string) *cli.App {
|
||||||
CmdMigrateStorage,
|
CmdMigrateStorage,
|
||||||
CmdDumpRepository,
|
CmdDumpRepository,
|
||||||
CmdRestoreRepository,
|
CmdRestoreRepository,
|
||||||
CmdActions,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subCmdWithConfig = append(subCmdWithConfig, subCmdWithConfigArgs...)
|
||||||
|
|
||||||
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
|
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
|
||||||
subCmdStandalone := []*cli.Command{
|
subCmdStandalone := []*cli.Command{
|
||||||
CmdCert,
|
CmdCert,
|
||||||
CmdGenerate,
|
CmdGenerate,
|
||||||
CmdDocs,
|
CmdDocs,
|
||||||
}
|
}
|
||||||
|
subCmdStandalone = append(subCmdStandalone, subCmdsStandaloneArgs...)
|
||||||
|
|
||||||
app.DefaultCommand = CmdWeb.Name
|
app.DefaultCommand = CmdWeb.Name
|
||||||
|
|
||||||
|
|
|
@ -2582,10 +2582,9 @@ LEVEL = Info
|
||||||
; [actions]
|
; [actions]
|
||||||
;; Enable/Disable actions capabilities
|
;; Enable/Disable actions capabilities
|
||||||
;ENABLED = true
|
;ENABLED = true
|
||||||
;;
|
;; Default address to get action plugins, e.g. the default value means downloading from "https://code.forgejo.org/actions/checkout" for "uses: actions/checkout@v3"
|
||||||
;; Default platform to get action plugins, `github` for `https://github.com`, `self` for the current Gitea instance.
|
;DEFAULT_ACTIONS_URL = https://code.forgejo.org
|
||||||
;DEFAULT_ACTIONS_URL = github
|
;; Default artifact retention time in days, default is 90 days
|
||||||
;; Default artifact retention time in days. Artifacts could have their own retention periods by setting the `retention-days` option in `actions/upload-artifact` step.
|
|
||||||
;ARTIFACT_RETENTION_DAYS = 90
|
;ARTIFACT_RETENTION_DAYS = 90
|
||||||
;; Timeout to stop the task which have running status, but haven't been updated for a long time
|
;; Timeout to stop the task which have running status, but haven't been updated for a long time
|
||||||
;ZOMBIE_TASK_TIMEOUT = 10m
|
;ZOMBIE_TASK_TIMEOUT = 10m
|
||||||
|
|
68
models/actions/forgejo.go
Normal file
68
models/actions/forgejo.go
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package actions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
gouuid "github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterRunner(ctx context.Context, ownerID, repoID int64, token string, labels []string, name, version string) (*ActionRunner, error) {
|
||||||
|
uuid, err := gouuid.FromBytes([]byte(token[:16]))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("gouuid.FromBytes %v", err)
|
||||||
|
}
|
||||||
|
uuidString := uuid.String()
|
||||||
|
|
||||||
|
var runner ActionRunner
|
||||||
|
|
||||||
|
has, err := db.GetEngine(ctx).Where("uuid=?", uuidString).Get(&runner)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("GetRunner %v", err)
|
||||||
|
} else if !has {
|
||||||
|
//
|
||||||
|
// The runner does not exist yet, create it
|
||||||
|
//
|
||||||
|
saltBytes, err := util.CryptoRandomBytes(16)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("CryptoRandomBytes %v", err)
|
||||||
|
}
|
||||||
|
salt := hex.EncodeToString(saltBytes)
|
||||||
|
|
||||||
|
hash := auth_model.HashToken(token, salt)
|
||||||
|
|
||||||
|
runner = ActionRunner{
|
||||||
|
UUID: uuidString,
|
||||||
|
TokenHash: hash,
|
||||||
|
TokenSalt: salt,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := CreateRunner(ctx, &runner); err != nil {
|
||||||
|
return &runner, fmt.Errorf("can't create new runner %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Update the existing runner
|
||||||
|
//
|
||||||
|
name, _ = util.SplitStringAtByteN(name, 255)
|
||||||
|
|
||||||
|
runner.Name = name
|
||||||
|
runner.OwnerID = ownerID
|
||||||
|
runner.RepoID = repoID
|
||||||
|
runner.Version = version
|
||||||
|
runner.AgentLabels = labels
|
||||||
|
|
||||||
|
if err := UpdateRunner(ctx, &runner, "name", "owner_id", "repo_id", "version", "agent_labels"); err != nil {
|
||||||
|
return &runner, fmt.Errorf("can't update the runner %+v %w", runner, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &runner, nil
|
||||||
|
}
|
29
models/actions/forgejo_test.go
Normal file
29
models/actions/forgejo_test.go
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package actions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/subtle"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestActions_RegisterRunner(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
ownerID := int64(0)
|
||||||
|
repoID := int64(0)
|
||||||
|
token := "0123456789012345678901234567890123456789"
|
||||||
|
labels := []string{}
|
||||||
|
name := "runner"
|
||||||
|
version := "v1.2.3"
|
||||||
|
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, labels, name, version)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, name, runner.Name)
|
||||||
|
|
||||||
|
assert.EqualValues(t, 1, subtle.ConstantTimeCompare([]byte(runner.TokenHash), []byte(auth_model.HashToken(token, runner.TokenSalt))), "the token cannot be verified with the same method as routers/api/actions/runner/interceptor.go as of 8228751c55d6a4263f0fec2932ca16181c09c97d")
|
||||||
|
}
|
|
@ -11,10 +11,3 @@
|
||||||
issue_id: 1
|
issue_id: 1
|
||||||
is_read: true
|
is_read: true
|
||||||
is_mentioned: false
|
is_mentioned: false
|
||||||
|
|
||||||
-
|
|
||||||
id: 3
|
|
||||||
uid: 2
|
|
||||||
issue_id: 1 # duplicated with id 2
|
|
||||||
is_read: false
|
|
||||||
is_mentioned: true
|
|
||||||
|
|
|
@ -8,23 +8,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func AddCombinedIndexToIssueUser(x *xorm.Engine) error {
|
func AddCombinedIndexToIssueUser(x *xorm.Engine) error {
|
||||||
type OldIssueUser struct {
|
|
||||||
IssueID int64
|
|
||||||
UID int64
|
|
||||||
Cnt int64
|
|
||||||
}
|
|
||||||
|
|
||||||
var duplicatedIssueUsers []OldIssueUser
|
|
||||||
if err := x.SQL("select * from (select issue_id, uid, count(1) as cnt from issue_user group by issue_id, uid) a where a.cnt > 1").
|
|
||||||
Find(&duplicatedIssueUsers); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, issueUser := range duplicatedIssueUsers {
|
|
||||||
if _, err := x.Exec("delete from issue_user where id in (SELECT id FROM issue_user WHERE issue_id = ? and uid = ? limit ?)", issueUser.IssueID, issueUser.UID, issueUser.Cnt-1); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type IssueUser struct {
|
type IssueUser struct {
|
||||||
UID int64 `xorm:"INDEX unique(uid_to_issue)"` // User ID.
|
UID int64 `xorm:"INDEX unique(uid_to_issue)"` // User ID.
|
||||||
IssueID int64 `xorm:"INDEX unique(uid_to_issue)"`
|
IssueID int64 `xorm:"INDEX unique(uid_to_issue)"`
|
||||||
|
|
|
@ -15,10 +15,52 @@ import (
|
||||||
func PrepareOldRepository(t *testing.T) (*xorm.Engine, func()) {
|
func PrepareOldRepository(t *testing.T) (*xorm.Engine, func()) {
|
||||||
type Repository struct { // old struct
|
type Repository struct { // old struct
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
ObjectFormatName string `xorm:"VARCHAR(6) NOT NULL DEFAULT 'sha1'"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommitStatus struct { // old struct
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
ContextHash string `xorm:"char(40)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Comment struct { // old struct
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
CommitSHA string `xorm:"VARCHAR(40)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PullRequest struct { // old struct
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
MergeBase string `xorm:"VARCHAR(40)"`
|
||||||
|
MergedCommitID string `xorm:"VARCHAR(40)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Review struct { // old struct
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
CommitID string `xorm:"VARCHAR(40)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReviewState struct { // old struct
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
CommitSHA string `xorm:"VARCHAR(40)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RepoArchiver struct { // old struct
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
CommitID string `xorm:"VARCHAR(40)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Release struct { // old struct
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
Sha1 string `xorm:"VARCHAR(40)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RepoIndexerStatus struct { // old struct
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
CommitSha string `xorm:"VARCHAR(40)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare and load the testing database
|
// Prepare and load the testing database
|
||||||
return base.PrepareTestEnv(t, 0, new(Repository))
|
return base.PrepareTestEnv(t, 0, new(Repository), new(CommitStatus), new(Comment), new(PullRequest), new(Review), new(ReviewState), new(RepoArchiver), new(Release), new(RepoIndexerStatus))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_RepositoryFormat(t *testing.T) {
|
func Test_RepositoryFormat(t *testing.T) {
|
||||||
|
|
|
@ -40,11 +40,14 @@ func IsWorkflow(path string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.HasPrefix(path, ".gitea/workflows") || strings.HasPrefix(path, ".github/workflows")
|
return strings.HasPrefix(path, ".forgejo/workflows") || strings.HasPrefix(path, ".gitea/workflows") || strings.HasPrefix(path, ".github/workflows")
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListWorkflows(commit *git.Commit) (git.Entries, error) {
|
func ListWorkflows(commit *git.Commit) (git.Entries, error) {
|
||||||
tree, err := commit.SubTree(".gitea/workflows")
|
tree, err := commit.SubTree(".forgejo/workflows")
|
||||||
|
if _, ok := err.(git.ErrNotExist); ok {
|
||||||
|
tree, err = commit.SubTree(".gitea/workflows")
|
||||||
|
}
|
||||||
if _, ok := err.(git.ErrNotExist); ok {
|
if _, ok := err.(git.ErrNotExist); ok {
|
||||||
tree, err = commit.SubTree(".github/workflows")
|
tree, err = commit.SubTree(".github/workflows")
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestElasticsearchIndexer(t *testing.T) {
|
func TestElasticsearchIndexer(t *testing.T) {
|
||||||
|
t.Skip("elasticsearch not found in Forgejo test yet")
|
||||||
// The elasticsearch instance started by pull-db-tests.yml > test-unit > services > elasticsearch
|
// The elasticsearch instance started by pull-db-tests.yml > test-unit > services > elasticsearch
|
||||||
url := "http://elastic:changeme@elasticsearch:9200"
|
url := "http://elastic:changeme@elasticsearch:9200"
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMeilisearchIndexer(t *testing.T) {
|
func TestMeilisearchIndexer(t *testing.T) {
|
||||||
|
t.Skip("meilisearch not found in Forgejo test yet")
|
||||||
// The meilisearch instance started by pull-db-tests.yml > test-unit > services > meilisearch
|
// The meilisearch instance started by pull-db-tests.yml > test-unit > services > meilisearch
|
||||||
url := "http://meilisearch:7700"
|
url := "http://meilisearch:7700"
|
||||||
key := "" // auth has been disabled in test environment
|
key := "" // auth has been disabled in test environment
|
||||||
|
|
32
modules/private/forgejo_actions.go
Normal file
32
modules/private/forgejo_actions.go
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package private
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ActionsRunnerRegisterRequest struct {
|
||||||
|
Token string
|
||||||
|
Scope string
|
||||||
|
Labels []string
|
||||||
|
Name string
|
||||||
|
Version string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ActionsRunnerRegister(ctx context.Context, token, scope string, labels []string, name, version string) (string, ResponseExtra) {
|
||||||
|
reqURL := setting.LocalURL + "api/internal/actions/register"
|
||||||
|
|
||||||
|
req := newInternalRequest(ctx, reqURL, "POST", ActionsRunnerRegisterRequest{
|
||||||
|
Token: token,
|
||||||
|
Scope: scope,
|
||||||
|
Labels: labels,
|
||||||
|
Name: name,
|
||||||
|
Version: version,
|
||||||
|
})
|
||||||
|
|
||||||
|
resp, extra := requestJSONResp(req, &ResponseText{})
|
||||||
|
return resp.Text, extra
|
||||||
|
}
|
|
@ -56,8 +56,8 @@ func TestBaseRedis(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
if !waitRedisReady("redis://127.0.0.1:6379/0", 0) {
|
if !waitRedisReady("redis://127.0.0.1:6379/0", 0) {
|
||||||
redisServer = redisServerCmd(t)
|
redisServer = redisServerCmd(t)
|
||||||
if redisServer == nil && os.Getenv("CI") == "" {
|
if true {
|
||||||
t.Skip("redis-server not found")
|
t.Skip("redis-server not found in Forgejo test yet")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert.NoError(t, redisServer.Start())
|
assert.NoError(t, redisServer.Start())
|
||||||
|
|
|
@ -7,8 +7,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Actions settings
|
// Actions settings
|
||||||
|
@ -25,7 +23,7 @@ var (
|
||||||
SkipWorkflowStrings []string `ìni:"SKIP_WORKFLOW_STRINGS"`
|
SkipWorkflowStrings []string `ìni:"SKIP_WORKFLOW_STRINGS"`
|
||||||
}{
|
}{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
DefaultActionsURL: defaultActionsURLGitHub,
|
DefaultActionsURL: defaultActionsURLForgejo,
|
||||||
SkipWorkflowStrings: []string{"[skip ci]", "[ci skip]", "[no ci]", "[skip actions]", "[actions skip]"},
|
SkipWorkflowStrings: []string{"[skip ci]", "[ci skip]", "[no ci]", "[skip actions]", "[actions skip]"},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -39,18 +37,14 @@ func (url defaultActionsURL) URL() string {
|
||||||
case defaultActionsURLSelf:
|
case defaultActionsURLSelf:
|
||||||
return strings.TrimSuffix(AppURL, "/")
|
return strings.TrimSuffix(AppURL, "/")
|
||||||
default:
|
default:
|
||||||
// This should never happen, but just in case, use GitHub as fallback
|
return string(url)
|
||||||
return "https://github.com"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
defaultActionsURLForgejo = "https://code.forgejo.org"
|
||||||
defaultActionsURLGitHub = "github" // https://github.com
|
defaultActionsURLGitHub = "github" // https://github.com
|
||||||
defaultActionsURLSelf = "self" // the root URL of the self-hosted Gitea instance
|
defaultActionsURLSelf = "self" // the root URL of the self-hosted instance
|
||||||
// DefaultActionsURL only supports GitHub and the self-hosted Gitea.
|
|
||||||
// It's intentionally not supported more, so please be cautious before adding more like "gitea" or "gitlab".
|
|
||||||
// If you get some trouble with `uses: username/action_name@version` in your workflow,
|
|
||||||
// please consider to use `uses: https://the_url_you_want_to_use/username/action_name@version` instead.
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func loadActionsFrom(rootCfg ConfigProvider) error {
|
func loadActionsFrom(rootCfg ConfigProvider) error {
|
||||||
|
@ -60,19 +54,6 @@ func loadActionsFrom(rootCfg ConfigProvider) error {
|
||||||
return fmt.Errorf("failed to map Actions settings: %v", err)
|
return fmt.Errorf("failed to map Actions settings: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if urls := string(Actions.DefaultActionsURL); urls != defaultActionsURLGitHub && urls != defaultActionsURLSelf {
|
|
||||||
url := strings.Split(urls, ",")[0]
|
|
||||||
if strings.HasPrefix(url, "https://") || strings.HasPrefix(url, "http://") {
|
|
||||||
log.Error("[actions] DEFAULT_ACTIONS_URL does not support %q as custom URL any longer, fallback to %q",
|
|
||||||
urls,
|
|
||||||
defaultActionsURLGitHub,
|
|
||||||
)
|
|
||||||
Actions.DefaultActionsURL = defaultActionsURLGitHub
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("unsupported [actions] DEFAULT_ACTIONS_URL: %q", urls)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't support to read configuration from [actions]
|
// don't support to read configuration from [actions]
|
||||||
Actions.LogStorage, err = getStorage(rootCfg, "actions_log", "", nil)
|
Actions.LogStorage, err = getStorage(rootCfg, "actions_log", "", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -110,7 +110,6 @@ func Test_getDefaultActionsURLForActions(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
iniStr string
|
iniStr string
|
||||||
wantErr assert.ErrorAssertionFunc
|
|
||||||
wantURL string
|
wantURL string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
@ -118,8 +117,7 @@ func Test_getDefaultActionsURLForActions(t *testing.T) {
|
||||||
iniStr: `
|
iniStr: `
|
||||||
[actions]
|
[actions]
|
||||||
`,
|
`,
|
||||||
wantErr: assert.NoError,
|
wantURL: "https://code.forgejo.org",
|
||||||
wantURL: "https://github.com",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "github",
|
name: "github",
|
||||||
|
@ -127,7 +125,6 @@ func Test_getDefaultActionsURLForActions(t *testing.T) {
|
||||||
[actions]
|
[actions]
|
||||||
DEFAULT_ACTIONS_URL = github
|
DEFAULT_ACTIONS_URL = github
|
||||||
`,
|
`,
|
||||||
wantErr: assert.NoError,
|
|
||||||
wantURL: "https://github.com",
|
wantURL: "https://github.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -136,35 +133,15 @@ DEFAULT_ACTIONS_URL = github
|
||||||
[actions]
|
[actions]
|
||||||
DEFAULT_ACTIONS_URL = self
|
DEFAULT_ACTIONS_URL = self
|
||||||
`,
|
`,
|
||||||
wantErr: assert.NoError,
|
|
||||||
wantURL: "http://test_get_default_actions_url_for_actions:3000",
|
wantURL: "http://test_get_default_actions_url_for_actions:3000",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "custom url",
|
|
||||||
iniStr: `
|
|
||||||
[actions]
|
|
||||||
DEFAULT_ACTIONS_URL = https://gitea.com
|
|
||||||
`,
|
|
||||||
wantErr: assert.NoError,
|
|
||||||
wantURL: "https://github.com",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "custom urls",
|
name: "custom urls",
|
||||||
iniStr: `
|
iniStr: `
|
||||||
[actions]
|
[actions]
|
||||||
DEFAULT_ACTIONS_URL = https://gitea.com,https://github.com
|
DEFAULT_ACTIONS_URL = https://example.com
|
||||||
`,
|
`,
|
||||||
wantErr: assert.NoError,
|
wantURL: "https://example.com",
|
||||||
wantURL: "https://github.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invalid",
|
|
||||||
iniStr: `
|
|
||||||
[actions]
|
|
||||||
DEFAULT_ACTIONS_URL = gitea
|
|
||||||
`,
|
|
||||||
wantErr: assert.Error,
|
|
||||||
wantURL: "https://github.com",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +149,7 @@ DEFAULT_ACTIONS_URL = gitea
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
cfg, err := NewConfigProviderFromData(tt.iniStr)
|
cfg, err := NewConfigProviderFromData(tt.iniStr)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if !tt.wantErr(t, loadActionsFrom(cfg)) {
|
if !assert.NoError(t, loadActionsFrom(cfg)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert.EqualValues(t, tt.wantURL, Actions.DefaultActionsURL.URL())
|
assert.EqualValues(t, tt.wantURL, Actions.DefaultActionsURL.URL())
|
||||||
|
|
|
@ -22,7 +22,7 @@ func TestMinioStorageIterator(t *testing.T) {
|
||||||
}
|
}
|
||||||
testStorageIterator(t, setting.MinioStorageType, &setting.Storage{
|
testStorageIterator(t, setting.MinioStorageType, &setting.Storage{
|
||||||
MinioConfig: setting.MinioStorageConfig{
|
MinioConfig: setting.MinioStorageConfig{
|
||||||
Endpoint: "127.0.0.1:9000",
|
Endpoint: "minio:9000",
|
||||||
AccessKeyID: "123456",
|
AccessKeyID: "123456",
|
||||||
SecretAccessKey: "12345678",
|
SecretAccessKey: "12345678",
|
||||||
Bucket: "gitea",
|
Bucket: "gitea",
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
package private
|
package private
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
gocontext "context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -64,7 +65,11 @@ func GenerateActionsRunnerToken(ctx *context.PrivateContext) {
|
||||||
ctx.PlainText(http.StatusOK, token.Token)
|
ctx.PlainText(http.StatusOK, token.Token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseScope(ctx *context.PrivateContext, scope string) (ownerID, repoID int64, err error) {
|
func ParseScope(ctx gocontext.Context, scope string) (ownerID, repoID int64, err error) {
|
||||||
|
return parseScope(ctx, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseScope(ctx gocontext.Context, scope string) (ownerID, repoID int64, err error) {
|
||||||
ownerID = 0
|
ownerID = 0
|
||||||
repoID = 0
|
repoID = 0
|
||||||
if scope == "" {
|
if scope == "" {
|
||||||
|
|
209
tests/integration/cmd_forgejo_actions_test.go
Normal file
209
tests/integration/cmd_forgejo_actions_test.go
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
gocontext "context"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
actions_model "code.gitea.io/gitea/models/actions"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_CmdForgejo_Actions(t *testing.T) {
|
||||||
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
||||||
|
token, err := cmdForgejoCaptureOutput(t, []string{"forgejo", "forgejo-cli", "actions", "generate-runner-token"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 40, len(token))
|
||||||
|
|
||||||
|
secret, err := cmdForgejoCaptureOutput(t, []string{"forgejo", "forgejo-cli", "actions", "generate-secret"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 40, len(secret))
|
||||||
|
|
||||||
|
_, err = cmdForgejoCaptureOutput(t, []string{"forgejo", "forgejo-cli", "actions", "register"})
|
||||||
|
assert.ErrorContains(t, err, "at least one of the --secret")
|
||||||
|
|
||||||
|
for _, testCase := range []struct {
|
||||||
|
testName string
|
||||||
|
scope string
|
||||||
|
secret string
|
||||||
|
errorMessage string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
testName: "bad user",
|
||||||
|
scope: "baduser",
|
||||||
|
secret: "0123456789012345678901234567890123456789",
|
||||||
|
errorMessage: "user does not exist",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "bad repo",
|
||||||
|
scope: "org25/badrepo",
|
||||||
|
secret: "0123456789012345678901234567890123456789",
|
||||||
|
errorMessage: "repository does not exist",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "secret length != 40",
|
||||||
|
scope: "org25",
|
||||||
|
secret: "0123456789",
|
||||||
|
errorMessage: "40 characters long",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "secret is not a hexadecimal string",
|
||||||
|
scope: "org25",
|
||||||
|
secret: "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
|
||||||
|
errorMessage: "must be an hexadecimal string",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(testCase.testName, func(t *testing.T) {
|
||||||
|
cmd := []string{"forgejo", "forgejo-cli", "actions", "register", "--secret", testCase.secret, "--scope", testCase.scope}
|
||||||
|
output, err := cmdForgejoCaptureOutput(t, cmd)
|
||||||
|
assert.ErrorContains(t, err, testCase.errorMessage)
|
||||||
|
assert.EqualValues(t, "", output)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
secret = "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
|
||||||
|
expecteduuid := "44444444-4444-4444-4444-444444444444"
|
||||||
|
|
||||||
|
for _, testCase := range []struct {
|
||||||
|
testName string
|
||||||
|
secretOption func() string
|
||||||
|
stdin []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
testName: "secret from argument",
|
||||||
|
secretOption: func() string {
|
||||||
|
return "--secret=" + secret
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "secret from stdin",
|
||||||
|
secretOption: func() string {
|
||||||
|
return "--secret-stdin"
|
||||||
|
},
|
||||||
|
stdin: []string{secret},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "secret from file",
|
||||||
|
secretOption: func() string {
|
||||||
|
secretFile := t.TempDir() + "/secret"
|
||||||
|
assert.NoError(t, os.WriteFile(secretFile, []byte(secret), 0o644))
|
||||||
|
return "--secret-file=" + secretFile
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(testCase.testName, func(t *testing.T) {
|
||||||
|
cmd := []string{"forgejo", "forgejo-cli", "actions", "register", testCase.secretOption(), "--scope=org26"}
|
||||||
|
uuid, err := cmdForgejoCaptureOutput(t, cmd, testCase.stdin...)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, expecteduuid, uuid)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
secret = "0123456789012345678901234567890123456789"
|
||||||
|
expecteduuid = "30313233-3435-3637-3839-303132333435"
|
||||||
|
|
||||||
|
for _, testCase := range []struct {
|
||||||
|
testName string
|
||||||
|
scope string
|
||||||
|
secret string
|
||||||
|
name string
|
||||||
|
labels string
|
||||||
|
version string
|
||||||
|
uuid string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
testName: "org",
|
||||||
|
scope: "org25",
|
||||||
|
secret: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
||||||
|
uuid: "41414141-4141-4141-4141-414141414141",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "user and repo",
|
||||||
|
scope: "user2/repo2",
|
||||||
|
secret: "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
|
||||||
|
uuid: "42424242-4242-4242-4242-424242424242",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "labels",
|
||||||
|
scope: "org25",
|
||||||
|
name: "runnerName",
|
||||||
|
labels: "label1,label2,label3",
|
||||||
|
version: "v1.2.3",
|
||||||
|
secret: "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC",
|
||||||
|
uuid: "43434343-4343-4343-4343-434343434343",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "insert a runner",
|
||||||
|
scope: "user10/repo6",
|
||||||
|
name: "runnerName",
|
||||||
|
labels: "label1,label2,label3",
|
||||||
|
version: "v1.2.3",
|
||||||
|
secret: secret,
|
||||||
|
uuid: expecteduuid,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "update an existing runner",
|
||||||
|
scope: "user5/repo4",
|
||||||
|
name: "runnerNameChanged",
|
||||||
|
labels: "label1,label2,label3,more,label",
|
||||||
|
version: "v1.2.3-suffix",
|
||||||
|
secret: secret,
|
||||||
|
uuid: expecteduuid,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(testCase.testName, func(t *testing.T) {
|
||||||
|
cmd := []string{
|
||||||
|
"forgejo", "forgejo-cli", "actions", "register",
|
||||||
|
"--secret", testCase.secret, "--scope", testCase.scope,
|
||||||
|
}
|
||||||
|
if testCase.name != "" {
|
||||||
|
cmd = append(cmd, "--name", testCase.name)
|
||||||
|
}
|
||||||
|
if testCase.labels != "" {
|
||||||
|
cmd = append(cmd, "--labels", testCase.labels)
|
||||||
|
}
|
||||||
|
if testCase.version != "" {
|
||||||
|
cmd = append(cmd, "--version", testCase.version)
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Run twice to verify it is idempotent
|
||||||
|
//
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
uuid, err := cmdForgejoCaptureOutput(t, cmd)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.EqualValues(t, testCase.uuid, uuid) {
|
||||||
|
ownerName, repoName, found := strings.Cut(testCase.scope, "/")
|
||||||
|
action, err := actions_model.GetRunnerByUUID(gocontext.Background(), uuid)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: action.OwnerID})
|
||||||
|
assert.Equal(t, ownerName, user.Name, action.OwnerID)
|
||||||
|
|
||||||
|
if found {
|
||||||
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: action.RepoID})
|
||||||
|
assert.Equal(t, repoName, repo.Name, action.RepoID)
|
||||||
|
}
|
||||||
|
if testCase.name != "" {
|
||||||
|
assert.EqualValues(t, testCase.name, action.Name)
|
||||||
|
}
|
||||||
|
if testCase.labels != "" {
|
||||||
|
labels := strings.Split(testCase.labels, ",")
|
||||||
|
assert.EqualValues(t, labels, action.AgentLabels)
|
||||||
|
}
|
||||||
|
if testCase.version != "" {
|
||||||
|
assert.EqualValues(t, testCase.version, action.Version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
36
tests/integration/cmd_forgejo_test.go
Normal file
36
tests/integration/cmd_forgejo_test.go
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/cmd/forgejo"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func cmdForgejoCaptureOutput(t *testing.T, args []string, stdin ...string) (string, error) {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
|
app := cli.NewApp()
|
||||||
|
app.Writer = buf
|
||||||
|
app.ErrWriter = buf
|
||||||
|
ctx := context.Background()
|
||||||
|
ctx = forgejo.ContextSetNoInit(ctx, true)
|
||||||
|
ctx = forgejo.ContextSetNoExit(ctx, true)
|
||||||
|
ctx = forgejo.ContextSetStdout(ctx, buf)
|
||||||
|
ctx = forgejo.ContextSetStderr(ctx, buf)
|
||||||
|
if len(stdin) > 0 {
|
||||||
|
ctx = forgejo.ContextSetStdin(ctx, strings.NewReader(strings.Join(stdin, "")))
|
||||||
|
}
|
||||||
|
app.Commands = []*cli.Command{
|
||||||
|
forgejo.CmdForgejo(ctx),
|
||||||
|
}
|
||||||
|
err := app.Run(args)
|
||||||
|
|
||||||
|
return buf.String(), err
|
||||||
|
}
|
|
@ -20,12 +20,6 @@ DATADIR = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/indexers/issues.queue
|
||||||
[queue]
|
[queue]
|
||||||
TYPE = immediate
|
TYPE = immediate
|
||||||
|
|
||||||
[queue.code_indexer]
|
|
||||||
TYPE = immediate
|
|
||||||
|
|
||||||
[queue.push_update]
|
|
||||||
TYPE = immediate
|
|
||||||
|
|
||||||
[repository]
|
[repository]
|
||||||
ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/gitea-repositories
|
ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/gitea-repositories
|
||||||
|
|
||||||
|
@ -96,6 +90,7 @@ COLORIZE = true
|
||||||
LEVEL = Debug
|
LEVEL = Debug
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
|
PASSWORD_HASH_ALGO = argon2
|
||||||
DISABLE_GIT_HOOKS = false
|
DISABLE_GIT_HOOKS = false
|
||||||
INSTALL_LOCK = true
|
INSTALL_LOCK = true
|
||||||
SECRET_KEY = 9pCviYTWSb
|
SECRET_KEY = 9pCviYTWSb
|
||||||
|
|
|
@ -12,8 +12,6 @@ SSL_MODE = disable
|
||||||
[indexer]
|
[indexer]
|
||||||
REPO_INDEXER_ENABLED = true
|
REPO_INDEXER_ENABLED = true
|
||||||
REPO_INDEXER_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/indexers/repos.bleve
|
REPO_INDEXER_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/indexers/repos.bleve
|
||||||
ISSUE_INDEXER_TYPE = elasticsearch
|
|
||||||
ISSUE_INDEXER_CONN_STR = http://elastic:changeme@elasticsearch:9200
|
|
||||||
|
|
||||||
[queue.issue_indexer]
|
[queue.issue_indexer]
|
||||||
TYPE = level
|
TYPE = level
|
||||||
|
@ -22,12 +20,6 @@ DATADIR = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/indexers/issues.queue
|
||||||
[queue]
|
[queue]
|
||||||
TYPE = immediate
|
TYPE = immediate
|
||||||
|
|
||||||
[queue.code_indexer]
|
|
||||||
TYPE = immediate
|
|
||||||
|
|
||||||
[queue.push_update]
|
|
||||||
TYPE = immediate
|
|
||||||
|
|
||||||
[repository]
|
[repository]
|
||||||
ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/gitea-repositories
|
ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/gitea-repositories
|
||||||
|
|
||||||
|
@ -94,6 +86,7 @@ COLORIZE = true
|
||||||
LEVEL = Debug
|
LEVEL = Debug
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
|
PASSWORD_HASH_ALGO = argon2
|
||||||
DISABLE_GIT_HOOKS = false
|
DISABLE_GIT_HOOKS = false
|
||||||
INSTALL_LOCK = true
|
INSTALL_LOCK = true
|
||||||
SECRET_KEY = 9pCviYTWSb
|
SECRET_KEY = 9pCviYTWSb
|
||||||
|
|
|
@ -21,12 +21,6 @@ DATADIR = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/indexers/issues.queue
|
||||||
[queue]
|
[queue]
|
||||||
TYPE = immediate
|
TYPE = immediate
|
||||||
|
|
||||||
[queue.code_indexer]
|
|
||||||
TYPE = immediate
|
|
||||||
|
|
||||||
[queue.push_update]
|
|
||||||
TYPE = immediate
|
|
||||||
|
|
||||||
[repository]
|
[repository]
|
||||||
ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/gitea-repositories
|
ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/gitea-repositories
|
||||||
|
|
||||||
|
@ -97,6 +91,7 @@ COLORIZE = true
|
||||||
LEVEL = Debug
|
LEVEL = Debug
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
|
PASSWORD_HASH_ALGO = argon2
|
||||||
DISABLE_GIT_HOOKS = false
|
DISABLE_GIT_HOOKS = false
|
||||||
INSTALL_LOCK = true
|
INSTALL_LOCK = true
|
||||||
SECRET_KEY = 9pCviYTWSb
|
SECRET_KEY = 9pCviYTWSb
|
||||||
|
|
|
@ -16,12 +16,6 @@ DATADIR = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/indexers/issues.queue
|
||||||
[queue]
|
[queue]
|
||||||
TYPE = immediate
|
TYPE = immediate
|
||||||
|
|
||||||
[queue.code_indexer]
|
|
||||||
TYPE = immediate
|
|
||||||
|
|
||||||
[queue.push_update]
|
|
||||||
TYPE = immediate
|
|
||||||
|
|
||||||
[repository]
|
[repository]
|
||||||
ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/gitea-repositories
|
ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-sqlite/gitea-repositories
|
||||||
|
|
||||||
|
@ -93,6 +87,7 @@ COLORIZE = true
|
||||||
LEVEL = Debug
|
LEVEL = Debug
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
|
PASSWORD_HASH_ALGO = argon2
|
||||||
DISABLE_GIT_HOOKS = false
|
DISABLE_GIT_HOOKS = false
|
||||||
INSTALL_LOCK = true
|
INSTALL_LOCK = true
|
||||||
SECRET_KEY = 9pCviYTWSb
|
SECRET_KEY = 9pCviYTWSb
|
||||||
|
|
Loading…
Reference in a new issue