diff --git a/.forgejo/workflows/packages.yml b/.forgejo/workflows/packages.yml new file mode 100644 index 0000000..75fd222 --- /dev/null +++ b/.forgejo/workflows/packages.yml @@ -0,0 +1,41 @@ +on: + pull_request: + push: + branches: + - 'main' + +jobs: + actions: + runs-on: self-hosted + strategy: + matrix: + info: + - version: v1.22 + branch: next + forgejo: https://codeberg.org + repo: forgejo-experimental/forgejo + tests: ${{ vars.V1_22_TESTS }} + - version: v1.21 + forgejo: https://codeberg.org + repo: forgejo/forgejo + tests: ${{ vars.V1_21_TESTS }} + steps: + - uses: actions/checkout@v4 + + - uses: https://code.forgejo.org/actions/setup-forgejo@v2 + with: + install-only: true + + - name: 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 "packages/run.sh $binary $full_version ${{ matrix.info.version }} ${{ matrix.info.tests }}" forgejo diff --git a/README.md b/README.md index 7d1aaa7..a458be0 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,27 @@ specifically for testing such as They are designed to run using Forgejo releases and development versions compiled from designated repositories. -## Hacking +# Hacking -To run and debug workflows from `actions/example-*`, from the root of -the source directory, with docker and forgejo-curl.sh installed, mimic -what `.forgejo/workflows/actions.yml` does. There may be some manual -tweaking (such as creating temporary directories) because the tests -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. +docker and sudo must be installed with insecure registries allowed in +/etc/docker/daemon.json for the IP that will be used for forgejo such +as: -### Prepare the Forgejo instance and the runner +```json +{ + "insecure-registries": [ "10.80.4.76:3000" ] +} +``` + +Use setup-forgejo from source. + +The [setup-forgejo](https://code.forgejo.org/actions/setup-forgejo) +repository is a [Forgejo +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. ```sh git clone https://code.forgejo.org/actions/setup-forgejo @@ -31,6 +41,23 @@ export DIR=/tmp/end-to-end rm -fr /tmp/end-to-end ; sudo rm -fr /srv/example ; sudo mkdir /srv/example ; sudo chown -R $USER /srv/example ``` +Run using Forgejo built from source. + +```sh +make TAGS='bindata sqlite sqlite_unlock_notify' generate forgejo +cp -a forgejo $DIR/forgejo +``` + +## Running actions locally + +To run and debug workflows from `actions/example-*`, from the root of +the source directory, with docker and forgejo-curl.sh installed, mimic +what `.forgejo/workflows/actions.yml` does. There may be some manual +tweaking (such as creating temporary directories) because the tests +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 @@ -56,7 +83,7 @@ make TAGS='bindata sqlite sqlite_unlock_notify' generate forgejo cp -a forgejo $DIR/forgejo ``` -### Remote testing +Remote testing To reduce the runtime the following variables can be set to control the number of cases run by the @@ -67,3 +94,35 @@ it does not exist, all tests are run. * `V1_22_TESTS` * `V1_21_TESTS` * `V1_20_TESTS` + +## Running packages locally + +To run and debug package tests, from the root of the source directory. + +Run one test + +```sh +packages/run.sh https://codeberg.org/forgejo-experimental/forgejo/releases/download/v1.22.0-test/forgejo-1.22.0-test-linux-amd64 v1.22.0-test v1_22 alpine # runs packages/alpine.sh +``` + +Cleanup. It will teardown Forgejo and not run them because there is nothing to test. + +```sh +packages/run.sh https://codeberg.org/forgejo-experimental/forgejo/releases/download/v1.22.0-test/forgejo-1.22.0-test-linux-amd64 v1.22.0-test v1_22 none +``` +Run all examples for v1_22 + +```sh +packages/run.sh https://codeberg.org/forgejo-experimental/forgejo/releases/download/v1.22.0-test/forgejo-1.22.0-test-linux-amd64 v1.22.0-test v1_22 +``` + +Remote testing + +To reduce the runtime the following variables can be set to control +the number of cases run by the +[packages test](.forgejo/workflows/packages.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. + +* `V1_22_PACKAGES_TESTS` +* `V1_21_PACKAGES_TESTS` diff --git a/forgejo/build.sh b/forgejo/build.sh index c78bbdd..5ee106d 100755 --- a/forgejo/build.sh +++ b/forgejo/build.sh @@ -1,4 +1,6 @@ #!/bin/bash +# Copyright 2024 The Forgejo Authors +# SPDX-License-Identifier: MIT set -ex diff --git a/lib/lib.sh b/lib/lib.sh new file mode 100644 index 0000000..f5155c0 --- /dev/null +++ b/lib/lib.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Copyright 2024 The Forgejo Authors +# SPDX-License-Identifier: MIT + +set -e +set -o pipefail + +export DEBIAN_FRONTEND=noninteractive + +if test $(id -u) != 0 ; then + SUDO=sudo +fi + +PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: ' diff --git a/packages/alpine.sh b/packages/alpine.sh new file mode 100644 index 0000000..96c619b --- /dev/null +++ b/packages/alpine.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# Copyright 2024 The Forgejo Authors +# SPDX-License-Identifier: MIT + +SELF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source $SELF_DIR/../lib/lib.sh + +function main() { + local d=$SELF_DIR/alpine + local token=$(cat $DIR/forgejo-token) + local url=$(cat $DIR/forgejo-url) + + docker run --rm --volume $d:$d:ro --workdir $d docker.io/alpine:3.19 ash -c "./test.sh $url $token" +} + +"${@:-main}" diff --git a/packages/alpine/package-source/APKBUILD b/packages/alpine/package-source/APKBUILD new file mode 100644 index 0000000..ce75e29 --- /dev/null +++ b/packages/alpine/package-source/APKBUILD @@ -0,0 +1,26 @@ +# -*- mode: Shell-script; eval: (setq indent-tabs-mode 't); eval: (setq tab-width 4) -*- +# Maintainer: Dominic Meiser +pkgname=forgejo-2174 +pkgver=1.0 +pkgrel=0 +pkgdesc="Forgejo #2174 Reproduction" +url="https://msrd0.dev/msrd0/$pkgname" +arch="x86_64" +license="custom" + +# using x86_64 instead of noarch as a workaround of +# https://codeberg.org/forgejo/forgejo/issues/2173 +subpackages="$pkgname-openrc::x86_64" + +source="forgejo_2174 forgejo_2174.init" +builddir="$srcdir" + +package() { + install -D -m755 "$srcdir/forgejo_2174" "$pkgdir"/usr/bin/forgejo_2174 + install -D -m755 "$srcdir/forgejo_2174.init" "$pkgdir"/etc/init.d/forgejo_2174 +} + +sha512sums=" +651c2a816510a18981bcd45077eb5acd6e58511d641949ddc690e326b81018d851eb7f1c88e2336eada2f216606ce2aa0569eb2d02d7c423c80705cc00acf838 forgejo_2174 +b1cba77139cdaf9e0cdd78de93becbb3891ec59646e8d2cb40620b230bd798d51e6d9c58e65b584812a6bb8eb2b9c9f89262a8700a39c62af8ec8ea09aee4e29 forgejo_2174.init +" diff --git a/packages/alpine/package-source/forgejo_2174 b/packages/alpine/package-source/forgejo_2174 new file mode 100755 index 0000000..b12f87b --- /dev/null +++ b/packages/alpine/package-source/forgejo_2174 @@ -0,0 +1,3 @@ +#!/bin/sh + +echo "Hello World" diff --git a/packages/alpine/package-source/forgejo_2174.init b/packages/alpine/package-source/forgejo_2174.init new file mode 100755 index 0000000..06b7f20 --- /dev/null +++ b/packages/alpine/package-source/forgejo_2174.init @@ -0,0 +1,7 @@ +#!/sbin/openrc-run + +command="/usr/bin/forgejo_2174" + +depend() { + need net +} diff --git a/packages/alpine/test.sh b/packages/alpine/test.sh new file mode 100755 index 0000000..e210879 --- /dev/null +++ b/packages/alpine/test.sh @@ -0,0 +1,58 @@ +#!/bin/busybox ash +set -exuo pipefail + +forgejo_url=$1 +forgejo_token=$2 + +# initialize abuild +apk update +apk add --no-cache alpine-sdk sudo util-linux +adduser -D user -h /home/user +addgroup user abuild +echo "root ALL=(ALL) ALL" >/etc/sudoers +echo "%abuild ALL=(ALL) NOPASSWD: ALL" >>/etc/sudoers +mkdir -p /var/cache/distfiles +chgrp abuild /var/cache/distfiles +chmod 775 /var/cache/distfiles +mkdir -p "/home/user/.abuild" +echo "/home/user/.abuild/user.rsa" | abuild-keygen -i -b 4096 +echo 'PACKAGER_PRIVKEY=/home/user/.abuild/user.rsa' >/home/user/.abuild/abuild.conf +chown -R "user:user" /home/user/ + +# make sure we own the relevant directory +cp -r package-source /srv/alpine +cd /srv +mkdir packages +echo "REPODEST=/srv/packages" >>/home/user/.abuild/abuild.conf +cat /home/user/.abuild/abuild.conf +chown -R user:user alpine packages + +# build the package +sudo -u user APKBUILD=alpine/APKBUILD abuild -r + +# upload new package +cd packages/srv/x86_64/ +for file in $(find . -name '*.apk' -type f | sed -e 's,./,,'); do + # remove old package + curl \ + --fail \ + -H "Authorization: token $forgejo_token" \ + -X DELETE \ + "$forgejo_url/api/packages/root/alpine/3.19/forgejo-2174/$file" \ + || true + + # upload new package + curl \ + --fail \ + -H "Authorization: token $forgejo_token" \ + -T "$file" \ + "$forgejo_url/api/packages/root/alpine/3.19/forgejo-2174" +done + +# ensure that the install-if condition works as expected +apk add openrc +(cd /etc/apk/keys && curl -JO $forgejo_url/api/packages/root/alpine/key) +echo "$forgejo_url/api/packages/root/alpine/3.19/forgejo-2174" >>/etc/apk/repositories +apk add forgejo-2174 +[ -e /usr/bin/forgejo_2174 ] # from the installed package +[ -e /etc/init.d/forgejo_2174 ] # from the -openrc package installed because of the install-if condition diff --git a/packages/run.sh b/packages/run.sh new file mode 100755 index 0000000..2a8f991 --- /dev/null +++ b/packages/run.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# Copyright 2024 The Forgejo Authors +# SPDX-License-Identifier: MIT + +SELF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source $SELF_DIR/../lib/lib.sh + +function run() { + local package=$1 + + bash -ex $SELF_DIR/$package.sh +} + +function packages_v1_21() { + echo 'alpine' +} + +function packages_v1_22() { + packages_v1_21 +} + +function setup() { + local binary=$1 + forgejo-binary.sh setup root admin1234 $binary +} + +function teardown() { + forgejo-curl.sh logout + 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 + packages=$(packages_${version/./_}) + else + packages="$@" + fi + + if test "$packages" = "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 url=$(cat $DIR/forgejo-auth-url) + export token=$(cat $DIR/forgejo-token) + + for package in $packages ; do + echo "======================== BEGIN package-$package ===================" + if ! time run $package >& /tmp/run.out ; then + sed -e 's/^/[RUN] /' < /tmp/run.out + echo "======================== FAIL package-$package ===================" + 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 package-$package ===================" + done +} + +main "$@"