diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..6b8710a7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +.git diff --git a/.editorconfig b/.editorconfig index c17e5955..669640db 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,3 +1,10 @@ root = true + [*] -tab_width: 8 +indent_style = space +indent_size = 4 +tab_width = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.forgejo/prepare-end-to-end/action.yml b/.forgejo/prepare-end-to-end/action.yml index 0fa27942..8ae5cdd8 100644 --- a/.forgejo/prepare-end-to-end/action.yml +++ b/.forgejo/prepare-end-to-end/action.yml @@ -1,9 +1,13 @@ +inputs: + built: + description: 'True if a source build is available, false otherwise' + runs: using: "composite" steps: - name: cache S3 binaries id: S3 - uses: https://code.forgejo.org/actions/cache@v3 + uses: https://data.forgejo.org/actions/cache@v4 with: path: | /usr/local/bin/minio @@ -11,18 +15,26 @@ runs: /usr/local/bin/garage key: S3 - - uses: https://code.forgejo.org/actions/setup-forgejo@v2 + - uses: https://data.forgejo.org/actions/setup-forgejo@v3.1.6 with: install-only: true - run: forgejo-binary.sh ensure_user forgejo + - name: inputs context dump for debug + run: | + set -x + cat <> $FORGEJO_OUTPUT + echo "built=no" >> $FORGEJO_OUTPUT + exit 0 + fi + + set -x # # SQLite needs gcc to be compiled # @@ -41,93 +47,120 @@ jobs: apt-get -q install -y -qq build-essential d=/tmp/forgejo-binaries - mkdir $d /tmp/forgejo-upload - for version in $(ls forgejo/sources) ; do - forgejo=$d/forgejo-$version-dev + for version in $(cat forgejo/build-from-sources) ; do lib/build.sh $version $d + forgejo=$d/forgejo-$version-dev $forgejo --version - mv $forgejo /tmp/forgejo-upload + mv $forgejo /tmp/forgejo-upload/forgejo-$version done + + echo "forgejo_versions_json=$(node -p "JSON.stringify(process.argv[1].split(' '))" "$(cat forgejo/build-from-sources)")" >> $FORGEJO_OUTPUT + echo "built=yes" >> $FORGEJO_OUTPUT + + - name: steps context dump for debug + run: | + set -x + cat <> $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@v2.1 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 }}" + built: ${{ needs.build.outputs.built }} + - name: install zstd + run: | + export DEBIAN_FRONTEND=noninteractive + apt-get -q install -y -qq zstd + - name: cache GitLab OCI image + uses: https://data.forgejo.org/actions/cache@v4 + with: + path: | + /srv/forgejo-binaries/gitlab + key: gitlab + - name: setup dbus + run: | + apt-get -q install -y -qq dbus + systemctl enable --now dbus + - name: run test_federation + run: | + chown -R forgejo:forgejo . + su forgejo -c "./end-to-end.sh test_federation" + - if: ${{ needs.build.outputs.built == 'yes' }} + uses: ./.forgejo/upload-coverage + with: + scope: federation + - name: full logs + if: always() + run: su forgejo -c "./end-to-end.sh show_logs" upgrade: name: upgrade and storage needs: [build] - runs-on: lxc-bookworm + runs-on: lxc-trixie steps: - - uses: https://code.forgejo.org/actions/checkout@v4 + - uses: https://data.forgejo.org/actions/checkout@v4 - uses: ./.forgejo/prepare-end-to-end + with: + built: ${{ needs.build.outputs.built }} - run: su forgejo -c "./end-to-end.sh test_upgrades" - run: su forgejo -c "./end-to-end.sh test_storage" + - if: ${{ needs.build.outputs.built == 'yes' }} + uses: ./.forgejo/upload-coverage + with: + scope: upgrade - name: full logs if: always() run: su forgejo -c "./end-to-end.sh show_logs" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..e31cb6d8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,50 @@ +FROM data.forgejo.org/oci/node:24-trixie + +ENV PATH=$PATH:/setup-forgejo +ENV _CONTAINERS_USERNS_CONFIGURED="" + +RUN apt-get update && \ + apt-get --assume-yes --no-install-recommends install \ + aardvark-dns \ + ca-certificates \ + curl \ + daemon \ + fuse-overlayfs \ + gettext \ + git \ + jq \ + libcap2-bin \ + neovim \ + nftables \ + passt \ + podman \ + podman-compose \ + podman-docker \ + procps \ + pup \ + slirp4netns \ + sudo \ + tcpdump \ + uidmap \ + wget && \ + adduser -u 1001 forgejo-tests && \ + groupadd wheel && \ + adduser forgejo-tests wheel && \ + echo "%wheel ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers && \ + echo "forgejo-tests:10000:9999" > /etc/subuid && \ + echo "forgejo-tests:10000:9999" > /etc/subgid && \ + mkdir /srv/forgejo-binaries && \ + chown forgejo-tests:forgejo-tests /srv/forgejo-binaries && \ + apt-get clean && \ + apt-get autoremove --purge && \ + apt-get autoclean + +COPY --chown=1001:1001 . /e2e + +RUN git clone https://code.forgejo.org/actions/setup-forgejo.git /setup-forgejo + +USER forgejo-tests + +WORKDIR /e2e + +ENTRYPOINT /bin/bash diff --git a/README.md b/README.md index 2b409dae..33fcfdbd 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,36 @@ # Forgejo end-to-end tests +- [Forgejo end-to-end tests](#forgejo-end-to-end-tests) + - [Removing legacy tests](#removing-legacy-tests) + - [Hacking](#hacking) + - [Running from locally built binary](#running-from-locally-built-binary) + - [Forgejo](#forgejo) + - [Forgejo runner](#forgejo-runner) + - [Running from locally built container image](#running-from-locally-built-container-image) + - [Running actions tests locally](#running-actions-tests-locally) + - [Running federation tests locally](#running-federation-tests-locally) + - [Federated Mastodon Follow Test](#federated-mastodon-follow-test) + - [Running other tests locally](#running-other-tests-locally) + - [Running tests in Docker/Podman](#running-tests-in-dockerpodman) + A series of tests scenarios and assertions covering [Forgejo](https://codeberg.org/forgejo/forgejo) and the [Forgejo -runner](https://code.forgejo.org/forgejo/runner). They partially rely -on [Forgejo actions](https://code.forgejo.org/actions) developped -specifically for testing such as -[setup-forgejo](https://code.forgejo.org/actions/setup-forgejo). +runner](https://code.forgejo.org/forgejo/runner). They are designed to run using Forgejo releases and development versions compiled from designated repositories. -# Hacking +## Removing legacy tests + +End-to-end tests cover the supported range of releases and when one of +them is EOL, it must be removed as well as the tests that target it +specifically. Otherwise the test suite would grow indefinitely. + +When a release is EOL, a branch is cut with a name following the +pattern `legacy/vX.Y-vA.B`. For instance when `v8.0` is published and +`v1.21` is EOL, the branch `legacy/v8.0-v1.21` is cut. + +## Hacking 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 @@ -20,13 +40,13 @@ as: { "insecure-registries": [ "10.0.0.0/8" ] } -``` +``` 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 +Action](https://forgejo.org/docs/v7.0/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. @@ -39,31 +59,76 @@ git clone https://code.forgejo.org/forgejo/end-to-end cd end-to-end ``` -## Running from locally built binary +### Running from locally built binary + +Before injecting a manually built binary, make sure a simple test was +run so that the directories are populated. + +#### Forgejo + +From a checkout of https://codeberg.org/forgejo/forgejo/ ```sh -make TAGS='bindata sqlite sqlite_unlock_notify' generate forgejo -cp -a forgejo /srv/forgejo-binaries/forgejo-7.0-dev +make clean-all && make frontend && make TAGS='bindata sqlite sqlite_unlock_notify' generate forgejo +cp -a forgejo /srv/forgejo-binaries/forgejo-11.0 ``` -It will be used whenver the version `7.0-dev` is specified in a test. +It will be used whenever the version `11.0` is specified in a test. -## Running actions locally +#### Forgejo runner + +From a checkout of https://code.forgejo.org/forgejo/runner + +```sh +make --always-make forgejo-runner +cp forgejo-runner /tmp/forgejo-end-to-end/forgejo-runner +``` + +### Running from locally built container image + +```bash +docker buildx build --output=type=docker --tag codeberg.org/forgejo/forgejo:latest . +``` + +## Running actions tests 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 +what `.forgejo/workflows/end-to-end.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. ```sh -./end-to-end.sh actions_setup 1.21 +export FORGEJO_RUNNER_LOGS=/tmp/forgejo-end-to-end/forgejo-runner.log +./end-to-end.sh run dependencies +./end-to-end.sh actions_setup 10.0 firefox 0.0.0.0:3000 # user root / admin1234 -./end-to-end.sh actions_verify_example artifacts +./end-to-end.sh actions_verify_example echo ./end-to-end.sh actions_teardown ``` + +Note that `with-docker-tcp` requires the docker daemon listens to +tcp://127.0.0.1:2375. See `actions/actions.sh` for how to do that. + +## Running federation tests locally + +To run and debug scenarios from `federation/*`, from the root of +the source directory, mimic what `.forgejo/workflows/end-to-end.yml` does. + +```sh +./end-to-end.sh run dependencies +./end-to-end.sh federation_setup 12.0 +firefox 0.0.0.0:3001 # user root / admin1234 +firefox 0.0.0.0:3002 # user root / admin1234 +firefox 0.0.0.0:3003 # user root / admin1234 +./end-to-end.sh federation_verify_scenario star +./end-to-end.sh federation_verify_scenario gotosocial +./end-to-end.sh federation_verify_scenario mastodon +./end-to-end.sh federation_teardown +``` + ## Running other tests locally To run and debug tests, from the root of the source directory. @@ -80,3 +145,10 @@ Cleanup. It will teardown the Forgejo instance. ```sh ./end-to-end.sh stop ``` + +## Running tests in Docker/Podman + +There is an included Dockerfile in which the tests can be run. Building the +conatiner will copy the the entire repo state into the container from which +changes to the tests can be tested. Note: running in podman requires the +`--privileged` flag because this will run podman in podman for some tests. diff --git a/actions/actions.sh b/actions/actions.sh index def5fefd..0b200824 100755 --- a/actions/actions.sh +++ b/actions/actions.sh @@ -1,57 +1,71 @@ # Copyright 2024 The Forgejo Authors # SPDX-License-Identifier: MIT -ACTIONS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +ACTIONS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +function actions_export_variables() { + export HOST_PORT + export url=http://${FORGEJO_USER}:${FORGEJO_PASSWORD}@${HOST_PORT} + export token=$(cat $DOT_FORGEJO_CURL/token) +} + +function actions_verify_feature() { + local feature=$1 + + actions_export_variables + + export FEATURE_DIR=$ACTIONS_DIR/feature-$feature + + echo "============================ RUN feature-$feature ===================" + bash -ex $FEATURE_DIR/run.sh || return 1 +} function actions_verify_example() { - local example=$1 + local example=$1 - export HOST_PORT - export url=http://${FORGEJO_USER}:${FORGEJO_PASSWORD}@${HOST_PORT} - export token=$(cat $DOT_FORGEJO_CURL/token) + actions_export_variables + actions_cleanup_example_volume - actions_cleanup_example_volume + export example + export EXAMPLE_DIR=$ACTIONS_DIR/example-$example - 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/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/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 - 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 + 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/ + 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 + if test $(id -u) != 0; then + $SUDO chown $(id -u) /srv fi - if ! test -d /srv/example ; then - mkdir -p /srv/example - return + if ! test -d /srv/example; then + mkdir -p /srv/example + return fi $SUDO rm -fr /srv/example/* @@ -74,55 +88,102 @@ function actions_setup() { function actions_teardown() { forgejo-curl.sh logout forgejo-runner.sh teardown - stop_daemon forgejo + stop_forgejo } function actions_runner_version() { local runner_version=$($DIR/forgejo-runner --version | sed -n -e 's/forgejo-runner version v//p') - if test -z "$runner_version" ; then - $DIR/forgejo-runner --version - echo failed to parse version - false + if test -z "$runner_version"; then + $DIR/forgejo-runner --version + echo failed to parse version + false fi echo $runner_version } +function prepare_dockerd() { + mkdir -p /etc/systemd/system/docker.service.d + cat >/etc/systemd/system/docker.service.d/override.conf <<'EOF' +[Service] +ExecStart= +ExecStart=/usr/sbin/dockerd -H unix:///var/run/docker.sock -H tcp://127.0.0.1:2375 --containerd=/run/containerd/containerd.sock $DOCKER_OPTS +EOF + systemctl daemon-reload + if ! systemctl restart docker.service; then + journalctl --no-pager --unit docker.service + return 1 + fi + netstat -lntp | grep 127.0.0.1:2375 +} + function test_actions() { - local versions="${1:-1.20 1.21 $RELEASE_NUMBERS_AND_DEV}" + local versions="${1:-$RELEASE_NUMBERS}" - for version in $versions ; do + for version in $versions; do - actions_setup $version - local runner_version=$(actions_runner_version) + actions_setup $version + local runner_version=$(actions_runner_version) - log_info "Testing actions with Forgejo $version & Forgejo runner $runner_version" + log_info "Testing actions with Forgejo $version & Forgejo runner $runner_version" - if dpkg --compare-versions $version ge 7.0 && dpkg --compare-versions $runner_version gt 3.3.0 ; then - for example in artifacts-v4 ; do - run actions_verify_example $example - done - fi - - 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 ; do - run actions_verify_example $example - done - fi - - if dpkg --compare-versions $version gt 1.20 && dpkg --compare-versions $version lt 7.1 ; then - for example in cron ; do - run actions_verify_example $example - done - fi - - if dpkg --compare-versions $version ge 7.1 ; then - for example in post-7-0-schedule ; do + run actions_verify_example with-docker-tcp + if dpkg --compare-versions $runner_version gt 5.0.2; then + for example in with-docker-host with-docker-socket without-docker-socket; do run actions_verify_example $example done fi + + if dpkg --compare-versions $runner_version gt 10.0.0; then + run actions_verify_example force-rebuild + fi + + if dpkg --compare-versions $version ge 7.0 && dpkg --compare-versions $runner_version gt 3.3.0; then + for example in artifacts-v4; do + run actions_verify_example $example + done + fi + + for example in echo matrix needs workflow-call lxc config-options cache cache-pull-request checkout service container expression local-action docker-action if if-fail push tag push-cancel artifacts pull-request context private-workflow-call create-runner-file; do + run actions_verify_example $example + done + + if dpkg --compare-versions $runner_version ge 6.3.0; then + run actions_verify_example cache-proxy + fi + + if dpkg --compare-versions $runner_version ge 8.0.0; then + run actions_verify_example shell + fi + + if dpkg --compare-versions $version lt 7.1; then + for example in cron; do + run actions_verify_example $example + done + fi + + if dpkg --compare-versions $version ge 7.1; then + for example in automerge post-7-0-schedule; do + run actions_verify_example $example + done + fi + + if dpkg --compare-versions $version ge 8.0; then + for example in workflow-dispatch; do + run actions_verify_example $example + done + fi + + if dpkg --compare-versions $version ge 9.0; then + run actions_verify_example schedule-noncancel + fi + + if dpkg --compare-versions $version ge 14.0; then + run actions_verify_example matrix-dynamic + fi + + if dpkg --compare-versions $version ge 15.0; then + run actions_verify_example workflow-call-expansion + run actions_verify_example id-tokens + fi done } diff --git a/actions/default-app.ini b/actions/default-app.ini index 7ef8df13..455262fc 100644 --- a/actions/default-app.ini +++ b/actions/default-app.ini @@ -1,5 +1,5 @@ -RUN_MODE = prod -WORK_PATH = ${WORK_PATH} +RUN_MODE = dev +WORK_PATH = forgejo-work-path [server] APP_DATA_PATH = ${WORK_PATH}/data @@ -18,7 +18,7 @@ PATH = ${WORK_PATH}/forgejo.db [log] MODE = file LEVEL = trace -ROUTER = file +logger.router.MODE = file [log.file] FILE_NAME = forgejo.log diff --git a/actions/example-artifacts-v4/.forgejo/workflows/test.yml b/actions/example-artifacts-v4/.forgejo/workflows/test.yml index d2153546..526def6d 100644 --- a/actions/example-artifacts-v4/.forgejo/workflows/test.yml +++ b/actions/example-artifacts-v4/.forgejo/workflows/test.yml @@ -7,7 +7,7 @@ jobs: - run: touch artifacts/ONE artifacts/TWO - - uses: https://code.forgejo.org/forgejo/upload-artifact@v4 + - uses: https://data.forgejo.org/forgejo/upload-artifact@v4 with: name: many-artifacts path: artifacts/ @@ -16,7 +16,7 @@ jobs: needs: [upload-many] runs-on: docker steps: - - uses: https://code.forgejo.org/forgejo/download-artifact@v4 + - uses: https://data.forgejo.org/forgejo/download-artifact@v4 - run: | test -f many-artifacts/ONE @@ -29,7 +29,7 @@ jobs: - run: echo hello > path/to/artifact/world.txt - - uses: https://code.forgejo.org/forgejo/upload-artifact@v4 + - uses: https://data.forgejo.org/forgejo/upload-artifact@v4 with: name: my-artifact path: path/to/artifact/world.txt @@ -40,7 +40,7 @@ jobs: steps: - run: "! test -f world.txt" - - uses: https://code.forgejo.org/forgejo/download-artifact@v4 + - uses: https://data.forgejo.org/forgejo/download-artifact@v4 with: name: my-artifact diff --git a/actions/example-automerge/.forgejo/workflows/test.yml b/actions/example-automerge/.forgejo/workflows/test.yml new file mode 100644 index 00000000..7bb4ce29 --- /dev/null +++ b/actions/example-automerge/.forgejo/workflows/test.yml @@ -0,0 +1,13 @@ +on: + pull_request: + +jobs: + test: + runs-on: docker + container: + image: data.forgejo.org/oci/node:20-bookworm + options: "--volume /srv/example:/srv/example" + + steps: + - run: | + ${{ vars.SCRIPT }} diff --git a/actions/example-automerge/run.sh b/actions/example-automerge/run.sh new file mode 100755 index 00000000..1d48860f --- /dev/null +++ b/actions/example-automerge/run.sh @@ -0,0 +1,108 @@ +TMPDIR=$(mktemp -d) + +trap "rm -fr $TMPDIR" EXIT + +source $EXAMPLE_DIR/../../lib/lib.sh + +api=$url/api/v1 +repo=root/example-automerge +export d=/srv/example/automerge + +function reset_automerge_pr() { + # + # repository with a pull_request event workflow that always succeeds + # + mkdir -p $d + + forgejo-curl.sh api_json -X DELETE $api/repos/$repo >&/dev/null || true + forgejo-test-helper.sh push_workflow actions/example-$example $url root example-$example setup-forgejo $token + + forgejo-curl.sh api_json -X DELETE $api/repos/$repo/actions/variables/SCRIPT >&/dev/null || true + forgejo-curl.sh api_json -X POST --data-raw '{"value":"true"}' $api/repos/$repo/actions/variables/SCRIPT + + ( + cd $d + rm -fr example-automerge + git clone $url/$repo + cd example-automerge + git checkout -b other + git config user.email root@example.com + git config user.name username + touch file-unique-to-the-pr-branch + echo other >>README + git add . + git commit -m 'other change' + git push --force -u origin other + ) + + # + # make sure the runner won't race with the sequence that follows + # + forgejo-runner.sh teardown + # + # create a PR and schedule it for automerge when the workflow succeeds + # + api_pr_delete_all $api $repo + forgejo-curl.sh api_json --data-raw '{"title":"PR title","base":"main","head":"other"}' $api/repos/$repo/pulls >$TMPDIR/pr.json + local pr=$(jq -r .number <$TMPDIR/pr.json) + forgejo-curl.sh api_json --data-raw '{"Do":"merge","merge_when_checks_succeed":true}' $api/repos/$repo/pulls/$pr/merge + if api_pr_is_merged $api $repo $pr; then + echo pull request already merged although it should not be + return 1 + fi +} + +function verify_automerge_on_status_success() { + reset_automerge_pr + local pr=$(jq -r .number <$TMPDIR/pr.json) + # + # run the workflow + # + forgejo-runner.sh run + local sha=$(api_branch_tip $api $repo other) + api_pr_wait_success $api $repo $sha + # + # verify the PR was automerged + # + if ! retry api_pr_is_merged $api $repo $pr; then + echo pull request is not automerged as expected + return 1 + fi +} + +function verify_automerge_on_reviewer_approval() { + reset_automerge_pr + local pr=$(jq -r .number <$TMPDIR/pr.json) + # + # require at least one review for a PR to be merged + # + api_branch_protect $api $repo main + # + # run the workflow + # + forgejo-runner.sh run + local sha=$(api_branch_tip $api $repo other) + api_pr_wait_success $api $repo $sha + # + # approve the PR + # + local username=user1 + api_user_create $api $username $username@example.com + api_user_make_admin $api $username + user_login $username + DOT=$API_TMPDIR/$username api_pr_approve $api $repo $pr + # + # verify the PR was automerged + # + if ! retry api_pr_is_merged $api $repo $pr; then + echo pull request is not automerged as expected + return 1 + fi +} + +function main() { + verify_automerge_on_status_success + verify_automerge_on_reviewer_approval +} + +main diff --git a/actions/example-automerge/setup.sh b/actions/example-automerge/setup.sh new file mode 100755 index 00000000..9476a675 --- /dev/null +++ b/actions/example-automerge/setup.sh @@ -0,0 +1 @@ +mkdir -p /srv/example/automerge diff --git a/actions/example-cache-proxy/getter/.forgejo/workflows/get.yml b/actions/example-cache-proxy/getter/.forgejo/workflows/get.yml new file mode 100644 index 00000000..5dc434dd --- /dev/null +++ b/actions/example-cache-proxy/getter/.forgejo/workflows/get.yml @@ -0,0 +1,25 @@ +on: [push] + +jobs: + build: + runs-on: docker + container: + image: data.forgejo.org/oci/node:20-bookworm + steps: + - name: cache restore + id: cachestep + uses: https://data.forgejo.org/actions/cache/restore@v4 + with: + path: | + /usr/local/bin/something + key: thecoolsecretcachekey + + - name: verify something + run: | + set -x + test SOMETHING = $(cat /usr/local/bin/something) + + - name: cache hit + run: | + set -x + test "${{ steps.cachestep.outputs.cache-hit }}" = true diff --git a/actions/example-cache-proxy/run.sh b/actions/example-cache-proxy/run.sh new file mode 100644 index 00000000..a4b15599 --- /dev/null +++ b/actions/example-cache-proxy/run.sh @@ -0,0 +1,22 @@ +source $EXAMPLE_DIR/../../lib/lib.sh + +api=$url/api/v1 +repostorer=root/example-cache-proxy-storer +repogetter=root/example-cache-proxy-getter + +function main() { + forgejo-curl.sh api_json -X DELETE $api/repos/$repostorer >&/dev/null || true + forgejo-curl.sh api_json -X DELETE $api/repos/$repogetter >&/dev/null || true + + forgejo-test-helper.sh push_workflow actions/example-$example/storer $url root example-$example-storer setup-forgejo $token + local shastorer=$(forgejo-test-helper.sh branch_tip $url $repostorer main) + + forgejo-test-helper.sh wait_success $url $repostorer $shastorer + + forgejo-test-helper.sh push_workflow actions/example-$example/getter $url root example-$example-getter setup-forgejo $token + local shagetter=$(forgejo-test-helper.sh branch_tip $url $repogetter main) + + forgejo-test-helper.sh wait_failure $url $repogetter $shagetter +} + +main diff --git a/actions/example-cache-proxy/runner-config.yaml b/actions/example-cache-proxy/runner-config.yaml new file mode 100644 index 00000000..851c2c2a --- /dev/null +++ b/actions/example-cache-proxy/runner-config.yaml @@ -0,0 +1,29 @@ +log: + level: debug + +runner: + file: .runner + capacity: 1 + env_file: .env + timeout: 3h + insecure: false + fetch_timeout: 5s + fetch_interval: 2s + labels: ["docker:docker://code.forgejo.org/oci/node:20-bookworm"] + +cache: + enabled: true + dir: "/srv/example/cache" + host: "" + port: 0 + +container: + network: "bridge" + privileged: false + options: + workdir_parent: + valid_volumes: ["/srv/example"] + docker_host: "" + +host: + workdir_parent: diff --git a/actions/example-cache-proxy/setup.sh b/actions/example-cache-proxy/setup.sh new file mode 100755 index 00000000..9c1f5adf --- /dev/null +++ b/actions/example-cache-proxy/setup.sh @@ -0,0 +1 @@ +FORGEJO_RUNNER_CONFIG=$EXAMPLE_DIR/runner-config.yaml forgejo-runner.sh reload diff --git a/actions/example-cache-proxy/storer/.forgejo/workflows/store.yml b/actions/example-cache-proxy/storer/.forgejo/workflows/store.yml new file mode 100644 index 00000000..db9b101a --- /dev/null +++ b/actions/example-cache-proxy/storer/.forgejo/workflows/store.yml @@ -0,0 +1,17 @@ +on: [push] + +jobs: + build: + runs-on: docker + container: + image: data.forgejo.org/oci/node:20-bookworm + steps: + - name: create something + run: echo SOMETHING > /usr/local/bin/something + + - name: cache save + uses: https://data.forgejo.org/actions/cache/save@v4 + with: + path: | + /usr/local/bin/something + key: thecoolsecretcachekey diff --git a/actions/example-cache-proxy/teardown.sh b/actions/example-cache-proxy/teardown.sh new file mode 100755 index 00000000..b410c513 --- /dev/null +++ b/actions/example-cache-proxy/teardown.sh @@ -0,0 +1 @@ +forgejo-runner.sh reload diff --git a/actions/example-cache-pull-request/.forgejo/workflows/test.yml b/actions/example-cache-pull-request/.forgejo/workflows/test.yml new file mode 100644 index 00000000..43a96d41 --- /dev/null +++ b/actions/example-cache-pull-request/.forgejo/workflows/test.yml @@ -0,0 +1,96 @@ +on: + pull_request: + types: + - opened + - closed + +jobs: + save-cache: + runs-on: docker + container: + image: data.forgejo.org/oci/node:20-bookworm + steps: + - name: cache restore + id: cachestep1 + uses: https://data.forgejo.org/actions/cache/restore@v4 + with: + path: | + /usr/local/bin/something + key: cachekey-${{ forge.event.pull_request.head.repo.full_name }} + + - name: cache hit + run: | + set -x + test "${{ steps.cachestep1.outputs.cache-hit }}" != true + + - name: create something + run: echo SOMETHING > /usr/local/bin/something + + - name: cache save + uses: https://data.forgejo.org/actions/cache/save@v4 + with: + path: | + /usr/local/bin/something + key: ${{ steps.cachestep1.outputs.cache-primary-key }} + + restore-cache: + runs-on: docker + needs: [save-cache] + container: + image: data.forgejo.org/oci/node:20-bookworm + steps: + - name: cache restore + id: cachestep2 + uses: https://data.forgejo.org/actions/cache/restore@v4 + with: + path: | + /usr/local/bin/something + key: cachekey-${{ forge.event.pull_request.head.repo.full_name }} + + - name: verify something + run: | + set -x + test SOMETHING = $(cat /usr/local/bin/something) + + - name: cache hit + run: | + set -x + test "${{ steps.cachestep2.outputs.cache-hit }}" = true + + test: + runs-on: docker + needs: [restore-cache] + container: + image: data.forgejo.org/oci/node:20-bookworm + options: "--volume /srv/example:/srv/example" + + steps: + - name: setup + shell: bash + run: | + set -x + test $FORGEJO_TOKEN = ${{ env.FORGEJO_TOKEN }} + test $FORGEJO_TOKEN = ${{ forge.token }} + export DEBIAN_FRONTEND=noninteractive ; apt-get -qq update ; apt-get install -y -qq curl git >& /dev/null + curl -sS -o /usr/local/bin/forgejo-curl.sh https://code.forgejo.org/forgejo/forgejo-curl/raw/branch/main/forgejo-curl.sh && chmod +x /usr/local/bin/forgejo-curl.sh + forgejo-curl.sh --token "$FORGEJO_TOKEN" login $FORGEJO_SERVER_URL + forgejo-curl.sh api_json $FORGEJO_SERVER_URL/api/v1/user + + - name: determine if the PR is from a fork + id: forked + run: | + set -x + if test ${{ forge.event.pull_request.base.repo.full_name }} = ${{ forge.event.pull_request.head.repo.full_name }} ; then + echo value=false >> $FORGEJO_OUTPUT + else + echo value=true >> $FORGEJO_OUTPUT + fi + + - name: save event + run: | + set -x + d=/srv/example/cache-pull-request/contexts/${{ forgejo.event.pull_request.head.repo.owner.username }}/$FORGEJO_EVENT_NAME + mkdir -p $d + cat > $d/forgejo-${{ forgejo.event.action }} <<'EOF' + ${{ toJSON(forgejo) }} + EOF diff --git a/actions/example-cache-pull-request/assert-contexts-closed.sh b/actions/example-cache-pull-request/assert-contexts-closed.sh new file mode 100755 index 00000000..4c0f8e27 --- /dev/null +++ b/actions/example-cache-pull-request/assert-contexts-closed.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -ex + +c=$d/contexts + +for user in cache-fork-org root; do + test -f $c/$user/pull_request/forgejo-closed +done diff --git a/actions/example-cache-pull-request/assert-contexts-opened.sh b/actions/example-cache-pull-request/assert-contexts-opened.sh new file mode 100755 index 00000000..73fcccda --- /dev/null +++ b/actions/example-cache-pull-request/assert-contexts-opened.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -ex + +c=$d/contexts + +for user in cache-fork-org root; do + test -f $c/$user/pull_request/forgejo-opened +done diff --git a/actions/example-cache-pull-request/run.sh b/actions/example-cache-pull-request/run.sh new file mode 100755 index 00000000..85020281 --- /dev/null +++ b/actions/example-cache-pull-request/run.sh @@ -0,0 +1,80 @@ +TMPDIR=$(mktemp -d) + +trap "rm -fr $TMPDIR" EXIT + +api=$url/api/v1 +export d=/srv/example/cache-pull-request + +function main() { + mkdir -p $d + + # + # open a pull request + # - from the same repository + # - from a forked repository + # + forgejo-test-helper.sh push_workflow actions/example-$example $url root example-$example setup-forgejo $token + + forgejo-curl.sh api_json --data-raw '{"username":"cache-fork-org"}' $api/orgs + forgejo-curl.sh api_json --data-raw '{"organization":"cache-fork-org"}' $api/repos/root/example-cache-pull-request/forks + + ( + cd $d + git clone $url/cache-fork-org/example-cache-pull-request fork + cd fork + git config user.email root@example.com + git config user.name username + touch file-unique-to-the-pr-branch + git add . + git commit -m 'fork change' + git push + ) + + forgejo.sh retry forgejo-curl.sh api_json --data-raw '{"title":"PR from fork","base":"main","head":"cache-fork-org:main"}' $api/repos/root/example-cache-pull-request/pulls + + ( + cd $d + git clone $url/root/example-cache-pull-request + cd example-cache-pull-request + git checkout -b other + git config user.email root@example.com + git config user.name username + touch file-unique-to-the-forked-pr + git add . + git commit -m 'other change' + git push --force -u origin other + ) + + forgejo.sh retry forgejo-curl.sh api_json --data-raw '{"title":"PR same repo","base":"main","head":"other"}' $api/repos/root/example-cache-pull-request/pulls + + export RETRY_DELAYS="10 20 60 60 60 60 60" + + # + # wait for the opened event to succeed using the cache on all pull requests + # + if ! forgejo.sh retry $EXAMPLE_DIR/assert-contexts-opened.sh; then + echo "assert-contexts-opened.sh failed; printing related logs and information:" + find $d + sed -e 's/^/[RUNNER LOGS]/' <$FORGEJO_RUNNER_LOGS + return 1 + fi + + # + # merge all pull requests + # + forgejo-curl.sh api_json $api/repos/root/example-cache-pull-request/pulls | jq -r '.[] | .number' | while read pr; do + forgejo-curl.sh api_json --data-raw '{"Do":"merge"}' $api/repos/root/example-cache-pull-request/pulls/$pr/merge + done + + # + # wait for the closed event to succeed using the cache on all pull requests + # + if ! forgejo.sh retry $EXAMPLE_DIR/assert-contexts-closed.sh; then + echo "assert-contexts-closed.sh failed; printing related logs and information:" + find $d + sed -e 's/^/[RUNNER LOGS]/' <$FORGEJO_RUNNER_LOGS + return 1 + fi +} + +main diff --git a/actions/example-cache-pull-request/runner-config.yaml b/actions/example-cache-pull-request/runner-config.yaml new file mode 100644 index 00000000..11818cc5 --- /dev/null +++ b/actions/example-cache-pull-request/runner-config.yaml @@ -0,0 +1,30 @@ + +log: + level: debug + +runner: + file: .runner + capacity: 1 + env_file: .env + timeout: 3h + insecure: false + fetch_timeout: 5s + fetch_interval: 2s + labels: ["docker:docker://code.forgejo.org/oci/node:20-bookworm"] + +cache: + enabled: true + dir: "/srv/example/cache" + host: "" + port: 0 + +container: + network: "bridge" + privileged: false + options: + workdir_parent: + valid_volumes: ["/srv/example"] + docker_host: "" + +host: + workdir_parent: diff --git a/actions/example-cache-pull-request/setup.sh b/actions/example-cache-pull-request/setup.sh new file mode 100755 index 00000000..0fb6d859 --- /dev/null +++ b/actions/example-cache-pull-request/setup.sh @@ -0,0 +1,2 @@ +mkdir -p /srv/example/cache-pull-request +FORGEJO_RUNNER_CONFIG=$EXAMPLE_DIR/runner-config.yaml forgejo-runner.sh reload diff --git a/actions/example-cache-pull-request/teardown.sh b/actions/example-cache-pull-request/teardown.sh new file mode 100755 index 00000000..b410c513 --- /dev/null +++ b/actions/example-cache-pull-request/teardown.sh @@ -0,0 +1 @@ +forgejo-runner.sh reload diff --git a/actions/example-cache/.forgejo/workflows/test.yml b/actions/example-cache/.forgejo/workflows/test.yml new file mode 100644 index 00000000..7acc5c59 --- /dev/null +++ b/actions/example-cache/.forgejo/workflows/test.yml @@ -0,0 +1,54 @@ +on: [push] + +jobs: + save-cache: + runs-on: docker + container: + image: data.forgejo.org/oci/node:20-bookworm + steps: + - name: cache restore + id: cachestep1 + uses: https://data.forgejo.org/actions/cache/restore@v4 + with: + path: | + /usr/local/bin/something + key: cachekey + + - name: cache hit + run: | + set -x + test "${{ steps.cachestep1.outputs.cache-hit }}" != true + + - name: create something + run: echo SOMETHING > /usr/local/bin/something + + - name: cache save + uses: https://data.forgejo.org/actions/cache/save@v4 + with: + path: | + /usr/local/bin/something + key: ${{ steps.cachestep1.outputs.cache-primary-key }} + + restore-cache: + runs-on: docker + needs: [save-cache] + container: + image: data.forgejo.org/oci/node:20-bookworm + steps: + - name: cache restore + id: cachestep2 + uses: https://data.forgejo.org/actions/cache/restore@v4 + with: + path: | + /usr/local/bin/something + key: cachekey + + - name: verify something + run: | + set -x + test SOMETHING = $(cat /usr/local/bin/something) + + - name: cache hit + run: | + set -x + test "${{ steps.cachestep2.outputs.cache-hit }}" = true diff --git a/actions/example-cache/runner-config.yaml b/actions/example-cache/runner-config.yaml new file mode 100644 index 00000000..11818cc5 --- /dev/null +++ b/actions/example-cache/runner-config.yaml @@ -0,0 +1,30 @@ + +log: + level: debug + +runner: + file: .runner + capacity: 1 + env_file: .env + timeout: 3h + insecure: false + fetch_timeout: 5s + fetch_interval: 2s + labels: ["docker:docker://code.forgejo.org/oci/node:20-bookworm"] + +cache: + enabled: true + dir: "/srv/example/cache" + host: "" + port: 0 + +container: + network: "bridge" + privileged: false + options: + workdir_parent: + valid_volumes: ["/srv/example"] + docker_host: "" + +host: + workdir_parent: diff --git a/actions/example-cache/setup.sh b/actions/example-cache/setup.sh new file mode 100755 index 00000000..9c1f5adf --- /dev/null +++ b/actions/example-cache/setup.sh @@ -0,0 +1 @@ +FORGEJO_RUNNER_CONFIG=$EXAMPLE_DIR/runner-config.yaml forgejo-runner.sh reload diff --git a/actions/example-cache/teardown.sh b/actions/example-cache/teardown.sh new file mode 100755 index 00000000..b410c513 --- /dev/null +++ b/actions/example-cache/teardown.sh @@ -0,0 +1 @@ +forgejo-runner.sh reload diff --git a/actions/example-config-options/.forgejo/workflows/test.yml b/actions/example-config-options/.forgejo/workflows/test.yml new file mode 100644 index 00000000..7845e441 --- /dev/null +++ b/actions/example-config-options/.forgejo/workflows/test.yml @@ -0,0 +1,26 @@ +on: [push] + +jobs: + test: + runs-on: docker + container: + options: "--hostname customname" + steps: + - run: | + test -f /srv/example-config-options-volume-valid + - run: | + ! test -w /srv/example-config-options-volume-valid + - run: | + ! test -f /srv/example-config-options-volume-invalid + - run: | + set -x + test "$FROB" = "NITZ" + - run: | + set -x + test "$VAR_FROM_ENV_FILE" = "VALUE_FROM_ENV_FILE" + - run: | + set -x + test "$VAR_FROM_ENV_IN_CONFIG" = "VALUE_FROM_ENV_IN_CONFIG" + - run: | + set -x + test "$(cat /etc/hostname)" = customname diff --git a/actions/example-config-options/env_file b/actions/example-config-options/env_file new file mode 100644 index 00000000..c5b811ba --- /dev/null +++ b/actions/example-config-options/env_file @@ -0,0 +1 @@ +VAR_FROM_ENV_FILE=VALUE_FROM_ENV_FILE diff --git a/actions/example-config-options/runner-config.yaml b/actions/example-config-options/runner-config.yaml new file mode 100644 index 00000000..37b7b0ae --- /dev/null +++ b/actions/example-config-options/runner-config.yaml @@ -0,0 +1,33 @@ + +log: + level: debug + job_level: debug + +runner: + file: .runner + capacity: 1 + envs: + VAR_FROM_ENV_IN_CONFIG: VALUE_FROM_ENV_IN_CONFIG + env_file: env_file + timeout: 3h + insecure: true + fetch_timeout: 5s + fetch_interval: 2s + labels: ["docker:docker://code.forgejo.org/oci/node:20-bookworm"] + +cache: + enabled: false + dir: "" + host: "" + port: 0 + +container: + network: "" + privileged: false + options: "--volume /srv/example-config-options-volume-valid:/srv/example-config-options-volume-valid:ro --volume /srv/example-config-options-volume-invalid:/srv/example-config-options-volume-invalid --env FROB=NITZ" + workdir_parent: + valid_volumes: ["/srv/example-config-options-volume-valid"] + docker_host: "" + +host: + workdir_parent: diff --git a/actions/example-config-options/setup.sh b/actions/example-config-options/setup.sh new file mode 100755 index 00000000..1e62e683 --- /dev/null +++ b/actions/example-config-options/setup.sh @@ -0,0 +1,6 @@ +>/srv/example-config-options-volume-valid +>/srv/example-config-options-volume-invalid +TMPDIR=$(mktemp -d) +cp $EXAMPLE_DIR/runner-config.yaml $EXAMPLE_DIR/env_file $TMPDIR +sed -i -e "s|env_file:.*|env_file: $TMPDIR/env_file|" $TMPDIR/runner-config.yaml +FORGEJO_RUNNER_CONFIG=$TMPDIR/runner-config.yaml forgejo-runner.sh reload diff --git a/actions/example-config-options/teardown.sh b/actions/example-config-options/teardown.sh new file mode 100755 index 00000000..b410c513 --- /dev/null +++ b/actions/example-config-options/teardown.sh @@ -0,0 +1 @@ +forgejo-runner.sh reload diff --git a/actions/example-container/.forgejo/workflows/test.yml b/actions/example-container/.forgejo/workflows/test.yml index 583df87e..ecf04290 100644 --- a/actions/example-container/.forgejo/workflows/test.yml +++ b/actions/example-container/.forgejo/workflows/test.yml @@ -3,6 +3,6 @@ jobs: test: runs-on: docker container: - image: alpine:3.19 + image: data.forgejo.org/oci/alpine:3.23 steps: - run: grep Alpine /etc/os-release diff --git a/actions/example-context/.forgejo/workflows/test.yml b/actions/example-context/.forgejo/workflows/test.yml index a894bfd2..07f80fa9 100644 --- a/actions/example-context/.forgejo/workflows/test.yml +++ b/actions/example-context/.forgejo/workflows/test.yml @@ -4,7 +4,7 @@ jobs: test: runs-on: docker container: - image: code.forgejo.org/oci/node:20-bookworm + image: data.forgejo.org/oci/node:20-bookworm volumes: - /srv/example:/srv/example steps: @@ -15,174 +15,240 @@ jobs: test "$CI" = true test "$CI" = "${{ env.CI }}" - - name: GITHUB_ACTION + - name: FORGEJO_ACTION run: | set -x - echo "$GITHUB_ACTION" | grep -E '^[0-9]+$' - test "$GITHUB_ACTION" = "${{ env.GITHUB_ACTION }}" - test "$GITHUB_ACTION" = "${{ github.ACTION }}" + echo "$FORGEJO_ACTION" | grep -E '^[0-9]+$' + test "$FORGEJO_ACTION" = "${{ env.FORGEJO_ACTION }}" + test "$FORGEJO_ACTION" = "${{ github.ACTION }}" + test "$FORGEJO_ACTION" = "${{ forge.ACTION }}" + test "$FORGEJO_ACTION" = "${{ forgejo.ACTION }}" + test "$FORGEJO_ACTION" = "$GITHUB_ACTION" # See also actions/example-local-action/.forgejo/local-action/action.yml - - name: GITHUB_ACTION_PATH + - name: FORGEJO_ACTION_PATH run: | set -x - test -z "$GITHUB_ACTION_PATH" - test "$GITHUB_ACTION_PATH" = "${{ env.GITHUB_ACTION_PATH }}" - test "$GITHUB_ACTION_PATH" = "${{ github.ACTION_PATH }}" + test -z "$FORGEJO_ACTION_PATH" + test "$FORGEJO_ACTION_PATH" = "${{ env.FORGEJO_ACTION_PATH }}" + test "$FORGEJO_ACTION_PATH" = "${{ github.ACTION_PATH }}" + test "$FORGEJO_ACTION_PATH" = "${{ forge.ACTION_PATH }}" + test "$FORGEJO_ACTION_PATH" = "${{ forgejo.ACTION_PATH }}" + test "$FORGEJO_ACTION_PATH" = "$GITHUB_ACTION_PATH" - name: when running an action - if: ${{ env.GITHUB_ACTIONS }} + if: ${{ env.FORGEJO_ACTIONS }} uses: SELF@main with: input-one: "otherone" - - name: GITHUB_ACTION_REPOSITORY - run: test -f /srv/example/example-context/GITHUB_ACTION_REPOSITORY + - name: FORGEJO_ACTION_REPOSITORY + run: test -f /srv/example/example-context/FORGEJO_ACTION_REPOSITORY - - name: GITHUB_ACTION_PATH - run: test -f /srv/example/example-context/GITHUB_ACTION_PATH + - name: FORGEJO_ACTION_PATH + run: test -f /srv/example/example-context/FORGEJO_ACTION_PATH - - name: GITHUB_ACTIONS + - name: FORGEJO_ACTIONS run: | set -x - test "$GITHUB_ACTIONS" = true - test "$GITHUB_ACTIONS" = "${{ env.GITHUB_ACTIONS }}" + test "$FORGEJO_ACTIONS" = true + test "$FORGEJO_ACTIONS" = "${{ env.FORGEJO_ACTIONS }}" + test "$FORGEJO_ACTIONS" = "$GITHUB_ACTIONS" - - name: GITHUB_ACTOR + - name: FORGEJO_ACTOR run: | set -x - test "$GITHUB_ACTOR" - test "$GITHUB_ACTOR" = "${{ env.GITHUB_ACTOR }}" - test "$GITHUB_ACTOR" = "${{ github.ACTOR }}" + test "$FORGEJO_ACTOR" + test "$FORGEJO_ACTOR" = "${{ env.FORGEJO_ACTOR }}" + test "$FORGEJO_ACTOR" = "${{ github.ACTOR }}" + test "$FORGEJO_ACTOR" = "${{ forge.ACTOR }}" + test "$FORGEJO_ACTOR" = "${{ forgejo.ACTOR }}" + test "$FORGEJO_ACTOR" = "$GITHUB_ACTOR" - - name: GITHUB_API_URL + - name: FORGEJO_API_URL shell: bash run: | set -x - [[ "$GITHUB_API_URL" =~ /api/v1$ ]] - test "$GITHUB_API_URL" = "${{ env.GITHUB_API_URL }}" - test "$GITHUB_API_URL" = "${{ github.API_URL }}" + [[ "$FORGEJO_API_URL" =~ /api/v1$ ]] + test "$FORGEJO_API_URL" = "${{ env.FORGEJO_API_URL }}" + test "$FORGEJO_API_URL" = "${{ github.API_URL }}" + test "$FORGEJO_API_URL" = "${{ forge.API_URL }}" + test "$FORGEJO_API_URL" = "${{ forgejo.API_URL }}" + test "$FORGEJO_API_URL" = "$GITHUB_API_URL" # See also actions/example-pull-request/.forgejo/workflows/test.yml - - name: GITHUB_BASE_REF + - name: FORGEJO_BASE_REF run: | set -x - test -z "$GITHUB_BASE_REF" - test "$GITHUB_BASE_REF" = "${{ env.GITHUB_BASE_REF }}" - test "$GITHUB_BASE_REF" = "${{ github.BASE_REF }}" + test -z "$FORGEJO_BASE_REF" + test "$FORGEJO_BASE_REF" = "${{ env.FORGEJO_BASE_REF }}" + test "$FORGEJO_BASE_REF" = "${{ github.BASE_REF }}" + test "$FORGEJO_BASE_REF" = "${{ forge.BASE_REF }}" + test "$FORGEJO_BASE_REF" = "${{ forgejo.BASE_REF }}" + test "$FORGEJO_BASE_REF" = "$GITHUB_BASE_REF" # See also actions/example-pull-request/.forgejo/workflows/test.yml - - name: GITHUB_HEAD_REF + - name: FORGEJO_HEAD_REF run: | set -x - test -z "$GITHUB_HEAD_REF" - test "$GITHUB_HEAD_REF" = "${{ env.GITHUB_HEAD_REF }}" - test "$GITHUB_HEAD_REF" = "${{ github.HEAD_REF }}" + test -z "$FORGEJO_HEAD_REF" + test "$FORGEJO_HEAD_REF" = "${{ env.FORGEJO_HEAD_REF }}" + test "$FORGEJO_HEAD_REF" = "${{ github.HEAD_REF }}" + test "$FORGEJO_HEAD_REF" = "${{ forge.HEAD_REF }}" + test "$FORGEJO_HEAD_REF" = "${{ forgejo.HEAD_REF }}" + test "$FORGEJO_HEAD_REF" = "$GITHUB_HEAD_REF" - - name: GITHUB_ENV + - name: FORGEJO_ENV run: | set -x - test -f "$GITHUB_ENV" - test "$GITHUB_ENV" = "${{ env.GITHUB_ENV }}" + test -f "$FORGEJO_ENV" + test "$FORGEJO_ENV" = "${{ env.FORGEJO_ENV }}" + test "$FORGEJO_ENV" = "$GITHUB_ENV" - - name: GITHUB_EVENT_NAME + - name: FORGEJO_EVENT_NAME run: | set -x - test "$GITHUB_EVENT_NAME" = push - test "$GITHUB_EVENT_NAME" = "${{ env.GITHUB_EVENT_NAME }}" - test "$GITHUB_EVENT_NAME" = "${{ github.EVENT_NAME }}" + test "$FORGEJO_EVENT_NAME" = push + test "$FORGEJO_EVENT_NAME" = "${{ env.FORGEJO_EVENT_NAME }}" + test "$FORGEJO_EVENT_NAME" = "${{ github.EVENT_NAME }}" + test "$FORGEJO_EVENT_NAME" = "${{ forge.EVENT_NAME }}" + test "$FORGEJO_EVENT_NAME" = "${{ forgejo.EVENT_NAME }}" + test "$FORGEJO_EVENT_NAME" = "$GITHUB_EVENT_NAME" - - name: GITHUB_JOB + - name: FORGEJO_JOB run: | set -x - test "$GITHUB_JOB" = test - test "$GITHUB_JOB" = "${{ env.GITHUB_JOB }}" - test "$GITHUB_JOB" = "${{ github.JOB }}" + test "$FORGEJO_JOB" = test + test "$FORGEJO_JOB" = "${{ env.FORGEJO_JOB }}" + test "$FORGEJO_JOB" = "${{ github.JOB }}" + test "$FORGEJO_JOB" = "${{ forge.JOB }}" + test "$FORGEJO_JOB" = "${{ forgejo.JOB }}" + test "$FORGEJO_JOB" = "$GITHUB_JOB" - - name: GITHUB_OUTPUT + - name: FORGEJO_OUTPUT run: | set -x - test -f "$GITHUB_OUTPUT" - test "$GITHUB_OUTPUT" = "${{ env.GITHUB_OUTPUT }}" + test -f "$FORGEJO_OUTPUT" + test "$FORGEJO_OUTPUT" = "${{ env.FORGEJO_OUTPUT }}" + test "$FORGEJO_OUTPUT" = "$GITHUB_OUTPUT" - - name: GITHUB_PATH + - name: FORGEJO_PATH run: | set -x - test -f "$GITHUB_PATH" - test "$GITHUB_PATH" = "${{ env.GITHUB_PATH }}" + test -f "$FORGEJO_PATH" + test "$FORGEJO_PATH" = "${{ env.FORGEJO_PATH }}" + test "$FORGEJO_PATH" = "$GITHUB_PATH" - - name: GITHUB_REF + - name: FORGEJO_REF shell: bash run: | set -x - [[ "$GITHUB_REF" =~ ^refs/ ]] - test "$GITHUB_REF" = "${{ env.GITHUB_REF }}" - test "$GITHUB_REF" = "${{ github.REF }}" + [[ "$FORGEJO_REF" =~ ^refs/ ]] + test "$FORGEJO_REF" = "${{ env.FORGEJO_REF }}" + test "$FORGEJO_REF" = "${{ github.REF }}" + test "$FORGEJO_REF" = "${{ forge.REF }}" + test "$FORGEJO_REF" = "${{ forgejo.REF }}" + test "$FORGEJO_REF" = "$GITHUB_REF" - - name: GITHUB_REF_NAME + - name: FORGEJO_REF_NAME shell: bash run: | set -x - ! [[ "$GITHUB_REF_NAME" =~ ^refs/ ]] - test "$GITHUB_REF_NAME" = "${{ env.GITHUB_REF_NAME }}" - test "$GITHUB_REF_NAME" = "${{ github.REF_NAME }}" + ! [[ "$FORGEJO_REF_NAME" =~ ^refs/ ]] + test "$FORGEJO_REF_NAME" = "${{ env.FORGEJO_REF_NAME }}" + test "$FORGEJO_REF_NAME" = "${{ github.REF_NAME }}" + test "$FORGEJO_REF_NAME" = "${{ forge.REF_NAME }}" + test "$FORGEJO_REF_NAME" = "${{ forgejo.REF_NAME }}" + test "$FORGEJO_REF_NAME" = "$GITHUB_REF_NAME" - - name: GITHUB_REPOSITORY + - name: FORGEJO_REPOSITORY run: | set -x - test "$GITHUB_REPOSITORY" = root/example-context - test "$GITHUB_REPOSITORY" = "${{ env.GITHUB_REPOSITORY }}" - test "$GITHUB_REPOSITORY" = "${{ github.REPOSITORY }}" + test "$FORGEJO_REPOSITORY" = root/example-context + test "$FORGEJO_REPOSITORY" = "${{ env.FORGEJO_REPOSITORY }}" + test "$FORGEJO_REPOSITORY" = "${{ github.REPOSITORY }}" + test "$FORGEJO_REPOSITORY" = "${{ forge.REPOSITORY }}" + test "$FORGEJO_REPOSITORY" = "${{ forgejo.REPOSITORY }}" + test "$FORGEJO_REPOSITORY" = "$GITHUB_REPOSITORY" - - name: GITHUB_REPOSITORY_OWNER + - name: FORGEJO_REPOSITORY_OWNER run: | set -x - test "$GITHUB_REPOSITORY_OWNER" = root - test "$GITHUB_REPOSITORY_OWNER" = "${{ env.GITHUB_REPOSITORY_OWNER }}" - test "$GITHUB_REPOSITORY_OWNER" = "${{ github.REPOSITORY_OWNER }}" + test "$FORGEJO_REPOSITORY_OWNER" = root + test "$FORGEJO_REPOSITORY_OWNER" = "${{ env.FORGEJO_REPOSITORY_OWNER }}" + test "$FORGEJO_REPOSITORY_OWNER" = "${{ github.REPOSITORY_OWNER }}" + test "$FORGEJO_REPOSITORY_OWNER" = "${{ forge.REPOSITORY_OWNER }}" + test "$FORGEJO_REPOSITORY_OWNER" = "${{ forgejo.REPOSITORY_OWNER }}" + test "$FORGEJO_REPOSITORY_OWNER" = "$GITHUB_REPOSITORY_OWNER" - - name: GITHUB_RUN_NUMBER + - name: FORGEJO_RUN_NUMBER run: | set -x - echo "$GITHUB_RUN_NUMBER" | grep -E '^[0-9]+$' - test "$GITHUB_RUN_NUMBER" = "${{ env.GITHUB_RUN_NUMBER }}" - test "$GITHUB_RUN_NUMBER" = "${{ github.RUN_NUMBER }}" + echo "$FORGEJO_RUN_NUMBER" | grep -E '^[0-9]+$' + test "$FORGEJO_RUN_NUMBER" = "${{ env.FORGEJO_RUN_NUMBER }}" + test "$FORGEJO_RUN_NUMBER" = "${{ github.RUN_NUMBER }}" + test "$FORGEJO_RUN_NUMBER" = "${{ forge.RUN_NUMBER }}" + test "$FORGEJO_RUN_NUMBER" = "${{ forgejo.RUN_NUMBER }}" + test "$FORGEJO_RUN_NUMBER" = "$GITHUB_RUN_NUMBER" - - name: GITHUB_SERVER_URL + - name: FORGEJO_RUN_ID + run: | + set -x + echo "$FORGEJO_RUN_ID" | grep -E '^[0-9]+$' + test "$FORGEJO_RUN_ID" = "${{ env.FORGEJO_RUN_ID }}" + test "$FORGEJO_RUN_ID" = "${{ github.RUN_ID }}" + test "$FORGEJO_RUN_ID" = "${{ forge.RUN_ID }}" + test "$FORGEJO_RUN_ID" = "${{ forgejo.RUN_ID }}" + test "$FORGEJO_RUN_ID" = "$GITHUB_RUN_ID" + + - name: FORGEJO_SERVER_URL shell: bash run: | set -x - [[ "$GITHUB_SERVER_URL" =~ ^http ]] - test "$GITHUB_SERVER_URL" = "${{ env.GITHUB_SERVER_URL }}" - test "$GITHUB_SERVER_URL" = "${{ github.SERVER_URL }}" + [[ "$FORGEJO_SERVER_URL" =~ ^http ]] + test "$FORGEJO_SERVER_URL" = "${{ env.FORGEJO_SERVER_URL }}" + test "$FORGEJO_SERVER_URL" = "${{ github.SERVER_URL }}" + test "$FORGEJO_SERVER_URL" = "${{ forge.SERVER_URL }}" + test "$FORGEJO_SERVER_URL" = "${{ forgejo.SERVER_URL }}" + test "$FORGEJO_SERVER_URL" = "$GITHUB_SERVER_URL" - - name: GITHUB_SHA + - name: FORGEJO_SHA run: | set -x - test "$GITHUB_SHA" - test "$GITHUB_SHA" = "${{ env.GITHUB_SHA }}" - test "$GITHUB_SHA" = "${{ github.SHA }}" + test "$FORGEJO_SHA" + test "$FORGEJO_SHA" = "${{ env.FORGEJO_SHA }}" + test "$FORGEJO_SHA" = "${{ github.SHA }}" + test "$FORGEJO_SHA" = "${{ forge.SHA }}" + test "$FORGEJO_SHA" = "${{ forgejo.SHA }}" + test "$FORGEJO_SHA" = "$GITHUB_SHA" - - name: GITHUB_STEP_SUMMARY + - name: FORGEJO_STEP_SUMMARY run: | set -x - test -f "$GITHUB_STEP_SUMMARY" - test "$GITHUB_STEP_SUMMARY" = "${{ env.GITHUB_STEP_SUMMARY }}" + test -f "$FORGEJO_STEP_SUMMARY" + test "$FORGEJO_STEP_SUMMARY" = "${{ env.FORGEJO_STEP_SUMMARY }}" + test "$FORGEJO_STEP_SUMMARY" = "$GITHUB_STEP_SUMMARY" # See also actions/example-pull-request/.forgejo/workflows/test.yml - - name: GITHUB_TOKEN + - name: FORGEJO_TOKEN run: | set -x - test "$GITHUB_TOKEN" - test "$GITHUB_TOKEN" = "${{ env.GITHUB_TOKEN }}" - test "$GITHUB_TOKEN" = "${{ github.TOKEN }}" + test "$FORGEJO_TOKEN" + test "$FORGEJO_TOKEN" = "${{ env.FORGEJO_TOKEN }}" + test "$FORGEJO_TOKEN" = "${{ github.TOKEN }}" + test "$FORGEJO_TOKEN" = "${{ forge.TOKEN }}" + test "$FORGEJO_TOKEN" = "${{ forgejo.TOKEN }}" + test "$FORGEJO_TOKEN" = "$GITHUB_TOKEN" - - name: GITHUB_WORKSPACE + - name: FORGEJO_WORKSPACE run: | set -x - test -d "$GITHUB_WORKSPACE" - test "$GITHUB_WORKSPACE" = "${{ env.GITHUB_WORKSPACE }}" - test "$GITHUB_WORKSPACE" = "${{ github.WORKSPACE }}" + test -d "$FORGEJO_WORKSPACE" + test "$FORGEJO_WORKSPACE" = "${{ env.FORGEJO_WORKSPACE }}" + test "$FORGEJO_WORKSPACE" = "${{ github.WORKSPACE }}" + test "$FORGEJO_WORKSPACE" = "${{ forge.WORKSPACE }}" + test "$FORGEJO_WORKSPACE" = "${{ forgejo.WORKSPACE }}" + test "$FORGEJO_WORKSPACE" = "$GITHUB_WORKSPACE" - name: RUNNER_ARCH run: | @@ -194,11 +260,10 @@ jobs: set -x test "$RUNNER_OS" = Linux - # runner 3.3.0 $RUNNER_TOOL_CACHE is not an existing directory - # - name: RUNNER_TOOL_CACHE - # run: | - # set -x - # test -d "$RUNNER_TOOL_CACHE" + - name: RUNNER_TOOL_CACHE + run: | + set -x + test "$RUNNER_TOOL_CACHE" - name: RUNNER_TEMP run: | diff --git a/actions/example-context/action-for-context/action.yml b/actions/example-context/action-for-context/action.yml index dcb8f2b7..e675d6ca 100644 --- a/actions/example-context/action-for-context/action.yml +++ b/actions/example-context/action-for-context/action.yml @@ -6,18 +6,27 @@ inputs: runs: using: "composite" steps: - - name: GITHUB_ACTION_REPOSITORY + - name: FORGEJO_ACTION_REPOSITORY run: | set -x - test "$GITHUB_ACTION_REPOSITORY" = root/action-for-context - test "$GITHUB_ACTION_REPOSITORY" = "${{ env.GITHUB_ACTION_REPOSITORY }}" - test "$GITHUB_ACTION_REPOSITORY" = "${{ github.ACTION_REPOSITORY }}" - touch /srv/example/example-context/GITHUB_ACTION_REPOSITORY + test "$FORGEJO_ACTION_REPOSITORY" = root/action-for-context + test "$FORGEJO_ACTION_REPOSITORY" = "${{ env.FORGEJO_ACTION_REPOSITORY }}" + test "$FORGEJO_ACTION_REPOSITORY" = "${{ github.ACTION_REPOSITORY }}" + test "$FORGEJO_ACTION_REPOSITORY" = "${{ forge.ACTION_REPOSITORY }}" + test "$FORGEJO_ACTION_REPOSITORY" = "${{ forgejo.ACTION_REPOSITORY }}" + test "$FORGEJO_ACTION_REPOSITORY" = "$GITHUB_ACTION_REPOSITORY" + touch /srv/example/example-context/FORGEJO_ACTION_REPOSITORY - - name: GITHUB_ACTION_PATH + - name: FORGEJO_ACTION_PATH shell: bash run: | set -x - [[ "$GITHUB_ACTION_PATH" =~ action-for-context@main$ ]] - test "$GITHUB_ACTION_PATH" = "${{ github.ACTION_PATH }}" - touch /srv/example/example-context/GITHUB_ACTION_PATH + # prior to Forgejo runner 8.0.0 the action path is built out of the file path. + # with Forgejo runner 8.0.0 and above is it a 64 character hash string + # e.g. /var/run/act/actions/1b/5c1802fa47e35716c2a0977bc907049d31aef29191cba400011c0b38b52d12 + [[ "$FORGEJO_ACTION_PATH" =~ action-for-context@main$ ]] || [[ "$FORGEJO_ACTION_PATH" =~ /[0-9a-f]{2}/[0-9a-f]{62}$ ]] + test "$FORGEJO_ACTION_PATH" = "${{ github.ACTION_PATH }}" + test "$FORGEJO_ACTION_PATH" = "${{ forge.ACTION_PATH }}" + test "$FORGEJO_ACTION_PATH" = "${{ forgejo.ACTION_PATH }}" + test "$FORGEJO_ACTION_PATH" = "$GITHUB_ACTION_PATH" + touch /srv/example/example-context/FORGEJO_ACTION_PATH diff --git a/actions/example-create-runner-file/.forgejo/workflows/test.yaml b/actions/example-create-runner-file/.forgejo/workflows/test.yaml new file mode 100644 index 00000000..e44397dd --- /dev/null +++ b/actions/example-create-runner-file/.forgejo/workflows/test.yaml @@ -0,0 +1,9 @@ +on: + push: + +jobs: + test: + runs-on: create-runner-file + steps: + - run: | + echo "OK" diff --git a/actions/example-create-runner-file/run.sh b/actions/example-create-runner-file/run.sh new file mode 100644 index 00000000..637132e5 --- /dev/null +++ b/actions/example-create-runner-file/run.sh @@ -0,0 +1,40 @@ +source "lib/lib.sh" + +api="$url/api/v1" + +function main() { + local repo + repo="root/example-$example" + + secret="$(openssl rand -hex 20)" + runner_name="runner-$(openssl rand -hex 5)" + + create_offline_registration_token "$runner_name" root "$secret" + + # Changing to $DIR is necessary so that `.runner` gets created there. Otherwise, `forgejo-runner` would not pick it up. + pushd "$DIR" || exit 1 + ./forgejo-runner -c "$EXAMPLE_DIR/runner-config.yaml" create-runner-file --instance "http://$IP:3000" --name "$runner_name" --secret "$secret" --connect + popd || exit 1 + + FORGEJO_RUNNER_CONFIG="$EXAMPLE_DIR/runner-config.yaml" forgejo-runner.sh reload + + label_count=$(jq '.labels | length ' "$DIR/.runner") + if [[ "$label_count" != "1" ]] ; then + echo "Unexpected number of labels in .runner file: $label_count instead of 1" >&2 + exit 1 + fi + + runner_label=$(jq -r '.labels[0]' "$DIR/.runner") + if [[ "$runner_label" != "create-runner-file:docker://code.forgejo.org/oci/node:24-trixie" ]] ; then + echo "Unexpected runner label: '$runner_label' instead of create-runner-file:docker://code.forgejo.org/oci/node:24-trixie" >&2 + exit 1 + fi + + forgejo-test-helper.sh push_workflow "actions/example-$example" "$url" root "example-$example" setup-forgejo "$token" + + local sha + sha="$(forgejo-test-helper.sh branch_tip "$url" "$repo" main)" + forgejo-test-helper.sh wait_success "$url" "$repo" "$sha" +} + +main diff --git a/actions/example-create-runner-file/runner-config.yaml b/actions/example-create-runner-file/runner-config.yaml new file mode 100644 index 00000000..7096728f --- /dev/null +++ b/actions/example-create-runner-file/runner-config.yaml @@ -0,0 +1,31 @@ + +log: + level: debug + +runner: + file: .runner + capacity: 1 + env_file: .env + timeout: 3h + insecure: false + fetch_timeout: 5s + fetch_interval: 2s + labels: + - "create-runner-file:docker://code.forgejo.org/oci/node:24-trixie" + +cache: + enabled: true + dir: "/srv/example/cache" + host: "" + port: 0 + +container: + network: "bridge" + privileged: false + options: + workdir_parent: + valid_volumes: ["/srv/example"] + docker_host: "" + +host: + workdir_parent: diff --git a/actions/example-cron/.forgejo/workflows/test.yml b/actions/example-cron/.forgejo/workflows/test.yml index 2eedd142..58ae70a6 100644 --- a/actions/example-cron/.forgejo/workflows/test.yml +++ b/actions/example-cron/.forgejo/workflows/test.yml @@ -6,17 +6,17 @@ jobs: test: runs-on: docker container: - image: code.forgejo.org/oci/debian:bookworm + image: data.forgejo.org/oci/debian:trixie options: "--volume /srv/example:/srv/example" steps: - - run: | - touch /srv/example/cron-volume/DONE - - name: save context run: | - d=/srv/example/cron/contexts/$GITHUB_EVENT_NAME + d=/srv/example/cron/contexts/$FORGEJO_EVENT_NAME mkdir -p $d cat > $d/github <<'EOF' ${{ toJSON(github) }} EOF + + - run: | + touch /srv/example/cron-volume/DONE diff --git a/actions/example-cron/run.sh b/actions/example-cron/run.sh index f95045f8..bf19e981 100755 --- a/actions/example-cron/run.sh +++ b/actions/example-cron/run.sh @@ -7,7 +7,7 @@ forgejo-test-helper.sh push_workflow actions/example-$example $url root example- # See https://codeberg.org/forgejo/forgejo/pulls/1941 for more information # function verify_ref() { - local ref=$(sqlite3 $DIR/forgejo-work-path/forgejo.db 'select ref from action_schedule') + local ref=$(sqlite3 $DIR/forgejo-work-path/forgejo.db 'select ref from action_schedule') test "${ref##*/}" = "main" } verify_ref @@ -16,12 +16,12 @@ forgejo-curl.sh api_json --data '{"new_branch_name":"zzzz"}' $api/repos/root/exa verify_ref # cron runs once per minute, give it three minutes max before declaring failure -if ! RETRY_DELAYS="30 30 30 30 30 30" forgejo.sh retry test -f /srv/example/cron-volume/DONE ; then +if ! RETRY_DELAYS="30 30 30 30 30 30" forgejo.sh retry test -f /srv/example/cron-volume/DONE; then cat $FORGEJO_RUNNER_LOGS false fi c=/srv/example/cron/contexts/schedule/github cat $c -test "schedule" = "$(jq -r .event_name < $c)" -test "schedule" = "$(jq -r .event.action < $c)" +test "schedule" = "$(jq -r .event_name <$c)" +test "schedule" = "$(jq -r .event.action <$c)" diff --git a/actions/example-docker-action/.forgejo/workflows/test.yml b/actions/example-docker-action/.forgejo/workflows/test.yml index 988a81ed..d7ff2b98 100644 --- a/actions/example-docker-action/.forgejo/workflows/test.yml +++ b/actions/example-docker-action/.forgejo/workflows/test.yml @@ -9,11 +9,11 @@ jobs: # - uses: https://code.forgejo.org/forgejo/test-setup-forgejo-docker@main with: - args: ${{ github.workspace }}/SOMEFILE + args: ${{ forgejo.workspace }}/SOMEFILE # # ... which then also exists in the job workspace # because both docker containers are automatically # sharing the volume that contains it. # - run: | - test -f ${{ github.workspace }}/SOMEFILE + test -f ${{ forgejo.workspace }}/SOMEFILE diff --git a/actions/example-expression/.forgejo/workflows/test.yml b/actions/example-expression/.forgejo/workflows/test.yml index ab4bb646..ba37759e 100644 --- a/actions/example-expression/.forgejo/workflows/test.yml +++ b/actions/example-expression/.forgejo/workflows/test.yml @@ -23,7 +23,7 @@ jobs: if: ${{ env.KEY1 == 'nogood' }} - name: if does not skip id: conditional - run: echo 'check=good' >> $GITHUB_OUTPUT + run: echo 'check=good' >> $FORGEJO_OUTPUT if: env.KEY1 == 'value1' - name: verify if did not skip run: test ${{ steps.conditional.outputs.check }} = good @@ -98,10 +98,11 @@ jobs: set -x test "${{ fromJSON('["one","two"]')[0] }}" = 'one' - # As of act v1.13.0 this fails for real (before it pretended to work but did not) - # - name: hashFiles - # run: | - # set -x - # hash="bd52020371c038c4ad38a8d2df05dfa1a220d40fbe1ae83b63d6010cb527e531" - # test "${{ hashFiles('actions/example-expression/.forgejo/fileone.txt') }}" = $hash - # test "${{ hashFiles('actions/example-expression/.forgejo/fileone.*') }}" = $hash + - uses: actions/checkout@v4 + + - name: hashFiles + run: | + set -x + hash="aea6ca2329c852f5b480ec35e1fe09d39a6bd1b50f4f9cc38fbd4fef870dc107" + test "${{ hashFiles('.forgejo/fileone.txt') }}" = $hash + test "${{ hashFiles('.forgejo/fileone.*') }}" = $hash diff --git a/actions/example-force-rebuild/.forgejo/workflows/test.yml b/actions/example-force-rebuild/.forgejo/workflows/test.yml new file mode 100644 index 00000000..d6f8b3e9 --- /dev/null +++ b/actions/example-force-rebuild/.forgejo/workflows/test.yml @@ -0,0 +1,11 @@ +on: [push] + +jobs: + ls: + runs-on: docker + steps: + - uses: https://code.forgejo.org/forgejo/test-setup-forgejo-docker@main + with: + args: ${{ forgejo.workspace }}/SOMEFILE + - run: | + test -f ${{ forgejo.workspace }}/SOMEFILE diff --git a/actions/example-force-rebuild/run.sh b/actions/example-force-rebuild/run.sh new file mode 100755 index 00000000..b783b3a2 --- /dev/null +++ b/actions/example-force-rebuild/run.sh @@ -0,0 +1,69 @@ +TMPDIR=$(mktemp -d) + +trap "rm -fr $TMPDIR" EXIT + +function setup_with_rebuild() { + FORGEJO_RUNNER_CONFIG=$EXAMPLE_DIR/runner-config-with-rebuild.yml forgejo-runner.sh reload +} + +function setup_without_rebuild() { + FORGEJO_RUNNER_CONFIG=$EXAMPLE_DIR/runner-config-without-rebuild.yml forgejo-runner.sh reload +} + +function run() { + local dir="$1" + local expected="$2" + local repo=root/example-$example + forgejo-test-helper.sh push_workflow $dir $url root example-$example setup-forgejo $token + sha=$(forgejo-test-helper.sh branch_tip $url $repo main) + forgejo-test-helper.sh wait_$expected $url $repo $sha +} + +function get_remote_image() { + docker image ls --format='{{ .Repository }}' | grep '^runner-remote-docker-action' +} + +function remove_remote_images() { + docker image ls --format='{{ .Repository }}' | grep '^runner-remote-docker-action' | while read image; do + docker rmi $image + done +} + +function was_built() { + grep --quiet 'docker build -t runner-remote-docker-action' $FORGEJO_RUNNER_LOGS +} + +function main() { + local dir=$TMPDIR/repository + cp -a $EXAMPLE_DIR $dir + + remove_remote_images + + : + : Run one + : + setup_without_rebuild + run $dir success + local image="$(get_remote_image)" + test "$image" + was_built + + : + : Run two: verify the image was not rebuilt + : + setup_without_rebuild # resets the logs + run $dir success + test "$image" = "$(get_remote_image)" + ! was_built + + : + : Run two: verify the image was rebuilt and + : the image name stayed the same + : + setup_with_rebuild + run $dir success + test "$image" = "$(get_remote_image)" + was_built +} + +main diff --git a/actions/example-force-rebuild/runner-config-with-rebuild.yml b/actions/example-force-rebuild/runner-config-with-rebuild.yml new file mode 100644 index 00000000..6dee7b32 --- /dev/null +++ b/actions/example-force-rebuild/runner-config-with-rebuild.yml @@ -0,0 +1,31 @@ +log: + level: trace + job_level: trace + +runner: + file: .runner + capacity: 1 + env_file: .env + timeout: 3h + insecure: false + fetch_timeout: 5s + fetch_interval: 2s + labels: ["docker:docker://code.forgejo.org/oci/node:20-bookworm"] + +cache: + enabled: false + dir: "" + host: "" + port: 0 + +container: + network: "bridge" + privileged: false + options: + workdir_parent: + valid_volumes: ["/srv/example"] + docker_host: "" + force_rebuild: true + +host: + workdir_parent: diff --git a/actions/example-force-rebuild/runner-config-without-rebuild.yml b/actions/example-force-rebuild/runner-config-without-rebuild.yml new file mode 100644 index 00000000..8d9f71bb --- /dev/null +++ b/actions/example-force-rebuild/runner-config-without-rebuild.yml @@ -0,0 +1,31 @@ +log: + level: trace + job_level: trace + +runner: + file: .runner + capacity: 1 + env_file: .env + timeout: 3h + insecure: false + fetch_timeout: 5s + fetch_interval: 2s + labels: ["docker:docker://code.forgejo.org/oci/node:20-bookworm"] + +cache: + enabled: false + dir: "" + host: "" + port: 0 + +container: + network: "bridge" + privileged: false + options: + workdir_parent: + valid_volumes: ["/srv/example"] + docker_host: "" + force_rebuild: false + +host: + workdir_parent: diff --git a/actions/example-force-rebuild/teardown.sh b/actions/example-force-rebuild/teardown.sh new file mode 100755 index 00000000..b410c513 --- /dev/null +++ b/actions/example-force-rebuild/teardown.sh @@ -0,0 +1 @@ +forgejo-runner.sh reload diff --git a/actions/example-id-tokens/.forgejo/workflows/test.yml b/actions/example-id-tokens/.forgejo/workflows/test.yml new file mode 100644 index 00000000..31c49156 --- /dev/null +++ b/actions/example-id-tokens/.forgejo/workflows/test.yml @@ -0,0 +1,78 @@ +on: [push] + +env: + JWT_CLI_VERSION: 6.2.0 # renovate: datasource=github-releases depName=jwt-cli packageName=mike-engel/jwt-cli + +jobs: + generation-allowed: + enable-openid-connect: true + runs-on: docker + container: + image: data.forgejo.org/oci/ci:1 + steps: + - run: curl -L -o jwt-linux.tar.gz https://github.com/mike-engel/jwt-cli/releases/download/${{ env.JWT_CLI_VERSION }}/jwt-linux-musl.tar.gz && tar -xvzf ./jwt-linux.tar.gz && chmod a+x ./jwt + - name: validate token generation works + run: | + RAW_JWT=$(curl -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=exampleAudience" | jq -r ".value") + if [[ -z "RAW_JWT" ]]; then + echo "Error: RAW_JWT should be set" + exit 1 + fi + + DECODED_JWT_BODY=$(echo $RAW_JWT | jq -R 'split(".") | .[1] | @base64d | fromjson') + if [[ -z "$DECODED_JWT_BODY" ]]; then + echo "Error: DECODED_JWT_BODY should be set" + exit 1 + fi + + ISS=$(echo $DECODED_JWT_BODY | jq -r '.iss') + if [[ -z "$ISS" ]]; then + echo "Error: ISS should be set" + exit 1 + fi + + curl "$ISS/.well-known/keys" > jwks.json + JWKS=$(cat ./jwks.json) + if [[ -z "$JWKS" ]]; then + echo "Error: JWKS should be set" + exit 1 + fi + + # Verify that the JWT decodes with the JWKS data + ./jwt decode -S @./jwks.json -A RS256 $RAW_JWT || (echo "Error: failed signature validation" && exit 1) + + WORKFLOW=$(echo $DECODED_JWT_BODY | jq -r '.workflow') + AUD=$(echo $DECODED_JWT_BODY | jq -r '.aud') + EVENT_NAME=$(echo $DECODED_JWT_BODY | jq -r '.event_name') + SUB=$(echo $DECODED_JWT_BODY | jq -r '.sub') + if [[ "$WORKFLOW" != "test.yml" ]]; then + echo "Error: WORKFLOW should be test.yml but is $WORKFLOW" + exit 1 + fi + if [[ "$AUD" != "exampleAudience" ]]; then + echo "Error: AUD should be exampleAudience but is $AUD" + exit 1 + fi + if [[ "$EVENT_NAME" != "push" ]]; then + echo "Error: EVENT_NAME should be push but is $EVENT_NAME" + exit 1 + fi + if [[ "$SUB" != "repo:root/example-id-tokens:ref:refs/heads/main" ]]; then + echo "Error: SUB should be repo:root/example-id-tokens:ref:refs/heads/main but is $SUB" + exit 1 + fi + + generation-not-allowed: + enable-openid-connect: false + runs-on: docker + steps: + - name: check variables are unset + run: | + if [[ -n "$ACTIONS_ID_TOKEN_REQUEST_TOKEN" ]]; then + echo "Error: ACTIONS_ID_TOKEN_REQUEST_TOKEN should be unset" + exit 1 + fi + if [[ -n "$ACTIONS_ID_TOKEN_REQUEST_URL" ]]; then + echo "Error: ACTIONS_ID_TOKEN_REQUEST_TOKEN should be unset" + exit 1 + fi diff --git a/actions/example-if-cancel/.forgejo/workflows/test.yml b/actions/example-if-cancel/.forgejo/workflows/test.yml index 5a921988..d6800175 100644 --- a/actions/example-if-cancel/.forgejo/workflows/test.yml +++ b/actions/example-if-cancel/.forgejo/workflows/test.yml @@ -1,9 +1,3 @@ -# -# As of Forgejo v1.20 running this example would require using the web -# endpoints because there is no API to do the same. -# -# It was manually tested to **not work** with Forgejo v1.21 & runner 3.0.1 -# on: [push] jobs: diff --git a/actions/example-if/.forgejo/workflows/test.yml b/actions/example-if/.forgejo/workflows/test.yml index cc9401ce..355d9f20 100644 --- a/actions/example-if/.forgejo/workflows/test.yml +++ b/actions/example-if/.forgejo/workflows/test.yml @@ -8,7 +8,7 @@ jobs: - name: if true if: true id: if_true - run: echo 'check=good' >> $GITHUB_OUTPUT + run: echo 'check=good' >> $FORGEJO_OUTPUT - name: verify if true was run run: test ${{ steps.if_true.outputs.check }} = good diff --git a/actions/example-local-action/.forgejo/local-action/action.yml b/actions/example-local-action/.forgejo/local-action/action.yml index 79637578..900bc1c1 100644 --- a/actions/example-local-action/.forgejo/local-action/action.yml +++ b/actions/example-local-action/.forgejo/local-action/action.yml @@ -13,10 +13,10 @@ outputs: runs: using: "composite" steps: - - name: GITHUB_ACTION_PATH + - name: FORGEJO_ACTION_PATH run: | set -x - test "$(basename $GITHUB_ACTION_PATH)" = local-action - test "$GITHUB_ACTION_PATH" = "${{ env.GITHUB_ACTION_PATH }}" + test -e "$FORGEJO_ACTION_PATH" + test "$FORGEJO_ACTION_PATH" = "${{ env.FORGEJO_ACTION_PATH }}" - - run: echo key=${{ inputs.input-two-required }} >> $GITHUB_OUTPUT + - run: echo key=${{ inputs.input-two-required }} >> $FORGEJO_OUTPUT diff --git a/actions/example-lxc/.forgejo/workflows/test.yml b/actions/example-lxc/.forgejo/workflows/test.yml new file mode 100644 index 00000000..e7aa3fd9 --- /dev/null +++ b/actions/example-lxc/.forgejo/workflows/test.yml @@ -0,0 +1,16 @@ +on: [push] + +jobs: + job1: + runs-on: lxc + steps: + - uses: https://data.forgejo.org/actions/checkout@v4 + - run: systemctl --no-pager list-units + job2: + runs-on: lxc + steps: + - run: echo OK2 + job3: + runs-on: lxc + steps: + - run: echo OK3 diff --git a/actions/example-lxc/runner-config.yaml b/actions/example-lxc/runner-config.yaml new file mode 100644 index 00000000..617b3920 --- /dev/null +++ b/actions/example-lxc/runner-config.yaml @@ -0,0 +1,31 @@ + +log: + level: debug + job_level: debug + +runner: + file: .runner + capacity: 1 + env_file: .env + timeout: 3h + insecure: false + fetch_timeout: 5s + fetch_interval: 2s + labels: ["lxc:lxc://debian:bookworm"] + +cache: + enabled: false + dir: "" + host: "" + port: 0 + +container: + network: "bridge" + privileged: false + options: + workdir_parent: + valid_volumes: ["/srv/example"] + docker_host: "" + +host: + workdir_parent: diff --git a/actions/example-lxc/setup.sh b/actions/example-lxc/setup.sh new file mode 100755 index 00000000..9c1f5adf --- /dev/null +++ b/actions/example-lxc/setup.sh @@ -0,0 +1 @@ +FORGEJO_RUNNER_CONFIG=$EXAMPLE_DIR/runner-config.yaml forgejo-runner.sh reload diff --git a/actions/example-lxc/teardown.sh b/actions/example-lxc/teardown.sh new file mode 100755 index 00000000..b410c513 --- /dev/null +++ b/actions/example-lxc/teardown.sh @@ -0,0 +1 @@ +forgejo-runner.sh reload diff --git a/actions/example-matrix-dynamic/.forgejo/workflows/test.yml b/actions/example-matrix-dynamic/.forgejo/workflows/test.yml new file mode 100644 index 00000000..170a009b --- /dev/null +++ b/actions/example-matrix-dynamic/.forgejo/workflows/test.yml @@ -0,0 +1,49 @@ +on: [push] +jobs: + define-matrix: + runs-on: docker + outputs: + scalar-value: ${{ steps.define.outputs.scalar }} + array-value: ${{ steps.define.outputs.array }} + matrix-value: ${{ steps.define.outputs.matrix }} + steps: + - id: define + run: | + echo 'scalar=scalar value' >> "$FORGEJO_OUTPUT" + echo 'array=["value 1", "value 2"]' >> "$FORGEJO_OUTPUT" + echo 'matrix={"dimension-1": ["d1 v1", "d1 v2"], "dimension-2": ["d2 v1", "d2 v2"]}' >> "$GITHUB_OUTPUT" + + scalar-job: + runs-on: docker + needs: define-matrix + strategy: + matrix: + scalar: + - "${{ needs.define-matrix.outputs.scalar-value }}" + - hard-coded value + steps: + - run: | + set -x + [ "${{ matrix.scalar }}" = "scalar value" ] || [ "${{ matrix.scalar }}" = "hard-coded value" ] || exit 1 + + array-job: + runs-on: docker + needs: define-matrix + strategy: + matrix: + array: ${{ fromJSON(needs.define-matrix.outputs.array-value) }} + steps: + - run: | + set -x + [ "${{ matrix.array }}" = "value 1" ] || [ "${{ matrix.array }}" = "value 2" ] || exit 1 + + matrix-job: + runs-on: docker + needs: define-matrix + strategy: + matrix: ${{ fromJSON(needs.define-matrix.outputs.matrix-value) }} + steps: + - run: | + set -x + [ "${{ matrix.dimension-1 }}" = "d1 v1" ] || [ "${{ matrix.dimension-1 }}" = "d1 v2" ] || exit 1 + [ "${{ matrix.dimension-2 }}" = "d2 v1" ] || [ "${{ matrix.dimension-2 }}" = "d2 v2" ] || exit 1 diff --git a/actions/example-matrix-dynamic/run.sh b/actions/example-matrix-dynamic/run.sh new file mode 100644 index 00000000..18b8fc05 --- /dev/null +++ b/actions/example-matrix-dynamic/run.sh @@ -0,0 +1,10 @@ +forgejo-test-helper.sh run_workflow actions/example-$example $url root example-$example setup-forgejo $token + +# Verify that the matrix in the job was expanded correctly by checking that +# there are 9 completed jobs, by their commit statuses being present on the +# main branch's HEAD. +api=$url/api/v1 +sha=$(forgejo-curl.sh api_json $api/repos/root/example-matrix-dynamic/branches/main | jq -r ".commit.id") +num_runs=$(forgejo-curl.sh api_json $api/repos/root/example-matrix-dynamic/commits/$sha/status | jq ".total_count") +echo "Expecting 9 commit statuses, found $num_runs commit statuses" +test $num_runs = 9 diff --git a/actions/example-matrix/.forgejo/workflows/test.yml b/actions/example-matrix/.forgejo/workflows/test.yml new file mode 100644 index 00000000..34de0a59 --- /dev/null +++ b/actions/example-matrix/.forgejo/workflows/test.yml @@ -0,0 +1,12 @@ +on: [push] +jobs: + test: + runs-on: docker + name: name-${{ matrix.version }} + strategy: + matrix: + version: [1.18, 1.19] + steps: + - run: | + set -x + test "${{ matrix.version }}" diff --git a/actions/example-needs/.forgejo/workflows/test.yml b/actions/example-needs/.forgejo/workflows/test.yml new file mode 100644 index 00000000..d38a1e75 --- /dev/null +++ b/actions/example-needs/.forgejo/workflows/test.yml @@ -0,0 +1,19 @@ +on: [push] +jobs: + job1: + runs-on: docker + outputs: + job1output: ${{ steps.step1.outputs.value }} + steps: + - id: step1 + run: | + set -x + echo "value=value1" >> $FORGEJO_OUTPUT + + job2: + needs: [job1] + runs-on: docker + steps: + - run: | + set -x + test "${{ needs.job1.outputs.job1output }}" = "value1" diff --git a/actions/example-post-7-0-schedule/.forgejo/workflows/test.yml b/actions/example-post-7-0-schedule/.forgejo/workflows/test.yml index ee7c233c..94eb4961 100644 --- a/actions/example-post-7-0-schedule/.forgejo/workflows/test.yml +++ b/actions/example-post-7-0-schedule/.forgejo/workflows/test.yml @@ -6,18 +6,18 @@ jobs: test: runs-on: ${{ vars.TEST_SCHEDULE_RUNSON }} container: - image: code.forgejo.org/oci/debian:bookworm + image: data.forgejo.org/oci/debian:trixie options: "--volume /srv/example:/srv/example" steps: - - run: | - echo "TEST_SCHEDULE_RUNSON=${{ vars.TEST_SCHEDULE_RUNSON }}" - touch /srv/example/post-7-0-schedule-volume/DONE - - name: save context run: | - d=/srv/example/post-7-0-schedule/contexts/$GITHUB_EVENT_NAME + d=/srv/example/post-7-0-schedule/contexts/$FORGEJO_EVENT_NAME mkdir -p $d cat > $d/github <<'EOF' ${{ toJSON(github) }} - EOF \ No newline at end of file + EOF + + - run: | + echo "TEST_SCHEDULE_RUNSON=${{ vars.TEST_SCHEDULE_RUNSON }}" + touch /srv/example/post-7-0-schedule-volume/DONE diff --git a/actions/example-post-7-0-schedule/run.sh b/actions/example-post-7-0-schedule/run.sh index e6e13094..29617c17 100755 --- a/actions/example-post-7-0-schedule/run.sh +++ b/actions/example-post-7-0-schedule/run.sh @@ -10,7 +10,7 @@ forgejo-curl.sh web --form name=TEST_SCHEDULE_RUNSON --form data=docker http://$ # See https://codeberg.org/forgejo/forgejo/pulls/1941 for more information # function verify_ref() { - local ref=$(sqlite3 $DIR/forgejo-work-path/forgejo.db 'select ref from action_schedule') + local ref=$(sqlite3 $DIR/forgejo-work-path/forgejo.db 'select ref from action_schedule') test "${ref##*/}" = "main" } verify_ref @@ -19,12 +19,12 @@ forgejo-curl.sh api_json --data '{"new_branch_name":"zzzz"}' $api/repos/root/exa verify_ref # runs once per minute, give it three minutes max before declaring failure -if ! RETRY_DELAYS="30 30 30 30 30 30" forgejo.sh retry test -f /srv/example/post-7-0-schedule-volume/DONE ; then +if ! RETRY_DELAYS="30 30 30 30 30 30" forgejo.sh retry test -f /srv/example/post-7-0-schedule-volume/DONE; then cat $FORGEJO_RUNNER_LOGS false fi c=/srv/example/post-7-0-schedule/contexts/schedule/github cat $c -test "schedule" = "$(jq -r .event_name < $c)" -test "schedule" = "$(jq -r .event.action < $c)" \ No newline at end of file +test "schedule" = "$(jq -r .event_name <$c)" +test "schedule" = "$(jq -r .event.action <$c)" diff --git a/actions/example-post-7-0-schedule/setup.sh b/actions/example-post-7-0-schedule/setup.sh index 9e170739..5592dbeb 100755 --- a/actions/example-post-7-0-schedule/setup.sh +++ b/actions/example-post-7-0-schedule/setup.sh @@ -1 +1 @@ -mkdir -p /srv/example/post-7-0-schedule-volume \ No newline at end of file +mkdir -p /srv/example/post-7-0-schedule-volume diff --git a/actions/example-private-workflow-call/.forgejo/workflows/reusable.yaml b/actions/example-private-workflow-call/.forgejo/workflows/reusable.yaml new file mode 100644 index 00000000..48832449 --- /dev/null +++ b/actions/example-private-workflow-call/.forgejo/workflows/reusable.yaml @@ -0,0 +1,10 @@ +on: + workflow_call: + +jobs: + build: + runs-on: "docker" + container: + image: data.forgejo.org/oci/node:24-trixie + steps: + - run: echo 'OK' diff --git a/actions/example-private-workflow-call/.forgejo/workflows/test.yaml b/actions/example-private-workflow-call/.forgejo/workflows/test.yaml new file mode 100644 index 00000000..9bb279b3 --- /dev/null +++ b/actions/example-private-workflow-call/.forgejo/workflows/test.yaml @@ -0,0 +1,11 @@ +on: + push: + +jobs: + test: + # `runs-on` disables workflow expansion. We want that in this case, because then Forgejo Runner has to authenticate + # itself to access the reusable workflow. + runs-on: docker + container: + image: data.forgejo.org/oci/node:24-trixie + uses: ./.forgejo/workflows/reusable.yaml diff --git a/actions/example-private-workflow-call/run.sh b/actions/example-private-workflow-call/run.sh new file mode 100644 index 00000000..e71dc991 --- /dev/null +++ b/actions/example-private-workflow-call/run.sh @@ -0,0 +1,42 @@ +api="$url/api/v1" +export d=/srv/example/private-workflow-call + +function main() { + mkdir -p "$d" + + local repo + repo="root/example-$example" + + forgejo-test-helper.sh push_workflow "actions/example-$example" "$url" root "example-$example" setup-forgejo "$token" + + # push_workflow creates the repository and triggers a first workflow run. Wait for it to succeed. Ensures that the + # workflow is valid. + local sha + sha="$(forgejo-test-helper.sh branch_tip "$url" "$repo" main)" + forgejo-test-helper.sh wait_success "$url" "$repo" "$sha" + + # Make the repository private. That is necessary to verify that Forgejo Runner includes the correct credentials when + # cloning the workflow. + forgejo-curl.sh api_json -X PATCH --data-raw '{"private":true}' "$api/repos/root/example-$example" + + # Create a new commit that triggers a new workflow run that can be identified uniquely. + ( + cd "$d" || exit 1 + git clone "$url/root/example-$example" + cd "example-$example" || exit 1 + git config user.email root@example.com + git config user.name username + echo "A new file" > test.txt + git add . + git commit -m 'Commit a new file' + git push + ) + + # Wait for the workflow pulled from the private repository to succeed. + local new_sha + new_sha="$(forgejo-test-helper.sh branch_tip "$url" "$repo" main)" + [[ "$new_sha" != "$sha" ]] || exit 1 + forgejo-test-helper.sh wait_success "$url" "$repo" "$new_sha" +} + +main diff --git a/actions/example-private-workflow-call/setup.sh b/actions/example-private-workflow-call/setup.sh new file mode 100644 index 00000000..fd443948 --- /dev/null +++ b/actions/example-private-workflow-call/setup.sh @@ -0,0 +1 @@ +mkdir -p /srv/example/private-workflow-call diff --git a/actions/example-pull-request/.forgejo/workflows/test.yml b/actions/example-pull-request/.forgejo/workflows/test.yml index 772a38f8..34a915a0 100644 --- a/actions/example-pull-request/.forgejo/workflows/test.yml +++ b/actions/example-pull-request/.forgejo/workflows/test.yml @@ -9,7 +9,7 @@ jobs: test: runs-on: docker container: - image: code.forgejo.org/oci/node:20-bookworm + image: data.forgejo.org/oci/node:20-bookworm options: "--volume /srv/example:/srv/example" steps: @@ -17,45 +17,45 @@ jobs: shell: bash run: | set -x - test $GITHUB_TOKEN = ${{ env.GITHUB_TOKEN }} - test $GITHUB_TOKEN = ${{ github.token }} + test $FORGEJO_TOKEN = ${{ env.FORGEJO_TOKEN }} + test $FORGEJO_TOKEN = ${{ forgejo.token }} export DEBIAN_FRONTEND=noninteractive ; apt-get -qq update ; apt-get install -y -qq curl git >& /dev/null curl -sS -o /usr/local/bin/forgejo-curl.sh https://code.forgejo.org/forgejo/forgejo-curl/raw/branch/main/forgejo-curl.sh && chmod +x /usr/local/bin/forgejo-curl.sh - forgejo-curl.sh --token "$GITHUB_TOKEN" login $GITHUB_SERVER_URL - forgejo-curl.sh api_json $GITHUB_SERVER_URL/api/v1/user + forgejo-curl.sh --token "$FORGEJO_TOKEN" login $FORGEJO_SERVER_URL + forgejo-curl.sh api_json $FORGEJO_SERVER_URL/api/v1/user - name: determine if the PR is from a fork id: forked run: | - if test ${{ github.event.pull_request.base.repo.full_name }} = ${{ github.event.pull_request.head.repo.full_name }} ; then - echo value=false >> $GITHUB_OUTPUT + if test ${{ forgejo.event.pull_request.base.repo.full_name }} = ${{ forge.event.pull_request.head.repo.full_name }} ; then + echo value=false >> $FORGEJO_OUTPUT else - echo value=true >> $GITHUB_OUTPUT + echo value=true >> $FORGEJO_OUTPUT fi # See also actions/example-context/.forgejo/workflows/test.yml - - name: env.GITHUB_BASE_REF + - name: env.FORGEJO_BASE_REF run: | set -x - test "$GITHUB_BASE_REF" = main - test "$GITHUB_BASE_REF" = "${{ env.GITHUB_BASE_REF }}" + test "$FORGEJO_BASE_REF" = main + test "$FORGEJO_BASE_REF" = "${{ env.FORGEJO_BASE_REF }}" # See also actions/example-context/.forgejo/workflows/test.yml - - name: env.GITHUB_HEAD_REF + - name: env.FORGEJO_HEAD_REF run: | set -x if ${{ steps.forked.outputs.value }} ; then - test "$GITHUB_HEAD_REF" = main + test "$FORGEJO_HEAD_REF" = main else - test "$GITHUB_HEAD_REF" = other + test "$FORGEJO_HEAD_REF" = other fi - test "$GITHUB_HEAD_REF" = "${{ env.GITHUB_HEAD_REF }}" + test "$FORGEJO_HEAD_REF" = "${{ env.FORGEJO_HEAD_REF }}" - name: secrets shell: bash run: | set -x - case $GITHUB_EVENT_NAME in + case $FORGEJO_EVENT_NAME in pull_request_target) # # all PRs: secrets @@ -76,7 +76,7 @@ jobs: fi ;; *) - echo unexpected event $GITHUB_EVENT_NAME + echo unexpected event $FORGEJO_EVENT_NAME false ;; esac @@ -95,9 +95,9 @@ jobs: # # create an issue # - base_repo=${{ github.event.pull_request.base.repo.full_name }} - forgejo-curl.sh api_json --data-raw '{"title":"ISSUE"}' $GITHUB_SERVER_URL/api/v1/repos/$base_repo/issues - url=$(echo $GITHUB_SERVER_URL | sed -e "s|://|://$GITHUB_TOKEN@|") + base_repo=${{ forgejo.event.pull_request.base.repo.full_name }} + forgejo-curl.sh api_json --data-raw '{"title":"ISSUE"}' $FORGEJO_SERVER_URL/api/v1/repos/$base_repo/issues + url=$(echo $FORGEJO_SERVER_URL | sed -e "s|://|://$FORGEJO_TOKEN@|") git clone $url/$base_repo base branch=B$RANDOM ( @@ -108,7 +108,7 @@ jobs: echo CHANGE >> README git add . git commit -m 'change' - case $GITHUB_EVENT_NAME in + case $FORGEJO_EVENT_NAME in pull_request_target|pull_request) # # repository write scope via http git passthrough @@ -117,15 +117,15 @@ jobs: # # repository write scope via the API # - assert_fail_if_forked forgejo-curl.sh api_json --data-raw '{"title":"PR","base":"main","head":"'$branch'"}' $GITHUB_SERVER_URL/api/v1/repos/$base_repo/pulls - assert_fail_if_forked forgejo-curl.sh api_json --data-raw '{"color":"#ffffff","name":"labelname"}' $GITHUB_SERVER_URL/api/v1/repos/$base_repo/labels + assert_fail_if_forked forgejo-curl.sh api_json --data-raw '{"title":"PR","base":"main","head":"'$branch'"}' $FORGEJO_SERVER_URL/api/v1/repos/$base_repo/pulls + assert_fail_if_forked forgejo-curl.sh api_json --data-raw '{"color":"#ffffff","name":"labelname"}' $FORGEJO_SERVER_URL/api/v1/repos/$base_repo/labels # # See https://codeberg.org/forgejo/forgejo/issues/1525 # - ! forgejo-curl.sh api_json --data-raw '{"new_branch_name":"B'$RANDOM'"}' $GITHUB_SERVER_URL/api/v1/repos/$base_repo/branches + ! forgejo-curl.sh api_json --data-raw '{"new_branch_name":"B'$RANDOM'"}' $FORGEJO_SERVER_URL/api/v1/repos/$base_repo/branches ;; *) - echo unexpected event $GITHUB_EVENT_NAME + echo unexpected event $FORGEJO_EVENT_NAME false ;; esac @@ -133,17 +133,17 @@ jobs: - name: save event run: | - d=/srv/example/pull-request/contexts/${{ github.event.pull_request.head.repo.owner.username }}/$GITHUB_EVENT_NAME + d=/srv/example/pull-request/contexts/${{ forgejo.event.pull_request.head.repo.owner.username }}/$FORGEJO_EVENT_NAME mkdir -p $d cat > $d/github <<'EOF' ${{ toJSON(github) }} EOF - - uses: https://code.forgejo.org/actions/checkout@v4 + - uses: https://data.forgejo.org/actions/checkout@v4 - name: checkout the default branch if pull_request_target run: | set -x - case $GITHUB_EVENT_NAME in + case $FORGEJO_EVENT_NAME in pull_request_target) ! test -f file-unique-to-the-pr-branch ;; @@ -151,7 +151,7 @@ jobs: test -f file-unique-to-the-pr-branch ;; *) - echo unexpected event $GITHUB_EVENT_NAME + echo unexpected event $FORGEJO_EVENT_NAME false ;; esac diff --git a/actions/example-pull-request/assert-contexts.sh b/actions/example-pull-request/assert-contexts.sh index 57f02571..83cd6606 100755 --- a/actions/example-pull-request/assert-contexts.sh +++ b/actions/example-pull-request/assert-contexts.sh @@ -4,8 +4,8 @@ set -ex c=$d/contexts -test opened = "$(jq -r .event.action < $c/fork-org/pull_request/github)" -test opened = "$(jq -r .event.action < $c/fork-org/pull_request_target/github)" +test opened = "$(jq -r .event.action <$c/fork-org/pull_request/github)" +test opened = "$(jq -r .event.action <$c/fork-org/pull_request_target/github)" -test opened = "$(jq -r .event.action < $c/root/pull_request/github)" -test opened = "$(jq -r .event.action < $c/root/pull_request_target/github)" +test opened = "$(jq -r .event.action <$c/root/pull_request/github)" +test opened = "$(jq -r .event.action <$c/root/pull_request_target/github)" diff --git a/actions/example-pull-request/run.sh b/actions/example-pull-request/run.sh index a262e6f4..de54e37c 100755 --- a/actions/example-pull-request/run.sh +++ b/actions/example-pull-request/run.sh @@ -12,45 +12,44 @@ function main() { forgejo-curl.sh api_json --data-raw '{"organization":"fork-org"}' $api/repos/root/example-pull-request/forks forgejo-curl.sh api_json -X PUT --data-raw '{"data":"AAAA"}' $api/repos/root/example-pull-request/actions/secrets/SECRET - ( - cd $d - git clone $url/fork-org/example-pull-request fork - cd fork - git config user.email root@example.com - git config user.name username - echo fork $PROOF >> README - touch file-unique-to-the-pr-branch - git add . - git commit -m 'fork change' - git push + cd $d + git clone $url/fork-org/example-pull-request fork + cd fork + git config user.email root@example.com + git config user.name username + echo fork $PROOF >>README + touch file-unique-to-the-pr-branch + git add . + git commit -m 'fork change' + git push ) forgejo.sh retry forgejo-curl.sh api_json --data-raw '{"title":"PR from fork","base":"main","head":"fork-org:main"}' $api/repos/root/example-pull-request/pulls ( - cd $d - git clone $url/root/example-pull-request - cd example-pull-request - git checkout -b other - git config user.email root@example.com - git config user.name username - touch file-unique-to-the-pr-branch - echo other $PROOF >> README - git add . - git commit -m 'other change' - git push --force -u origin other + cd $d + git clone $url/root/example-pull-request + cd example-pull-request + git checkout -b other + git config user.email root@example.com + git config user.name username + touch file-unique-to-the-pr-branch + echo other $PROOF >>README + git add . + git commit -m 'other change' + git push --force -u origin other ) forgejo.sh retry forgejo-curl.sh api_json --data-raw '{"title":"PR same repo","base":"main","head":"other"}' $api/repos/root/example-pull-request/pulls export RETRY_DELAYS="60 60 60 60 60 60 60" - for assert in $EXAMPLE_DIR/assert-*.sh ; do - if ! forgejo.sh retry $assert ; then - find $d - sed -e 's/^/[RUNNER LOGS]/' < $FORGEJO_RUNNER_LOGS - false - fi + for assert in $EXAMPLE_DIR/assert-*.sh; do + if ! forgejo.sh retry $assert; then + find $d + sed -e 's/^/[RUNNER LOGS]/' <$FORGEJO_RUNNER_LOGS + false + fi done } diff --git a/actions/example-pull-request/setup.sh b/actions/example-pull-request/setup.sh index 72c13c02..5f469629 100755 --- a/actions/example-pull-request/setup.sh +++ b/actions/example-pull-request/setup.sh @@ -1,2 +1 @@ mkdir -p /srv/example/pull-request - diff --git a/actions/example-push-cancel/run.sh b/actions/example-push-cancel/run.sh index dbdebb4c..891798ed 100755 --- a/actions/example-push-cancel/run.sh +++ b/actions/example-push-cancel/run.sh @@ -11,7 +11,7 @@ forgejo-test-helper.sh wait_running $url $repo $sha # # push to the same branch # -forgejo-test-helper.sh push_workflow actions/example-$example $url root example-$example setup-forgejo $token +forgejo-test-helper.sh push_workflow actions/example-echo $url root example-$example setup-forgejo $token # # wait for the workflow to be canceled as a result of the previous push # diff --git a/actions/example-push/.forgejo/workflows/test.yml b/actions/example-push/.forgejo/workflows/test.yml index 89763f29..ebf53d1b 100644 --- a/actions/example-push/.forgejo/workflows/test.yml +++ b/actions/example-push/.forgejo/workflows/test.yml @@ -9,14 +9,14 @@ jobs: test: runs-on: docker container: - image: code.forgejo.org/oci/node:20-bookworm + image: data.forgejo.org/oci/node:20-bookworm volumes: - /srv/example:/srv/example steps: - name: save event run: | - d=/srv/example/push/contexts/$GITHUB_EVENT_NAME + d=/srv/example/push/contexts/$FORGEJO_EVENT_NAME mkdir -p $d cat > $d/github <<'EOF' ${{ toJSON(github) }} diff --git a/actions/example-schedule-noncancel/.forgejo/workflows/schedule_continue.yml b/actions/example-schedule-noncancel/.forgejo/workflows/schedule_continue.yml new file mode 100644 index 00000000..7cc5bdb3 --- /dev/null +++ b/actions/example-schedule-noncancel/.forgejo/workflows/schedule_continue.yml @@ -0,0 +1,15 @@ +on: + schedule: + - cron: "* * * * *" +jobs: + test: + runs-on: docker + container: + image: data.forgejo.org/oci/debian:trixie + volumes: + - /srv/example:/srv/example + steps: + - run: | + while ! [ -f /srv/example/schedule-noncancel/PUSHED ]; do + sleep 3 + done diff --git a/actions/example-schedule-noncancel/run.sh b/actions/example-schedule-noncancel/run.sh new file mode 100755 index 00000000..b3756bf9 --- /dev/null +++ b/actions/example-schedule-noncancel/run.sh @@ -0,0 +1,99 @@ +repo=root/example-$example +# +# delete the repository +# +api=$url/api/v1 +if forgejo-curl.sh api_json -X GET $api/repos/root/example-$example; then + forgejo-curl.sh api_json -X DELETE $api/repos/root/example-$example +fi + +# +# push the repository +# +forgejo-test-helper.sh push_workflow actions/example-$example $url root example-$example setup-forgejo $token + +# +# get the run id of the workflow that just started +# +getScheduleRun() { + rm -f $DIR/forgejo-work-path/forgejo.copy.db + cp $DIR/forgejo-work-path/forgejo.db $DIR/forgejo-work-path/forgejo.copy.db + sqlite3 $DIR/forgejo-work-path/forgejo.copy.db \ + "pragma busy_timeout = 5000; \ + select action_run.id \ + from action_run \ + inner join action_schedule on action_run.schedule_id = action_schedule.id \ + inner join repository on action_schedule.repo_id = repository.id \ + where repository.name = 'example-schedule-noncancel' \ + order by action_run.created desc limit 1" | sed '2q;d' +} + +run_id=$(getScheduleRun) +while [ -z $run_id ]; do + echo waiting 5... + sleep 5 + run_id=$(getScheduleRun) +done + +echo Schedule run id: $run_id + +# +# Wait for it to be started +# +checkStarted() { + rm -f $DIR/forgejo-work-path/forgejo.copy.db + cp $DIR/forgejo-work-path/forgejo.db $DIR/forgejo-work-path/forgejo.copy.db + sqlite3 $DIR/forgejo-work-path/forgejo.copy.db \ + "pragma busy_timeout = 5000; \ + select id \ + from action_run \ + where id = $run_id \ + and started is not null" | sed '2q;d' +} + +started_check=$(checkStarted) +while [ -z $started_check ]; do + echo waiting 2... + sleep 2 + started_check=$(checkStarted) +done + +echo Run has started +echo Push to repo again + +# +# Push to the repo again +# +forgejo-test-helper.sh push_workflow actions/example-echo $url root example-$example setup-forgejo $token + +echo Signal to the workflow that the push has happened +mkdir -p /srv/example/schedule-noncancel +touch /srv/example/schedule-noncancel/PUSHED + +# +# Wait for the workflow to finish anyway +# +echo Wait for workflow to finish + +checkFinished() { + rm -f $DIR/forgejo-work-path/forgejo.copy.db + cp $DIR/forgejo-work-path/forgejo.db $DIR/forgejo-work-path/forgejo.copy.db + sqlite3 $DIR/forgejo-work-path/forgejo.copy.db \ + "pragma busy_timeout = 5000; \ + select status \ + from action_run \ + where id = $run_id \ + and (status != 6 and status != 5)" | sed '2q;d' +} + +finished_status=$(checkFinished) +while [ -z $finished_status ]; do + echo waiting 5... + sleep 5 + finished_status=$(checkFinished) +done + +echo Workflow finished. +rm -f $DIR/forgejo-work-path/forgejo.copy.db + +test $finished_status = 1 diff --git a/actions/example-schedule-noncancel/teardown.sh b/actions/example-schedule-noncancel/teardown.sh new file mode 100644 index 00000000..ae9987a3 --- /dev/null +++ b/actions/example-schedule-noncancel/teardown.sh @@ -0,0 +1,4 @@ +# +# this will effectively discard any linger workflow so they do not interfere with other tests +# +forgejo-runner.sh reload diff --git a/actions/example-service/.forgejo/workflows/test.yml b/actions/example-service/.forgejo/workflows/test.yml index 014653aa..11132c96 100644 --- a/actions/example-service/.forgejo/workflows/test.yml +++ b/actions/example-service/.forgejo/workflows/test.yml @@ -8,7 +8,7 @@ jobs: runs-on: docker services: pgsql: - image: code.forgejo.org/oci/postgres:15 + image: data.forgejo.org/oci/postgres:15 env: POSTGRES_DB: test POSTGRES_PASSWORD: postgres @@ -23,11 +23,11 @@ jobs: simple: runs-on: docker container: - image: code.forgejo.org/oci/debian:bookworm + image: data.forgejo.org/oci/debian:trixie services: pgsql: - image: code.forgejo.org/oci/postgres:15 + image: data.forgejo.org/oci/postgres:15 env: POSTGRES_DB: test POSTGRES_PASSWORD: postgres @@ -43,7 +43,7 @@ jobs: needs: [simple] runs-on: docker container: - image: code.forgejo.org/oci/debian:bookworm + image: data.forgejo.org/oci/debian:trixie options: "--volume /srv/example-service-volume-valid:/srv/example-service-volume-valid --volume /srv/example-service-volume-invalid:/srv/example-service-volume-invalid" steps: @@ -58,12 +58,12 @@ jobs: needs: [volume-on-step] runs-on: docker container: - image: code.forgejo.org/oci/debian:bookworm + image: data.forgejo.org/oci/debian:trixie options: "--volume /srv/example-service-volume-valid:/srv/example-service-volume-valid" services: myservice: - image: code.forgejo.org/oci/debian:bookworm + image: data.forgejo.org/oci/debian:trixie options: "--volume /srv/example-service-volume-valid:/srv/example-service-volume-valid" cmd: ["bash", "-c", "echo -n SUCCESS > /srv/example-service-volume-valid ; sleep infinity"] diff --git a/actions/example-service/runner-config.yaml b/actions/example-service/runner-config.yaml index 27981abe..c931a240 100644 --- a/actions/example-service/runner-config.yaml +++ b/actions/example-service/runner-config.yaml @@ -1,6 +1,6 @@ log: - level: info + level: debug runner: file: .runner diff --git a/actions/example-service/setup.sh b/actions/example-service/setup.sh index 3a9674ef..7bc1672a 100755 --- a/actions/example-service/setup.sh +++ b/actions/example-service/setup.sh @@ -1,3 +1,3 @@ -> /srv/example-service-volume-valid -> /srv/example-service-volume-invalid +>/srv/example-service-volume-valid +>/srv/example-service-volume-invalid FORGEJO_RUNNER_CONFIG=$EXAMPLE_DIR/runner-config.yaml forgejo-runner.sh reload diff --git a/actions/example-shell/.forgejo/workflows/test.yml b/actions/example-shell/.forgejo/workflows/test.yml new file mode 100644 index 00000000..5dad0b6e --- /dev/null +++ b/actions/example-shell/.forgejo/workflows/test.yml @@ -0,0 +1,87 @@ +on: [push] + +env: + ASSERT_SHELL: 'set -x ; readlink /proc/$$/exe ; readlink /proc/$$/exe | grep ' + +jobs: + default: + # docker:docker://code.forgejo.org/oci/node:22-bookworm + runs-on: docker + steps: + - name: default is bash + run: | + ${{ env.ASSERT_SHELL }} /bash + + sh-fallback: + needs: [default] + # alpine:docker://code.forgejo.org/oci/alpine:latest + runs-on: alpine + steps: + - name: default is bash but with a fallback to sh in case it does not exist + run: | + ${{ env.ASSERT_SHELL }} /busybox + + sh-fallback-with-container: + needs: [sh-fallback] + runs-on: docker + container: + image: data.forgejo.org/oci/alpine:latest + steps: + - name: default is bash but with a fallback to sh in case it does not exist + run: | + ${{ env.ASSERT_SHELL }} /busybox + + defaults-run: + needs: [sh-fallback-with-container] + # alpine:docker://code.forgejo.org/oci/alpine:latest + runs-on: alpine + defaults: + run: + shell: sh + steps: + - name: default is sh which is an alias for busybox in alpine + run: | + ${{ env.ASSERT_SHELL }} /busybox + + python: + needs: [alpine] + runs-on: docker + container: + image: data.forgejo.org/oci/python:slim + steps: + - name: python => python {0} + shell: python + run: | + print("something") + + other: + needs: [python] + runs-on: docker + container: + image: data.forgejo.org/oci/node:22-bookworm + steps: + - name: default is bash + run: | + ${{ env.ASSERT_SHELL }} /bash + + - name: bash => bash --noprofile --norc -e -o pipefail {0} + shell: bash + run: | + ${{ env.ASSERT_SHELL }} /bash + shopt -o + shopt -o | grep --quiet 'pipefail.*on' + + - name: sh => sh -e {0} + shell: sh + run: | + ${{ env.ASSERT_SHELL }} /dash + + - name: node => node {0} + shell: node + run: | + console.log("something") + + - name: dash -e {0} + shell: dash -e {0} + run: | + ${{ env.ASSERT_SHELL }} /dash diff --git a/actions/example-shell/runner-config.yaml b/actions/example-shell/runner-config.yaml new file mode 100644 index 00000000..4e4974d2 --- /dev/null +++ b/actions/example-shell/runner-config.yaml @@ -0,0 +1,32 @@ + +log: + level: debug + +runner: + file: .runner + capacity: 1 + env_file: .env + timeout: 3h + insecure: false + fetch_timeout: 5s + fetch_interval: 2s + labels: + - docker:docker://code.forgejo.org/oci/node:22-bookworm + - alpine:docker://code.forgejo.org/oci/alpine:latest + +cache: + enabled: false + dir: "" + host: "" + port: 0 + +container: + network: "" + privileged: false + options: + workdir_parent: + valid_volumes: [] + docker_host: "" + +host: + workdir_parent: diff --git a/actions/example-shell/setup.sh b/actions/example-shell/setup.sh new file mode 100755 index 00000000..9c1f5adf --- /dev/null +++ b/actions/example-shell/setup.sh @@ -0,0 +1 @@ +FORGEJO_RUNNER_CONFIG=$EXAMPLE_DIR/runner-config.yaml forgejo-runner.sh reload diff --git a/actions/example-shell/teardown.sh b/actions/example-shell/teardown.sh new file mode 100755 index 00000000..b410c513 --- /dev/null +++ b/actions/example-shell/teardown.sh @@ -0,0 +1 @@ +forgejo-runner.sh reload diff --git a/actions/example-tag/.forgejo/workflows/test.yml b/actions/example-tag/.forgejo/workflows/test.yml index c7e13570..1a2e4b91 100644 --- a/actions/example-tag/.forgejo/workflows/test.yml +++ b/actions/example-tag/.forgejo/workflows/test.yml @@ -7,14 +7,14 @@ jobs: test: runs-on: docker container: - image: code.forgejo.org/oci/node:20-bookworm + image: data.forgejo.org/oci/node:20-bookworm volumes: - /srv/example:/srv/example steps: - name: save event run: | - d=/srv/example/tag/contexts/$GITHUB_EVENT_NAME + d=/srv/example/tag/contexts/$FORGEJO_EVENT_NAME mkdir -p $d cat > $d/github <<'EOF' ${{ toJSON(github) }} diff --git a/actions/example-with-docker-host/.forgejo/workflows/test.yml b/actions/example-with-docker-host/.forgejo/workflows/test.yml new file mode 100644 index 00000000..454a10da --- /dev/null +++ b/actions/example-with-docker-host/.forgejo/workflows/test.yml @@ -0,0 +1,10 @@ +on: [push] + +jobs: + build: + runs-on: docker + container: + image: data.forgejo.org/oci/docker:28-cli + steps: + - run: ls -l /var/run/docker.sock + - run: docker ps diff --git a/actions/example-with-docker-host/runner-config.yaml b/actions/example-with-docker-host/runner-config.yaml new file mode 100644 index 00000000..839de20b --- /dev/null +++ b/actions/example-with-docker-host/runner-config.yaml @@ -0,0 +1,30 @@ + +log: + level: debug + +runner: + file: .runner + capacity: 1 + env_file: .env + timeout: 3h + insecure: false + fetch_timeout: 5s + fetch_interval: 2s + labels: ["docker:docker://code.forgejo.org/oci/node:20-bookworm"] + +cache: + enabled: true + dir: "/srv/example/cache" + host: "" + port: 0 + +container: + network: "bridge" + privileged: false + options: + workdir_parent: + valid_volumes: ["/srv/example"] + docker_host: "unix:///var/run/docker.sock" + +host: + workdir_parent: diff --git a/actions/example-with-docker-host/setup.sh b/actions/example-with-docker-host/setup.sh new file mode 100755 index 00000000..9c1f5adf --- /dev/null +++ b/actions/example-with-docker-host/setup.sh @@ -0,0 +1 @@ +FORGEJO_RUNNER_CONFIG=$EXAMPLE_DIR/runner-config.yaml forgejo-runner.sh reload diff --git a/actions/example-with-docker-host/teardown.sh b/actions/example-with-docker-host/teardown.sh new file mode 100755 index 00000000..b410c513 --- /dev/null +++ b/actions/example-with-docker-host/teardown.sh @@ -0,0 +1 @@ +forgejo-runner.sh reload diff --git a/actions/example-with-docker-socket/.forgejo/workflows/test.yml b/actions/example-with-docker-socket/.forgejo/workflows/test.yml new file mode 100644 index 00000000..454a10da --- /dev/null +++ b/actions/example-with-docker-socket/.forgejo/workflows/test.yml @@ -0,0 +1,10 @@ +on: [push] + +jobs: + build: + runs-on: docker + container: + image: data.forgejo.org/oci/docker:28-cli + steps: + - run: ls -l /var/run/docker.sock + - run: docker ps diff --git a/actions/example-with-docker-socket/runner-config.yaml b/actions/example-with-docker-socket/runner-config.yaml new file mode 100644 index 00000000..e09edaaa --- /dev/null +++ b/actions/example-with-docker-socket/runner-config.yaml @@ -0,0 +1,30 @@ + +log: + level: debug + +runner: + file: .runner + capacity: 1 + env_file: .env + timeout: 3h + insecure: false + fetch_timeout: 5s + fetch_interval: 2s + labels: ["docker:docker://code.forgejo.org/oci/node:20-bookworm"] + +cache: + enabled: true + dir: "/srv/example/cache" + host: "" + port: 0 + +container: + network: "bridge" + privileged: false + options: + workdir_parent: + valid_volumes: ["/srv/example"] + docker_host: "automount" + +host: + workdir_parent: diff --git a/actions/example-with-docker-socket/setup.sh b/actions/example-with-docker-socket/setup.sh new file mode 100755 index 00000000..9c1f5adf --- /dev/null +++ b/actions/example-with-docker-socket/setup.sh @@ -0,0 +1 @@ +FORGEJO_RUNNER_CONFIG=$EXAMPLE_DIR/runner-config.yaml forgejo-runner.sh reload diff --git a/actions/example-with-docker-socket/teardown.sh b/actions/example-with-docker-socket/teardown.sh new file mode 100755 index 00000000..b410c513 --- /dev/null +++ b/actions/example-with-docker-socket/teardown.sh @@ -0,0 +1 @@ +forgejo-runner.sh reload diff --git a/actions/example-with-docker-tcp/.forgejo/workflows/test.yml b/actions/example-with-docker-tcp/.forgejo/workflows/test.yml new file mode 100644 index 00000000..c4388ae8 --- /dev/null +++ b/actions/example-with-docker-tcp/.forgejo/workflows/test.yml @@ -0,0 +1,11 @@ +on: [push] + +jobs: + build: + runs-on: docker + container: + image: data.forgejo.org/oci/node:20-bookworm + steps: + - run: | + ! test -e /var/run/docker.sock + ! env | grep DOCKER_HOST diff --git a/actions/example-with-docker-tcp/runner-config.yaml b/actions/example-with-docker-tcp/runner-config.yaml new file mode 100644 index 00000000..730d9c88 --- /dev/null +++ b/actions/example-with-docker-tcp/runner-config.yaml @@ -0,0 +1,30 @@ + +log: + level: debug + +runner: + file: .runner + capacity: 1 + env_file: .env + timeout: 3h + insecure: false + fetch_timeout: 5s + fetch_interval: 2s + labels: ["docker:docker://code.forgejo.org/oci/node:20-bookworm"] + +cache: + enabled: true + dir: "/srv/example/cache" + host: "" + port: 0 + +container: + network: "bridge" + privileged: false + options: + workdir_parent: + valid_volumes: ["/srv/example"] + docker_host: "tcp://127.0.0.1:2375" + +host: + workdir_parent: diff --git a/actions/example-with-docker-tcp/setup.sh b/actions/example-with-docker-tcp/setup.sh new file mode 100755 index 00000000..9c1f5adf --- /dev/null +++ b/actions/example-with-docker-tcp/setup.sh @@ -0,0 +1 @@ +FORGEJO_RUNNER_CONFIG=$EXAMPLE_DIR/runner-config.yaml forgejo-runner.sh reload diff --git a/actions/example-with-docker-tcp/teardown.sh b/actions/example-with-docker-tcp/teardown.sh new file mode 100755 index 00000000..b410c513 --- /dev/null +++ b/actions/example-with-docker-tcp/teardown.sh @@ -0,0 +1 @@ +forgejo-runner.sh reload diff --git a/actions/example-without-docker-socket/.forgejo/workflows/test.yml b/actions/example-without-docker-socket/.forgejo/workflows/test.yml new file mode 100644 index 00000000..8d5c8371 --- /dev/null +++ b/actions/example-without-docker-socket/.forgejo/workflows/test.yml @@ -0,0 +1,6 @@ +on: [push] +jobs: + test: + runs-on: docker + steps: + - run: "! test -e /var/run/docker.sock" diff --git a/actions/example-workflow-call-expansion/.forgejo/workflows/reusable-layer-1.yml b/actions/example-workflow-call-expansion/.forgejo/workflows/reusable-layer-1.yml new file mode 100644 index 00000000..649392c1 --- /dev/null +++ b/actions/example-workflow-call-expansion/.forgejo/workflows/reusable-layer-1.yml @@ -0,0 +1,74 @@ +on: + workflow_call: + inputs: + input1: + required: true + type: string + input3: + required: true + type: string + outputs: + output1: + value: ${{ jobs.callee-1.outputs.job-output }} + output2: + value: ${{ jobs.callee-2.outputs.job-output }} + output3: + value: ${{ jobs.layer-2.outputs.output3 }} + output4: + value: ${{ jobs.layer-2.outputs.output4 }} + +jobs: + callee-1: + runs-on: docker + outputs: + job-output: callee-1-output + container: + image: data.forgejo.org/oci/node:22-bookworm + volumes: + - /srv/example:/srv/example + steps: + - name: verify workflow inputs + run: | + set -x + test "top-level-input1" = "${{ inputs.input1 }}" + test "dynamic output" = "${{ inputs.input3 }}" + - name: verify workflow secrets + run: | + set -x + test "AAAA" = "${{ secrets.secret1 }}" + test "BBBB1234" = "${{ secrets.secret2 }}" + test "" = "${{ secrets.secret3 }}" # wasn't specified to the workflow, should be absent + - name: indicate callee-1 hit + run: touch /srv/example/callee-1 + + layer-2: + needs: [callee-1] + uses: ./.forgejo/workflows/reusable-layer-2.yml + with: + input1: ${{ inputs.input1 }} + input2: mid-level-input2 + input3: ${{ inputs.input3 }} + input4: ${{ needs.callee-1.outputs.job-output }} + secrets: inherit + + callee-2: + needs: [callee-1, layer-2] + runs-on: docker + outputs: + job-output: callee-2-output + container: + image: data.forgejo.org/oci/node:22-bookworm + volumes: + - /srv/example:/srv/example + steps: + - name: verify callee-1 completed + run: | + set -x + test -f /srv/example/callee-1 + - name: verify layer-2 completed + run: | + set -x + test -f /srv/example/callee-3 + test -f /srv/example/callee-4 + - name: indicate callee-2 hit + run: touch /srv/example/callee-2 diff --git a/actions/example-workflow-call-expansion/.forgejo/workflows/reusable-layer-2.yml b/actions/example-workflow-call-expansion/.forgejo/workflows/reusable-layer-2.yml new file mode 100644 index 00000000..3b633ebd --- /dev/null +++ b/actions/example-workflow-call-expansion/.forgejo/workflows/reusable-layer-2.yml @@ -0,0 +1,63 @@ +on: + workflow_call: + inputs: + input1: + required: true + type: string + input2: + required: true + type: string + input3: + required: true + type: string + input4: + required: true + type: string + outputs: + output3: + value: ${{ jobs.callee-3.outputs.job-output }} + output4: + value: ${{ jobs.callee-4.outputs.job-output }} + +jobs: + callee-3: + runs-on: docker + outputs: + job-output: callee-3-output + container: + image: data.forgejo.org/oci/node:22-bookworm + volumes: + - /srv/example:/srv/example + steps: + - name: verify workflow inputs + run: | + set -x + test "top-level-input1" = "${{ inputs.input1 }}" + test "mid-level-input2" = "${{ inputs.input2 }}" + test "dynamic output" = "${{ inputs.input3 }}" + test "callee-1-output" = "${{ inputs.input4 }}" + - name: verify workflow secrets inherited + run: | + set -x + test "AAAA" = "${{ secrets.secret1 }}" + test "BBBB1234" = "${{ secrets.secret2 }}" + test "" = "${{ secrets.secret3 }}" # wasn't specified to the workflow, should be absent + - name: indicate callee-3 hit + run: touch /srv/example/callee-3 + + callee-4: + needs: callee-3 + runs-on: docker + outputs: + job-output: callee-4-output + container: + image: data.forgejo.org/oci/node:22-bookworm + volumes: + - /srv/example:/srv/example + steps: + - name: verify callee-3 completed + run: | + set -x + test -f /srv/example/callee-3 + - name: indicate callee-4 hit + run: touch /srv/example/callee-4 diff --git a/actions/example-workflow-call-expansion/.forgejo/workflows/test.yml b/actions/example-workflow-call-expansion/.forgejo/workflows/test.yml new file mode 100644 index 00000000..cd9290a2 --- /dev/null +++ b/actions/example-workflow-call-expansion/.forgejo/workflows/test.yml @@ -0,0 +1,53 @@ +on: + push: + +jobs: + pre-job: + runs-on: docker + container: + image: data.forgejo.org/oci/node:22-bookworm + outputs: + dynamic: "${{ steps.dynamic-step.outputs.dynamic }}" + steps: + - id: dynamic-step + run: echo "dynamic=dynamic output" >> $FORGEJO_OUTPUT + + layer-1: + needs: [pre-job] + uses: ./.forgejo/workflows/reusable-layer-1.yml + with: + input1: top-level-input1 + input3: ${{ needs.pre-job.outputs.dynamic }} + secrets: + secret1: AAAA + secret2: BBBB1234 + + verify: + needs: [layer-1] + runs-on: docker + container: + image: data.forgejo.org/oci/node:22-bookworm + volumes: + - /srv/example:/srv/example + steps: + - name: verify test config secret + run: | + set -x + # SECRET3 is set on the repo, but not passed into `reusable-layer-1.yml` so that we can test secrets don't + # leak into the workflow if they're not explicitly defined. This check verifies that the test environment has + # that secret, otherwise the test assertions that it isn't present within the workflow would be meaningless. + test "CCCC" = "${{ secrets.secret3 }}" + - name: verify callee-[0-4] completed + run: | + set -x + test -f /srv/example/callee-1 + test -f /srv/example/callee-2 + test -f /srv/example/callee-3 + test -f /srv/example/callee-4 + - name: verify workflow outputs + run: | + set -x + test "callee-1-output" = "${{ needs.layer-1.outputs.output1 }}" + test "callee-2-output" = "${{ needs.layer-1.outputs.output2 }}" + test "callee-3-output" = "${{ needs.layer-1.outputs.output3 }}" + test "callee-4-output" = "${{ needs.layer-1.outputs.output4 }}" diff --git a/actions/example-workflow-call-expansion/run.sh b/actions/example-workflow-call-expansion/run.sh new file mode 100644 index 00000000..07ca4cb7 --- /dev/null +++ b/actions/example-workflow-call-expansion/run.sh @@ -0,0 +1,12 @@ +repo=root/example-$example +api=$url/api/v1 + +# Prepare test repo +forgejo-test-helper.sh push_workflow actions/example-$example $url root example-$example setup-forgejo $token +sha=$(forgejo-test-helper.sh branch_tip $url $repo main) + +# Install a repo secret +forgejo-curl.sh api_json -X PUT --data-raw '{"data":"CCCC"}' $api/repos/$repo/actions/secrets/SECRET3 + +# Wait for action to complete +forgejo-test-helper.sh wait_success $url root/example-$example $sha diff --git a/actions/example-workflow-call/.forgejo/workflows/reusable.yml b/actions/example-workflow-call/.forgejo/workflows/reusable.yml new file mode 100644 index 00000000..6181aff6 --- /dev/null +++ b/actions/example-workflow-call/.forgejo/workflows/reusable.yml @@ -0,0 +1,35 @@ +on: + workflow_call: + inputs: + parameter1: + required: true + type: string + outputs: + output1: + value: ${{ jobs.callee.outputs.job-output }} + +jobs: + callee: + runs-on: docker + container: + image: data.forgejo.org/oci/node:22-bookworm + volumes: + - /srv/example:/srv/example + outputs: + job-output: ${{ steps.stepwithoutput.outputs.myvalue }} + steps: + + - id: stepwithoutput + run: | + set -x + test "${{ inputs.parameter1 }}" = "value1" + test "${{ secrets.secret }}" = "keep_it_private" + echo "myvalue=outputvalue1" >> $FORGEJO_OUTPUT + + - name: save event + run: | + d=/srv/example/push/contexts/$FORGEJO_EVENT_NAME + mkdir -p $d + cat > $d/github <<'EOF' + ${{ toJSON(github) }} + EOF diff --git a/actions/example-workflow-call/.forgejo/workflows/test.yml b/actions/example-workflow-call/.forgejo/workflows/test.yml new file mode 100644 index 00000000..fef61667 --- /dev/null +++ b/actions/example-workflow-call/.forgejo/workflows/test.yml @@ -0,0 +1,23 @@ +on: + push: + +jobs: + caller: + runs-on: docker + container: + image: data.forgejo.org/oci/node:22-bookworm + uses: ./.forgejo/workflows/reusable.yml + with: + parameter1: value1 + secrets: + secret: keep_it_private + + verify: + needs: [caller] + runs-on: docker + container: + image: data.forgejo.org/oci/node:22-bookworm + steps: + - run: | + set -x + test "${{ needs.caller.outputs.output1 }}" = "outputvalue1" diff --git a/actions/example-workflow-dispatch/.forgejo/workflows/test.yml b/actions/example-workflow-dispatch/.forgejo/workflows/test.yml new file mode 100644 index 00000000..3839f7b5 --- /dev/null +++ b/actions/example-workflow-dispatch/.forgejo/workflows/test.yml @@ -0,0 +1,57 @@ +on: + workflow_dispatch: + inputs: + logLevel: + description: 'Log Level' + required: true + default: 'warning' + type: choice + options: + - info + - warning + - debug + tags: + description: 'Test scenario tags' + required: false + type: boolean + boolean_default_true: + description: 'Test scenario tags' + required: true + type: boolean + default: true + boolean_default_false: + description: 'Test scenario tags' + required: false + type: boolean + default: false + number1_default: + description: 'Number w. default' + default: '100' + type: number + number2: + description: 'Number w/o. default' + type: number + string1_default: + description: 'String w. default' + default: 'Hello world' + type: string + string2: + description: 'String w/o. default' + required: true + type: string + +jobs: + test: + runs-on: docker + container: + image: data.forgejo.org/oci/debian:trixie + options: "--volume /srv/example:/srv/example" + + steps: + - name: save and display context + run: | + d=/srv/example/workflow-dispatch/contexts/$FORGEJO_EVENT_NAME + mkdir -p $d + tee $d/github <<'EOF' + ${{ toJSON(github) }} + EOF diff --git a/actions/example-workflow-dispatch/run.sh b/actions/example-workflow-dispatch/run.sh new file mode 100755 index 00000000..8a49365b --- /dev/null +++ b/actions/example-workflow-dispatch/run.sh @@ -0,0 +1,62 @@ +TMPDIR=$(mktemp -d) + +trap "rm -fr $TMPDIR" EXIT + +source $EXAMPLE_DIR/../../lib/lib.sh + +export d=/srv/example/tag +context=/srv/example/workflow-dispatch/contexts/workflow_dispatch/github +api=$url/api/v1 +repo=root/example-$example + +function context_wait() { + if ! forgejo.sh retry test -f $context; then + cat "$FORGEJO_RUNNER_LOGS" + false + fi +} + +function verify_required() { + local actual=$(forgejo-curl.sh api_json -w '%{http_code}' --data '{"ref":"main","inputs":{}}' $api/repos/$repo/actions/workflows/test.yml/dispatches) + local expected=400 + if test "$actual" != $expected; then + log_info "dispatch is expected to fail with status $expected because of string2 is a required value but got status $actual instead" + return 1 + fi +} + +function verify_inputs() { + local inputs='{"string2":"value2"}' + forgejo-curl.sh api_json --data '{"ref":"main","inputs":'$inputs'}' $api/repos/$repo/actions/workflows/test.yml/dispatches + cat >$TMPDIR/expected <<'EOF' + { + "boolean_default_false": "false", + "boolean_default_true": "true", + "logLevel": "warning", + "number1_default": "100", + "string1_default": "Hello world", + "string2": "value2" + } +EOF +} + +function run_tests() { + verify_required + + npm --silent install json-diff + verify_inputs + context_wait + node_modules/.bin/json-diff <(jq .event.inputs <$context) $TMPDIR/expected +} + +function main() { + mkdir -p $d + + forgejo-test-helper.sh push_workflow actions/example-$example $url root example-$example setup-forgejo $token + + run_tests + + test "workflow_dispatch" = "$(jq -r .event_name <$context)" +} + +main diff --git a/actions/example-workflow-dispatch/setup.sh b/actions/example-workflow-dispatch/setup.sh new file mode 100755 index 00000000..402b08ce --- /dev/null +++ b/actions/example-workflow-dispatch/setup.sh @@ -0,0 +1 @@ +mkdir -p /srv/example/workflow-dispatch diff --git a/actions/runner-config.yaml b/actions/runner-config.yaml index 12019d78..5859b08e 100644 --- a/actions/runner-config.yaml +++ b/actions/runner-config.yaml @@ -1,6 +1,6 @@ - log: - level: info + level: trace + job_level: trace runner: file: .runner diff --git a/end-to-end.sh b/end-to-end.sh index 04478c39..e57c8b1b 100755 --- a/end-to-end.sh +++ b/end-to-end.sh @@ -1,20 +1,11 @@ -#!/bin/bash +#!/usr/bin/env bash # SPDX-License-Identifier: MIT -# -# Debug loop from the source tree: -# -# ./end-to-end.sh dependencies -# ./end-to-end.sh build_all -# VERBOSE=true ./end-to-end.sh test_downgrade_1.20.2_fails -# -# Everything happens in /tmp/forgejo-end-to-end -# - -SELF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SELF="${BASH_SOURCE[0]}" source $SELF_DIR/lib/lib.sh +source $SELF_DIR/federation/federation.sh source $SELF_DIR/actions/actions.sh source $SELF_DIR/forgejo/fixtures.sh source $SELF_DIR/storage/storage.sh diff --git a/storage/legagy-relative-app.ini b/federation/ONE-app.ini similarity index 54% rename from storage/legagy-relative-app.ini rename to federation/ONE-app.ini index f5ea40fa..92a75b71 100644 --- a/storage/legagy-relative-app.ini +++ b/federation/ONE-app.ini @@ -1,13 +1,14 @@ RUN_MODE = prod -WORK_PATH = ${WORK_PATH} +WORK_PATH = forgejo-ONE [server] APP_DATA_PATH = ${WORK_PATH}/data DOMAIN = ${IP} -HTTP_PORT = 3000 -SSH_LISTEN_PORT = 2222 -LFS_START_SERVER = true -LFS_CONTENT_PATH = relative-lfs +HTTP_PORT = 3001 +SSH_LISTEN_PORT = 2201 + +[queue] +TYPE = immediate [database] DB_TYPE = sqlite3 @@ -15,8 +16,8 @@ PATH = ${WORK_PATH}/forgejo.db [log] MODE = file -LEVEL = debug -ROUTER = file +LEVEL = trace +logger.router.MODE = file [log.file] FILE_NAME = forgejo.log @@ -28,6 +29,6 @@ INSTALL_LOCK = true ENABLE_PUSH_CREATE_USER = true DEFAULT_PUSH_CREATE_PRIVATE = false -[picture] -AVATAR_UPLOAD_PATH = relative-avatars -REPOSITORY_AVATAR_UPLOAD_PATH = relative-repo-avatars +[federation] +ENABLED = true + diff --git a/storage/merged-app.ini b/federation/TWO-app.ini similarity index 62% rename from storage/merged-app.ini rename to federation/TWO-app.ini index 0a30227e..21448bda 100644 --- a/storage/merged-app.ini +++ b/federation/TWO-app.ini @@ -1,20 +1,23 @@ RUN_MODE = prod -WORK_PATH = ${WORK_PATH} +WORK_PATH = forgejo-TWO [server] APP_DATA_PATH = ${WORK_PATH}/data DOMAIN = ${IP} -HTTP_PORT = 3000 -SSH_LISTEN_PORT = 2222 -LFS_START_SERVER = true +HTTP_PORT = 3002 +SSH_LISTEN_PORT = 2202 + +[queue] +TYPE = immediate [database] DB_TYPE = sqlite3 +PATH = ${WORK_PATH}/forgejo.db [log] MODE = file -LEVEL = debug -ROUTER = file +LEVEL = trace +logger.router.MODE = file [log.file] FILE_NAME = forgejo.log @@ -26,8 +29,5 @@ INSTALL_LOCK = true ENABLE_PUSH_CREATE_USER = true DEFAULT_PUSH_CREATE_PRIVATE = false -[actions] +[federation] ENABLED = true - -[storage] -PATH = ${WORK_PATH}/merged diff --git a/federation/federation.sh b/federation/federation.sh new file mode 100755 index 00000000..4d7c09a5 --- /dev/null +++ b/federation/federation.sh @@ -0,0 +1,96 @@ +# Copyright 2024 The Forgejo Authors +# SPDX-License-Identifier: MIT + +FEDERATION_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +export FEDERATION_INSTANCES="ONE TWO" +export FEDERATION_CONFIGS + +function federation_setup_variables() { + if test "$FEDERATION_CONFIGS"; then + return + fi + for instance in $FEDERATION_INSTANCES; do + local config=$FEDERATION_DIR/$instance-app.ini + FEDERATION_CONFIGS="$FEDERATION_CONFIGS $config" + local base=$(work_path_base $config) + local work_path=$DIR/$base + local host_port=$(get_host_port $config) + + eval export ${instance}_CONFIG=$config + eval export ${instance}_CURL=$work_path/forgejo-curl.sh + eval export ${instance}_HOST_PORT=$host_port + done +} + +function federation_verify_scenario() { + local scenario=$1 + + federation_setup_variables + + export scenario + export SCENARIO_DIR=$FEDERATION_DIR/scenario-$scenario + + if test -f $SCENARIO_DIR/setup.sh; then + echo "============================ SETUP scenario-$scenario ===================" + bash -ex $SCENARIO_DIR/setup.sh || return 1 + fi + + echo "============================ RUN scenario-$scenario ===================" + bash -ex $SCENARIO_DIR/run.sh || return 1 + + if test -f $SCENARIO_DIR/teardown.sh; then + echo "============================ TEARDOWN scenario-$scenario ===================" + bash -ex $SCENARIO_DIR/teardown.sh || return 1 + fi +} + +function federation_setup() { + federation_setup_variables + + local version=$1 + federation_teardown + + local config + for config in $FEDERATION_CONFIGS; do + reset_forgejo $config + start_forgejo $version $config + done +} + +function federation_teardown() { + federation_setup_variables + + local config + for config in $FEDERATION_CONFIGS; do + stop_forgejo $config + done +} + +function test_federation() { + # start_gitlab gitlab/gitlab-ce:17.1.0-ce.0 + federation_setup_variables + + local versions="${1:-$RELEASE_NUMBERS}" + + for version in $versions; do + # name, minimum version + # NOTE: newline seperated, not comma :> + scenarios=( + "star 7.1" + "mastodon 14.0" + "gotosocial 14.0" + ) + + for scenario_version_str in "${scenarios[@]}"; do + IFS=' ' declare -a scenario_version="($scenario_version_str)" + + if dpkg --compare-versions "$version" lt "${scenario_version[1]}"; then + continue + fi + + federation_setup "$version" + run federation_verify_scenario "${scenario_version[0]}" + done + done +} diff --git a/federation/scenario-gotosocial/.gitignore b/federation/scenario-gotosocial/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/federation/scenario-gotosocial/run.sh b/federation/scenario-gotosocial/run.sh new file mode 100644 index 00000000..9fd57a7b --- /dev/null +++ b/federation/scenario-gotosocial/run.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +source "$DIR/federation_scenario-$scenario-env" + +if [[ -z "$password" ]]; then + exit 1 +fi + +if [[ -z "$port" ]]; then + exit 1 +fi + +status_code="$(curl -o /dev/null -w '%{http_code}' "http://localhost:$port/")" +if [[ "$status_code" != "200" ]]; then + exit 1 +fi diff --git a/federation/scenario-gotosocial/setup.sh b/federation/scenario-gotosocial/setup.sh new file mode 100644 index 00000000..fcf9a432 --- /dev/null +++ b/federation/scenario-gotosocial/setup.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +source $SCENARIO_DIR/../../lib/lib.sh + +GTS_VERSION="0.20.0" # renovate: datasource=docker depName=data.forgejo.org/oci/gotosocial + +echo "setting up gotosocial" + +tmpdir="$(mktemp --tmpdir -d gts.XXXXXXXXXX)" +cat << EOF > "$tmpdir/config.yaml" +host: "localhost:8080" +protocol: http +db-type: sqlite +db-address: /mount/gts.db3 + +http-client: + allow-ips: ["0.0.0.0/0", "::/0"] + insecure-outgoing: true +EOF + +podman unshare \ + chown 1000:1000 -R $tmpdir + +container_id="$( + podman run \ + -d \ + --env "GTS_CONFIG_PATH=/mount/config.yaml" \ + -v "$tmpdir:/mount" \ + -p "8080:8080" \ + --network=host \ + "data.forgejo.org/oci/gotosocial:$GTS_VERSION" \ + server start +)" + +function wait_gts_ready() { + http_status=$(curl -s -w \ + "%{http_code}" -o /dev/null \ + "http://localhost:8080/" + ) + + [[ "$http_status" == 200 ]] && echo "ready" +} + +retry wait_gts_ready + +password="verysecurepassword" +podman exec -it "$container_id" /gotosocial/gotosocial admin \ + account create \ + --username "test" \ + --email "test@localhost" \ + --password "$password" + +cat << EOF > "$DIR/federation_scenario-gotosocial-env" +password="$password" +port="8080" +container_id="$container_id" +EOF + diff --git a/federation/scenario-gotosocial/teardown.sh b/federation/scenario-gotosocial/teardown.sh new file mode 100644 index 00000000..6e6d556a --- /dev/null +++ b/federation/scenario-gotosocial/teardown.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +source "$DIR/federation_scenario-gotosocial-env" + +if [[ -z "$container_id" ]]; then + echo "gotosocial container ID not found, container may not be stopped" + exit 1 +fi + +podman stop "$container_id" +rm "$DIR/federation_scenario-gotosocial-env" + diff --git a/federation/scenario-mastodon/.gitignore b/federation/scenario-mastodon/.gitignore new file mode 100644 index 00000000..041e9d6f --- /dev/null +++ b/federation/scenario-mastodon/.gitignore @@ -0,0 +1,3 @@ +/resources/certs/forgejo* +/forgejo/certs/* +!/forgejo/certs/.gitkeep diff --git a/federation/scenario-mastodon/TEST_INSTRUCTION.md b/federation/scenario-mastodon/TEST_INSTRUCTION.md new file mode 100644 index 00000000..82d957b0 --- /dev/null +++ b/federation/scenario-mastodon/TEST_INSTRUCTION.md @@ -0,0 +1,38 @@ +# Manual testing + +1. compile forgejo binary to test on a debian/ubuntu system +2. start applications + * local forgejo: + ```sh + cd federation/scenario-mastodon + # create cert & startup & create test accounts + SCENARIO_DIR="." ./setup.sh + # Mastodon password in "/tmp/forgejo-end-to-end/federation_scenario-mastodon-env" + # Bind forgejo to localhost:3003 and set the domain to `forgejo` + ``` + * containerized forgejo: + ```sh + cd federation/scenario-mastodon + # Generate self-signed certs on first run + source ./functions.sh + generate_certs forgejo "./resources/certs" + mv "./resources/certs/forgejo"* "forgejo/certs" + + # Setup container + export FORGEJO_PATH="/path/to/forgejo/binary" + export COMPOSE_PROFILES="forgejo_container" + export MASTODON_HOST="mastodon-app" + + podman-compose up -d + podman-compose exec forgejo-app bash -c "/init/create_test_account.sh" + # Mastodon password is the last line of the output + podman-compose exec mastodon-app bash -c "/init/create_test_account.sh" + ``` +3. login to mastodon: http://localhost:4000 + 1. test@localhost - password from start app. +4. search for forgejo user: `https://forgejo/api/v1/activitypub/user-id/1` +5. Press follow +6. FYI: + 1. login to forgejo: http://localhost:3003/ + 2. me - me + 3. swagger-uri: http://localhost:3003/api/swagger#/activitypub diff --git a/federation/scenario-mastodon/compose.yaml b/federation/scenario-mastodon/compose.yaml new file mode 100644 index 00000000..ea7c28a6 --- /dev/null +++ b/federation/scenario-mastodon/compose.yaml @@ -0,0 +1,95 @@ +networks: + external_network: + internal_network: + internal: true + +services: + forgejo: + image: data.forgejo.org/oci/alpine:latest + volumes: + - ./forgejo/certs/:/usr/local/share/ca-certificates/ + - ./forgejo/init/:/init/ + - ./forgejo/etc/lighttpd.conf:/etc/lighttpd.conf + restart: unless-stopped + entrypoint: "sh /init/init.sh" + networks: + - external_network + - internal_network + + forgejo-app: + profiles: + - forgejo_container + # built from https://code.forgejo.org/federation/build-mastodon/src/branch/main/debian-containerfile + image: data.forgejo.org/federation/debian:trixie-cacerts + tmpfs: + - /data + volumes: + - ./forgejo-app/init/:/init/ + - ./forgejo-app/config/:/config/ + - ./resources/certs/:/usr/local/share/ca-certificates/ + - "${FORGEJO_PATH}:/usr/local/bin/forgejo" + ports: + - 3003:3003 + entrypoint: "sh /init/init.sh" + networks: + - external_network + - internal_network + + postgres: + image: data.forgejo.org/oci/postgres:14 + tmpfs: + - /var/lib/postgresql/data + environment: + POSTGRES_USER: postgres + POSTGRES_DB: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_HOST_AUTH_METHOD: trust + networks: + - internal_network + + redis: + image: data.forgejo.org/oci/redis:7.2 + tmpfs: + - /var/lib/redis/ + networks: + - internal_network + + mastodon-app: + # built from https://code.forgejo.org/federation/build-mastodon/src/branch/main/mastodon-containerfile + image: data.forgejo.org/federation/mastodon:v4.5-test + volumes: + - ./resources/certs:/usr/local/share/ca-certificates/ + - ./mastodon-app/init/:/init/ + environment: &mastodon_env + DB_HOST: postgres + DB_USER: postgres + DB_PASS: postgres + REDIS_HOST: redis + PORT: 4000 + LOCAL_DOMAIN: ${MASTODON_HOST}:4000 + ALTERNATE_DOMAINS: ${MASTODON_HOST},localhost + EMAIL_DOMAIN_ALLOWLIST: localhost + AUTHORIZED_FETCH: "true" + ALLOWED_PRIVATE_ADDRESSES: 0.0.0.0/0,::/0 + SECRET_KEY_BASE: bc1bdb4d3d57a2c292a8f145d5d3c921 + ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: fkSxKD2bF396kdQbrP1EJ7WbU7ZgNokR + ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: r0hvVmzBVsjxC7AMlwhOzmtc36ZCOS1E + ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: PhdFyyfy5xJ7WVd2lWBpcPScRQHzRTNr + ports: + - "4000:4000" + entrypoint: "sh /init/init.sh" + networks: + - external_network + - internal_network + + mastodon-sidekiq: + # built from https://code.forgejo.org/federation/build-mastodon/src/branch/main/mastodon-containerfile + image: data.forgejo.org/federation/mastodon:v4.5-test + volumes: + - ./resources/certs:/usr/local/share/ca-certificates/ + - ./mastodon-sidekiq/init/:/init/ + restart: unless-stopped + environment: *mastodon_env + entrypoint: "sh /init/init.sh" + networks: + - internal_network diff --git a/federation/scenario-mastodon/forgejo-app/config/app.ini b/federation/scenario-mastodon/forgejo-app/config/app.ini new file mode 100644 index 00000000..55ef4f61 --- /dev/null +++ b/federation/scenario-mastodon/forgejo-app/config/app.ini @@ -0,0 +1,32 @@ +RUN_MODE = prod + +[server] +APP_DATA_PATH = /data +DOMAIN = forgejo +ROOT_URL = https://forgejo/ +HTTP_PORT = 3003 +PROTOCOL = http + +[queue] +TYPE = immediate + +[database] +DB_TYPE = sqlite3 +PATH = /data/forgejo.db + +[log] +MODE = console +LEVEL = debug + +[security] +INSTALL_LOCK = true + +[repository] +ENABLE_PUSH_CREATE_USER = true +DEFAULT_PUSH_CREATE_PRIVATE = false + +[federation] +ENABLED = true + +[session] +COOKIE_SECURE = false diff --git a/federation/scenario-mastodon/forgejo-app/init/create_test_account.sh b/federation/scenario-mastodon/forgejo-app/init/create_test_account.sh new file mode 100755 index 00000000..33fc4807 --- /dev/null +++ b/federation/scenario-mastodon/forgejo-app/init/create_test_account.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +sleep 10 + +/usr/local/bin/forgejo -c /etc/forgejo/app.ini admin user create --username me --password me --email "me@example.com" --admin --must-change-password=false +/usr/local/bin/forgejo -c /etc/forgejo/app.ini admin user create --username to-be-followd --password to-be-followd --email "to-be-followd@example.com" --admin --must-change-password=false +/usr/local/bin/forgejo -c /etc/forgejo/app.ini admin user generate-access-token -u me -t token --scopes write:activitypub,write:repository,write:user diff --git a/federation/scenario-mastodon/forgejo-app/init/init.sh b/federation/scenario-mastodon/forgejo-app/init/init.sh new file mode 100755 index 00000000..3848fa53 --- /dev/null +++ b/federation/scenario-mastodon/forgejo-app/init/init.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +sudo update-ca-certificates + +sudo mkdir -p /data/forgejo +sudo chown forgejo:forgejo /data/forgejo +sudo install -D -o forgejo -g forgejo /config/app.ini /etc/forgejo/app.ini + +/usr/local/bin/forgejo -c /etc/forgejo/app.ini + diff --git a/federation/scenario-mastodon/forgejo/certs/.gitkeep b/federation/scenario-mastodon/forgejo/certs/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/federation/scenario-mastodon/forgejo/etc/lighttpd.conf b/federation/scenario-mastodon/forgejo/etc/lighttpd.conf new file mode 100644 index 00000000..325779ad --- /dev/null +++ b/federation/scenario-mastodon/forgejo/etc/lighttpd.conf @@ -0,0 +1,22 @@ +server.document-root = "/var/www" + +server.modules = ( + "mod_openssl", + "mod_proxy" +) + +$SERVER["socket"] == ":443" { + ssl.engine = "enable" + ssl.pemfile = "/usr/local/share/ca-certificates/forgejo-snakeoil.crt" + ssl.privkey = "/usr/local/share/ca-certificates/forgejo-snakeoil.key" +} + +proxy.server = ( + "" => ( + "forgejo" => ( + "host" => "host.containers.internal", + "port" => 3003, + ) + ) +) + diff --git a/federation/scenario-mastodon/forgejo/init/init.sh b/federation/scenario-mastodon/forgejo/init/init.sh new file mode 100755 index 00000000..6660768d --- /dev/null +++ b/federation/scenario-mastodon/forgejo/init/init.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +apk add lighttpd + +lighttpd -D -f /etc/lighttpd.conf + diff --git a/federation/scenario-mastodon/functions.sh b/federation/scenario-mastodon/functions.sh new file mode 100644 index 00000000..507131cc --- /dev/null +++ b/federation/scenario-mastodon/functions.sh @@ -0,0 +1,32 @@ +function generate_certs() { + + host=${1} + cert_location=${2} + + rootCertificate="${cert_location}/custom-snakeoil-rootCA.crt" + rootCertKey="${cert_location}/custom-snakeoil-rootCA.key" + extensionFile="${cert_location}/${host}-snakeoil.ext" + keyFile="${cert_location}/${host}-snakeoil.key" + csrFile="${cert_location}/${host}-snakeoil.csr" + crtAltSubFile="${cert_location}/${host}-snakeoil.crt" + + cat << EOF > ${extensionFile} +authorityKeyIdentifier=keyid,issuer +basicConstraints=CA:FALSE +subjectAltName = @alt_names +[alt_names] +DNS.1 = ${host} +DNS.2 = localhost +EOF + + # Create CSR + openssl req -newkey rsa:2048 -nodes -keyout ${keyFile} \ + -out ${csrFile} -subj "/CN=${host}" -addext "subjectAltName=DNS:localhost" + + # Sign Our CSR with the root CA cert + openssl x509 -req -CA ${rootCertificate} \ + -CAkey ${rootCertKey} \ + -in ${csrFile} \ + -out ${crtAltSubFile} \ + -days 3650 -CAcreateserial -extfile ${extensionFile} +} \ No newline at end of file diff --git a/federation/scenario-mastodon/mastodon-app/init/create_test_account.sh b/federation/scenario-mastodon/mastodon-app/init/create_test_account.sh new file mode 100755 index 00000000..283000fb --- /dev/null +++ b/federation/scenario-mastodon/mastodon-app/init/create_test_account.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +account_create="$(tootctl accounts create test --email test@localhost --role Owner --confirmed)" +tootctl account modify test --approve + +echo "${account_create}" + +password=$(echo "${account_create}" | + tail -n 1 | + sed 's/New password: //' | + sed 's/\r//' +) + +echo "$password" diff --git a/federation/scenario-mastodon/mastodon-app/init/init.sh b/federation/scenario-mastodon/mastodon-app/init/init.sh new file mode 100755 index 00000000..731aa55d --- /dev/null +++ b/federation/scenario-mastodon/mastodon-app/init/init.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +sudo update-ca-certificates +sudo touch /opt/mastodon/log/prod.log +sudo chown mastodon: /opt/mastodon/log/prod.log +rails db:setup +bundle exec puma -C config/puma.rb +#sleep 2h diff --git a/federation/scenario-mastodon/mastodon-sidekiq/init/init.sh b/federation/scenario-mastodon/mastodon-sidekiq/init/init.sh new file mode 100755 index 00000000..af9c5190 --- /dev/null +++ b/federation/scenario-mastodon/mastodon-sidekiq/init/init.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +sudo update-ca-certificates +sudo touch /opt/mastodon/log/prod.log +sudo chown mastodon: /opt/mastodon/log/prod.log +bundle exec sidekiq +#sleep 2h diff --git a/federation/scenario-mastodon/resources/certs/custom-snakeoil-rootCA.crt b/federation/scenario-mastodon/resources/certs/custom-snakeoil-rootCA.crt new file mode 100644 index 00000000..91a0d144 --- /dev/null +++ b/federation/scenario-mastodon/resources/certs/custom-snakeoil-rootCA.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDGTCCAgGgAwIBAgIUU+o53CfULAHTgPuCq/Ua8JRTWLIwDQYJKoZIhvcNAQEL +BQAwGzEZMBcGA1UEAwwQY29kZS5mb3JnZWpvLm9yZzAgFw0yNTEwMjMwODI2NTVa +GA8yMTI1MDkyOTA4MjY1NVowGzEZMBcGA1UEAwwQY29kZS5mb3JnZWpvLm9yZzCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKJl1YjGLoYK5J7wCbgL7WCZ +DGznwmp2SxpxJx/9Y6Pldt1QXTp0/VrR/H8iu3bNh13jmupXTKyGHU94MTNHER1T +/jbGw8LRPWCIYNjpYFZU17glTGs/DOieh7acuuvu+imoamk1oRLVaaHDewz09Tc2 +wkklCH+2ME2TC6mHIqpHOLO//ESEU0Glo+/mVMEcTJf9zdDhSGhZPKhXEaWgrLMo +EV3r0hpxHCE21OeaRrOKjMtOfp6/v0yKAsJ0QbLHXw1JDauiMWHUxp1H3jIHGgtc +0ALdiS1fhYi8zX3bkbMfctjREVtbhO0Aqps5pvDjhjTNyTmSQ3dkkU37W7Mz+WkC +AwEAAaNTMFEwHQYDVR0OBBYEFKXOSikliKVL6VYbbcaOR3k3khKyMB8GA1UdIwQY +MBaAFKXOSikliKVL6VYbbcaOR3k3khKyMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBADE4RGzIXT3LsLGxqRiuOPrXnOTy6izD0sXraJGPWOTEm0MB +H+MnV1YmqRiafwCTbKyiTfzF50JX0zwa6NnkK7k7tyht7O2B0/1VfsrIaXGBP05B +pZMC1bMSaDEu+zvRUDFvNiE5Oxkw0LGy44o36e3SNCEXMCYU3fiTX/5IxfB/a1Bk ++5tNfpK4CKwyk2/pb8ClgBldYGxfp/hyzTVh7y4c5bSRzoawGxq2ipfmJbSBYEme +vyySFXJI1W9ih8utE2sQKbRS7YrwxSNS9Uj6qwixTlHB5a/MzlFmD630VkmkI1qq +5VkQxq7dJSTlVHX8qiQqvGoPPIp5ucbBDmyj2A8= +-----END CERTIFICATE----- diff --git a/federation/scenario-mastodon/resources/certs/custom-snakeoil-rootCA.key b/federation/scenario-mastodon/resources/certs/custom-snakeoil-rootCA.key new file mode 100644 index 00000000..b4b13057 --- /dev/null +++ b/federation/scenario-mastodon/resources/certs/custom-snakeoil-rootCA.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCiZdWIxi6GCuSe +8Am4C+1gmQxs58JqdksacScf/WOj5XbdUF06dP1a0fx/Irt2zYdd45rqV0yshh1P +eDEzRxEdU/42xsPC0T1giGDY6WBWVNe4JUxrPwzonoe2nLrr7vopqGppNaES1Wmh +w3sM9PU3NsJJJQh/tjBNkwuphyKqRzizv/xEhFNBpaPv5lTBHEyX/c3Q4UhoWTyo +VxGloKyzKBFd69IacRwhNtTnmkaziozLTn6ev79MigLCdEGyx18NSQ2rojFh1Mad +R94yBxoLXNAC3YktX4WIvM1925GzH3LY0RFbW4TtAKqbOabw44Y0zck5kkN3ZJFN ++1uzM/lpAgMBAAECggEAAdGmR0j0k/ISyfhYnFJfFAfBN+x0a1wl7rOjDP/Tg7r9 +Ln21yzYTJJcfnu5TaOfLH84KrRwrT6JhhfaYn64PC8PmH/rXDftPsFSOt/DZo2+B +vaSgGyWcMVqdnNOOep6IXq36rr3krwQra14Rmbbm36AYihh+iuzbB4w0vPvpwDwv +G9DITTLrIwDRbXReZ13FjqphP5dqT6jG7BnRLe7vyQ7CJwYdUDLkg2YLykwbHvco +DISS3IoYgF5R7KaGpwH2iFmeHYwXaVH9Y0RyjEvxp87iK8Awvm4yn7hWBx9NsMm2 +of7107TlFBU81JbG09KQZ+mS3S4C9XfQScqBoP66tQKBgQDYS4QhwkYFNusN8z+U +63IGMxJXMF0bvF1zqjhrfkdX16jDD7v8cMbZAjk80obmRdhFpNiuaCT7dbnXpt7L +Ppfu6IkcJsAJc32lbWGc56XzfzDnNecvQbCbMnRYI5GDzcTTY+ObgyhJv4SwuD3E +kdHhxOFPuxlLFey9eg9vC6ADnQKBgQDANX5oEqvVty8gn+cOU3fEiqQ+ZqvcgMcL +CUQYIAUDvXjZuXTbU0cSzgZnZi3JwtEVwj0u+0eXXlju6AVgKC/yd4aIpQ2f6hXO +UlODWIqiNq3lVgjatO6zQ2CXuBeV7crX6odNrhkvSwSPNlC2Ra7QZ8Uk0PpX0sTm +JyuMA/WBPQKBgQCkqulPYj44nhTZrAUN9Sn7+knOQy2/feqPsln9zEe4YqFCz+nI +SHu6nuzAl27IRQhgDR5BuVvebUQtIAeiKGc3JaWs3vt4topDtUCJWfqHpJ+whuMY +oSQ5I3Jb38ha1f8xCG0x6ep0KvB0MfAkhPeKsH7wWnrpJSn1HsY9PlZ2KQKBgQCS +/xZKb6UdEDipocDqkukw1bsgwhLD03TmOtLqBGrxXlFzacM2DW14sznwkBOKj0Sq +eF+kc6Zf3Fb1d1rNHE73B3RLQre1yiedIBcgh3GW92xszSx+XwuC64+O2Mqo7jBI +iuOpg/Fc2umEwUxe6dH1Lrd2HaCn09ikD+bc8RYsHQKBgQDXfAiAf3MdzG8+4zgD +kzfZsUXRUm3ACqrkhlUOzPsh2y5yGO0gxkrUR4ps2+wn0aapwYi+JdbEHpDqI4Ze +vE3d8ZgLF4ER+uuiayuItMIFa8T0AiH1oJMptUY4kgj1AaG0b3+ZxU/uGXjpciyA +a7/psxJ+in3AQ005JGir8rx+gA== +-----END PRIVATE KEY----- diff --git a/federation/scenario-mastodon/run.sh b/federation/scenario-mastodon/run.sh new file mode 100644 index 00000000..7e07a1b8 --- /dev/null +++ b/federation/scenario-mastodon/run.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +source "$DIR/federation_scenario-$scenario-env" + +if [[ -z "$password" ]]; then + exit 1 +fi + +if [[ -z "$port" ]]; then + exit 1 +fi + +status_code="$(curl -o /dev/null -w '%{http_code}' "http://localhost:$port/")" +if [[ "$status_code" != "200" ]]; then + exit 1 +fi + diff --git a/federation/scenario-mastodon/setup.sh b/federation/scenario-mastodon/setup.sh new file mode 100755 index 00000000..cb9efb98 --- /dev/null +++ b/federation/scenario-mastodon/setup.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +source "$SCENARIO_DIR/../../lib/lib.sh" +source "$SCENARIO_DIR/functions.sh" + +echo "Setting up Forgejo x Mastodon" + +if [[ ! -d "$DIR" ]]; then + mkdir -p "$DIR" +fi + +echo "Generating forgejo & mastodon self-signed certificate" + +generate_certs forgejo "$SCENARIO_DIR/resources/certs" + +mv "$SCENARIO_DIR/resources/certs/forgejo"* "$SCENARIO_DIR/forgejo/certs/" + +export MASTODON_HOST="localhost" + +podman-compose \ + -f "$SCENARIO_DIR/compose.yaml" \ + up -d + +function wait_up() { + command="$(podman-compose \ + -f "$SCENARIO_DIR/compose.yaml" \ + exec mastodon-app \ + bin/tootctl accounts + )" + + first="$(head -n 1 <<< "$command")" + [[ "$first" == *"Commands:"* ]] && echo "ready" +} + +retry wait_up + +password="$(podman-compose \ + -f "$SCENARIO_DIR/compose.yaml" \ + exec mastodon-app \ + bash -c "/init/create_test_account.sh" | \ + tail -n 1 | \ + sed 's/\r//' +)" + +cat << EOF > "$DIR/federation_scenario-mastodon-env" +password="$password" +port="4000" +EOF diff --git a/federation/scenario-mastodon/teardown.sh b/federation/scenario-mastodon/teardown.sh new file mode 100644 index 00000000..5e5d35f4 --- /dev/null +++ b/federation/scenario-mastodon/teardown.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +podman-compose \ + -f "$SCENARIO_DIR/compose.yaml" \ + down + +rm "$DIR/federation_scenario-mastodon-env" + diff --git a/federation/scenario-star/run.sh b/federation/scenario-star/run.sh new file mode 100644 index 00000000..ad340d22 --- /dev/null +++ b/federation/scenario-star/run.sh @@ -0,0 +1,47 @@ +TMPDIR=$(mktemp -d) + +trap "rm -fr $TMPDIR" EXIT + +source $SCENARIO_DIR/../../lib/lib.sh + +function star_count() { + local curl=$1 + local host_port=$2 + local count=$3 + + $curl api_json http://$host_port/api/v1/repos/root/test >$TMPDIR/count.json + if test $count != $(jq -r .stars_count <$TMPDIR/count.json); then + jq . <$TMPDIR/count.json + return 1 + fi +} + +# +# create a repo on each instance +# +$ONE_CURL api_json --data '{"name":"test","auto_init":true}' $ONE_HOST_PORT/api/v1/user/repos >$TMPDIR/one-repo.json +one_repo_id=$(jq -r .id <$TMPDIR/one-repo.json) +$TWO_CURL api_json --data '{"name":"test","auto_init":true}' $TWO_HOST_PORT/api/v1/user/repos >$TMPDIR/two-repo.json +two_repo_id=$(jq -r .id <$TMPDIR/two-repo.json) + +# +# the repo in instance two is federated with the repo in instance one +# +$ONE_CURL web --form action=federation --form following_repos=http://$TWO_HOST_PORT/api/v1/activitypub/repository-id/$two_repo_id http://$ONE_HOST_PORT/root/test/settings + +# +# check that both repo have 0 star +# +star_count $ONE_CURL $ONE_HOST_PORT 0 +star_count $TWO_CURL $TWO_HOST_PORT 0 + +# +# star the repo on instance one and expect the star to show on instance two +# +$ONE_CURL api_json -X PUT $ONE_HOST_PORT/api/v1/user/starred/root/test + +# +# check that both repo have 1 star +# +star_count $ONE_CURL $ONE_HOST_PORT 1 +retry star_count $TWO_CURL $TWO_HOST_PORT 1 diff --git a/federation/scenario-star/setup.sh b/federation/scenario-star/setup.sh new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/federation/scenario-star/setup.sh @@ -0,0 +1 @@ + diff --git a/federation/scenario-star/teardown.sh b/federation/scenario-star/teardown.sh new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/federation/scenario-star/teardown.sh @@ -0,0 +1 @@ + diff --git a/forgejo/fixtures.sh b/forgejo/fixtures.sh index 9e7f5ca2..b49abf50 100644 --- a/forgejo/fixtures.sh +++ b/forgejo/fixtures.sh @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -FIXTURES_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +FIXTURES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source $FIXTURES_DIR/fixtures/storage.sh source $FIXTURES_DIR/fixtures/doctor.sh diff --git a/forgejo/fixtures/doctor.sh b/forgejo/fixtures/doctor.sh index 04e5b99e..c0d81099 100644 --- a/forgejo/fixtures/doctor.sh +++ b/forgejo/fixtures/doctor.sh @@ -1,7 +1,9 @@ # SPDX-License-Identifier: MIT function doctor_run() { - local version=$1 + local config=$1 + local base=$(work_path_base $config) + local work_path=$DIR/$base - $DIR/forgejocli doctor check --all # --log-file - + $work_path/forgejocli doctor check --all # --log-file - } diff --git a/forgejo/fixtures/storage.sh b/forgejo/fixtures/storage.sh index 0de79b5b..80b7c70c 100644 --- a/forgejo/fixtures/storage.sh +++ b/forgejo/fixtures/storage.sh @@ -15,7 +15,7 @@ function fixture_get_paths_s3() { ( mc ls --quiet --recursive testS3/$path | sed -e "s|.* |$path/|" - ) > $DIR/path + ) >$DIR/path } function fixture_content_search_s3() { @@ -23,15 +23,15 @@ function fixture_content_search_s3() { local expected="$2" fixture_get_paths_s3 $path - if test $(wc -l < $DIR/path) -lt 1 ; then - echo expected at least one but got "'$(cat $DIR/path)'" - return 1 + if test $(wc -l <$DIR/path) -lt 1; then + echo expected at least one but got "'$(cat $DIR/path)'" + return 1 fi - for filename in $(cat $DIR/path) ; do - local content=$(mc cat testS3/$filename | base64 -w0) - if test "$content" = "$expected" ; then - return 0 - fi + for filename in $(cat $DIR/path); do + local content=$(mc cat testS3/$filename | base64 -w0) + if test "$content" = "$expected"; then + return 0 + fi done echo nothing in $path found with the expected content "$expected" return 1 @@ -41,7 +41,10 @@ function fixture_get_paths_local() { local path=$1 local work_path=$DIR/forgejo-work-path - ( cd $work_path ; find $path -type f) > $DIR/path + ( + cd $work_path + find $path -type f + ) >$DIR/path } function fixture_get_one_path() { @@ -50,7 +53,7 @@ function fixture_get_one_path() { fixture_get_paths_$storage $path - if test $(wc -l < $DIR/path) != 1 ; then + if test $(wc -l <$DIR/path) != 1; then echo expected one path but got cat $DIR/path return 1 @@ -77,7 +80,7 @@ function fixture_lfs_create() { ( cd $DIR/fixture git lfs track "*.txt" - echo CONTENT > file.txt + echo CONTENT >file.txt git add . git commit -m 'lfs files' git push @@ -87,11 +90,11 @@ function fixture_lfs_create() { function fixture_lfs_assert() { local d=$(mktemp -d) ( - git clone http://${FORGEJO_USER}:${FORGEJO_PASSWORD}@${HOST_PORT}/${FORGEJO_USER}/${FORGEJO_REPO} $d/${FORGEJO_REPO} - cd $d/${FORGEJO_REPO} - rm file.txt + git clone http://${FORGEJO_USER}:${FORGEJO_PASSWORD}@${HOST_PORT}/${FORGEJO_USER}/${FORGEJO_REPO} $d/${FORGEJO_REPO} + cd $d/${FORGEJO_REPO} + rm file.txt git-lfs checkout file.txt - test -f file.txt + test -f file.txt ) rm -fr $d } @@ -110,7 +113,7 @@ function fixture_lfs_assert_local() { } function fixture_packages_create() { - echo PACKAGE_CONTENT > $DIR/fixture/package + echo PACKAGE_CONTENT >$DIR/fixture/package forgejo-curl.sh api_json -X DELETE http://${HOST_PORT}/api/packages/${FORGEJO_USER}/generic/test_package/1.0.0/file.txt || true forgejo-curl.sh api_json --upload-file $DIR/fixture/package http://${HOST_PORT}/api/packages/${FORGEJO_USER}/generic/test_package/1.0.0/file.txt } @@ -128,7 +131,7 @@ function fixture_packages_assert_local() { } function fixture_avatars_create() { - echo -n $ONEPIXEL | base64 --decode > $DIR/avatar.png + echo -n $ONEPIXEL | base64 --decode >$DIR/avatar.png forgejo-curl.sh web --form avatar=@$DIR/avatar.png http://${HOST_PORT}/user/settings/avatar } @@ -145,10 +148,8 @@ function fixture_avatars_assert_local() { } function fixture_repo_avatars_create() { - echo -n $ONEPIXEL | base64 --decode > $DIR/repo-avatar.png + echo -n $ONEPIXEL | base64 --decode >$DIR/repo-avatar.png forgejo-curl.sh web --form avatar=@$DIR/repo-avatar.png http://${HOST_PORT}/${FORGEJO_USER}/${FORGEJO_REPO}/settings/avatar - # v1.21 only - #forgejo-curl.sh api_json -X POST --data-raw '{"body":"'$avatar'"}' http://${HOST_PORT}/api/v1/repos/${FORGEJO_USER}/${FORGEJO_REPO}/avatar } function fixture_repo_avatars_assert_s3() { @@ -166,17 +167,17 @@ function fixture_repo_avatars_assert_local() { } function fixture_attachments_create_1_18() { - echo -n $ONEPIXEL | base64 --decode > $DIR/attachment.png + echo -n $ONEPIXEL | base64 --decode >$DIR/attachment.png forgejo-curl.sh web --trace-ascii - --form file=@$DIR/attachment.png http://${HOST_PORT}/${FORGEJO_USER}/${FORGEJO_REPO}/issues/attachments } function fixture_attachments_create() { - if forgejo-curl.sh api_json http://${HOST_PORT}/api/v1/version | grep --quiet --fixed-strings 1.18. ; then + if forgejo-curl.sh api_json http://${HOST_PORT}/api/v1/version | grep --quiet --fixed-strings 1.18.; then fixture_attachments_create_1_18 return fi id=$(forgejo-curl.sh api_json --data-raw '{"title":"TITLE"}' http://${HOST_PORT}/api/v1/repos/${FORGEJO_USER}/${FORGEJO_REPO}/issues | jq .id) - echo -n $ONEPIXEL | base64 --decode > $DIR/attachment.png + echo -n $ONEPIXEL | base64 --decode >$DIR/attachment.png forgejo-curl.sh api --form name=attachment.png --form attachment=@$DIR/attachment.png http://${HOST_PORT}/api/v1/repos/${FORGEJO_USER}/${FORGEJO_REPO}/issues/$id/assets } @@ -206,18 +207,18 @@ function fixture_create() { git remote add origin http://${FORGEJO_USER}:${FORGEJO_PASSWORD}@${HOST_PORT}/${FORGEJO_USER}/${FORGEJO_REPO} git config user.email root@example.com git config user.name username - echo SOMETHING > README + echo SOMETHING >README git add README git commit -m 'initial commit' git push --set-upstream --force origin main ) - for fun in ${STORAGE_FUN} ; do + for fun in ${STORAGE_FUN}; do fixture_${fun}_create done } function fixture_assert() { - for fun in lfs ; do + for fun in lfs; do fixture_${fun}_assert done } diff --git a/forgejo/sources/10.0 b/forgejo/sources/10.0 new file mode 100644 index 00000000..7c1c0138 --- /dev/null +++ b/forgejo/sources/10.0 @@ -0,0 +1 @@ +https://codeberg.org/forgejo/forgejo forgejo 10.0.0+gitea-1.22 diff --git a/forgejo/sources/11.0 b/forgejo/sources/11.0 new file mode 100644 index 00000000..0286dcaf --- /dev/null +++ b/forgejo/sources/11.0 @@ -0,0 +1 @@ +https://codeberg.org/forgejo/forgejo forgejo 11.0.0 diff --git a/forgejo/sources/12.0 b/forgejo/sources/12.0 new file mode 100644 index 00000000..1ed248e4 --- /dev/null +++ b/forgejo/sources/12.0 @@ -0,0 +1 @@ +https://codeberg.org/forgejo/forgejo forgejo 12.0.0 diff --git a/forgejo/sources/13.0 b/forgejo/sources/13.0 new file mode 100644 index 00000000..24bcca16 --- /dev/null +++ b/forgejo/sources/13.0 @@ -0,0 +1 @@ +https://codeberg.org/forgejo/forgejo forgejo 13.0.0 diff --git a/forgejo/sources/14.0 b/forgejo/sources/14.0 new file mode 100644 index 00000000..84203a1b --- /dev/null +++ b/forgejo/sources/14.0 @@ -0,0 +1 @@ +https://codeberg.org/forgejo/forgejo forgejo 14.0.0 diff --git a/forgejo/sources/15.0 b/forgejo/sources/15.0 new file mode 100644 index 00000000..595283d3 --- /dev/null +++ b/forgejo/sources/15.0 @@ -0,0 +1 @@ +https://codeberg.org/forgejo/forgejo forgejo 15.0.0 diff --git a/forgejo/sources/7.0 b/forgejo/sources/7.0 index b033f014..0e2cc26e 100644 --- a/forgejo/sources/7.0 +++ b/forgejo/sources/7.0 @@ -1 +1 @@ -https://codeberg.org/forgejo/forgejo v7.0/forgejo 7.0.0+gitea-1.22.0 +https://codeberg.org/forgejo/forgejo v7.0/forgejo 7.0.0+gitea-1.21.0 diff --git a/forgejo/sources/8.0 b/forgejo/sources/8.0 index 14122738..42ce80b7 100644 --- a/forgejo/sources/8.0 +++ b/forgejo/sources/8.0 @@ -1 +1 @@ -https://codeberg.org/forgejo/forgejo forgejo 8.0.0+gitea-1.22.0 +https://codeberg.org/forgejo/forgejo v8.0/forgejo 8.0.0+gitea-1.22.0 diff --git a/forgejo/sources/9.0 b/forgejo/sources/9.0 new file mode 100644 index 00000000..bd6c2d0f --- /dev/null +++ b/forgejo/sources/9.0 @@ -0,0 +1 @@ +https://codeberg.org/forgejo/forgejo forgejo 9.0.0+gitea-1.22.0 diff --git a/lib/api.sh b/lib/api.sh new file mode 100644 index 00000000..cc56f506 --- /dev/null +++ b/lib/api.sh @@ -0,0 +1,148 @@ +#!/bin/bash +# Copyright 2024 The Forgejo Authors +# SPDX-License-Identifier: MIT + +API_TMPDIR=$(mktemp -d) +: ${PASSWORD:=admin1234} + +function api_user_make_admin() { + local api="$1" username="$2" + + forgejo-curl.sh api_json -X PATCH --data '{"admin":true}' $api/admin/users/$username +} + +function api_user_create() { + local api="$1" username="$2" email="$3" + log_info "(re)create user $username" + forgejo-curl.sh api_json -X DELETE $api/admin/users/$username?purge=true >&/dev/null || true + forgejo-curl.sh api_json --data '{"username":"'$username'","email":"'$email'","password":"admin1234","must_change_password":false}' $api/admin/users +} + +function user_login() { + local username=$1 + ( + export DOT=$API_TMPDIR/$username + forgejo-curl.sh logout + forgejo-curl.sh --user $username --password "admin1234" login http://${HOST_PORT} + ) +} + +function api_branch_tip() { + local api="$1" + local repo="$2" + local branch="$3" + + retry forgejo-curl.sh api_json $api/repos/$repo/branches/$branch >&/dev/null + forgejo-curl.sh api_json $api/repos/$repo/branches/$branch | jq --raw-output .commit.id +} + +function api_branch_protect() { + local api="$1" + local repo="$2" + local branch="$3" + + forgejo-curl.sh api_json -X DELETE $api/repos/${repo}/branch_protections/$branch >&/dev/null || true + forgejo-curl.sh api_json --data '{"branch_name":"'$branch'","required_approvals":1}' $api/repos/${repo}/branch_protections +} + +function api_pr_approve() { + local api="$1" + local repo="$2" + local pr="$3" + + forgejo-curl.sh api_json --data '{"event":"APPROVED"}' $api/repos/${repo}/pulls/$pr/reviews +} + +function api_pr_is_merged() { + local api="$1" + local repo="$2" + local pr="$3" + + forgejo-curl.sh api_json $api/repos/$repo/pulls/$pr >$API_TMPDIR/pr.json + $(jq -r .merged <$API_TMPDIR/pr.json) +} + +function api_pr_delete_all() { + local api="$1" + local repo="$2" + + forgejo-curl.sh api_json $api/repos/${repo}/pulls | jq --raw-output '.[] | .number' | while read pr; do + forgejo-curl.sh api_json -X DELETE $api/repos/${repo}/issues/$pr + done +} + +function api_pr_get_status() { + local api="$1" + local repo="$2" + local sha="$3" + + forgejo-curl.sh api_json $api/repos/$repo/commits/$sha/status +} + +function api_pr_check_status() { + local api="$1" + local repo="$2" + local sha="$3" + local expected_status="$4" + local expected_description="$5" + + api_pr_get_status $api $repo $sha >$API_TMPDIR/status.json + local status="$(jq --raw-output .state <$API_TMPDIR/status.json)" + local description="$(jq --raw-output .statuses[0].description <$API_TMPDIR/status.json)" + if test "$status" = "$expected_status" && test -z "$expected_description" -o "$description" = "$expected_description"; then + echo OK + elif test "$status" = "failure" -o "$status" = "success"; then + echo NOK + else + echo RETRY + fi +} + +function api_pr_wait_success() { + api_pr_wait_status success "$@" +} + +function api_pr_wait_failure() { + api_pr_wait_status failure "$@" +} + +function api_pr_wait_running() { + api_pr_wait_status pending "$@" "Has started running" +} + +function api_pr_wait_log() { + local sha="$1" expected_status="$2" expected_description="$3" + local status="$(jq --raw-output .state <$API_TMPDIR/status.json)" + local description="$(jq --raw-output .statuses[0].description <$API_TMPDIR/status.json)" + if test "$expected_description"; then + expected_description=" '$expected_description'" + fi + log_info "$sha status waiting '$expected_status'$expected_description, currently '$status' '$description'" +} + +# default loop delay is 3600 sec (1 hour) +: ${API_LOOPS:=100} +: ${API_LOOP_DELAY:=36} + +function api_pr_wait_status() { + local status="$1" + local api="$2" + local repo="$3" + local sha="$4" + local description="$5" + + for i in $(seq $API_LOOPS); do + if test $(api_pr_check_status "$api" "$repo" "$sha" "$status" "$description") != RETRY; then + break + fi + api_pr_wait_log "$sha" "$status" "$description" + sleep $API_LOOP_DELAY + done + if test $(api_pr_check_status "$api" "$repo" "$sha" "$status" "$description") = "OK"; then + log_info "$sha status OK" + else + api_pr_get_status $api $repo $sha | jq .statuses + log_info "$sha status NOK" + return 1 + fi +} diff --git a/lib/build.sh b/lib/build.sh index 9ad74eca..8fac7201 100755 --- a/lib/build.sh +++ b/lib/build.sh @@ -4,16 +4,16 @@ set -ex -SELF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" version=$1 dir_binaries=$2 v=$(echo $version | sed -E -e 's/^([0-9]+\.[0-9]+).*/\1/') src=$dir_binaries/src-$v -read url ref semver < $SELF_DIR/../forgejo/sources/$v +read url ref semver <$SELF_DIR/../forgejo/sources/$v -if ! test -d $src ; then +if ! test -d $src; then mkdir -p $src cd $src git init @@ -22,13 +22,21 @@ else cd $src fi -if ! [[ "$ref" =~ ^refs/ ]] ; then +if ! [[ "$ref" =~ ^refs/ ]]; then ref=refs/heads/$ref fi +for retry in 1 2 3; do + if timeout 15m git fetch --update-head-ok origin +$ref:$ref; then + break + else + echo "Retry git fetch in 60 seconds" + sleep 60 + fi +done git fetch --update-head-ok origin +$ref:$ref git switch --force-create $v $ref -export TAGS="bindata sqlite sqlite_unlock_notify" FORGEJO_VERSION=$semver +export TAGS="bindata sqlite sqlite_unlock_notify" FORGEJO_VERSION=$semver EXTRA_GOFLAGS="-cover" make deps-backend backend make generate forgejo cp -a forgejo $dir_binaries/forgejo-$v-dev diff --git a/lib/lib.sh b/lib/lib.sh index aea34c29..b1e9409f 100644 --- a/lib/lib.sh +++ b/lib/lib.sh @@ -2,9 +2,11 @@ # Copyright 2024 The Forgejo Authors # SPDX-License-Identifier: MIT -LIB_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -if ${VERBOSE:-false} ; then +source $LIB_DIR/api.sh + +if ${VERBOSE:-false}; then set -ex PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: ' else @@ -15,8 +17,8 @@ set -o pipefail export DEBIAN_FRONTEND=noninteractive -if test $(id -u) != 0 ; then - SUDO=sudo +if test $(id -u) != 0; then + SUDO=sudo fi IP=$(hostname -I | cut -f1 -d' ') @@ -24,17 +26,17 @@ IP=$(hostname -I | cut -f1 -d' ') # # Forgejo releases for which a branch exists (7.0/forgejo etc.) # -RELEASE_NUMBERS="7.0 8.0" +RELEASE_NUMBERS="11.0 14.0 15.0" PREFIX=============== -HOST_PORT=$IP:3000 export DIR=/tmp/forgejo-end-to-end DIR_BINARIES=/srv/forgejo-binaries +COVERAGE_DIR="$DIR/coverage" export DOT_FORGEJO_CURL=$DIR/forgejo-curl export DOT=$DOT_FORGEJO_CURL # for backward compatibility with forgejo-curl.sh 1.0.0 : ${FORGEJO_USER:=root} : ${FORGEJO_PASSWORD:=admin1234} -RELEASE_NUMBERS_AND_DEV="$(for r in $RELEASE_NUMBERS ; do echo -n "$r $r-dev " ; done)" +: ${FORGEJO_INSTANCE:=https://codeberg.org} ORGANIZATIONS=$(cat $LIB_DIR/ORGANIZATIONS) function log_info() { @@ -43,50 +45,38 @@ function log_info() { function dependencies() { - if ! test -f /usr/local/bin/forgejo-curl.sh ; then - $SUDO curl --fail -sS https://code.forgejo.org/forgejo/forgejo-curl/raw/branch/main/forgejo-curl.sh -o /usr/local/bin/forgejo-curl.sh - $SUDO chmod +x /usr/local/bin/forgejo-curl.sh + if ! test -f /usr/local/bin/forgejo-curl.sh; then + $SUDO curl --fail -sS https://code.forgejo.org/forgejo/forgejo-curl/raw/branch/main/forgejo-curl.sh -o /usr/local/bin/forgejo-curl.sh + $SUDO chmod +x /usr/local/bin/forgejo-curl.sh fi - if ! which make curl daemon git-lfs jq sqlite3 > /dev/null ; then + if ! which make curl daemon git-lfs jq sqlite3 skopeo podman podman-compose pup >/dev/null; then $SUDO apt-get update -qq - $SUDO apt-get install -y -qq make curl daemon git-lfs jq sqlite3 gettext-base + $SUDO apt-get install -y -qq make curl daemon git-lfs jq sqlite3 skopeo podman podman-compose pup fi - if ! test -f /usr/local/bin/mc || ! test -f /usr/local/bin/minio ; then + if ! test -f /usr/local/bin/mc || ! test -f /usr/local/bin/minio; then $SUDO curl --fail -sS https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc $SUDO curl --fail -sS https://dl.min.io/server/minio/release/linux-amd64/minio -o /usr/local/bin/minio fi - if ! test -x /usr/local/bin/mc || ! test -x /usr/local/bin/minio ; then + if ! test -x /usr/local/bin/mc || ! test -x /usr/local/bin/minio; then $SUDO chmod +x /usr/local/bin/mc $SUDO chmod +x /usr/local/bin/minio fi - if ! test -f /usr/local/bin/garage > /dev/null ; then + if ! test -f /usr/local/bin/garage >/dev/null; then $SUDO curl --fail -sS https://garagehq.deuxfleurs.fr/_releases/v0.8.2/x86_64-unknown-linux-musl/garage -o /usr/local/bin/garage fi - if ! test -x /usr/local/bin/garage > /dev/null ; then + if ! test -x /usr/local/bin/garage >/dev/null; then $SUDO chmod +x /usr/local/bin/garage fi } -function build_all() { - for dev in $RELEASE_NUMBERS ; do - local forgejo=$DIR_BINARIES/forgejo-$dev-dev - if test -f $forgejo ; then - log_info $dev already exists - else - $LIB_DIR/build.sh $dev $DIR_BINARIES - log_info $dev built from sources - fi - done -} - function retry() { rm -f $DIR/wait-for.out success=false - for delay in 1 1 5 5 15 ; do - if "$@" >> $DIR/wait-for.out 2>&1 ; then + for delay in 1 1 5 5 15 15 15; do + if "$@" >>$DIR/wait-for.out 2>&1; then success=true break fi @@ -94,54 +84,95 @@ function retry() { echo waiting $delay sleep $delay done - if test $success = false ; then + if test $success = false; then cat $DIR/wait-for.out return 1 fi } +function get_versions() { + local releases=$1 + local page=1 + local tmp=$(mktemp) + while true; do + curl --fail -sS "$releases?limit=100&page=$page" | jq -r '.[] | .tag_name' >$tmp + cat $tmp + if ! test -s $tmp; then + break + fi + page=$(expr $page + 1) + done | grep -v -e '-rc' | sort --version-sort +} + function full_version() { local version=$1 local owner=$2 - if [[ $version =~ ^[0-9]+\.[0-9]+$ ]] ; then - full_version=$(curl -sS https://codeberg.org/api/v1/repos/$owner/forgejo/releases | jq -r '.[] | .tag_name | select(startswith("v'$version'"))' | sort --reverse --version-sort | head -1) - echo ${full_version#v} + if [[ $version =~ ^[0-9]+\.[0-9]+$ ]]; then + full_version=$(get_versions "$FORGEJO_INSTANCE/api/v1/repos/$owner/forgejo/releases" | sed -n -e "/^v$version/p" | sort --reverse --version-sort | head -1) + echo ${full_version#v} else - echo $version + echo $version fi } -function download() { +function download_forgejo() { local version=$1 - if ! test -f $DIR_BINARIES/forgejo-$version ; then + if ! test -f $DIR_BINARIES/forgejo-$version; then mkdir -p $DIR_BINARIES - for owner in $ORGANIZATIONS ; do - full_version=$(full_version $version $owner) - if test "$full_version" = "" ; then - continue - fi - if wget -O $DIR_BINARIES/forgejo-$version --quiet https://codeberg.org/$owner/forgejo/releases/download/v$full_version/forgejo-$full_version-linux-amd64 ; then - break - fi - done - if test -s $DIR_BINARIES/forgejo-$version ; then - if test "$version" != "$full_version" ; then - log_info "downloaded $full_version for $version" - fi - else - echo unable to download Forgejo $version - return 1 - fi + for owner in $ORGANIZATIONS; do + full_version=$(full_version $version $owner) + if test "$full_version" = ""; then + continue + fi + if wget -O $DIR_BINARIES/forgejo-$version --quiet $FORGEJO_INSTANCE/$owner/forgejo/releases/download/v$full_version/forgejo-$full_version-linux-amd64; then + break + fi + done + if test -s $DIR_BINARIES/forgejo-$version; then + if test "$version" != "$full_version"; then + log_info "downloaded Forgejo $full_version for $version" + fi + else + echo unable to download Forgejo $version + return 1 + fi chmod +x $DIR_BINARIES/forgejo-$version fi } -function cleanup_logs() { - local work_path=$DIR/forgejo-work-path +function download_gitea() { + local version=$1 - rm -f $DIR/*.log + if ! test -f $DIR_BINARIES/gitea-$version; then + mkdir -p $DIR_BINARIES + if [[ $version =~ ^[0-9]+\.[0-9]+$ ]]; then + full_version=$(git ls-remote --refs --tags --sort=version:refname https://git-mirror.forgejo.org/go-gitea/gitea "v$version*" | sed -n -E -e "s|^.*/v($version[\.0-9]*)$|\1|p" | tail -1) + else + full_version=$version + fi + wget -O $DIR_BINARIES/gitea-$version --quiet https://dl.gitea.com/gitea/$full_version/gitea-$full_version-linux-amd64 + + if test -s $DIR_BINARIES/gitea-$version; then + if test "$version" != "$full_version"; then + log_info "downloaded Gitea $full_version for $version" + fi + else + echo unable to download Gitea $version + return 1 + fi + chmod +x $DIR_BINARIES/gitea-$version + fi +} + +function cleanup_logs() { + local config=$1 + + local base=$(work_path_base $config) + local work_path=$DIR/$base + + rm -f $DIR/$base*.log rm -f $work_path/log/*.log } @@ -149,44 +180,117 @@ function clobber() { rm -fr /tmp/forgejo-end-to-end } +: ${GITLAB_USER:=root} +: ${GITLAB_PASSWORD:=Wrobyak4} +: ${GITLAB_PORT:=8181} + +function start_gitlab_cache_load() { + local image=$1 + local d=$DIR_BINARIES/gitlab + if test -d $d; then + log_info "loading $image from $d" + skopeo copy dir:$d docker-daemon:$image + fi +} + +function start_gitlab_cache_save() { + local image=$1 + local d=$DIR_BINARIES/gitlab + if ! test -d $d; then + log_info "saving $image to $d" + skopeo copy docker-daemon:$image dir:$d + fi +} + +function start_gitlab() { + local image=$1 + local config=$2 + + start_gitlab_cache_load $image + + local GITLAB_OMNIBUS_CONFIG="nginx['listen_https'] = false ; nginx['listen_port'] = 8181 ; external_url 'http://$IP:$GITLAB_PORT'; gitlab_rails['gitlab_shell_ssh_port'] = 2221; $config" + docker run --name="test-gitlab" --shm-size=128M -d \ + -e GITLAB_OMNIBUS_CONFIG="$GITLAB_OMNIBUS_CONFIG" \ + -p 2221:22 -p $GITLAB_PORT:8181 \ + $image >&/dev/null &/dev/null +} + +function stop_forgejo() { + local config=$1 + + stop_daemon $(work_path_base $config) +} + +function start_gitea() { + local version=$1 + local config=$2 + + download_gitea $version + start_forgejo_daemon $version $DIR_BINARIES/gitea-$version $config +} + function start_forgejo() { local version=$1 + local config=$2 - download $version - start_forgejo_daemon $version $DIR_BINARIES/forgejo-$version + download_forgejo $version + start_forgejo_daemon $version $DIR_BINARIES/forgejo-$version $config } function start_forgejo_daemon() { local version=$1 local binary=$2 + local config=$3 - 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 -- $binary --config $work_path/app.ini --work-path $work_path - if ! retry grep --no-messages --quiet 'Starting server on' $work_path/log/forgejo.log ; then - grep '' $DIR/*.log - grep '' $work_path/log/*.log 2> /dev/null + local base=$(work_path_base $config) + local work_path=$DIR/$base + mkdir -p $COVERAGE_DIR + daemon --chdir=$DIR --unsafe --env="TERM=$TERM" --env="HOME=$HOME" --env="PATH=$PATH" --env="GOCOVERDIR=$COVERAGE_DIR" --pidfile=$DIR/$base-pid --errlog=$DIR/$base-err.log --output=$DIR/$base-out.log -- $binary --config $work_path/app.ini --work-path $work_path + if ! retry grep --no-messages --quiet 'Starting server on' $work_path/log/forgejo.log; then + grep '' $DIR/$base*.log + grep '' $work_path/log/*.log 2>/dev/null return 1 fi - echo "$binary --config $work_path/app.ini --work-path $work_path" '"$@"' > $DIR/forgejocli - chmod +x $DIR/forgejocli - create_user_and_login $version + echo "$binary --config $work_path/app.ini --work-path $work_path" '"$@"' >$work_path/forgejocli + chmod +x $work_path/forgejocli + cp -a $work_path/forgejocli $DIR/forgejocli # because setup-forgejo/forgejo-runner.sh expects it here + create_user_and_login $version $config } function start_minio() { mkdir -p $DIR/minio daemon --chdir=$DIR --unsafe \ - --env="PATH=$PATH" \ - --env=MINIO_ROOT_USER=123456 \ - --env=MINIO_ROOT_PASSWORD=12345678 \ - --env=MINIO_VOLUMES=$DIR/minio \ - --pidfile=$DIR/minio-pid --errlog=$DIR/minio-err.log --output=$DIR/minio-out.log -- /usr/local/bin/minio server - retry mc alias set testS3 http://127.0.0.1:9000 123456 12345678 >& /dev/null + --env="PATH=$PATH" \ + --env=MINIO_ROOT_USER=123456 \ + --env=MINIO_ROOT_PASSWORD=12345678 \ + --env=MINIO_VOLUMES=$DIR/minio \ + --pidfile=$DIR/minio-pid --errlog=$DIR/minio-err.log --output=$DIR/minio-out.log -- /usr/local/bin/minio server + retry mc alias set testS3 http://127.0.0.1:9000 123456 12345678 >&/dev/null mc alias set testS3 http://127.0.0.1:9000 123456 12345678 } function start_garage() { mkdir -p $DIR/garage/{data,meta} - cat > $DIR/garage/garage.toml <$DIR/garage/garage.toml < $work_path/app.ini + sed -e "s/\${IP}/$IP/g" \ + -e "s|\${WORK_PATH}|$work_path|g" \ + -e "s|^WORK_PATH = .*|WORK_PATH = $work_path|" \ + <$config >$work_path/app.ini } function reset_minio() { @@ -261,29 +388,53 @@ function reset_garage() { function create_user_and_login() { local version=$1 + local config=$2 + + local work_path=$DIR/$(work_path_base $config) local email="$FORGEJO_USER@example.com" - if ! $DIR/forgejocli admin user list | grep --quiet "$email" ; then - $DIR/forgejocli admin user create --admin --username "$FORGEJO_USER" --password "$FORGEJO_PASSWORD" --email $email + if ! $work_path/forgejocli admin user list | grep --quiet "$email"; then + $work_path/forgejocli admin user create --admin --username "$FORGEJO_USER" --password "$FORGEJO_PASSWORD" --email $email fi forgejo-curl.sh logout local scopes='--scopes ["all"]' - if echo $version | grep --quiet 1.18 ; then + if echo $version | grep --quiet 1.18; then scopes="" fi - forgejo-curl.sh --user "$FORGEJO_USER" --password "$FORGEJO_PASSWORD" $scopes login http://${HOST_PORT} + forgejo-curl.sh --user "$FORGEJO_USER" --password "$FORGEJO_PASSWORD" $scopes login http://$(get_host_port $config) + + local forgejo_curl=$work_path/forgejo-curl.sh + cat >$forgejo_curl < $DIR/$fun.out + >$DIR/$fun.out tail --follow $DIR/$fun.out |& sed --unbuffered -n -e "/^$PREFIX/s/^$PREFIX //p" & local pid=$! - if ! VERBOSE=true $SELF $fun "$@" >& $DIR/$fun.out ; then + if ! VERBOSE=true $SELF $fun "$@" >&$DIR/$fun.out; then kill $pid cat $DIR/$fun.out echo Failure running $fun diff --git a/packages/alpine-1.21/test.sh b/packages/alpine-1.21/test.sh deleted file mode 100755 index e2108797..00000000 --- a/packages/alpine-1.21/test.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/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/alpine-7.0-dev b/packages/alpine-7.0-dev deleted file mode 120000 index a2389c03..00000000 --- a/packages/alpine-7.0-dev +++ /dev/null @@ -1 +0,0 @@ -alpine-7.0-test \ No newline at end of file diff --git a/packages/alpine-7.0-test/package-source/forgejo-2174/APKBUILD b/packages/alpine-7.0-test/package-source/forgejo-2174/APKBUILD deleted file mode 100644 index ce75e29d..00000000 --- a/packages/alpine-7.0-test/package-source/forgejo-2174/APKBUILD +++ /dev/null @@ -1,26 +0,0 @@ -# -*- 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-7.0-test/package-source/forgejo-2174/forgejo_2174 b/packages/alpine-7.0-test/package-source/forgejo-2174/forgejo_2174 deleted file mode 100755 index b12f87b3..00000000 --- a/packages/alpine-7.0-test/package-source/forgejo-2174/forgejo_2174 +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -echo "Hello World" diff --git a/packages/alpine-7.0-test/package-source/forgejo-2174/forgejo_2174.init b/packages/alpine-7.0-test/package-source/forgejo-2174/forgejo_2174.init deleted file mode 100755 index 06b7f209..00000000 --- a/packages/alpine-7.0-test/package-source/forgejo-2174/forgejo_2174.init +++ /dev/null @@ -1,7 +0,0 @@ -#!/sbin/openrc-run - -command="/usr/bin/forgejo_2174" - -depend() { - need net -} diff --git a/packages/alpine-app.ini b/packages/alpine-app.ini index 113f242d..21f95ffc 100644 --- a/packages/alpine-app.ini +++ b/packages/alpine-app.ini @@ -1,5 +1,5 @@ RUN_MODE = prod -WORK_PATH = ${WORK_PATH} +WORK_PATH = forgejo-work-path [server] APP_DATA_PATH = ${WORK_PATH}/data @@ -15,7 +15,7 @@ PATH = ${WORK_PATH}/forgejo.db [log] MODE = file LEVEL = trace -ROUTER = file +logger.router.MODE = file [log.file] FILE_NAME = forgejo.log diff --git a/packages/alpine.sh b/packages/alpine.sh index b3e5b5d2..ce5c4ac8 100644 --- a/packages/alpine.sh +++ b/packages/alpine.sh @@ -1,24 +1,26 @@ -# Copyright 2024 The Forgejo Authors +# Copyright 2025 The Forgejo Authors # SPDX-License-Identifier: MIT function test_packages_alpine_version() { local alpine_version=$1 forgejo_version=$2 - stop_daemon forgejo + stop_forgejo reset_forgejo $PACKAGES_DIR/alpine-app.ini start_forgejo $forgejo_version - local d=$PACKAGES_DIR/alpine-$forgejo_version + local d=$PACKAGES_DIR/alpine local token=$(cat $DIR/forgejo-curl/token) local url=http://${HOST_PORT} log_info "alpine:$alpine_version & Forgejo $forgejo_version" - docker run --rm --volume $d:$d:ro --workdir $d docker.io/alpine:$alpine_version ash -c "./test.sh $url $token" + docker run --rm --volume $d:$d:ro --workdir $d code.forgejo.org/oci/alpine:$alpine_version ash -c "./test.sh $url $token" } function test_packages_alpine() { - for alpine_version in 3.18 3.19 ; do - for forgejo_version in 1.21 7.0-test 7.0-dev ; do - test_packages_alpine_version $alpine_version $forgejo_version - done + local forgejo_versions="${1:-$RELEASE_NUMBERS}" + + for alpine_version in 3.22 3.23; do + for forgejo_version in $forgejo_versions; do + test_packages_alpine_version $alpine_version $forgejo_version + done done } diff --git a/packages/alpine-7.0-test/package-source/forgejo-2173/APKBUILD b/packages/alpine/package-source/forgejo-2173/APKBUILD similarity index 100% rename from packages/alpine-7.0-test/package-source/forgejo-2173/APKBUILD rename to packages/alpine/package-source/forgejo-2173/APKBUILD diff --git a/packages/alpine-7.0-test/package-source/forgejo-2173/forgejo_2173 b/packages/alpine/package-source/forgejo-2173/forgejo_2173 similarity index 100% rename from packages/alpine-7.0-test/package-source/forgejo-2173/forgejo_2173 rename to packages/alpine/package-source/forgejo-2173/forgejo_2173 diff --git a/packages/alpine-7.0-test/package-source/forgejo-2173/forgejo_2173.init b/packages/alpine/package-source/forgejo-2173/forgejo_2173.init similarity index 100% rename from packages/alpine-7.0-test/package-source/forgejo-2173/forgejo_2173.init rename to packages/alpine/package-source/forgejo-2173/forgejo_2173.init diff --git a/packages/alpine-1.21/package-source/APKBUILD b/packages/alpine/package-source/forgejo-2174/APKBUILD similarity index 100% rename from packages/alpine-1.21/package-source/APKBUILD rename to packages/alpine/package-source/forgejo-2174/APKBUILD diff --git a/packages/alpine-1.21/package-source/forgejo_2174 b/packages/alpine/package-source/forgejo-2174/forgejo_2174 similarity index 100% rename from packages/alpine-1.21/package-source/forgejo_2174 rename to packages/alpine/package-source/forgejo-2174/forgejo_2174 diff --git a/packages/alpine-1.21/package-source/forgejo_2174.init b/packages/alpine/package-source/forgejo-2174/forgejo_2174.init similarity index 100% rename from packages/alpine-1.21/package-source/forgejo_2174.init rename to packages/alpine/package-source/forgejo-2174/forgejo_2174.init diff --git a/packages/alpine-7.0-test/test.sh b/packages/alpine/test.sh similarity index 69% rename from packages/alpine-7.0-test/test.sh rename to packages/alpine/test.sh index 45bb60e9..4676e7ce 100755 --- a/packages/alpine-7.0-test/test.sh +++ b/packages/alpine/test.sh @@ -6,7 +6,7 @@ forgejo_token=$2 # initialize abuild apk update -apk add --no-cache alpine-sdk sudo util-linux +apk add --no-cache alpine-sdk sudo util-linux curl adduser -D user -h /home/user addgroup user abuild echo "root ALL=(ALL) ALL" >/etc/sudoers @@ -36,28 +36,28 @@ sudo -u user APKBUILD=alpine/forgejo-2173/APKBUILD abuild -r # upload new package cd packages/alpine/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/e2e-tests/$file" \ - || true + # remove old package + curl \ + --fail \ + -H "Authorization: token $forgejo_token" \ + -X DELETE \ + "$forgejo_url/api/packages/root/alpine/3.21/e2e-tests/$file" || + true - # upload new package - curl \ - --fail \ - -H "Authorization: token $forgejo_token" \ - -T "$file" \ - "$forgejo_url/api/packages/root/alpine/3.19/e2e-tests" + # upload new package + curl \ + --fail \ + -H "Authorization: token $forgejo_token" \ + -T "$file" \ + "$forgejo_url/api/packages/root/alpine/3.21/e2e-tests" 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/e2e-tests" >>/etc/apk/repositories +echo "$forgejo_url/api/packages/root/alpine/3.21/e2e-tests" >>/etc/apk/repositories apk add forgejo-2174 forgejo-2173 -[ -e /usr/bin/forgejo_2174 ] # from the installed package -[ -e /usr/bin/forgejo_2173 ] # from the installed package +[ -e /usr/bin/forgejo_2174 ] # from the installed package +[ -e /usr/bin/forgejo_2173 ] # from the installed package [ -e /etc/init.d/forgejo_2174 ] # from the -openrc package installed because of the install-if condition [ -e /etc/init.d/forgejo_2173 ] # from the -openrc package installed because of the install-if condition diff --git a/packages/packages.sh b/packages/packages.sh index 002ed796..4fc9c6a4 100644 --- a/packages/packages.sh +++ b/packages/packages.sh @@ -7,5 +7,7 @@ PACKAGES_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source $PACKAGES_DIR/alpine.sh function test_packages() { - run test_packages_alpine + local forgejo_versions="${1:-$RELEASE_NUMBERS}" + + run test_packages_alpine $forgejo_versions } diff --git a/renovate.json b/renovate.json new file mode 100644 index 00000000..6b4cadc2 --- /dev/null +++ b/renovate.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "local>forgejo/renovate-config" + ], + "packageRules": [ + { + "description": "Separate test actions", + "matchFileNames": ["actions/**"], + "additionalBranchPrefix": "actions", + "commitMessageTopic": "{{depName}} (test actions)" + } + ] +} diff --git a/run.sh b/run.sh new file mode 100755 index 00000000..92a91611 --- /dev/null +++ b/run.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +podman build -t forgejo-e2e . +patchelf ../forgejo/forgejo --set-interpreter /lib64/ld-linux-x86-64.so.2 +podman run \ + -it --privileged \ + -v ../forgejo/gitea:/srv/forgejo-binaries/forgejo-14.0 \ + -p 3001-3003:3001-3003 \ + -p 4000:4000 \ + -p 8080:8080 \ + forgejo-e2e diff --git a/storage/default-app.ini b/storage/default-app.ini index 113f242d..21f95ffc 100644 --- a/storage/default-app.ini +++ b/storage/default-app.ini @@ -1,5 +1,5 @@ RUN_MODE = prod -WORK_PATH = ${WORK_PATH} +WORK_PATH = forgejo-work-path [server] APP_DATA_PATH = ${WORK_PATH}/data @@ -15,7 +15,7 @@ PATH = ${WORK_PATH}/forgejo.db [log] MODE = file LEVEL = trace -ROUTER = file +logger.router.MODE = file [log.file] FILE_NAME = forgejo.log diff --git a/storage/misplace-app.ini b/storage/misplace-app.ini deleted file mode 100644 index 9ffe725d..00000000 --- a/storage/misplace-app.ini +++ /dev/null @@ -1,60 +0,0 @@ -RUN_MODE = prod -WORK_PATH = ${WORK_PATH} - -[server] -APP_DATA_PATH = ${WORK_PATH}/elsewhere -DOMAIN = ${IP} -HTTP_PORT = 3000 -SSH_LISTEN_PORT = 2222 -LFS_START_SERVER = true - -[database] -DB_TYPE = sqlite3 - -[log] -MODE = file -LEVEL = debug -ROUTER = file - -[log.file] -FILE_NAME = forgejo.log - -[security] -INSTALL_LOCK = true - -[repository] -ENABLE_PUSH_CREATE_USER = true -DEFAULT_PUSH_CREATE_PRIVATE = false - -[actions] -ENABLED = true - -[attachment] - -[storage.attachments] -PATH = ${WORK_PATH}/data/attachments - -[lfs] - -[storage.lfs] -PATH = ${WORK_PATH}/data/lfs - -[avatar] - -[storage.avatars] -PATH = ${WORK_PATH}/data/avatars - -[repo-avatar] - -[storage.repo-avatars] -PATH = ${WORK_PATH}/data/repo-avatars - -[repo-archive] - -[storage.repo-archive] -PATH = ${WORK_PATH}/data/repo-archive - -[packages] - -[storage.packages] -PATH = ${WORK_PATH}/data/packages diff --git a/storage/misplace-s3-app.ini b/storage/misplace-s3-app.ini deleted file mode 100644 index 490abbe1..00000000 --- a/storage/misplace-s3-app.ini +++ /dev/null @@ -1,90 +0,0 @@ -RUN_MODE = prod -WORK_PATH = ${WORK_PATH} - -[server] -APP_DATA_PATH = ${WORK_PATH}/elsewhere -DOMAIN = ${IP} -HTTP_PORT = 3000 -SSH_LISTEN_PORT = 2222 -LFS_START_SERVER = true - -[database] -DB_TYPE = sqlite3 - -[log] -MODE = file -LEVEL = debug -ROUTER = file - -[log.file] -FILE_NAME = forgejo.log - -[security] -INSTALL_LOCK = true - -[repository] -ENABLE_PUSH_CREATE_USER = true -DEFAULT_PUSH_CREATE_PRIVATE = false - -[actions] -ENABLED = true - -[attachment] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[lfs] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[repo-avatar] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[avatar] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[repo-archive] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[packages] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false diff --git a/storage/misplace-s3-two-app.ini b/storage/misplace-s3-two-app.ini deleted file mode 100644 index bcf65c8e..00000000 --- a/storage/misplace-s3-two-app.ini +++ /dev/null @@ -1,114 +0,0 @@ -RUN_MODE = prod -WORK_PATH = ${WORK_PATH} - -[server] -APP_DATA_PATH = ${WORK_PATH}/elsewhere -DOMAIN = ${IP} -HTTP_PORT = 3000 -SSH_LISTEN_PORT = 2222 -LFS_START_SERVER = true - -[database] -DB_TYPE = sqlite3 - -[log] -MODE = file -LEVEL = debug -ROUTER = file - -[log.file] -FILE_NAME = forgejo.log - -[security] -INSTALL_LOCK = true - -[repository] -ENABLE_PUSH_CREATE_USER = true -DEFAULT_PUSH_CREATE_PRIVATE = false - -[actions] -ENABLED = true - -[storage.attachments] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[storage.lfs] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[picture] -AVATAR_STORAGE_TYPE = minio -REPOSITORY_AVATAR_STORAGE_TYPE = minio - -[storage.repo-avatars] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[storage.minio] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[storage] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[storage.avatars] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[storage.repo-archive] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false - -[storage.packages] -STORAGE_TYPE = minio -SERVE_DIRECT = false -MINIO_ENDPOINT = 127.0.0.1:9000 -MINIO_ACCESS_KEY_ID = 123456 -MINIO_SECRET_ACCESS_KEY = 12345678 -MINIO_BUCKET = forgejo -MINIO_LOCATION = us-east-1 -MINIO_USE_SSL = false diff --git a/storage/relative-app.ini b/storage/relative-app.ini deleted file mode 100644 index 5bce502a..00000000 --- a/storage/relative-app.ini +++ /dev/null @@ -1,45 +0,0 @@ -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 - -[database] -DB_TYPE = sqlite3 - -[log] -MODE = file -LEVEL = debug -ROUTER = file - -[log.file] -FILE_NAME = forgejo.log - -[security] -INSTALL_LOCK = true - -[repository] -ENABLE_PUSH_CREATE_USER = true -DEFAULT_PUSH_CREATE_PRIVATE = false - -[attachment] -PATH = relative-attachments - -[lfs] -PATH = relative-lfs - -[avatar] -PATH = relative-avatars - -[repo-avatar] -PATH = relative-repo-avatars - -[repo-archive] -PATH = relative-repo-archive - -[packages] -PATH = relative-packages diff --git a/storage/specific-app.ini b/storage/specific-app.ini index 980a3b09..02629581 100644 --- a/storage/specific-app.ini +++ b/storage/specific-app.ini @@ -1,5 +1,5 @@ RUN_MODE = prod -WORK_PATH = ${WORK_PATH} +WORK_PATH = forgejo-work-path [server] APP_DATA_PATH = ${WORK_PATH}/elsewhere @@ -14,7 +14,7 @@ DB_TYPE = sqlite3 [log] MODE = file LEVEL = debug -ROUTER = file +logger.router.MODE = file [log.file] FILE_NAME = forgejo.log diff --git a/storage/stable-s3-app.ini b/storage/stable-s3-app.ini index 667bfbac..ef4ff0bd 100644 --- a/storage/stable-s3-app.ini +++ b/storage/stable-s3-app.ini @@ -1,5 +1,5 @@ RUN_MODE = prod -WORK_PATH = ${WORK_PATH} +WORK_PATH = forgejo-work-path [server] APP_DATA_PATH = ${WORK_PATH}/elsewhere @@ -14,7 +14,7 @@ DB_TYPE = sqlite3 [log] MODE = file LEVEL = debug -ROUTER = file +logger.router.MODE = file [log.file] FILE_NAME = forgejo.log diff --git a/storage/storage-relative-app.ini b/storage/storage-relative-app.ini deleted file mode 100644 index d0b70234..00000000 --- a/storage/storage-relative-app.ini +++ /dev/null @@ -1,45 +0,0 @@ -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 - -[database] -DB_TYPE = sqlite3 - -[log] -MODE = file -LEVEL = debug -ROUTER = file - -[log.file] -FILE_NAME = forgejo.log - -[security] -INSTALL_LOCK = true - -[repository] -ENABLE_PUSH_CREATE_USER = true -DEFAULT_PUSH_CREATE_PRIVATE = false - -[storage.attachments] -PATH = relative-attachments - -[storage.lfs] -PATH = relative-lfs - -[storage.avatars] -PATH = relative-avatars - -[storage.repo-avatars] -PATH = relative-repo-avatars - -[storage.repo-archive] -PATH = relative-repo-archive - -[storage.packages] -PATH = relative-packages diff --git a/storage/storage.sh b/storage/storage.sh index b08e6bc6..8fdb64fc 100755 --- a/storage/storage.sh +++ b/storage/storage.sh @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -STORAGE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +STORAGE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" STORAGE_PATHS="attachments avatars lfs packages repo-archive repo-avatars" @@ -14,7 +14,7 @@ function storage_reset() { function verify_storage() { local work_path=$DIR/forgejo-work-path - for path in ${STORAGE_PATHS} ; do + for path in ${STORAGE_PATHS}; do test -d $work_path/data/$path done } @@ -22,7 +22,7 @@ function verify_storage() { function cleanup_storage() { local work_path=$DIR/forgejo-work-path - for path in ${STORAGE_PATHS} ; do + for path in ${STORAGE_PATHS}; do rm -fr $work_path/data/$path done } @@ -31,26 +31,19 @@ function test_storage_stable_s3() { local work_path=$DIR/forgejo-work-path local s3_backend=${1:-minio} - log_info "See also https://codeberg.org/forgejo/forgejo/issues/1338" - - for version in 1.18 1.19 1.20.2-0 1.20.3-0 1.20 1.21 $RELEASE_NUMBERS_AND_DEV ; do + for version in $RELEASE_NUMBERS; do log_info "Forgejo $version & $s3_backend" stop storage_reset stable-s3 start $version $s3_backend fixture_create - for fun in ${STORAGE_FUN} ; do + for fun in ${STORAGE_FUN}; do fixture_${fun}_assert_s3 done done } -source $STORAGE_DIR/test-upgrade-1.20-storage.sh - function test_storage() { run test_storage_stable_s3 minio run test_storage_stable_s3 garage - - test_upgrade_1_20_storage - run test_forgejo_database_v3_upgrades } diff --git a/storage/test-upgrade-1.20-storage.sh b/storage/test-upgrade-1.20-storage.sh deleted file mode 100644 index 063b56af..00000000 --- a/storage/test-upgrade-1.20-storage.sh +++ /dev/null @@ -1,223 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: MIT - -function test_downgrade_1.20.2_fails() { - local work_path=$DIR/forgejo-work-path - - log_info "See also https://codeberg.org/forgejo/forgejo/pulls/1225" - - log_info "downgrading from 1.20.3-0 to 1.20.2-0 fails" - stop - storage_reset default - start 1.20.3-0 - stop - download 1.20.2-0 - timeout 60 $DIR_BINARIES/forgejo-1.20.2-0 --config $work_path/app.ini --work-path $work_path || true - if ! grep --fixed-strings --quiet 'use the newer database' $work_path/log/forgejo.log ; then - cat $work_path/log/forgejo.log - return 1 - fi -} - -function test_bug_storage_merged() { - local work_path=$DIR/forgejo-work-path - - log_info "See also https://codeberg.org/forgejo/forgejo/pulls/1225" - - log_info "using < 1.20.3-0 and [storage].PATH merge all storage" - for version in 1.18.5-0 1.19.4-0 1.20.2-0 ; do - stop - storage_reset merged - start $version - for path in ${STORAGE_PATHS} ; do - ! test -d $work_path/data/$path - done - for path in ${STORAGE_PATHS} ; do - ! test -d $work_path/merged/$path - done - test -d $work_path/merged - done - stop - - log_info "upgrading from 1.20.2-0 with [storage].PATH fails" - download 1.20.3-0 - timeout 60 $DIR_BINARIES/forgejo-1.20.3-0 --config $work_path/app.ini --work-path $work_path || true - if ! grep --fixed-strings --quiet '[storage].PATH is set and may create storage issues' $work_path/log/forgejo.log ; then - cat $work_path/log/forgejo.log - return 1 - fi -} - -function test_bug_storage_relative_path() { - local work_path=$DIR/forgejo-work-path - - log_info "using < 1.20.3-0 legacy [server].XXXX and [picture].XXXX are relative to WORK_PATH" - for version in 1.18.5-0 1.19.4-0 1.20.2-0 ; do - stop - storage_reset legagy-relative - start $version - test -d $work_path/relative-lfs - test -d $work_path/relative-avatars - test -d $work_path/relative-repo-avatars - done - - log_info "using >= 1.20.3-0 legacy [server].XXXX and [picture].XXXX are relative to APP_DATA_PATH" - for version in 1.20.3-0 1.21.0-5-rc2 ; do - stop - storage_reset legagy-relative - start $version - test -d $work_path/data/relative-lfs - test -d $work_path/data/relative-avatars - test -d $work_path/data/relative-repo-avatars - done - - log_info "using >= 1.20.3-0 relative [storage.XXXX].PATHS are relative to APP_DATA_PATH" - for version in 1.20.3-0 1.21.0-5-rc2 ; do - stop - storage_reset storage-relative - start $version - for path in ${STORAGE_PATHS} ; do - test -d $work_path/data/relative-$path - done - done - - log_info "using 1.20.[12]-0 relative [storage.XXXX].PATHS are inconsistent" - for version in 1.20.2-0 ; do - stop - storage_reset storage-relative - start $version - test -d $work_path/data/packages - test -d $work_path/relative-repo-archive - test -d $work_path/relative-attachments - test -d $work_path/relative-lfs - test -d $work_path/data/avatars - test -d $work_path/data/repo-avatars - done - - log_info "using < 1.20 relative [storage.XXXX].PATHS are inconsistent" - for version in 1.18.5-0 1.19.4-0 ; do - stop - storage_reset storage-relative - start $version - test -d $work_path/relative-packages - test -d $work_path/relative-repo-archive - test -d $work_path/relative-attachments - test -d $work_path/data/lfs - test -d $work_path/data/avatars - test -d $work_path/data/repo-avatars - done - - log_info "using < 1.20.3-0 relative [XXXX].PATHS are relative to WORK_PATH" - for version in 1.18.5-0 1.19.4-0 1.20.2-0 ; do - stop - storage_reset relative - start $version - for path in ${STORAGE_PATHS} ; do - test -d $work_path/relative-$path - done - done - - log_info "using >= 1.20.3-0 relative [XXXX].PATHS are relative to APP_DATA_PATH" - for version in 1.20.3-0 1.21.0-5-rc2 ; do - stop - storage_reset relative - start $version - for path in ${STORAGE_PATHS} ; do - test -d $work_path/data/relative-$path - done - done - - stop -} - -function test_bug_storage_s3_misplace() { - local work_path=$DIR/forgejo-work-path - local s3_backend=${2:-minio} - - log_info "See also https://codeberg.org/forgejo/forgejo/issues/1338" - - for version in 1.20.2-0 1.20.3-0 ; do - log_info "Forgejo $version & $s3_backend" - stop - storage_reset misplace-s3 - start $version $s3_backend - fixture_create - for fun in ${STORAGE_FUN} ; do - fixture_${fun}_assert_s3 - done - done - - for version in 1.18.5-0 1.19.4-0 ; do - log_info "Forgejo $version & $s3_backend" - stop - storage_reset misplace-s3 - start $version $s3_backend - fixture_create - # - # some storage are in S3 - # - fixture_attachments_assert_s3 - fixture_lfs_assert_s3 - # - # others are in local - # - fixture_repo_archive_assert_local elsewhere/repo-archive - fixture_avatars_assert_local elsewhere/avatars - fixture_packages_assert_local elsewhere/packages - fixture_repo_avatars_assert_local elsewhere/repo-avatars - done -} - -function test_bug_storage_misplace() { - local work_path=$DIR/forgejo-work-path - - log_info "See also https://codeberg.org/forgejo/forgejo/pulls/1225" - - log_info "using < 1.20 and conflicting sections misplace storage" - for version in 1.18.5-0 1.19.4-0 ; do - stop - storage_reset misplace - start $version - # - # some storage are where they should be - # - test -d $work_path/data/packages - test -d $work_path/data/repo-archive - test -d $work_path/data/attachments - # - # others are under APP_DATA_PATH - # - test -d $work_path/elsewhere/lfs - test -d $work_path/elsewhere/avatars - test -d $work_path/elsewhere/repo-avatars - done - - log_info "using < 1.20.[12]-0 and conflicting sections ignores [storage.*]" - for version in 1.20.2-0 ; do - stop - storage_reset misplace - start $version - for path in ${STORAGE_PATHS} ; do - test -d $work_path/elsewhere/$path - done - done - - stop - - log_info "upgrading from 1.20.2-0 with conflicting sections fails" - download 1.20.3-0 - timeout 60 $DIR_BINARIES/forgejo-1.20.3-0 --config $work_path/app.ini --work-path $work_path || true - for path in ${STORAGE_PATHS} ; do - if ! grep --fixed-strings --quiet "[storage.$path] may conflict" $work_path/log/forgejo.log ; then - cat $work_path/log/forgejo.log - return 1 - fi - done -} - -function test_upgrade_1_20_storage() { - run test_bug_storage_misplace - run test_bug_storage_merged - run test_downgrade_1.20.2_fails - run test_bug_storage_s3_misplace -} diff --git a/upgrade/default-app.ini b/upgrade/default-app.ini index e8134aaf..49674738 100644 --- a/upgrade/default-app.ini +++ b/upgrade/default-app.ini @@ -1,5 +1,5 @@ RUN_MODE = prod -WORK_PATH = ${WORK_PATH} +WORK_PATH = forgejo-work-path [server] APP_DATA_PATH = ${WORK_PATH}/data @@ -22,7 +22,7 @@ PATH = ${WORK_PATH}/forgejo.db [log] MODE = file LEVEL = trace -ROUTER = file +logger.router.MODE = file [log.file] FILE_NAME = forgejo.log diff --git a/upgrade/test-pprof-upload.sh b/upgrade/test-pprof-upload.sh index 80425a9c..4495891a 100644 --- a/upgrade/test-pprof-upload.sh +++ b/upgrade/test-pprof-upload.sh @@ -1,42 +1,42 @@ # SPDX-License-Identifier: MIT function test_upload_profiles() { - FORGEJO_URL="http://localhost:6060" - PROFILECLI_URL="http://0.0.0.0:4040" + FORGEJO_URL="http://localhost:6060" + PROFILECLI_URL="http://0.0.0.0:4040" - endpoints=("/debug/pprof/allocs" "/debug/pprof/block" "/debug/pprof/goroutine" "/debug/pprof/mutex" "/debug/pprof/profile?seconds=5") - curl -fL https://github.com/grafana/pyroscope/releases/download/v1.1.5/profilecli_1.1.5_linux_amd64.tar.gz -o profilecli.tar.gz - tar xzf profilecli.tar.gz + endpoints=("/debug/pprof/allocs" "/debug/pprof/block" "/debug/pprof/goroutine" "/debug/pprof/mutex" "/debug/pprof/profile?seconds=5") + curl -fL https://github.com/grafana/pyroscope/releases/download/v1.1.5/profilecli_1.1.5_linux_amd64.tar.gz -o profilecli.tar.gz + tar xzf profilecli.tar.gz - for endpoint in "${endpoints[@]}"; do - output=$(basename "$endpoint") - if [[ $endpoint == *"/profile"* ]]; then - output="profile" - fi - output="${output}.pprof" - # Download the content and save it to a file - curl -s "${FORGEJO_URL}${endpoint}" -o "${output}" - ./profilecli upload ${output} --url=${PROFILECLI_URL} + for endpoint in "${endpoints[@]}"; do + output=$(basename "$endpoint") + if [[ $endpoint == *"/profile"* ]]; then + output="profile" + fi + output="${output}.pprof" + # Download the content and save it to a file + curl -s "${FORGEJO_URL}${endpoint}" -o "${output}" + ./profilecli upload ${output} --url=${PROFILECLI_URL} - rm ${output} - done + rm ${output} + done } +PYROSCOPE_VERSION=1.12.1 # renovate: datasource=docker depName=data.forgejo.org/oci/pyroscope + function test_forgejo_pprof() { - stop - docker run --name test_pyroscope --rm -d -p 4040:4040 docker.io/grafana/pyroscope + stop + docker rm -f test_pyroscope + docker run --name test_pyroscope --rm -d -p 4040:4040 data.forgejo.org/oci/pyroscope:$PYROSCOPE_VERSION - - log_info "run 7.0-test" - start 7.0-test - test_upload_profiles - stop + reset_forgejo $UPGRADE_DIR/default-app.ini - log_info "run 8.0-test" - start 8.0-test - test_upload_profiles - stop - - docker stop test_pyroscope + for version in $RELEASE_NUMBERS; do + log_info "run $version" + start $version + test_upload_profiles + stop + done + docker stop test_pyroscope } diff --git a/upgrade/test-upgrade-forgejo-database-v3.sh b/upgrade/test-upgrade-forgejo-database-v3.sh deleted file mode 100644 index f15a4f38..00000000 --- a/upgrade/test-upgrade-forgejo-database-v3.sh +++ /dev/null @@ -1,35 +0,0 @@ -# SPDX-License-Identifier: MIT - -function test_forgejo_database_version() { - local expected_version=$1 - local work_path=$DIR/forgejo-work-path - - actual_version=$(sqlite3 $work_path/forgejo.db "select version from forgejo_version") - test "$expected_version" = "$actual_version" -} - -function test_forgejo_database_v3_upgrades_list_table() { - local table=$1 - local work_path=$DIR/forgejo-work-path - - sqlite3 $work_path/forgejo.db ".tables $table" .exit | grep --quiet $table -} - -function test_forgejo_database_v3_upgrades() { - local table=forgejo_auth_token - - stop - - upgrade_reset default - log_info "run 1.20.4-1" - start 1.20.4-1 - stop - ! test_forgejo_database_v3_upgrades_list_table $table - test_forgejo_database_version 2 - - log_info "run 1.20.5-0" - start 1.20.5-0 - stop - test_forgejo_database_v3_upgrades_list_table $table - test_forgejo_database_version 3 -} diff --git a/upgrade/upgrade.sh b/upgrade/upgrade.sh index 8de99032..29142499 100755 --- a/upgrade/upgrade.sh +++ b/upgrade/upgrade.sh @@ -1,17 +1,17 @@ # SPDX-License-Identifier: MIT -UPGRADE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +UPGRADE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" function upgrade_reset() { local config=$1 - reset_forgejo $UPGRADE_DIR/$config-app.ini + reset_forgejo $config reset_minio } function verify_storage() { local work_path=$DIR/forgejo-work-path - for path in ${STORAGE_PATHS} ; do + for path in ${STORAGE_PATHS}; do test -d $work_path/data/$path done } @@ -19,88 +19,92 @@ function verify_storage() { function cleanup_storage() { local work_path=$DIR/forgejo-work-path - for path in ${STORAGE_PATHS} ; do + for path in ${STORAGE_PATHS}; do rm -fr $work_path/data/$path done } function test_successful_upgrades() { stop - for config in default ; do - log_info "using $config app.ini" + for config in $UPGRADE_DIR/default-app.ini; do + log_info "using $config" upgrade_reset $config - version=1.18 + set $RELEASE_NUMBERS + version="$1" + shift log_info "run $version" cleanup_storage - start $version - fixture_create - fixture_assert - doctor_run $version + start $version + fixture_create + fixture_assert + doctor_run $config - for version in 1.19 1.20 1.21 $RELEASE_NUMBERS_AND_DEV ; do + for version in $@; do stop log_info "run $version" start $version verify_storage - fixture_assert - doctor_run $version + fixture_assert + doctor_run $config done + + migration_assert done } -function download_gitea() { - local version=$1 +function migration_assert() { + local work_path=$DIR/forgejo-work-path + local logfile=$work_path/log/forgejo.log - if ! test -f $DIR_BINARIES/gitea-$version ; then - mkdir -p $DIR_BINARIES - wget -O $DIR_BINARIES/gitea-$version --quiet https://dl.gitea.com/gitea/$version/gitea-$version-linux-amd64 - chmod +x $DIR_BINARIES/gitea-$version + grep --quiet 'ORM engine initialization successful' $logfile + if grep 'serveInstalled() \[[EW]\] Table' $logfile; then + echo "unexpected warnings in database initialization" + return 1 + fi + if grep 'Migrate() \[[EW]\]' $logfile; then + echo "unexpected warnings in database migration" + return 1 fi } -function start_gitea() { - local version=$1 - - download_gitea $version - start_forgejo_daemon $version $DIR_BINARIES/gitea-$version -} - function test_gitea_upgrades() { - stop - for config in default ; do - log_info "using $config app.ini" + local config=$UPGRADE_DIR/default-app.ini + # The Forgejo target migration version must be 10.0 because it is the last supported. + # https://forgejo.org/2024-12-gitea-compatibility/ + ( + echo gitea 1.21 forgejo 10.0 + echo gitea 1.22 forgejo 10.0 + ) | while read gitea gitea_version forgejo forgejo_version; do + log_info "upgrading from Gitea $gitea_version to Forgejo $forgejo_version" + stop upgrade_reset $config - version=1.21.10 - log_info "run gitea $version" + log_info "run Gitea $gitea_version" cleanup_storage - start_s3 minio - start_gitea $version - fixture_create - fixture_assert - doctor_run $version + start_s3 minio + start_gitea $gitea_version $config + fixture_create + fixture_assert + doctor_run $config - for version in 7.0-test ; do - stop - log_info "run forgejo $version" - start $version - verify_storage - fixture_assert - doctor_run $version - done + stop + log_info "run Forgejo $forgejo_version" + start $forgejo_version + verify_storage + fixture_assert + doctor_run $config + + migration_assert done } -source $UPGRADE_DIR/test-upgrade-forgejo-database-v3.sh source $UPGRADE_DIR/test-pprof-upload.sh function test_upgrades() { run dependencies - run build_all run test_successful_upgrades - run test_forgejo_database_v3_upgrades run test_forgejo_pprof run test_gitea_upgrades }