name: checks
on:
  push:
    branches:
      - 'main'
  pull_request:

enable-email-notifications: true

env:
  FORGEJO_HOST_PORT: 'forgejo:3000'
  FORGEJO_ADMIN_USER: 'root'
  FORGEJO_ADMIN_PASSWORD: 'admin1234'
  FORGEJO_RUNNER_SECRET: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
  FORGEJO_SCRIPT: |
    /usr/bin/s6-svscan /etc/s6 & sleep 10 ; su -c "forgejo admin user create --admin --username $FORGEJO_ADMIN_USER --password $FORGEJO_ADMIN_PASSWORD --email root@example.com" git && su -c "forgejo forgejo-cli actions register --labels docker --name therunner --secret $FORGEJO_RUNNER_SECRET" git && sleep infinity

jobs:
  build-and-tests:
    name: build and test
    if: vars.ROLE == 'forgejo-coding'
    runs-on: docker
    container:
      image: 'code.forgejo.org/oci/ci:1'

    services:
      forgejo:
        image: code.forgejo.org/forgejo/forgejo:11
        env:
          FORGEJO__security__INSTALL_LOCK: "true"
          FORGEJO__log__LEVEL: "debug"
          FORGEJO__actions__ENABLED: "true"
          FORGEJO_ADMIN_USER: root
          FORGEJO_ADMIN_PASSWORD: admin1234
          FORGEJO_RUNNER_SECRET: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
        cmd:
          - 'bash'
          - '-c'
          - '/usr/bin/s6-svscan /etc/s6 & sleep 10 ; su -c "forgejo admin user create --admin --username $FORGEJO_ADMIN_USER --password $FORGEJO_ADMIN_PASSWORD --email root@example.com" git && su -c "forgejo forgejo-cli actions register --labels docker --name therunner --secret $FORGEJO_RUNNER_SECRET" git && sleep infinity'

    steps:
      - uses: https://data.forgejo.org/actions/checkout@v4

      - uses: https://data.forgejo.org/actions/setup-go@v5
        with:
          go-version-file: go.mod

      - name: validate go version
        run: |
          set -ex
          toolchain=$(grep -oP '(?<=toolchain ).+' go.mod)
          version=$(go version | cut -d' ' -f3)
          if dpkg --compare-versions ${version#go} lt ${toolchain#go}; then
            echo "go version too low: $toolchain >= $version"
            exit 1
          fi

      - run: make vet

      - run: make build

      - uses: https://data.forgejo.org/actions/upload-artifact@v3
        with:
          name: forgejo-runner
          path: forgejo-runner

      - name: check the forgejo server is responding
        run: |
          sleep 10 # matches the sleep 10 in the bootstrap of the Forgejo instance
          # in case of a slow machine, give it time to bootstrap
          retry --delay=10 --times=6 bash -c 'test $FORGEJO_ADMIN_USER = $(curl -sS http://$FORGEJO_ADMIN_USER:$FORGEJO_ADMIN_PASSWORD@$FORGEJO_HOST_PORT/api/v1/user | jq --raw-output .login)'

      - run: make FORGEJO_URL=http://$FORGEJO_HOST_PORT test

  runner-exec-tests:
    name: runner exec tests
    if: vars.ROLE == 'forgejo-coding'
    runs-on: lxc-bookworm
    needs: [build-and-tests]
    steps:

      - uses: https://data.forgejo.org/actions/checkout@v4

      - uses: https://data.forgejo.org/actions/download-artifact@v3
        with:
          name: forgejo-runner

      - run: chmod +x forgejo-runner

      - name: install docker
        run: |
          mkdir /etc/docker
          cat > /etc/docker/daemon.json  <<EOF
          {
            "ipv6": true,
            "experimental": true,
            "ip6tables": true,
            "fixed-cidr-v6": "fd05:d0ca:1::/64",
            "default-address-pools": [
              {
                "base": "172.19.0.0/16",
                "size": 24
              },
              {
                "base": "fd05:d0ca:2::/104",
                "size": 112
              }
            ]
          }
          EOF
          apt --quiet install --yes -qq docker.io

      - name: forgejo-runner exec --enable-ipv6
        run: |
          set -x
          ./forgejo-runner exec --enable-ipv6 --workflows .forgejo/testdata/ipv6.yml
          if ./forgejo-runner exec --workflows .forgejo/testdata/ipv6.yml >& /tmp/out ; then
             cat /tmp/out
             echo "IPv6 not enabled, should fail"
             exit 1
          fi

      - name: forgejo-runner exec --var
        run: |
          set -x
          ./forgejo-runner exec --var MY_VAR=testvariable --workflows .forgejo/testdata/var.yml |& tee /tmp/var.out
          grep --quiet 'Success - Main echo "VAR -> testvariable"' /tmp/var.out

  integration-tests:
    name: integration tests
    if: vars.ROLE == 'forgejo-coding'
    runs-on: lxc-bookworm
    steps:
      - uses: https://data.forgejo.org/actions/checkout@v4

      - uses: https://data.forgejo.org/actions/setup-go@v5
        with:
          go-version-file: go.mod

      - name: apt install docker.io
        run: |
          export DEBIAN_FRONTEND=noninteractive
          apt-get update -qq
          apt-get -q install -qq -y docker.io

      - run: apt-get -q install -qq -y gcc # required for `-race`
      - name: integration test
        run: |
          go test -race ./act/container
          go test -race -timeout 30m ./act/runner/...

  runner-integration-tests:
    name: runner integration tests
    if: vars.ROLE == 'forgejo-coding'
    runs-on: lxc-bookworm
    needs: [build-and-tests]

    steps:
      - uses: https://data.forgejo.org/actions/checkout@v4

      - uses: https://data.forgejo.org/actions/setup-go@v5
        with:
          go-version-file: go.mod

      - name: install docker
        run: |
          mkdir /etc/docker
          cat > /etc/docker/daemon.json  <<EOF
          {
            "ipv6": true,
            "experimental": true,
            "ip6tables": true,
            "fixed-cidr-v6": "fd05:d0ca:1::/64",
            "default-address-pools": [
              {
                "base": "172.19.0.0/16",
                "size": 24
              },
              {
                "base": "fd05:d0ca:2::/104",
                "size": 112
              }
            ]
          }
          EOF
          apt --quiet install --yes -qq docker.io make

      - name: install LXC
        run: |
          act/runner/lxc-helpers.sh lxc_prepare_environment
          act/runner/lxc-helpers.sh lxc_install_lxc_inside 10.39.28 fdb1

      - run: apt-get -q install -qq -y gcc # required for `-race`

      - run: make integration-test

  validate-mocks:
    name: validate mocks
    if: vars.ROLE == 'forgejo-coding'
    runs-on: docker
    container:
      image: 'code.forgejo.org/oci/ci:1'

    steps:
      - uses: https://data.forgejo.org/actions/checkout@v4

      - uses: https://data.forgejo.org/actions/setup-go@v5
        with:
          go-version-file: go.mod

      - name: generate mocks
        run: |
          set -ex
          make deps-tools
          make generate
          make fmt

      - name: validate mocks
        run: |
          git diff --ignore-matching-lines='Code generated by mockery.*DO NOT EDIT' --quiet || {
            echo "[ERROR] Please apply the changes mockery suggests:"
            git diff --color=always
            exit 1
          }

  validate-pre-commit:
    name: validate pre-commit-hooks file
    if: vars.ROLE == 'forgejo-coding'
    runs-on: docker
    container:
      image: 'code.forgejo.org/oci/ci:1'

    steps:
      - uses: https://data.forgejo.org/actions/checkout@v4

      - name: install pre-commit
        env:
          DEBIAN_FRONTEND: noninteractive
          PIP_ROOT_USER_ACTION: ignore
          PIP_BREAK_SYSTEM_PACKAGES: 1
          PIP_PROGRESS_BAR: off
        run: |
          apt-get update -qq
          apt-get -q install -qq -y python3-pip
          python3 -m pip install 'pre-commit>=3.2.0'

      - name: validate .pre-commit-hooks.yaml
        run: pre-commit validate-manifest .pre-commit-hooks.yaml

      # Will fail due to `act/runner/testdata/local-action-fails-schema-validation/action/action.yml`
      - name: check pre-commit hook against local action files (should fail)
        continue-on-error: true
        run: |
          pre-commit try-repo --all-files --verbose . forgejo-runner-validate

      - name: check that a bad workflow file doesn’t validate (should fail)
        continue-on-error: true
        run: |
          mkdir -p test-repo
          cd test-repo
          git config set advice.defaultBranchName false
          git init --quiet
          mkdir -p .forgejo/workflows
          cp ../act/runner/testdata/local-action-fails-schema-validation/action/action.yml ./
          touch .forgejo/workflows/bad-workflow.yml
          cat > .pre-commit-config.yaml <<EOF
          repos:
            - repo: ..
              rev: ${{ forge.sha }}
              hooks:
                - id: forgejo-runner-validate
          EOF
          git add .
          pre-commit run --all-files --verbose forgejo-runner-validate
