diff --git a/.forgejo/workflows/integration.yml b/.forgejo/workflows/integration.yml index 1558dc2..d2768ad 100644 --- a/.forgejo/workflows/integration.yml +++ b/.forgejo/workflows/integration.yml @@ -31,3 +31,39 @@ jobs: forgejo-test-helper.sh run_workflow testdata/demo $url root demo setup-forgejo $token echo "============================ IPv6 ===================" forgejo-test-helper.sh run_workflow testdata/ipv6 $url root ipv6 setup-forgejo $token + + binary: + runs-on: self-hosted + strategy: + matrix: + - binary: https://codeberg.org/forgejo/forgejo/releases/download/v1.21.2-1/forgejo-1.21.2-1-linux-amd64 + steps: + - uses: actions/checkout@v4 + - shell: bash + run: | + set -x + export DIR=$(mktemp -d) + export PATH=$(pwd):$PATH + LXC_IP_PREFIX=10.0.10 forgejo-dependencies.sh + + forgejo-binary.sh ensure_user forgejo + chown forgejo $DIR /usr/local/bin + su -c "DIR=$DIR bash -x forgejo-binary.sh setup root admin1234 ${{ matrix.binary }}" forgejo + + su -c "DIR=$DIR bash -x forgejo-runner.sh setup" forgejo + export FORGEJO_RUNNER_LOGS=$DIR/forgejo-runner.log + url=$(cat $DIR/forgejo-auth-url) + token=$(cat $DIR/forgejo-token) + + echo "============================ demo ===================" + FORGEJO_RUNNER_DIR=$DIR forgejo-test-helper.sh run_workflow testdata/demo $url root demo setup-forgejo $token + + su -c "DIR=$DIR forgejo-binary.sh teardown" forgejo + + echo "============================ verify zip downloading ===================" + export DEBIAN_FRONTEND=noninteractive + apt -q install -qq -y zip + mv $DIR/forgejo /tmp/forgejo + ( cd /tmp ; zip forgejo.zip forgejo ) + forgejo-binary.sh download file:///tmp/forgejo.zip + cmp --quiet /tmp/forgejo $DIR/forgejo diff --git a/README.md b/README.md index 40b7c3a..a70cb03 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,12 @@ Setup Forgejo and a runner. +If `binary` is specified, Forgejo downloads the binary from the URL and uses +it to start an instance. + +Otherwise, `image` and `image-version` must be specified and Forgejo +runs from the corresponding container image using docker. + The forgejo-test-helper.sh script is available to help test and debug actions. `forgejo=http://root:admin1234@${{ steps.forgejo.outputs.host-port }}` @@ -40,10 +46,11 @@ that [provides a LXC container](https://forgejo.org/docs/next/user/actions/#jobs | --- | --- | --- | --- | | image | Container image | `false` | codeberg.org/forgejo/forgejo | | image-version | Container image version | `false` | 1.20 | +| binary | URL to a Forgejo binary | `false` | | | user | Administrator user name | `false` | root | | password | Administrator password | `false` | admin1234 | | runner | Runner repository | `false` | https://code.forgejo.org/forgejo/runner | -| runner-version | Runner version. If it starts with @ (for instance @featurebranch), the runner will be built from source using the specified branch. | `false` | v3.0.1 | +| runner-version | Runner version. If it starts with @ (for instance @featurebranch), the runner will be built from source using the specified branch. | `false` | v3.3.0 | | container | Name of the container running the Forgejo instance | `false` | forgejo | | lxc-ip-prefix | Class C IP prefix used by LXC | `false` | 10.0.23 | | install-only | Only install Forgejo and the Forgejo runner, do not launch them | `false` | false | diff --git a/action.yml b/action.yml index 2b7df44..44e27e3 100644 --- a/action.yml +++ b/action.yml @@ -4,6 +4,12 @@ author: 'Forgejo authors' description: | Setup Forgejo and a runner. + If `binary` is specified, Forgejo downloads the binary from the URL and uses + it to start an instance. + + Otherwise, `image` and `image-version` must be specified and Forgejo + runs from the corresponding container image using docker. + The forgejo-test-helper.sh script is available to help test and debug actions. `forgejo=http://root:admin1234@${{ steps.forgejo.outputs.host-port }}` @@ -35,6 +41,8 @@ inputs: image-version: description: 'Container image version' default: '1.20' + binary: + description: 'URL to a Forgejo binary' user: description: 'Administrator user name' default: 'root' @@ -88,10 +96,17 @@ runs: echo "install-only is true, do not run Forgejo" exit 0 fi - export CONTAINER=${{ inputs.container }} - forgejo.sh setup ${{ inputs.user }} "${{ inputs.password }}" ${{ inputs.image }} ${{ inputs.image-version }} - forgejo-runner.sh setup ${{ inputs.runner }} ${{ inputs.runner-version }} http://$(cat forgejo-ip):3000/ - echo url="http://$(cat forgejo-ip):3000" >> $GITHUB_OUTPUT + if test "${{ inputs.binary }}"; then + forgejo-binary.sh ensure_user forgejo + chown forgejo $(pwd) /usr/local/bin + su -c "DIR=$(pwd) forgejo-binary.sh setup ${{ inputs.user }} ${{ inputs.password }} ${{ inputs.binary }}" forgejo + su -c "DIR=$(pwd) forgejo-runner.sh setup ${{ inputs.runner }} ${{ inputs.runner-version }} $(cat forgejo-url)" forgejo + else + export CONTAINER=${{ inputs.container }} + forgejo.sh setup ${{ inputs.user }} "${{ inputs.password }}" ${{ inputs.image }} ${{ inputs.image-version }} + forgejo-runner.sh setup ${{ inputs.runner }} ${{ inputs.runner-version }} $(cat forgejo-url) + fi + echo url="$(cat forgejo-url)" >> $GITHUB_OUTPUT echo host-port="$(cat forgejo-ip):3000" >> $GITHUB_OUTPUT echo token=$(cat forgejo-token) >> $GITHUB_OUTPUT echo runner-logs="$(pwd)/forgejo-runner.log" >> $GITHUB_OUTPUT diff --git a/forgejo-binary-app.ini b/forgejo-binary-app.ini new file mode 100644 index 0000000..b2a6922 --- /dev/null +++ b/forgejo-binary-app.ini @@ -0,0 +1,39 @@ +RUN_MODE = prod +WORK_PATH = ${WORK_PATH} + +[server] +APP_DATA_PATH = ${WORK_PATH}/data +HTTP_PORT = 3000 +LFS_START_SERVER = true + +[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 + +[queue] +TYPE = immediate + +[queue.code_indexer] +TYPE = immediate + +[queue.push_update] +TYPE = immediate diff --git a/forgejo-binary.sh b/forgejo-binary.sh new file mode 100755 index 0000000..e667c48 --- /dev/null +++ b/forgejo-binary.sh @@ -0,0 +1,121 @@ +#!/bin/bash +# SPDX-License-Identifier: MIT + +set -e + +SELF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source $SELF_DIR/forgejo-lib.sh + +: ${DIR:=/tmp/forgejo-binary} + +if ${VERBOSE:-false}; then set -x; fi + +function maybe_sudo() { + if test $(id -u) != 0 ; then + SUDO=sudo + fi +} + +function ensure_user() { + local user=$1 + + dependencies + adduser --quiet --comment $user --disabled-password $user + adduser $user sudo + adduser $user docker + sed -i -e 's/^%sudo.*/%sudo ALL=(ALL:ALL) NOPASSWD:ALL/' /etc/sudoers +} + +function dependencies() { + maybe_sudo + if ! which sudo curl daemon jq git-lfs ip sqlite3 envsubst unzip > /dev/null ; then + $SUDO apt-get update -qq + $SUDO apt-get -q install -y -qq sudo curl daemon jq git-lfs iproute2 sqlite3 gettext-base unzip + fi +} + +function cleanup_logs() { + local work_path=$DIR/forgejo-work-path + + rm -f $DIR/*.log + rm -f $work_path/log/*.log +} + +function download() { + local url="$1" + + if ! test -f $DIR/forgejo ; then + curl -sS $url > $DIR/forgejo.tmp + if file $DIR/forgejo.tmp | grep --quiet 'Zip archive' ; then + unzip $DIR/forgejo.tmp -d $DIR + rm -f $DIR/forgejo.tmp + else + mv $DIR/forgejo.tmp $DIR/forgejo + fi + chmod +x $DIR/forgejo + fi + echo $DIR/forgejo --version + $DIR/forgejo --version +} + +function create_user() { + local user="$1" + local password="$2" + local work_path=$DIR/forgejo-work-path + + if test -f $work_path/forgejo-token; then + return + fi + + $DIR/forgejocli admin user create --admin --username "$user" --password "$password" --email "$user@example.com" + $DIR/forgejocli admin user generate-access-token -u "$user" --raw --scopes all > $DIR/forgejo-token + export DOT=$DIR + local url="http://$(cat $DIR/forgejo-ip):3000" + echo "$url" > $DIR/forgejo-url + echo "http://${user}:${password}@$(cat $DIR/forgejo-ip):3000" > $DIR/forgejo-auth-url + retry forgejo-curl.sh --user "$user" --password "$password" --token @$DIR/forgejo-token login "$url" + echo forgejo-curl.sh api_json $url/api/forgejo/v1/version + forgejo-curl.sh api_json $url/api/forgejo/v1/version +} + +function start_forgejo() { + local work_path=$DIR/forgejo-work-path + daemon --chdir=$DIR --unsafe --env="TERM=$TERM" --env="HOME=$HOME" --env="PATH=$PATH" --pidfile=$DIR/forgejo-pid --errlog=$DIR/forgejo-err.log --output=$DIR/forgejo-out.log -- $DIR/forgejo --config $work_path/app.ini --work-path $work_path + if ! retry grep 'Starting server on' $work_path/log/forgejo.log ; then + cat $DIR/*.log + cat $work_path/log/*.log + return 1 + fi + echo "$DIR/forgejo --config $work_path/app.ini --work-path $work_path" '"$@"' > $DIR/forgejocli + chmod +x $DIR/forgejocli + hostname -I | cut -f1 -d' ' > $DIR/forgejo-ip +} + +function reset_forgejo() { + local config=$1 + local work_path=$DIR/forgejo-work-path + rm -fr $work_path + mkdir -p $work_path + WORK_PATH=$work_path envsubst < $SELF_DIR/$config-app.ini > $work_path/app.ini +} + +function teardown() { + stop_daemon forgejo $DIR + cleanup_logs +} + +function setup() { + local user="${1:-root}" + local password="${2:-admin1234}" + local url="${3:-https://codeberg.org/forgejo/forgejo/releases/download/v1.21.2-1/forgejo-1.21.2-1-linux-amd64}" + + dependencies + download "$url" + reset_forgejo forgejo-binary + start_forgejo + create_user "$user" "$password" +} + +mkdir -p $DIR + +"$@"