merge actions test into end-to-end.sh

* replace the high level test running actions tests with end-to-end.sh
* set DOMAIN to the IP instead of 127.0.0.1 for runner <-> forgejo communications
* move forgejo_cli from a function to a file so that it can be used by forgejo-runner.sh
* keep the documentation updates workflows separate because they need to open one PR per version
This commit is contained in:
Twenty Panda 2024-03-20 11:51:46 +01:00
parent 5bb5e037ce
commit 96f91063c9
21 changed files with 235 additions and 269 deletions

View file

@ -1,82 +0,0 @@
#
#
# https://code.forgejo.org/forgejo/end-to-end/settings/actions
#
# secrets.CASCADE_DOCS_ORIGIN_TOKEN
# https://code.forgejo.org/forgejo-ci scope write:issue, read:repository, read:user
# vars.CASCADE_DOCS_DESTINATION_DOER
# forgejo-cascading-pr (https://codeberg.org/forgejo-cascading-pr)
# secrets.CASCADE_DOCS_DESTINATION_TOKEN
# https://codeberg.org/forgejo-cascading-pr scope write:issue, write:repository, read:user
# vars.CASCADE_DOCS_FORCE_VERSION
# replace the generated documentation for a given version even if it has already
# been generated (e.g. v7.0.0-test)
#
on:
pull_request:
push:
branches:
- 'main'
jobs:
actions:
runs-on: self-hosted
strategy:
matrix:
info:
- version: v7.0
branch: next
forgejo: https://codeberg.org
repo: forgejo-experimental/forgejo
tests: ${{ vars.V7_0_TESTS }}
- version: v1.21
forgejo: https://codeberg.org
repo: forgejo/forgejo
tests: ${{ vars.V1_21_TESTS }}
- version: v1.20
forgejo: https://codeberg.org
repo: forgejo/forgejo
tests: ${{ vars.V1_20_TESTS }}
steps:
- uses: actions/checkout@v4
- uses: https://code.forgejo.org/actions/setup-forgejo@v2
with:
install-only: true
- name: run
id: run
if: matrix.info.tests != 'none'
shell: bash
run: |
set -x
forgejo-binary.sh ensure_user forgejo
full_version=$(curl -sS ${{ matrix.info.forgejo }}/api/v1/repos/${{ matrix.info.repo }}/releases | jq -r '.[] | .tag_name | select(startswith("${{ matrix.info.version }}"))' | sort -r | head -1)
binary=${{ matrix.info.forgejo }}/${{ matrix.info.repo }}/releases/download/${full_version}/forgejo-${full_version#v}-linux-amd64
export DIR=$(mktemp -d)
chown forgejo $DIR /srv
su -c "actions/run.sh $binary $full_version ${{ matrix.info.version }} ${{ matrix.info.tests }}" forgejo
echo full_version="$full_version" >> $GITHUB_OUTPUT
- name: update documentation
if: matrix.info.tests != 'none' && github.ref == 'refs/heads/main'
uses: https://code.forgejo.org/actions/cascading-pr@v1
with:
origin-url: ${{ env.GITHUB_SERVER_URL }}
origin-repo: ${{ github.repository }}
origin-token: ${{ secrets.CASCADE_DOCS_ORIGIN_TOKEN }}
origin-ref: refs/heads/main
destination-url: https://codeberg.org
destination-fork-repo: ${{ vars.CASCADE_DOCS_DESTINATION_DOER }}/docs
destination-repo: forgejo/docs
destination-branch: ${{ matrix.info.branch || matrix.info.version }}
destination-token: ${{ secrets.CASCADE_DOCS_DESTINATION_TOKEN }}
prefix: ${{ env.GITHUB_REPOSITORY }}-${{ matrix.info.version }}
update: .forgejo/cascading-docs
env:
FORCE_VERSION: "${{ vars.CASCADE_DOCS_FORCE_VERSION }}"
VERSION: "${{ steps.run.outputs.full_version }}"

View file

@ -1,3 +1,18 @@
#
#
# https://code.forgejo.org/forgejo/end-to-end/settings/actions
#
# secrets.CASCADE_DOCS_ORIGIN_TOKEN
# https://code.forgejo.org/forgejo-ci scope write:issue, read:repository, read:user
# vars.CASCADE_DOCS_DESTINATION_DOER
# forgejo-cascading-pr (https://codeberg.org/forgejo-cascading-pr)
# secrets.CASCADE_DOCS_DESTINATION_TOKEN
# https://codeberg.org/forgejo-cascading-pr scope write:issue, write:repository, read:user
# vars.CASCADE_DOCS_FORCE_VERSION
# replace the generated documentation for a given version even if it has already
# been generated (e.g. v7.0.0-test)
#
on:
pull_request:
push:
@ -47,6 +62,57 @@ jobs:
- uses: ./.forgejo/prepare-end-to-end
- run: su forgejo -c "./end-to-end.sh test_packages"
actions:
needs: [build]
runs-on: lxc-bookworm
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: ./.forgejo/prepare-end-to-end
- run: su forgejo -c "./end-to-end.sh test_actions"
actions-docs:
needs: [build]
runs-on: lxc-bookworm
if: github.ref == 'refs/heads/main'
strategy:
matrix:
info:
- version: 7.0
branch: next
forgejo: https://codeberg.org
repo: forgejo-experimental/forgejo
- version: 1.21
forgejo: https://codeberg.org
repo: forgejo/forgejo
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: ./.forgejo/prepare-end-to-end
- name: set full-version
id: full-version
shell: bash
run: |
set -x
full_version=$(./end-to-end.sh full_version ${{ matrix.info.version }})
echo value="$full_version" >> $GITHUB_OUTPUT
- run: su forgejo -c "./end-to-end.sh test_actions ${{ matrix.info.version }}"
- name: update documentation
uses: https://code.forgejo.org/actions/cascading-pr@v1
with:
origin-url: ${{ env.GITHUB_SERVER_URL }}
origin-repo: ${{ github.repository }}
origin-token: ${{ secrets.CASCADE_DOCS_ORIGIN_TOKEN }}
origin-ref: refs/heads/main
destination-url: https://codeberg.org
destination-fork-repo: ${{ vars.CASCADE_DOCS_DESTINATION_DOER }}/docs
destination-repo: forgejo/docs
destination-branch: ${{ matrix.info.branch || format('v{0}', matrix.info.version) }}
destination-token: ${{ secrets.CASCADE_DOCS_DESTINATION_TOKEN }}
prefix: ${{ env.GITHUB_REPOSITORY }}-${{ matrix.info.version }}
update: .forgejo/cascading-docs
env:
FORCE_VERSION: "${{ vars.CASCADE_DOCS_FORCE_VERSION }}"
VERSION: "${{ steps.full-version.outputs.value }}"
upgrade:
name: upgrade and storage
needs: [build]

View file

@ -30,24 +30,24 @@ Action](https://forgejo.org/docs/v1.21/user/actions/) which is meant
to be used in workflows. However, it is implemented as shell scripts that
can also be used to create Forgejo instances and runners locally. This
is convenient for testing and the reason why it needs to be added to the PATH.
For instance, it is a dependency of the `actions/run.sh` script.
For instance, it is a dependency of the `end-to-end.sh` script.
```sh
git clone https://code.forgejo.org/actions/setup-forgejo
export PATH=$(pwd)/setup-forgejo:$PATH
git clone https://code.forgejo.org/forgejo/end-to-end
cd end-to-end
export DIR=/tmp/forgejo-end-to-end
rm -fr /tmp/forgejo-end-to-end ; sudo rm -fr /srv/example ; sudo mkdir /srv/example ; sudo chown -R $USER /srv/example
```
Run using Forgejo built from source.
## Running from locally built binary
```sh
make TAGS='bindata sqlite sqlite_unlock_notify' generate forgejo
cp -a forgejo $DIR/forgejo
cp -a forgejo /srv/forgejo-binaries/forgejo-7.0-dev
```
It will be used whenver the version `7.0-dev` is specified in a test.
## Running actions locally
To run and debug workflows from `actions/example-*`, from the root of
@ -58,43 +58,12 @@ run as root in the context of Forgejo Actions and assume they have
admin permissions. But they do not need to run as root and must work
fine when run as a regular user.
Run one example
```sh
actions/run.sh https://codeberg.org/forgejo-experimental/forgejo/releases/download/v7.0.0-test/forgejo-7.0.0-test-linux-amd64 v7.0.0-test v7_0 cron # runs actions/example-cron
./end-to-end.sh actions_setup 1.21
firefox 0.0.0.0:3000 # user root / admin1234
./end-to-end.sh actions_verify_example artifacts
./end-to-end.sh actions_teardown
```
Cleanup. It will teardown Forgejo & the runner and not run them because there is nothing to test.
```sh
actions/run.sh https://codeberg.org/forgejo-experimental/forgejo/releases/download/v7.0.0-test/forgejo-7.0.0-test-linux-amd64 v7.0.0-test v7_0 none
```
Run all examples for v7_0
```sh
actions/run.sh https://codeberg.org/forgejo-experimental/forgejo/releases/download/v7.0.0-test/forgejo-7.0.0-test-linux-amd64 v7.0.0-test v7_0
```
Run from sources
```sh
make TAGS='bindata sqlite sqlite_unlock_notify' generate forgejo
cp -a forgejo $DIR/forgejo
```
Remote testing
To reduce the runtime the following variables can be set to control
the number of cases run by the
[actions](.forgejo/workflows/actions.yml) tests. If set to
**none** they are not run at all for that version of Forgejo. If
it does not exist, all tests are run.
* `v7_0_TESTS`
* `V1_21_TESTS`
* `V1_20_TESTS`
## Running other tests locally
To run and debug tests, from the root of the source directory.
@ -102,12 +71,12 @@ To run and debug tests, from the root of the source directory.
Run one test. When the test fails the instance can be inspected at http://0.0.0.0:3000
```sh
VERBOSE=true ./forgejo/upgrades/test-upgrade.sh test_packages_alpine
VERBOSE=true ./forgejo/upgrades/test-upgrade.sh test_storage_stable_s3 minio
./end-to-end.sh test_packages_alpine
./end-to-end.sh test_storage_stable_s3 minio
```
Cleanup. It will teardown the Forgejo instance.
```sh
./forgejo/upgrades/test-upgrade.sh stop
./end-to-end.sh stop
```

98
actions/actions.sh Executable file
View file

@ -0,0 +1,98 @@
# Copyright 2024 The Forgejo Authors
# SPDX-License-Identifier: MIT
ACTIONS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
function actions_verify_example() {
local example=$1
export url=http://${FORGEJO_USER}:${FORGEJO_PASSWORD}@${HOST_PORT}
export token=$(cat $DOT_FORGEJO_CURL/token)
actions_cleanup_example_volume
export example
export EXAMPLE_DIR=$ACTIONS_DIR/example-$example
if test -f $EXAMPLE_DIR/setup.sh ; then
echo "============================ SETUP example-$example ==================="
bash -ex $EXAMPLE_DIR/setup.sh || return 1
fi
if test -f $EXAMPLE_DIR/run.sh ; then
echo "============================ RUN example-$example ==================="
bash -ex $EXAMPLE_DIR/run.sh || return 1
else
forgejo-test-helper.sh run_workflow actions/example-$example $url root example-$example $example $token || return 1
fi
if test -f $EXAMPLE_DIR/teardown.sh ; then
echo "============================ TEARDOWN example-$example ==================="
bash -ex $EXAMPLE_DIR/teardown.sh || return 1
fi
actions_save_contexts $example
}
function actions_save_contexts() {
local example="$1"
if test -d /srv/example/$example/contexts; then
mkdir -p /srv/contexts
rsync -av /srv/example/$example/contexts/ /srv/contexts/$example/
fi
}
function actions_cleanup_example_volume() {
if test $(id -u) != 0 ; then
$SUDO chown $(id -u) /srv
fi
if ! test -d /srv/example ; then
mkdir -p /srv/example
return
fi
$SUDO rm -fr /srv/example/*
}
function actions_setup() {
local version=$1
actions_teardown
reset_forgejo $ACTIONS_DIR/default-app.ini
start_forgejo $version
export FORGEJO_RUNNER_LOGS=$DIR/forgejo-runner.log
actions_cleanup_example_volume
export FORGEJO_RUNNER_CONFIG=$ACTIONS_DIR/runner-config.yaml
forgejo-runner.sh setup '' '' http://${HOST_PORT}
}
function actions_teardown() {
forgejo-curl.sh logout
forgejo-runner.sh teardown
stop_daemon forgejo
}
function test_actions() {
local versions="${1:-1.20 1.21 $RELEASE_NUMBERS_AND_DEV}"
for version in $versions ; do
log_info "Testing actions for $version"
actions_setup $version
for example in echo checkout service container expression local-action docker-action if if-fail ; do
run actions_verify_example $example
done
if dpkg --compare-versions $version gt 1.20 ; then
for example in push tag push-cancel artifacts pull-request context cron ; do
run actions_verify_example $example
done
fi
done
}

35
actions/default-app.ini Normal file
View file

@ -0,0 +1,35 @@
RUN_MODE = prod
WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/data
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true
[queue]
TYPE = immediate
[database]
DB_TYPE = sqlite3
PATH = ${WORK_PATH}/forgejo.db
[log]
MODE = file
LEVEL = trace
ROUTER = file
[log.file]
FILE_NAME = forgejo.log
[security]
INSTALL_LOCK = true
[repository]
ENABLE_PUSH_CREATE_USER = true
DEFAULT_PUSH_CREATE_PRIVATE = false
DEFAULT_REPO_UNITS = repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages,repo.actions
[actions]
ENABLED = true

View file

@ -1,127 +0,0 @@
#!/bin/bash
set -e
set -o pipefail
SELF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
function run() {
local example=$1
export example
export EXAMPLE_DIR=$SELF_DIR/example-$example
if test -f $EXAMPLE_DIR/setup.sh ; then
echo "============================ SETUP example-$example ==================="
bash -ex $EXAMPLE_DIR/setup.sh || return 1
fi
if test -f $EXAMPLE_DIR/run.sh ; then
echo "============================ RUN example-$example ==================="
bash -ex $EXAMPLE_DIR/run.sh || return 1
else
forgejo-test-helper.sh run_workflow actions/example-$example $url root example-$example $example $token || return 1
fi
if test -f $EXAMPLE_DIR/teardown.sh ; then
echo "============================ TEARDOWN example-$example ==================="
bash -ex $EXAMPLE_DIR/teardown.sh || return 1
fi
}
function examples_v1_20() {
echo 'echo checkout service container expression local-action docker-action if if-fail'
}
function examples_v1_21() {
# keep "cron" last otherwise it will linger and pollute the following runs
echo 'echo push tag push-cancel artifacts service checkout pull-request container expression local-action context docker-action if if-fail cron'
}
function examples_v7_0() {
examples_v1_21
}
function save_contexts() {
local example="$1"
if test -d /srv/example/$example/contexts; then
mkdir -p /srv/contexts
rsync -av /srv/example/$example/contexts/ /srv/contexts/$example/
fi
}
function cleanup_example_volume() {
if ! test -d /srv/example ; then
mkdir -p /srv/example
return
fi
if test $(id -u) != 0 ; then
SUDO=sudo
fi
$SUDO rm -fr /srv/example/*
}
function setup() {
local binary=$1
forgejo-binary.sh setup root admin1234 $binary
cleanup_example_volume
export FORGEJO_RUNNER_CONFIG=$SELF_DIR/runner-config.yaml
forgejo-runner.sh setup
}
function teardown() {
forgejo-curl.sh logout
forgejo-runner.sh teardown
forgejo-binary.sh teardown
}
function main() {
local binary="$1"
shift
export full_version="$1"
shift
export version="$1"
shift
export DOT=$DIR/forgejo-curl
teardown
if test "$#" = 0 ; then
examples=$(examples_${version/./_})
else
examples="$@"
fi
if test "$examples" = "none" ; then
exit 0
fi
setup $binary
if ! test -f "$DIR/forgejo-auth-url" ; then
echo "DIR=$DIR must be a directory with a forgejo-auth-url file"
fi
export FORGEJO_RUNNER_LOGS=$DIR/forgejo-runner.log
export url=$(cat $DIR/forgejo-auth-url)
export token=$(cat $DIR/forgejo-token)
for example in $examples ; do
echo "======================== BEGIN example-$example ==================="
if ! time run $example >& /tmp/run.out ; then
sed -e 's/^/[RUN] /' < /tmp/run.out
echo "======================== FAIL example-$example ==================="
sleep 5 # hack for Forgejo v1.21 to workaround a bug by which the last lines of the output are moved to the next step
false
fi
echo "======================== END example-$example ==================="
save_contexts $example
cleanup_example_volume
done
}
main "$@"

View file

@ -15,6 +15,7 @@ SELF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SELF="${BASH_SOURCE[0]}"
source $SELF_DIR/lib/lib.sh
source $SELF_DIR/actions/actions.sh
source $SELF_DIR/forgejo/fixtures.sh
source $SELF_DIR/storage/storage.sh
source $SELF_DIR/upgrade/upgrade.sh

View file

@ -3,5 +3,5 @@
function doctor_run() {
local version=$1
forgejo_cli $version doctor check --all # --log-file -
$DIR/forgejocli doctor check --all # --log-file -
}

View file

@ -28,7 +28,7 @@ RELEASE_NUMBERS="7.0"
PREFIX===============
HOST_PORT=$IP:3000
DIR=/tmp/forgejo-end-to-end
export DIR=/tmp/forgejo-end-to-end
DIR_BINARIES=/srv/forgejo-binaries
export DOT_FORGEJO_CURL=$DIR/forgejo-curl
export DOT=$DOT_FORGEJO_CURL # for backward compatibility with forgejo-curl.sh 1.0.0
@ -47,9 +47,9 @@ function dependencies() {
$SUDO chmod +x /usr/local/bin/forgejo-curl.sh
fi
if ! which curl daemon jq git-lfs > /dev/null ; then
if ! which make curl daemon git-lfs jq sqlite3 > /dev/null ; then
$SUDO apt-get update -qq
$SUDO apt-get install -y -qq curl daemon git-lfs jq sqlite3 gettext-base
$SUDO apt-get install -y -qq make curl daemon git-lfs jq sqlite3 gettext-base
fi
if ! test -f /usr/local/bin/mc || ! test -f /usr/local/bin/minio ; then
@ -159,6 +159,8 @@ function start_forgejo() {
grep '' $work_path/log/*.log 2> /dev/null
return 1
fi
echo "$DIR_BINARIES/forgejo-$version --config $work_path/app.ini --work-path $work_path" '"$@"' > $DIR/forgejocli
chmod +x $DIR/forgejocli
create_user_and_login $version
}
@ -238,7 +240,7 @@ function reset_forgejo() {
local work_path=$DIR/forgejo-work-path
rm -fr $work_path
mkdir -p $work_path
WORK_PATH=$work_path envsubst < $config > $work_path/app.ini
IP=$IP WORK_PATH=$work_path envsubst < $config > $work_path/app.ini
}
function reset_minio() {
@ -249,20 +251,12 @@ function reset_garage() {
rm -fr $DIR/garage
}
function forgejo_cli() {
local version="$1"
shift
local work_path=$DIR/forgejo-work-path
$DIR_BINARIES/forgejo-$version --config $work_path/app.ini --work-path $work_path "$@"
}
function create_user_and_login() {
local version=$1
local email="$FORGEJO_USER@example.com"
if ! forgejo_cli $version admin user list | grep --quiet "$email" ; then
forgejo_cli $version admin user create --admin --username "$FORGEJO_USER" --password "$FORGEJO_PASSWORD" --email $email
if ! $DIR/forgejocli admin user list | grep --quiet "$email" ; then
$DIR/forgejocli admin user create --admin --username "$FORGEJO_USER" --password "$FORGEJO_PASSWORD" --email $email
fi
forgejo-curl.sh logout
@ -302,10 +296,10 @@ function run() {
local fun=$1
shift
echo Start running $fun
echo Start running $fun "$@"
mkdir -p $DIR
> $DIR/$fun.out
tail --follow $DIR/$fun.out | sed --unbuffered -n -e "/^$PREFIX/s/^$PREFIX //p" &
tail --follow $DIR/$fun.out |& sed --unbuffered -n -e "/^$PREFIX/s/^$PREFIX //p" &
local pid=$!
if ! VERBOSE=true $SELF $fun "$@" >& $DIR/$fun.out ; then
kill $pid

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/data
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/data
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/data
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/data
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/elsewhere
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/elsewhere
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/elsewhere
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/data
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/elsewhere
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/elsewhere
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/data
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true

View file

@ -3,6 +3,7 @@ WORK_PATH = ${WORK_PATH}
[server]
APP_DATA_PATH = ${WORK_PATH}/data
DOMAIN = ${IP}
HTTP_PORT = 3000
SSH_LISTEN_PORT = 2222
LFS_START_SERVER = true