diff --git a/.forgejo/cascading-pr-setup-forgejo b/.forgejo/cascading-pr-setup-forgejo deleted file mode 100755 index 06472a7..0000000 --- a/.forgejo/cascading-pr-setup-forgejo +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -set -ex - -setup_forgejo=$1 -setup_forgejo_pr=$2 -runner=$3 -runner_pr=$4 - -url=$(jq --raw-output .head.repo.html_url < $runner_pr) -test "$url" != null -branch=$(jq --raw-output .head.ref < $runner_pr) -test "$branch" != null -cd $setup_forgejo -./utils/upgrade-runner.sh $url @$branch -date > last-upgrade diff --git a/.forgejo/labelscompare.py b/.forgejo/labelscompare.py deleted file mode 100644 index 2274d38..0000000 --- a/.forgejo/labelscompare.py +++ /dev/null @@ -1,24 +0,0 @@ -import json - -expectedLabels = { - "maintainer": "contact@forgejo.org", - "org.opencontainers.image.authors": "Forgejo", - "org.opencontainers.image.url": "https://forgejo.org", - "org.opencontainers.image.documentation": "https://forgejo.org/docs/latest/admin/actions/#forgejo-runner", - "org.opencontainers.image.source": "https://code.forgejo.org/forgejo/runner", - "org.opencontainers.image.version": "1.2.3", - "org.opencontainers.image.vendor": "Forgejo", - "org.opencontainers.image.licenses": "MIT", - "org.opencontainers.image.title": "Forgejo Runner", - "org.opencontainers.image.description": "A runner for Forgejo Actions.", -} -inspect = None -with open("./labels.json", "r") as f: - inspect = json.load(f) - -assert inspect -labels = inspect[0]["Config"]["Labels"] - -for k, v in expectedLabels.items(): - assert k in labels, f"'{k}' is missing from labels" - assert labels[k] == v, f"expected {v} in key {k}, found {labels[k]}" diff --git a/.forgejo/testdata/ipv6.yml b/.forgejo/testdata/ipv6.yml deleted file mode 100644 index e0f7588..0000000 --- a/.forgejo/testdata/ipv6.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -on: push -jobs: - ipv6: - runs-on: docker - container: - image: code.forgejo.org/oci/debian:bookworm - steps: - - run: | - apt update -qq ; apt --quiet install -qq --yes iputils-ping - ping -c 1 -6 ::1 diff --git a/.forgejo/workflows/build-release-integration.yml b/.forgejo/workflows/build-release-integration.yml deleted file mode 100644 index 7f92218..0000000 --- a/.forgejo/workflows/build-release-integration.yml +++ /dev/null @@ -1,90 +0,0 @@ -name: Integration tests for the release process - -on: - push: - paths: - - go.mod - - Dockerfile - - .forgejo/workflows/build-release.yml - - .forgejo/workflows/build-release-integration.yml - pull_request: - paths: - - go.mod - - Dockerfile - - .forgejo/workflows/build-release.yml - - .forgejo/workflows/build-release-integration.yml - -jobs: - release-simulation: - runs-on: self-hosted - if: github.repository_owner != 'forgejo-integration' && github.repository_owner != 'forgejo-release' - steps: - - uses: actions/checkout@v3 - - - id: forgejo - uses: https://code.forgejo.org/actions/setup-forgejo@v1 - with: - user: root - password: admin1234 - image-version: 1.20 - lxc-ip-prefix: 10.0.9 - - - name: publish - run: | - set -x - - version=1.2.3 - cat > /etc/docker/daemon.json < $binary$suffix - if test "$suffix" = .xz ; then - unxz --keep $binary$suffix - fi - chmod +x $binary - ./$binary --version | grep $version - curl --fail -L -sS $url/root/runner/releases/download/v$version/$binary$suffix.sha256 > $binary$suffix.sha256 - shasum -a 256 --check $binary$suffix.sha256 - rm $binary$suffix - done - done - - docker pull ${{ steps.forgejo.outputs.host-port }}/root/runner:$version - - docker inspect ${{ steps.forgejo.outputs.host-port}}/root/runner:$version > labels.json - python3 .forgejo/labelscompare.py diff --git a/.forgejo/workflows/build-release.yml b/.forgejo/workflows/build-release.yml index 162befb..874f733 100644 --- a/.forgejo/workflows/build-release.yml +++ b/.forgejo/workflows/build-release.yml @@ -1,16 +1,6 @@ -# SPDX-License-Identifier: MIT -# -# https://code.forgejo.org/forgejo/runner -# -# Build the runner binaries and OCI images -# -# ROLE: forgejo-integration -# DOER: forgejo-ci -# TOKEN: -# name: Build release -on: +on: push: tags: 'v*' @@ -18,86 +8,126 @@ jobs: release: runs-on: self-hosted # root is used for testing, allow it - if: secrets.ROLE == 'forgejo-integration' || github.repository_owner == 'root' + if: github.repository_owner == 'forgejo-integration' || github.repository_owner == 'root' steps: - uses: actions/checkout@v3 - - name: Increase the verbosity when there are no secrets - id: verbose + - id: verbose run: | + # if there are no secrets, be verbose if test -z "${{ secrets.TOKEN }}"; then value=true else value=false fi echo "value=$value" >> "$GITHUB_OUTPUT" - - - name: Sanitize the name of the repository - id: repository + echo "shell=set -x" >> "$GITHUB_OUTPUT" + + - id: registry run: | - echo "value=${GITHUB_REPOSITORY##*/}" >> "$GITHUB_OUTPUT" - - - name: create test TOKEN - id: token - if: ${{ secrets.TOKEN == '' }} - run: | - apt-get -qq install -y jq + ${{ steps.verbose.outputs.shell }} url="${{ env.GITHUB_SERVER_URL }}" hostport=${url##http*://} hostport=${hostport%%/} - doer=root - api=http://$doer:admin1234@$hostport/api/v1/users/$doer/tokens - curl -sS -X DELETE $api/release - token=$(curl -sS -X POST -H 'Content-Type: application/json' --data-raw '{"name": "release", "scopes": ["all"]}' $api | jq --raw-output .sha1) - echo "value=${token}" >> "$GITHUB_OUTPUT" - - - name: version from ref_name - id: tag-version - run: | - version=${GITHUB_REF_NAME##*v} - echo "value=$version" >> "$GITHUB_OUTPUT" - - - name: release notes - id: release-notes - run: | - anchor=${{ steps.tag-version.outputs.value }} - anchor=${anchor//./-} + echo "host-port=${hostport}" >> "$GITHUB_OUTPUT" + if ! [[ $url =~ ^http:// ]] ; then + exit 0 + fi cat >> "$GITHUB_OUTPUT" <> "$GITHUB_OUTPUT" + echo "doer=${doer}" >> "$GITHUB_OUTPUT" - - name: build without TOKEN + - name: allow docker pull/push to forgejo + if: ${{ steps.registry.outputs.insecure }} + run: |- + mkdir /etc/docker + cat > /etc/docker/daemon.json < ~/.docker/config.json + env: + CI_REGISTRY: "${{ env.GITHUB_SERVER_URL }}${{ env.GITHUB_REPOSITORY_OWNER }}" + + - id: build + run: | + ${{ steps.verbose.outputs.shell }} + tag="${{ github.ref_name }}" + tag=${tag##*v} + echo "tag=$tag" >> "$GITHUB_OUTPUT" + echo "image=${{ steps.registry.outputs.host-port }}/${{ github.repository }}:${tag}" >> "$GITHUB_OUTPUT" + + - uses: https://github.com/docker/build-push-action@v4 + # workaround until https://github.com/docker/build-push-action/commit/d8823bfaed2a82c6f5d4799a2f8e86173c461aba is in @v4 or @v5 is released + env: + ACTIONS_RUNTIME_TOKEN: '' + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.build.outputs.image }} + + - run: | + ${{ steps.verbose.outputs.shell }} + mkdir -p release + for arch in amd64 arm64; do + docker create --platform linux/$arch --name runner ${{ steps.build.outputs.image }} + docker cp runner:/bin/forgejo-runner release/forgejo-runner-$arch + shasum -a 256 < release/forgejo-runner-$arch | cut -f1 -d ' ' > release/forgejo-runner-$arch.sha256 + docker rm runner + done + + - name: publish release (when TOKEN secret is NOT set) if: ${{ secrets.TOKEN == '' }} - uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v5 + uses: https://code.forgejo.org/actions/forgejo-release@v1 with: - forgejo: "${{ env.GITHUB_SERVER_URL }}" - owner: "${{ env.GITHUB_REPOSITORY_OWNER }}" - repository: "${{ steps.repository.outputs.value }}" - doer: root - sha: "${{ github.sha }}" - release-version: "${{ steps.tag-version.outputs.value }}" - token: ${{ steps.token.outputs.value }} - platforms: linux/amd64,linux/arm64 - release-notes: "${{ steps.release-notes.outputs.value }}" - binary-name: forgejo-runner - binary-path: /bin/forgejo-runner + direction: upload + release-dir: release + release-notes: "RELEASE-NOTES#${{ steps.build.outputs.tag }}" + token: ${{ steps.secrets.outputs.token }} verbose: ${{ steps.verbose.outputs.value }} - - name: build with TOKEN + - name: publish release (when TOKEN secret is set) if: ${{ secrets.TOKEN != '' }} - uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v5 + uses: https://code.forgejo.org/actions/forgejo-release@v1 with: - forgejo: "${{ env.GITHUB_SERVER_URL }}" - owner: "${{ env.GITHUB_REPOSITORY_OWNER }}" - repository: "${{ steps.repository.outputs.value }}" - doer: "${{ secrets.DOER }}" - sha: "${{ github.sha }}" - release-version: "${{ steps.tag-version.outputs.value }}" - token: "${{ secrets.TOKEN }}" - platforms: linux/amd64,linux/arm64 - release-notes: "${{ steps.release-notes.outputs.value }}" - binary-name: forgejo-runner - binary-path: /bin/forgejo-runner + direction: upload + release-dir: release + release-notes: "RELEASE-NOTES#${{ steps.build.outputs.tag }}" + token: ${{ secrets.TOKEN }} verbose: ${{ steps.verbose.outputs.value }} diff --git a/.forgejo/workflows/cascade-setup-forgejo.yml b/.forgejo/workflows/cascade-setup-forgejo.yml deleted file mode 100644 index 6d94f01..0000000 --- a/.forgejo/workflows/cascade-setup-forgejo.yml +++ /dev/null @@ -1,25 +0,0 @@ -# SPDX-License-Identifier: MIT -on: - pull_request_target: - types: - - opened - - synchronize - - closed -jobs: - cascade: - runs-on: docker - if: vars.CASCADE != 'no' - steps: - - uses: actions/cascading-pr@v1 - with: - origin-url: ${{ env.GITHUB_SERVER_URL }} - origin-repo: forgejo/runner - origin-token: ${{ secrets.CASCADING_PR_ORIGIN }} - origin-pr: ${{ github.event.pull_request.number }} - destination-url: ${{ env.GITHUB_SERVER_URL }} - destination-repo: actions/setup-forgejo - destination-fork-repo: cascading-pr/setup-forgejo - destination-branch: main - destination-token: ${{ secrets.CASCADING_PR_DESTINATION }} - close-merge: true - update: .forgejo/cascading-pr-setup-forgejo diff --git a/.forgejo/workflows/example-docker-compose.yml b/.forgejo/workflows/example-docker-compose.yml deleted file mode 100644 index 4e2f547..0000000 --- a/.forgejo/workflows/example-docker-compose.yml +++ /dev/null @@ -1,70 +0,0 @@ -# SPDX-License-Identifier: MIT -on: - push: - branches: - - 'main' - pull_request: - -jobs: - example-docker-compose: - runs-on: self-hosted - steps: - - uses: actions/checkout@v4 - - - name: Install docker - run: | - apt-get update -qq - export DEBIAN_FRONTEND=noninteractive - apt-get install -qq -y ca-certificates curl gnupg - install -m 0755 -d /etc/apt/keyrings - curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg - echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - apt-get update -qq - apt-get install -qq -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin=2.20.2-1~debian.11~bullseye - docker version - # - # docker compose is prone to non backward compatible changes, pin it - # - apt-get install -qq -y docker-compose-plugin=2.20.2-1~debian.11~bullseye - docker compose version - - - name: run the example - run: | - set -x - cd examples/docker-compose - secret=$(openssl rand -hex 20) - sed -i -e "s/{SHARED_SECRET}/$secret/" compose-forgejo-and-runner.yml - cli="docker compose --progress quiet -f compose-forgejo-and-runner.yml" - # - # Launch Forgejo & the runner - # - $cli up -d - for delay in $(seq 60) ; do test -f /srv/runner-data/.runner && break ; sleep 30 ; done - test -f /srv/runner-data/.runner - # - # Run the demo workflow - # - cli="$cli -f compose-demo-workflow.yml" - $cli up -d demo-workflow - # - # Wait for the demo workflow to complete - # - success='DEMO WORKFLOW SUCCESS' - failure='DEMO WORKFLOW FAILURE' - for delay in $(seq 60) ; do - $cli logs demo-workflow > /tmp/out - grep --quiet "$success" /tmp/out && break - grep --quiet "$failure" /tmp/out && break - $cli ps --all - $cli logs --tail=20 runner-daemon demo-workflow - sleep 30 - done - grep --quiet "$success" /tmp/out - $cli logs runner-daemon > /tmp/runner.log - grep --quiet 'Start image=code.forgejo.org/oci/node:20-bookworm' /tmp/runner.log - - - name: full docker compose logs - if: always() - run: | - cd examples/docker-compose - docker compose -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml logs diff --git a/.forgejo/workflows/integration.yml b/.forgejo/workflows/integration.yml new file mode 100644 index 0000000..895a4dc --- /dev/null +++ b/.forgejo/workflows/integration.yml @@ -0,0 +1,59 @@ +name: Integration tests for the release process + +on: + push: + paths: + - go.mod + - Dockerfile + - .forgejo/workflows/release.yml + - .forgejo/workflows/integration.yml + +jobs: + release-simulation: + runs-on: self-hosted + if: github.repository_owner != 'forgejo-integration' && github.repository_owner != 'forgejo-experimental' && github.repository_owner != 'forgejo-release' + steps: + - uses: actions/checkout@v3 + + - id: forgejo + uses: https://code.forgejo.org/actions/setup-forgejo@v1 + with: + user: root + password: admin1234 + image-version: 1.19 + lxc-ip-prefix: 10.0.9 + + - name: publish the runner release + run: | + set -x + + dir=$(mktemp -d) + trap "rm -fr $dir" EXIT + + url=http://root:admin1234@${{ steps.forgejo.outputs.host-port }} + export FORGEJO_RUNNER_LOGS="${{ steps.forgejo.outputs.runner-logs }}" + + # + # Create a new project with the runner and the release workflow only + # + rsync -a --exclude .git ./ $dir/ + rm $(find $dir/.forgejo/workflows/*.yml | grep -v release.yml) + forgejo-test-helper.sh push $dir $url root runner |& tee $dir/pushed + eval $(grep '^sha=' < $dir/pushed) + + # + # Push a tag to trigger the release workflow and wait for it to complete + # + forgejo-test-helper.sh api POST $url repos/root/runner/tags ${{ steps.forgejo.outputs.token }} --data-raw '{"tag_name": "v1.2.3", "target": "'$sha'"}' + LOOPS=180 forgejo-test-helper.sh wait_success "$url" root/runner $sha + + # + # Minimal sanity checks. e2e test is for the setup-forgejo action + # and the infrastructure playbook. + # + curl -L -sS $url/root/runner/releases/download/v1.2.3/forgejo-runner-amd64 > forgejo-runner + chmod +x forgejo-runner + ./forgejo-runner --version | grep 1.2.3 + curl -L -sS $url/root/runner/releases/download/v1.2.3/forgejo-runner-amd64.sha256 > forgejo-runner.one + shasum -a 256 < forgejo-runner | cut -f1 -d ' ' > forgejo-runner.two + diff forgejo-runner.one forgejo-runner.two diff --git a/.forgejo/workflows/publish-binary.yml b/.forgejo/workflows/publish-binary.yml new file mode 100644 index 0000000..68519d4 --- /dev/null +++ b/.forgejo/workflows/publish-binary.yml @@ -0,0 +1,40 @@ +name: Publish release + +on: + push: + tags: 'v*' + +jobs: + release: + runs-on: self-hosted + if: github.repository_owner == 'forgejo-release' && secrets.TOKEN != '' + steps: + + - name: install the certificate authority + run: | + apt-get install -qq -y wget + wget --no-check-certificate -O /usr/local/share/ca-certificates/enough.crt https://forgejo.octopuce.forgejo.org/forgejo/enough/raw/branch/main/certs/2023-05-13/ca.crt + update-ca-certificates --fresh + + - uses: actions/checkout@v3 + + - name: download release + uses: https://code.forgejo.org/actions/forgejo-release@v1 + with: + url: https://code.forgejo.org + repo: forgejo-integration/runner + direction: download + release-dir: release + download-retry: 60 + token: ${{ secrets.TOKEN }} + + - name: upload release + uses: https://code.forgejo.org/actions/forgejo-release@v1 + with: + url: https://code.forgejo.org + repo: forgejo/runner + direction: upload + release-dir: release + release-notes: "RELEASE-NOTES" + token: ${{ secrets.TOKEN }} + gpg-private-key: ${{ secrets.GPG }} diff --git a/.forgejo/workflows/publish-container-image.yml b/.forgejo/workflows/publish-container-image.yml new file mode 100644 index 0000000..f556ab2 --- /dev/null +++ b/.forgejo/workflows/publish-container-image.yml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: MIT +name: copy container images from integration to the destination organization + +on: + push: + tags: 'v*' + +jobs: + builder: + runs-on: self-hosted + if: github.repository_owner == 'forgejo-release' && secrets.TOKEN != '' + steps: + + - name: apt-get install docker.io + run: | + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -qq -y docker.io + + - name: login code.forgejo.org + uses: https://github.com/docker/login-action@v2 + with: + registry: code.forgejo.org + username: ${{ secrets.DOER }} + password: ${{ secrets.TOKEN }} + + - id: tag + run: | + tag="${{ github.ref_name }}" + tag=${tag##*v} + echo "tag=$tag" >> "$GITHUB_OUTPUT" + + - uses: https://code.forgejo.org/forgejo/forgejo-container-image@v1 + env: + VERIFY: 'false' + with: + url: https://code.forgejo.org + destination-owner: forgejo + owner: forgejo-integration + suffixes: ' ' + project: runner + tag: ${{ steps.tag.outputs.tag }} + doer: ${{ secrets.DOER }} + token: ${{ secrets.TOKEN }} + verbose: true diff --git a/.forgejo/workflows/publish-release.yml b/.forgejo/workflows/publish-release.yml deleted file mode 100644 index 35d8662..0000000 --- a/.forgejo/workflows/publish-release.yml +++ /dev/null @@ -1,42 +0,0 @@ -# SPDX-License-Identifier: MIT -# -# https://forgejo.octopuce.forgejo.org/forgejo-release/runner -# -# Copies & sign a release from code.forgejo.org/forgejo-integration/runner to code.forgejo.org/forgejo/runner -# -# ROLE: forgejo-release -# FORGEJO: https://code.forgejo.org -# FROM_OWNER: forgejo-integration -# TO_OWNER: forgejo -# DOER: release-team -# TOKEN: -# GPG_PRIVATE_KEY: -# GPG_PASSPHRASE: -# -name: publish - -on: - push: - tags: 'v*' - -jobs: - publish: - runs-on: self-hosted - if: secrets.DOER != '' && secrets.FORGEJO != '' && secrets.TO_OWNER != '' && secrets.FROM_OWNER != '' && secrets.TOKEN != '' - steps: - - uses: actions/checkout@v3 - - - name: copy & sign - uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v1 - with: - forgejo: ${{ secrets.FORGEJO }} - from-owner: ${{ secrets.FROM_OWNER }} - to-owner: ${{ secrets.TO_OWNER }} - repo: "runner" - ref-name: ${{ github.ref_name }} - container-suffixes: " " - doer: ${{ secrets.DOER }} - token: ${{ secrets.TOKEN }} - gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} - gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }} - verbose: ${{ secrets.VERBOSE }} diff --git a/.forgejo/workflows/test.yml b/.forgejo/workflows/test.yml index 677ab68..636c4ad 100644 --- a/.forgejo/workflows/test.yml +++ b/.forgejo/workflows/test.yml @@ -1,108 +1,24 @@ name: checks -on: - push: - branches: - - 'main' - pull_request: +on: + - pull_request + - push env: - FORGEJO_HOST_PORT: 'forgejo:3000' - FORGEJO_ADMIN_USER: 'root' - FORGEJO_ADMIN_PASSWORD: 'admin1234' - FORGEJO_RUNNER_SECRET: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' - FORGEJO_SCRIPT: | - /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 GOPROXY: https://goproxy.io,direct jobs: - build-and-tests: - name: build and test + lint: + name: check and test if: github.repository_owner != 'forgejo-integration' && github.repository_owner != 'forgejo-experimental' && github.repository_owner != 'forgejo-release' - runs-on: docker - - services: - forgejo: - image: codeberg.org/forgejo/forgejo:1.21 - env: - FORGEJO__security__INSTALL_LOCK: "true" - FORGEJO__log__LEVEL: "debug" - FORGEJO__actions__ENABLED: "true" - FORGEJO_ADMIN_USER: ${{ env.FORGEJO_ADMIN_USER }} - FORGEJO_ADMIN_PASSWORD: ${{ env.FORGEJO_ADMIN_PASSWORD }} - FORGEJO_RUNNER_SECRET: ${{ env.FORGEJO_RUNNER_SECRET }} - cmd: - - 'bash' - - '-c' - - ${{ env.FORGEJO_SCRIPT }} - + runs-on: ubuntu-latest steps: - uses: actions/setup-go@v3 with: - go-version: '1.21' - - - uses: actions/checkout@v4 - - - run: make vet - - - run: make build - - - uses: https://code.forgejo.org/actions/upload-artifact@v3 - with: - name: forgejo-runner - path: forgejo-runner - - - name: check the forgejo server is responding - run: | - apt-get update -qq - apt-get install -y -qq jq curl - 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: - needs: [build-and-tests] - name: runner exec tests - if: github.repository_owner != 'forgejo-integration' && github.repository_owner != 'forgejo-experimental' && github.repository_owner != 'forgejo-release' - runs-on: self-hosted - - steps: - - - uses: actions/checkout@v4 - - - uses: https://code.forgejo.org/actions/download-artifact@v3 - with: - name: forgejo-runner - - - name: install docker - run: | - mkdir /etc/docker - cat > /etc/docker/daemon.json <& /tmp/out ; then - cat /tmp/out - echo "IPv6 not enabled, should fail" - exit 1 - fi + go-version: 1.20 + - uses: actions/checkout@v3 + - name: vet checks + run: make vet + - name: build + run: make build + - name: test + run: make test diff --git a/.golangci.yml b/.golangci.yml index 41f9683..8505828 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,11 +1,14 @@ linters: enable: - gosimple + - deadcode - typecheck - govet - errcheck - staticcheck - unused + - structcheck + - varcheck - dupl #- gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time. - gofmt @@ -109,6 +112,7 @@ issues: - gocritic - linters: - unused + - deadcode text: "swagger" - path: contrib/pr/checkout.go linters: @@ -150,6 +154,9 @@ issues: - path: cmd/dump.go linters: - dupl + - path: services/webhook/webhook.go + linters: + - structcheck - text: "commentFormatting: put a space between `//` and comment text" linters: - gocritic diff --git a/Dockerfile b/Dockerfile index 50f1965..eb15271 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,47 +1,15 @@ -FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/tonistiigi/xx AS xx +#Build stage +FROM golang:1.20-alpine3.18 AS build-env -FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.21-alpine3.19 as build-env - -# -# Transparently cross compile for the target platform -# -COPY --from=xx / / -ARG TARGETPLATFORM -RUN apk --no-cache add clang lld -RUN xx-apk --no-cache add gcc musl-dev -RUN xx-go --wrap - -# Do not remove `git` here, it is required for getting runner version when executing `make build` -RUN apk add --no-cache build-base git +RUN apk --no-cache add build-base git COPY . /srv WORKDIR /srv +RUN make build -RUN make clean && make build - -FROM code.forgejo.org/oci/alpine:3.19 -ARG RELEASE_VERSION -RUN apk add --no-cache git bash +FROM alpine:3.18 +LABEL maintainer="contact@forgejo.org" COPY --from=build-env /srv/forgejo-runner /bin/forgejo-runner -LABEL maintainer="contact@forgejo.org" \ - org.opencontainers.image.authors="Forgejo" \ - org.opencontainers.image.url="https://forgejo.org" \ - org.opencontainers.image.documentation="https://forgejo.org/docs/latest/admin/actions/#forgejo-runner" \ - org.opencontainers.image.source="https://code.forgejo.org/forgejo/runner" \ - org.opencontainers.image.version="${RELEASE_VERSION}" \ - org.opencontainers.image.vendor="Forgejo" \ - org.opencontainers.image.licenses="MIT" \ - org.opencontainers.image.title="Forgejo Runner" \ - org.opencontainers.image.description="A runner for Forgejo Actions." - -ENV HOME=/data - -USER 1000:1000 - -WORKDIR /data - -VOLUME ["/data"] - -CMD ["/bin/forgejo-runner"] +ENTRYPOINT ["/bin/forgejo-runner"] diff --git a/Makefile b/Makefile index 3413168..4157810 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ GO ?= go SHASUM ?= shasum -a 256 HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" ) XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest -XGO_VERSION := go-1.21.x +XGO_VERSION := go-1.18.x GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10 LINUX_ARCHS ?= linux/amd64,linux/arm64 @@ -19,7 +19,6 @@ GOFILES := $(shell find . -type f -name "*.go" -o -name "go.mod" ! -name "genera DOCKER_IMAGE ?= gitea/act_runner DOCKER_TAG ?= nightly DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG) -DOCKER_ROOTLESS_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)-dind-rootless EXTLDFLAGS = -extldflags "-static" $(null) @@ -66,7 +65,7 @@ GO_PACKAGES_TO_VET ?= $(filter-out gitea.com/gitea/act_runner/internal/pkg/clien TAGS ?= -LDFLAGS ?= -X "gitea.com/gitea/act_runner/internal/pkg/ver.version=v$(RELASE_VERSION)" +LDFLAGS ?= -X "gitea.com/gitea/act_runner/internal/pkg/ver.version=$(RELASE_VERSION)" all: build @@ -104,7 +103,8 @@ test: fmt-check .PHONY: vet vet: @echo "Running go vet..." - @$(GO) vet $(GO_PACKAGES_TO_VET) + @$(GO) build code.gitea.io/gitea-vet + @$(GO) vet -vettool=gitea-vet $(GO_PACKAGES_TO_VET) install: $(GOFILES) $(GO) install -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' @@ -165,7 +165,6 @@ docker: ARG_DISABLE_CONTENT_TRUST=--disable-content-trust=false; \ fi; \ docker build $${ARG_DISABLE_CONTENT_TRUST} -t $(DOCKER_REF) . - docker build $${ARG_DISABLE_CONTENT_TRUST} -t $(DOCKER_ROOTLESS_REF) -f Dockerfile.rootless . clean: $(GO) clean -x -i ./... diff --git a/README.md b/README.md index ccf2e8b..c3e969c 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,51 @@ # Forgejo Runner -**WARNING:** this is [alpha release quality](https://en.wikipedia.org/wiki/Software_release_life_cycle#Alpha) code and should not be considered secure enough to deploy in production. +A daemon that connects to a Forgejo instance and runs jobs for continous integration. The high level [installation instructions](https://forgejo.org/docs/next/admin/actions/) are part of the Forgejo documentation. -A daemon that connects to a Forgejo instance and runs jobs for continous integration. The [installation and usage instructions](https://forgejo.org/docs/next/admin/actions/) are part of the Forgejo documentation. +# Configuration -# Reporting bugs +Display the usage with `forgejo-runner --help`. -When filing a bug in [the issue tracker](https://code.forgejo.org/forgejo/runner/issues), it is very helpful to propose a pull request [in the end-to-end tests](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions) repository that adds a reproducer. It will fail the CI and unambiguously demonstrate that the problem exists. In most cases it is enough to add a workflow ([see the echo example](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions/example-echo)). For more complicated cases it is also possible to add a runner config file as well as shell scripts to setup and teardown the test case ([see the service example](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions/example-service)). +For more information on the configuration file, see the [commented example](internal/pkg/config/config.example.yaml). # Hacking -The Forgejo runner depends on [a fork of ACT](https://code.forgejo.org/forgejo/act) and is a dependency of the [setup-forgejo action](https://code.forgejo.org/actions/setup-forgejo). See [the full dependency graph](https://code.forgejo.org/actions/cascading-pr/#forgejo-dependencies) for a global view. +The Forgejo runner depends on [a fork of ACT](https://code.forgejo.org/forgejo/act) and is a dependency of the [setup-forgejo action](https://code.forgejo.org/actions/setup-forgejo). Together they provide a development environment with end to end testing. Each repository also has some unit testing that can be used to quickly detect the simplest mistakes such as a failure to compile or static code checking failures (vulnerability, lint, etc.). + +Assuming the modifications to the [Forgejo runner](https://code.forgejo.org/forgejo/runner) are pushed to a fork in a branch named `wip-runner-change`, a pull request will verify it compiles and the binary is sane (running `forgejo-runner --version`). It will not verify that it is able to properly run jobs when connected to a live Forgejo instance. + +For end to end testing, a branch should be pushed to a fork of the [setup-forgejo action](https://code.forgejo.org/actions/setup-forgejo) with a [modification to the tests](https://code.forgejo.org/actions/setup-forgejo/src/commit/ae7f03683b7b05c7d9c6aaeacaf27843de0366a4/.forgejo/workflows/integration.yml#L10-L19), similar to: + +```yaml +# +# Uncomment the following for a shortcut to debugging the Forgejo runner. +# It will build the runner from a designated repository and branch instead of +# downloading it from a canonical release. +# +./forgejo-test-helper.sh build_runner https://code.forgejo.org/earl-warren/runner wip-runner-change +``` + +Where https://code.forgejo.org/earl-warren/runner is the URL of the Forgejo runner fork and `wip-runner-change` is the branch where the changes under test were pushed. When they do the `setup-forgejo` branch can be discarded. + +The runner can be released by merging the `wip-runner-change` branch and by pushing a new tag, for instance `v10.2.3`. Once published, the `setup-forgejo` action can be updated to default to this latest version knowing it already passed integration tests. + +## ACT + +Assuming the modifications to [ACT](https://code.forgejo.org/forgejo/act) are pushed to a fork in a branch named `wip-act-change`, a pull request will verify it compiles. It will not verify that the Forgejo runner can compile with it. + +For verifying it is compatible with the Forgejo runner, a branch should be pushed to a fork of the [Forgejo runner](https://code.forgejo.org/forgejo/runner) (for instance `wip-runner-change`) that uses the ACT version under test in the `wip-act-change` by modifying `go.mod` to contain something like the following and running `go mod tidy`: + +``` +replace github.com/nektos/act => code.forgejo.org/earl-warren/act wip-act-change +``` + +Where https://code.forgejo.org/earl-warren/act is the URL of the act fork and `wip-act-change` is the branch where the changes under test were pushed. It will not verify that it is able to properly run jobs when connected to a live Forgejo instance. The `wip-runner-change` branch must, in turn, be tested as explained above. When the Forgejo runner modified to include the changes in the `wip-act-change` branch pass the end to end test of the `setup-forgejo` action, it is ready to be released. + +ACT can be released by merging the `wip-act-change` branch and by pushing a new tag, for instance `v48.8.20`. Once published, the Forgejo runner can be updated to default to this latest version knowing it already passed end to end tests with something like: + +``` +replace github.com/nektos/act => code.forgejo.org/forgejo/act v48.8.20 +``` ## Local debug @@ -48,14 +83,13 @@ Building: cd runner ; rm -f forgejo-runner ; make forgejo-runner ``` -### Launch Forgejo and the runner +### Run Forgejo and the runner A Forgejo instance is launched with: ```shell -cd setup-forgejo -./forgejo.sh setup -firefox $(cat forgejo-url) +cd setup-forgejo ; ./forgejo.sh setup +firefox http://$(cat forgejo-ip):3000 ``` The user is `root` with password `admin1234`. The runner is registered with: @@ -63,30 +97,24 @@ The user is `root` with password `admin1234`. The runner is registered with: ``` cd setup-forgejo docker exec --user 1000 forgejo forgejo actions generate-runner-token > forgejo-runner-token -../runner/forgejo-runner register --no-interactive --instance "$(cat forgejo-url)" --name runner --token $(cat forgejo-runner-token) --labels docker:docker://node:20-bullseye,self-hosted:host://-self-hosted,lxc:lxc://debian:bullseye +../runner/forgejo-runner register --no-interactive --instance "http://$(cat forgejo-ip):3000/" --name runner --token $(cat forgejo-runner-token) --labels ubuntu-latest:docker://node:16-buster,self-hosted ``` -And launched with: +And launched in debug mode with: ```shell -cd setup-forgejo ; ../runner/forgejo-runner --config runner-config.yml daemon +cd setup-forgejo ; ACTIONS_STEP_DEBUG=true ../runner/forgejo-runner daemon ``` -Note that the `runner-config.yml` is required in that particular case -to configure the network in `bridge` mode, otherwise the runner will -create a network that cannot reach the forgejo instance. - ### Try a sample workflow -From the Forgejo web interface, create a repository and add the -following to `.forgejo/workflows/try.yaml`. It will launch the job and -the result can be observed from the `actions` tab. +From the Forgejo web interface, create a repository and add the following to `.forgejo/workflows/try.yaml`. It will launch the job and the result can be observed from the `actions` tab. ```yaml on: [push] jobs: ls: - runs-on: docker + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: | diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md deleted file mode 100644 index c4d9db3..0000000 --- a/RELEASE-NOTES.md +++ /dev/null @@ -1,102 +0,0 @@ -# Release Notes - -## 3.5.2 - -* Fix [crash in some cases when the YAML structure is not as expected](https://code.forgejo.org/forgejo/runner/issues/267). - -## 3.5.1 - -* Fix [CVE-2024-24557](https://nvd.nist.gov/vuln/detail/CVE-2024-24557) -* [Add report_interval option to config](https://code.forgejo.org/forgejo/runner/pulls/220) to allow setting the interval of status and log reports - -## 3.5.0 - -* [Allow graceful shutdowns](https://code.forgejo.org/forgejo/runner/pulls/202): when receiving a signal (INT or TERM) wait for running jobs to complete (up to shutdown_timeout). -* [Fix label declaration](https://code.forgejo.org/forgejo/runner/pulls/176): Runner in daemon mode now takes labels found in config.yml into account when declaration was successful. -* [Fix the docker compose example](https://code.forgejo.org/forgejo/runner/pulls/175) to workaround the race on labels. -* [Fix the kubernetes dind example](https://code.forgejo.org/forgejo/runner/pulls/169). -* [Rewrite ::group:: and ::endgroup:: commands like github](https://code.forgejo.org/forgejo/runner/pulls/183). -* [Added opencontainers labels to the image](https://code.forgejo.org/forgejo/runner/pulls/195) -* [Upgrade the default container to node:20](https://code.forgejo.org/forgejo/runner/pulls/203) - -## 3.4.1 - -* Fixes a regression introduced in 3.4.0 by which a job with no image explicitly set would - [be bound to the host](https://code.forgejo.org/forgejo/runner/issues/165) - network instead of a custom network (empty string in the configuration file). - -## 3.4.0 - -Although this version is able to run [actions/upload-artifact@v4](https://code.forgejo.org/actions/upload-artifact/src/tag/v4) and [actions/download-artifact@v4](https://code.forgejo.org/actions/download-artifact/src/tag/v4), these actions will fail because it does not run against GitHub.com. A fork of those two actions with this check disabled is made available at: - -* https://code.forgejo.org/forgejo/upload-artifact/src/tag/v4 -* https://code.forgejo.org/forgejo/download-artifact/src/tag/v4 - -and they can be used as shown in [an example from the end-to-end test suite](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions/example-artifacts-v4/.forgejo/workflows/test.yml). - -* When running against codeberg.org, the default poll frequency is 30s instead of 2s. -* Fix compatibility issue with actions/{upload,download}-artifact@v4. -* Upgrade ACT v1.20.0 which brings: - * `[container].options` from the config file is exposed in containers created by the workflows - * the expressions in the value of `jobs..runs-on` are evaluated - * fix a bug causing the evaluated expression of `jobs..runs-on` to fail if it was an array - * mount `act-toolcache:/opt/hostedtoolcache` instead of `act-toolcache:/toolcache` - * a few improvements to the readability of the error messages displayed in the logs - * `amd64` can be used instead of `x86_64` and `arm64` intead of `aarch64` when specifying the architecture - * fixed YAML parsing bugs preventing dispatch workflows to be parsed correctly - * add support for `runs-on.labels` which is equivalent to `runs-on` followed by a list of labels - * the expressions in the service `ports` and `volumes` values are evaluated - * network aliases are only supported when the network is user specified, not when it is provided by the runner -* If `[runner].insecure` is true in the configuration, insecure cloning actions is allowed - -## 3.3.0 - -* Support IPv6 with addresses from a private range and NAT for - docker:// with --enable-ipv6 and [container].enable_ipv6 - lxc:// always - -## 3.2.0 - -* Support LXC container capabilities via `lxc:lxc://debian:bookworm:k8s` or `lxc:lxc://debian:bookworm:docker lxc k8s` -* Update ACT v1.16.0 to resolve a [race condition when bootstraping LXC templates](https://code.forgejo.org/forgejo/act/pulls/23) - -## 3.1.0 - -The `self-hosted` label that was hardwired to be a LXC container -running `debian:bullseye` was reworked and documented ([user guide](https://forgejo.org/docs/next/user/actions/#jobsjob_idruns-on) and [admin guide](https://forgejo.org/docs/next/admin/actions/#labels-and-runs-on)). - -There now are two different schemes: `lxc://` for LXC containers and -`host://` for running directly on the host. - -* Support the `host://` scheme for running directly on the host. -* Support the `lxc://` scheme in labels -* Update [code.forgejo.org/forgejo/act v1.14.0](https://code.forgejo.org/forgejo/act/pulls/19) to implement both self-hosted and LXC schemes - -## 3.0.3 - -* Update [code.forgejo.org/forgejo/act v1.13.0](https://code.forgejo.org/forgejo/runner/pulls/106) to keep up with github.com/nektos/act - -## 3.0.2 - -* Update [code.forgejo.org/forgejo/act v1.12.0](https://code.forgejo.org/forgejo/runner/pulls/106) to upgrade the node installed in the LXC container to node20 - -## 3.0.1 - -* Update [code.forgejo.org/forgejo/act v1.11.0](https://code.forgejo.org/forgejo/runner/pulls/86) to resolve a bug preventing actions based on node20 from running, such as [checkout@v4](https://code.forgejo.org/actions/checkout/src/tag/v4). - -## 3.0.0 - -* Publish a rootless OCI image -* Refactor the release process - -## 2.5.0 - -* Update [code.forgejo.org/forgejo/act v1.10.0](https://code.forgejo.org/forgejo/runner/pulls/71) - -## 2.4.0 - -* Update [code.forgejo.org/forgejo/act v1.9.0](https://code.forgejo.org/forgejo/runner/pulls/64) - -## 2.3.0 - -* Add support for [offline registration](https://forgejo.org/docs/next/admin/actions/#offline-registration). diff --git a/contrib/forgejo-runner.service b/contrib/forgejo-runner.service deleted file mode 100644 index ace922a..0000000 --- a/contrib/forgejo-runner.service +++ /dev/null @@ -1,18 +0,0 @@ -[Unit] -Description=Forgejo Runner -Documentation=https://forgejo.org/docs/latest/admin/actions/ -After=docker.service - -[Service] -ExecStart=forgejo-runner daemon -ExecReload=/bin/kill -s HUP $MAINPID - -# This user and working directory must already exist -User=runner -WorkingDirectory=/home/runner -Restart=on-failure -TimeoutSec=0 -RestartSec=10 - -[Install] -WantedBy=multi-user.target diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index f9dd774..0000000 --- a/examples/README.md +++ /dev/null @@ -1,10 +0,0 @@ -This directory contains a collection of usage and deployment examples. - -Workflow examples can be found [in the documentation](https://forgejo.org/docs/next/user/actions/) -and in the [sources of the setup-forgejo](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata) action. - -| Section | Description | -|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [`docker`](docker) | using the host docker server by mounting the socket | -| [`docker-compose`](docker-compose) | all in one docker-compose with the Forgejo server, the runner and docker in docker | -| [`kubernetes`](kubernetes) | a sample deployment for the Forgejo runner | diff --git a/examples/docker-compose/README.md b/examples/docker-compose/README.md deleted file mode 100644 index a3e6e9b..0000000 --- a/examples/docker-compose/README.md +++ /dev/null @@ -1,113 +0,0 @@ -## Docker compose with docker-in-docker - -The `compose-forgejo-and-runner.yml` compose file runs a Forgejo -instance and registers a `Forgejo runner`. A docker server is also -launched within a container (using -[dind](https://hub.docker.com/_/docker/tags?name=dind)) and will be -used by the `Forgejo runner` to execute the workflows. - -### Quick start - -```sh -rm -fr /srv/runner-data /srv/forgejo-data -secret=$(openssl rand -hex 20) -sed -i -e "s/{SHARED_SECRET}/$secret/" compose-forgejo-and-runner.yml -docker compose -f compose-forgejo-and-runner.yml up -d -``` - -Visit http://0.0.0.0:8080/admin/actions/runners with login `root` and password `{ROOT_PASSWORD}` and see the runner is registered with the label `docker`. - -> NOTE: the `Your ROOT_URL in app.ini is "http://localhost:3000/", it's unlikely matching the site you are visiting.` message is a warning that can be ignored in the context of this example. - -```sh -docker compose -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml up demo-workflow -``` - -Visit http://0.0.0.0:8080/root/test/actions/runs/1 and see that the job ran. - - -### Running - -Create a shared secret with: - -```sh -openssl rand -hex 20 -``` - -Replace all occurences of {SHARED_SECRET} in -[compose-forgejo-and-runner.yml](compose-forgejo-and-runner.yml). - -> **NOTE:** a token obtained from the Forgejo web interface cannot be used as a shared secret. - -Replace {ROOT_PASSWORD} with a secure password in -[compose-forgejo-and-runner.yml](compose-forgejo-and-runner.yml). - -```sh -docker compose -f compose-forgejo-and-runner.yml up -Creating docker-compose_docker-in-docker_1 ... done -Creating docker-compose_forgejo_1 ... done -Creating docker-compose_runner-register_1 ... done -... -docker-in-docker_1 | time="2023-08-24T10:22:15.023338461Z" level=warning msg="WARNING: API is accessible on http://0.0.0.0:2376 -... -forgejo_1 | 2023/08/24 10:22:14 ...s/graceful/server.go:75:func1() [D] Starting server on tcp:0.0.0.0:3000 (PID: 19) -... -runner-daemon_1 | time="2023-08-24T10:22:16Z" level=info msg="Starting runner daemon" -``` - -### Manual testing - -To login the Forgejo instance: - -* URL: http://0.0.0.0:8080 -* user: `root` -* password: `{ROOT_PASSWORD}` - -`Forgejo Actions` is enabled by default when creating a repository. - -## Tests workflow - -The `compose-demo-workflow.yml` compose file runs two demo workflows: -* one to verify the `Forgejo runner` can pick up a task from the Forgejo instance -and run it to completion. -* one to verify docker can be run inside the `Forgejo runner` container. - -A new repository is created in root/test with the following workflows: - -#### `.forgejo/workflows/demo.yml`: - -```yaml -on: [push] -jobs: - test: - runs-on: docker - steps: - - run: echo All Good -``` - -#### `.forgejo/workflows/demo_docker.yml` - -```yaml -on: [push] -jobs: - test_docker: - runs-on: ubuntu-22.04 - steps: - - run: docker info -``` - -A wait loop expects the status of the check associated with the -commit in Forgejo to show "success" to assert the workflow was run. - -### Running - -```sh -$ docker-compose -f compose-forgejo-and-runner.yml -f compose-demo-workflow.yml up demo-workflow -... -demo-workflow_1 | To http://forgejo:3000/root/test -demo-workflow_1 | + 5ce134e...261cc79 main -> main (forced update) -demo-workflow_1 | branch 'main' set up to track 'http://root:admin1234@forgejo:3000/root/test/main'. -... -demo-workflow_1 | running -... -``` diff --git a/examples/docker-compose/compose-demo-workflow.yml b/examples/docker-compose/compose-demo-workflow.yml deleted file mode 100644 index 90e7d52..0000000 --- a/examples/docker-compose/compose-demo-workflow.yml +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2024 The Forgejo Authors. -# SPDX-License-Identifier: MIT - -services: - - demo-workflow: - image: code.forgejo.org/oci/alpine:3.19 - links: - - forgejo - command: >- - sh -ec ' - apk add --quiet git curl jq ; - mkdir -p /srv/demo ; - cd /srv/demo ; - git init --initial-branch=main ; - mkdir -p .forgejo/workflows ; - echo "{ on: [push], jobs: { test: { runs-on: docker, steps: [ {uses: actions/checkout@v4}, { run: echo All Good } ] } } }" > .forgejo/workflows/demo.yml ; - echo "{ on: [push], jobs: { test_docker: { runs-on: ubuntu-22.04, steps: [ { run: docker info } ] } } }" > .forgejo/workflows/demo_docker.yml ; - git add . ; - git config user.email root@example.com ; - git config user.name username ; - git commit -m demo ; - while : ; do - git push --set-upstream --force http://root:{ROOT_PASSWORD}@forgejo:3000/root/test main && break ; - sleep 5 ; - done ; - sha=`git rev-parse HEAD` ; - for delay in 1 1 1 1 2 5 5 10 10 10 15 30 30 30 30 30 30 30 ; do - curl -sS -f http://forgejo:3000/api/v1/repos/root/test/commits/$$sha/status | jq --raw-output .state | tee status ; - if grep success status ; then echo DEMO WORKFLOW SUCCESS && break ; fi ; - if grep failure status ; then echo DEMO WORKFLOW FAILURE && break ; fi ; - sleep $$delay ; - done ; - grep success status || echo DEMO WORKFLOW FAILURE - ' diff --git a/examples/docker-compose/compose-forgejo-and-runner.yml b/examples/docker-compose/compose-forgejo-and-runner.yml deleted file mode 100644 index 4794985..0000000 --- a/examples/docker-compose/compose-forgejo-and-runner.yml +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright 2024 The Forgejo Authors. -# SPDX-License-Identifier: MIT - -# -# Create a secret with: -# -# openssl rand -hex 20 -# -# Replace all occurences of {SHARED_SECRET} below with the output. -# -# NOTE: a token obtained from the Forgejo web interface cannot be used -# as a shared secret. -# -# Replace {ROOT_PASSWORD} with a secure password -# - -volumes: - docker_certs: - -services: - - docker-in-docker: - image: code.forgejo.org/oci/docker:dind - hostname: docker # Must set hostname as TLS certificates are only valid for docker or localhost - privileged: true - environment: - DOCKER_TLS_CERTDIR: /certs - DOCKER_HOST: docker-in-docker - volumes: - - docker_certs:/certs - - forgejo: - image: codeberg.org/forgejo/forgejo:1.21 - command: >- - bash -c ' - /bin/s6-svscan /etc/s6 & - sleep 10 ; - su -c "forgejo forgejo-cli actions register --secret {SHARED_SECRET}" git ; - su -c "forgejo admin user create --admin --username root --password {ROOT_PASSWORD} --email root@example.com" git ; - sleep infinity - ' - environment: - FORGEJO__security__INSTALL_LOCK: "true" - FORGEJO__log__LEVEL: "debug" - FORGEJO__repository__ENABLE_PUSH_CREATE_USER: "true" - FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE: "false" - FORGEJO__repository__DEFAULT_REPO_UNITS: "repo.code,repo.actions" - volumes: - - /srv/forgejo-data:/data - ports: - - 8080:3000 - - runner-register: - image: code.forgejo.org/forgejo/runner:3.4.1 - links: - - docker-in-docker - - forgejo - environment: - DOCKER_HOST: tcp://docker-in-docker:2376 - volumes: - - /srv/runner-data:/data - user: 0:0 - command: >- - bash -ec ' - while : ; do - forgejo-runner create-runner-file --connect --instance http://forgejo:3000 --name runner --secret {SHARED_SECRET} && break ; - sleep 1 ; - done ; - sed -i -e "s|\"labels\": null|\"labels\": [\"docker:docker://code.forgejo.org/oci/node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]|" .runner ; - forgejo-runner generate-config > config.yml ; - sed -i -e "s|network: .*|network: host|" config.yml ; - sed -i -e "s|^ envs:$$| envs:\n DOCKER_HOST: tcp://docker:2376\n DOCKER_TLS_VERIFY: 1\n DOCKER_CERT_PATH: /certs/client|" config.yml ; - sed -i -e "s|^ options:| options: -v /certs/client:/certs/client|" config.yml ; - sed -i -e "s| valid_volumes: \[\]$$| valid_volumes:\n - /certs/client|" config.yml ; - chown -R 1000:1000 /data - ' - - runner-daemon: - image: code.forgejo.org/forgejo/runner:3.4.1 - links: - - docker-in-docker - - forgejo - environment: - DOCKER_HOST: tcp://docker:2376 - DOCKER_CERT_PATH: /certs/client - DOCKER_TLS_VERIFY: "1" - volumes: - - /srv/runner-data:/data - - docker_certs:/certs - command: >- - bash -c ' - while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done - ' diff --git a/examples/docker/README.md b/examples/docker/README.md deleted file mode 100644 index 628c99c..0000000 --- a/examples/docker/README.md +++ /dev/null @@ -1,12 +0,0 @@ -The following assumes: - -* a docker server runs on the host -* the docker group of the host is GID 133 -* a `.runner` file exists in /tmp/data -* a `runner-config.yml` file exists in /tmp/data - -```sh -docker run -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/data:/data --user 1000:133 --rm code.forgejo.org/forgejo/runner:3.0.0 forgejo-runner --config runner-config.yaml daemon -``` - -The workflows will run using the host docker srever diff --git a/examples/kubernetes/README.md b/examples/kubernetes/README.md deleted file mode 100644 index d00cf1a..0000000 --- a/examples/kubernetes/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## Kubernetes Docker in Docker Deployment - -Registers Kubernetes pod runners using [offline registration](https://forgejo.org/docs/v1.21/admin/actions/#offline-registration), allowing the scaling of runners as needed. - -NOTE: Docker in Docker (dind) requires elevated privileges on Kubernetes. The current way to achieve this is to set the pod `SecurityContext` to `privileged`. Keep in mind that this is a potential security issue that has the potential for a malicious application to break out of the container context. - -[`dind-docker.yaml`](dind-docker.yaml) creates a deployment and secret for Kubernetes to act as a runner. The Docker credentials are re-generated each time the pod connects and does not need to be persisted. diff --git a/examples/kubernetes/dind-docker.yaml b/examples/kubernetes/dind-docker.yaml deleted file mode 100644 index 534432d..0000000 --- a/examples/kubernetes/dind-docker.yaml +++ /dev/null @@ -1,87 +0,0 @@ -# Secret data. -# You will need to retrive this from the web UI, and your Forgejo instance must be running v1.21+ -# Alternatively, create this with -# kubectl create secret generic runner-secret --from-literal=token=your_offline_token_here -apiVersion: v1 -stringData: - token: your_offline_secret_here -kind: Secret -metadata: - name: runner-secret ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: forgejo-runner - name: forgejo-runner -spec: - # Two replicas means that if one is busy, the other can pick up jobs. - replicas: 2 - selector: - matchLabels: - app: forgejo-runner - strategy: {} - template: - metadata: - creationTimestamp: null - labels: - app: forgejo-runner - spec: - restartPolicy: Always - volumes: - - name: docker-certs - emptyDir: {} - - name: runner-data - emptyDir: {} - # Initialise our configuration file using offline registration - # https://forgejo.org/docs/v1.21/admin/actions/#offline-registration - initContainers: - - name: runner-register - image: code.forgejo.org/forgejo/runner:3.2.0 - command: ["forgejo-runner", "register", "--no-interactive", "--token", $(RUNNER_SECRET), "--name", $(RUNNER_NAME), "--instance", $(FORGEJO_INSTANCE_URL)] - env: - - name: RUNNER_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: RUNNER_SECRET - valueFrom: - secretKeyRef: - name: runner-secret - key: token - - name: FORGEJO_INSTANCE_URL - value: http://forgejo-http.forgejo.svc.cluster.local:3000 - resources: - limits: - cpu: "0.50" - memory: "64Mi" - volumeMounts: - - name: runner-data - mountPath: /data - containers: - - name: runner - image: code.forgejo.org/forgejo/runner:3.0.0 - command: ["sh", "-c", "while ! nc -z localhost 2376 code.forgejo.org/forgejo/act v1.21.3 +replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.6.0 diff --git a/go.sum b/go.sum index 498a542..681a06a 100644 --- a/go.sum +++ b/go.sum @@ -1,109 +1,96 @@ -code.forgejo.org/forgejo/act v1.21.3 h1:EeJbrz0aar2QhIcBlOW5gjK1rjrQxcAvQSPpG/R1h5w= -code.forgejo.org/forgejo/act v1.21.3/go.mod h1:+PcvJ9iv+NTFeJSh79ra9Jbk9l0vvyA9D9me5/dbxYM= -code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU= -code.gitea.io/actions-proto-go v0.4.0/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas= -code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI= -code.gitea.io/gitea-vet v0.2.3/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE= -connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk= -connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +code.forgejo.org/forgejo/act v1.6.0 h1:RBJFRsmxNzfj0dKQb2aplu3NjtfI8TLdGsGqxmx9lcQ= +code.forgejo.org/forgejo/act v1.6.0/go.mod h1:1ffiGQZAZCLuk9QEBDdbRuQj1GL4uAQk6GNNtcEnPmI= +code.gitea.io/actions-proto-go v0.2.1 h1:ToMN/8thz2q10TuCq8dL2d8mI+/pWpJcHCvG+TELwa0= +code.gitea.io/actions-proto-go v0.2.1/go.mod h1:00ys5QDo1iHN1tHNvvddAcy2W/g+425hQya1cCSvq9A= +code.gitea.io/gitea-vet v0.2.3-0.20230113022436-2b1561217fa5 h1:daBEK2GQeqGikJESctP5Cu1i33z5ztAD4kyQWiw185M= +code.gitea.io/gitea-vet v0.2.3-0.20230113022436-2b1561217fa5/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= -github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/Microsoft/hcsshim v0.9.8 h1:lf7xxK2+Ikbj9sVf2QZsouGjRjEp2STj1yDHgoVtU5k= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= +github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= -github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= -github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= -github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= -github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= -github.com/containerd/containerd v1.7.13 h1:wPYKIeGMN8vaggSKuV1X0wZulpMz4CrgEsZdaCyB6Is= -github.com/containerd/containerd v1.7.13/go.mod h1:zT3up6yTRfEUa6+GsITYIJNgSVL9NQ4x4h1RPzk0Wu4= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= -github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= -github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/avast/retry-go/v4 v4.3.1 h1:Mtg11F9PdAIMkMiio2RKcYauoVHjl2aB3zQJJlzD4cE= +github.com/avast/retry-go/v4 v4.3.1/go.mod h1:rg6XFaiuFYII0Xu3RDbZQkxCofFwruZKW8oEF1jpWiU= +github.com/bufbuild/connect-go v1.3.1 h1:doJP6Q8Ypg6haUT2IAZJPWHUN9rAUp+F9MfK7yhu1zs= +github.com/bufbuild/connect-go v1.3.1/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I= +github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= +github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= +github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY= +github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/containerd v1.6.20 h1:+itjwpdqXpzHB/QAiWc/BZCjjVfcNgw69w/oIeF4Oy0= +github.com/containerd/containerd v1.6.20/go.mod h1:apei1/i5Ux2FzrK6+DM/suEsGuK/MeVOfy8tR2q7Wnw= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v25.0.3+incompatible h1:KLeNs7zws74oFuVhgZQ5ONGZiXUUdgsdy6/EsX/6284= -github.com/docker/cli v25.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= -github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg= -github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= -github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/cli v23.0.4+incompatible h1:xClB7PsiATttDHj8ce5qvJcikiApNy7teRR1XkoBZGs= +github.com/docker/cli v23.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v23.0.4+incompatible h1:Kd3Bh9V/rO+XpTP/BLqM+gx8z7+Yb0AA2Ibj+nNo4ek= +github.com/docker/docker v23.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= -github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= -github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= -github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= +github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= +github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= +github.com/go-git/go-git/v5 v5.6.2-0.20230411180853-ce62f3e9ff86 h1:vbnwVQwGOr4xwrtcZ1lrhWHPMIgWkhNv+2+smiA2HHk= +github.com/go-git/go-git/v5 v5.6.2-0.20230411180853-ce62f3e9ff86/go.mod h1:Q3/DKr39xeJ3oEAVC8Q1+BlJK3OMsOQsksNb3s+9M1A= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= @@ -114,42 +101,47 @@ github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4 github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= +github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/moby/buildkit v0.13.2 h1:nXNszM4qD9E7QtG7bFWPnDI1teUQFQglBzon/IU3SzI= -github.com/moby/buildkit v0.13.2/go.mod h1:2cyVOv9NoHM7arphK9ZfHIWKn9YVZRFd1wXB8kKmEzY= -github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= -github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= +github.com/moby/buildkit v0.11.6 h1:VYNdoKk5TVxN7k4RvZgdeM4GOyRvIi4Z8MXOY7xvyUs= +github.com/moby/buildkit v0.11.6/go.mod h1:GCqKfHhz+pddzfgaR7WmHVEE3nKKZMMDPpK8mh3ZLv4= +github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= +github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= -github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd h1:aY7OQNf2XqY/JQ6qREWamhI/81os/agb2BAGpcx5yWI= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8= +github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= @@ -158,43 +150,55 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rhysd/actionlint v1.6.27 h1:xxwe8YmveBcC8lydW6GoHMGmB6H/MTqUU60F2p10wjw= -github.com/rhysd/actionlint v1.6.27/go.mod h1:m2nFUjAnOrxCMXuOMz9evYBRCLUsMnKY2IJl/N5umbk= +github.com/rhysd/actionlint v1.6.24 h1:5f61cF5ssP2pzG0jws5bEsfZBNhbBcO9nl7vTzVKjzs= +github.com/rhysd/actionlint v1.6.24/go.mod h1:gQmz9r2wlcpLy+VdbzK0GINJQnAK5/sNH3BpwW4Mt5I= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= -github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= +github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= -github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0= +github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/timshannon/bolthold v0.0.0-20210913165410-232392fc8a6a h1:oIi7H/bwFUYKYhzKbHc+3MvHRWqhQwXVB4LweLMiVy0= github.com/timshannon/bolthold v0.0.0-20210913165410-232392fc8a6a/go.mod h1:iSvujNDmpZ6eQX+bg/0X3lF7LEmZ8N77g2a/J/+Zt2U= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= @@ -204,129 +208,125 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= -go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= -google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k= -google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= -gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/internal/app/cmd/cache-server.go b/internal/app/cmd/cache-server.go deleted file mode 100644 index 21b3352..0000000 --- a/internal/app/cmd/cache-server.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2023 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package cmd - -import ( - "context" - "fmt" - "os" - "os/signal" - - "gitea.com/gitea/act_runner/internal/pkg/config" - - "github.com/nektos/act/pkg/artifactcache" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -type cacheServerArgs struct { - Dir string - Host string - Port uint16 -} - -func runCacheServer(ctx context.Context, configFile *string, cacheArgs *cacheServerArgs) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - cfg, err := config.LoadDefault(*configFile) - if err != nil { - return fmt.Errorf("invalid configuration: %w", err) - } - - initLogging(cfg) - - var ( - dir = cfg.Cache.Dir - host = cfg.Cache.Host - port = cfg.Cache.Port - ) - - // cacheArgs has higher priority - if cacheArgs.Dir != "" { - dir = cacheArgs.Dir - } - if cacheArgs.Host != "" { - host = cacheArgs.Host - } - if cacheArgs.Port != 0 { - port = cacheArgs.Port - } - - cacheHandler, err := artifactcache.StartHandler( - dir, - host, - port, - log.StandardLogger().WithField("module", "cache_request"), - ) - if err != nil { - return err - } - - log.Infof("cache server is listening on %v", cacheHandler.ExternalURL()) - - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) - <-c - - return nil - } -} diff --git a/internal/app/cmd/cmd.go b/internal/app/cmd/cmd.go index 48341dc..a95c473 100644 --- a/internal/app/cmd/cmd.go +++ b/internal/app/cmd/cmd.go @@ -41,8 +41,6 @@ func Execute(ctx context.Context) { registerCmd.Flags().StringVar(®Args.Labels, "labels", "", "Runner tags, comma separated") rootCmd.AddCommand(registerCmd) - rootCmd.AddCommand(createRunnerFileCmd(ctx, &configFile)) - // ./act_runner daemon daemonCmd := &cobra.Command{ Use: "daemon", @@ -65,19 +63,6 @@ func Execute(ctx context.Context) { }, }) - // ./act_runner cache-server - var cacheArgs cacheServerArgs - cacheCmd := &cobra.Command{ - Use: "cache-server", - Short: "Start a cache server for the cache action", - Args: cobra.MaximumNArgs(0), - RunE: runCacheServer(ctx, &configFile, &cacheArgs), - } - cacheCmd.Flags().StringVarP(&cacheArgs.Dir, "dir", "d", "", "Cache directory") - cacheCmd.Flags().StringVarP(&cacheArgs.Host, "host", "s", "", "Host of the cache server") - cacheCmd.Flags().Uint16VarP(&cacheArgs.Port, "port", "p", 0, "Port of the cache server") - rootCmd.AddCommand(cacheCmd) - // hide completion command rootCmd.CompletionOptions.HiddenDefaultCmd = true diff --git a/internal/app/cmd/create-runner-file.go b/internal/app/cmd/create-runner-file.go deleted file mode 100644 index a972624..0000000 --- a/internal/app/cmd/create-runner-file.go +++ /dev/null @@ -1,164 +0,0 @@ -// SPDX-License-Identifier: MIT - -package cmd - -import ( - "context" - "encoding/hex" - "fmt" - "os" - - pingv1 "code.gitea.io/actions-proto-go/ping/v1" - "connectrpc.com/connect" - gouuid "github.com/google/uuid" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - - "gitea.com/gitea/act_runner/internal/app/run" - "gitea.com/gitea/act_runner/internal/pkg/client" - "gitea.com/gitea/act_runner/internal/pkg/config" - "gitea.com/gitea/act_runner/internal/pkg/ver" -) - -type createRunnerFileArgs struct { - Connect bool - InstanceAddr string - Secret string - Name string -} - -func createRunnerFileCmd(ctx context.Context, configFile *string) *cobra.Command { - var argsVar createRunnerFileArgs - cmd := &cobra.Command{ - Use: "create-runner-file", - Short: "Create a runner file using a shared secret used to pre-register the runner on the Forgejo instance", - Args: cobra.MaximumNArgs(0), - RunE: runCreateRunnerFile(ctx, &argsVar, configFile), - } - cmd.Flags().BoolVar(&argsVar.Connect, "connect", false, "tries to connect to the instance using the secret (Forgejo v1.21 instance or greater)") - cmd.Flags().StringVar(&argsVar.InstanceAddr, "instance", "", "Forgejo instance address") - cmd.MarkFlagRequired("instance") - cmd.Flags().StringVar(&argsVar.Secret, "secret", "", "secret shared with the Forgejo instance via forgejo-cli actions register") - cmd.MarkFlagRequired("secret") - cmd.Flags().StringVar(&argsVar.Name, "name", "", "Runner name") - - return cmd -} - -// must be exactly the same as fogejo/models/actions/forgejo.go -func uuidFromSecret(secret string) (string, error) { - uuid, err := gouuid.FromBytes([]byte(secret[:16])) - if err != nil { - return "", fmt.Errorf("gouuid.FromBytes %v", err) - } - return uuid.String(), nil -} - -// should be exactly the same as forgejo/cmd/forgejo/actions.go -func validateSecret(secret string) error { - secretLen := len(secret) - if secretLen != 40 { - return fmt.Errorf("the secret must be exactly 40 characters long, not %d", secretLen) - } - if _, err := hex.DecodeString(secret); err != nil { - return fmt.Errorf("the secret must be an hexadecimal string: %w", err) - } - return nil -} - -func ping(cfg *config.Config, reg *config.Registration) error { - // initial http client - cli := client.New( - reg.Address, - cfg.Runner.Insecure, - "", - "", - ver.Version(), - ) - - _, err := cli.Ping(context.Background(), connect.NewRequest(&pingv1.PingRequest{ - Data: reg.UUID, - })) - if err != nil { - return fmt.Errorf("ping %s failed %w", reg.Address, err) - } - return nil -} - -func runCreateRunnerFile(ctx context.Context, args *createRunnerFileArgs, configFile *string) func(cmd *cobra.Command, args []string) error { - return func(*cobra.Command, []string) error { - log.SetLevel(log.DebugLevel) - log.Info("Creating runner file") - - // - // Prepare the registration data - // - cfg, err := config.LoadDefault(*configFile) - if err != nil { - return fmt.Errorf("invalid configuration: %w", err) - } - - if err := validateSecret(args.Secret); err != nil { - return err - } - - uuid, err := uuidFromSecret(args.Secret) - if err != nil { - return err - } - - name := args.Name - if name == "" { - name, _ = os.Hostname() - log.Infof("Runner name is empty, use hostname '%s'.", name) - } - - reg := &config.Registration{ - Name: name, - UUID: uuid, - Token: args.Secret, - Address: args.InstanceAddr, - } - - // - // Verify the Forgejo instance is reachable - // - if err := ping(cfg, reg); err != nil { - return err - } - - // - // Save the registration file - // - if err := config.SaveRegistration(cfg.Runner.File, reg); err != nil { - return fmt.Errorf("failed to save runner config to %s: %w", cfg.Runner.File, err) - } - - // - // Verify the secret works - // - if args.Connect { - cli := client.New( - reg.Address, - cfg.Runner.Insecure, - reg.UUID, - reg.Token, - ver.Version(), - ) - - runner := run.NewRunner(cfg, reg, cli) - resp, err := runner.Declare(ctx, cfg.Runner.Labels) - - if err != nil && connect.CodeOf(err) == connect.CodeUnimplemented { - log.Warn("Cannot verify the connection because the Forgejo instance is lower than v1.21") - } else if err != nil { - log.WithError(err).Error("fail to invoke Declare") - return err - } else { - log.Infof("connection successful: %s, with version: %s, with labels: %v", - resp.Msg.Runner.Name, resp.Msg.Runner.Version, resp.Msg.Runner.Labels) - } - } - return nil - } -} diff --git a/internal/app/cmd/create-runner-file_test.go b/internal/app/cmd/create-runner-file_test.go deleted file mode 100644 index 4f3acb8..0000000 --- a/internal/app/cmd/create-runner-file_test.go +++ /dev/null @@ -1,118 +0,0 @@ -// SPDX-License-Identifier: MIT - -package cmd - -import ( - "bytes" - "context" - "os" - "testing" - - runnerv1 "code.gitea.io/actions-proto-go/runner/v1" - "connectrpc.com/connect" - "gitea.com/gitea/act_runner/internal/pkg/client" - "gitea.com/gitea/act_runner/internal/pkg/config" - "gitea.com/gitea/act_runner/internal/pkg/ver" - - "github.com/spf13/cobra" - "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v3" -) - -func executeCommand(ctx context.Context, cmd *cobra.Command, args ...string) (string, error) { - buf := new(bytes.Buffer) - cmd.SetOut(buf) - cmd.SetErr(buf) - cmd.SetArgs(args) - - err := cmd.ExecuteContext(ctx) - - return buf.String(), err -} - -func Test_createRunnerFileCmd(t *testing.T) { - configFile := "config.yml" - ctx := context.Background() - cmd := createRunnerFileCmd(ctx, &configFile) - output, err := executeCommand(ctx, cmd) - assert.ErrorContains(t, err, `required flag(s) "instance", "secret" not set`) - assert.Contains(t, output, "Usage:") -} - -func Test_validateSecret(t *testing.T) { - assert.ErrorContains(t, validateSecret("abc"), "exactly 40 characters") - assert.ErrorContains(t, validateSecret("ZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), "must be an hexadecimal") -} - -func Test_uuidFromSecret(t *testing.T) { - uuid, err := uuidFromSecret("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") - assert.NoError(t, err) - assert.EqualValues(t, uuid, "41414141-4141-4141-4141-414141414141") -} - -func Test_ping(t *testing.T) { - cfg := &config.Config{} - address := os.Getenv("FORGEJO_URL") - if address == "" { - address = "https://code.forgejo.org" - } - reg := &config.Registration{ - Address: address, - UUID: "create-runner-file_test.go", - } - assert.NoError(t, ping(cfg, reg)) -} - -func Test_runCreateRunnerFile(t *testing.T) { - // - // Set the .runner file to be in a temporary directory - // - dir := t.TempDir() - configFile := dir + "/config.yml" - runnerFile := dir + "/.runner" - cfg, err := config.LoadDefault("") - cfg.Runner.File = runnerFile - yamlData, err := yaml.Marshal(cfg) - assert.NoError(t, err) - assert.NoError(t, os.WriteFile(configFile, yamlData, 0o666)) - - instance, has := os.LookupEnv("FORGEJO_URL") - if !has { - instance = "https://code.forgejo.org" - } - secret, has := os.LookupEnv("FORGEJO_RUNNER_SECRET") - assert.True(t, has) - name := "testrunner" - - // - // Run create-runner-file - // - ctx := context.Background() - cmd := createRunnerFileCmd(ctx, &configFile) - output, err := executeCommand(ctx, cmd, "--connect", "--secret", secret, "--instance", instance, "--name", name) - assert.NoError(t, err) - assert.EqualValues(t, "", output) - - // - // Read back the runner file and verify its content - // - reg, err := config.LoadRegistration(runnerFile) - assert.NoError(t, err) - assert.EqualValues(t, secret, reg.Token) - assert.EqualValues(t, instance, reg.Address) - - // - // Verify that fetching a task successfully returns there is - // no task for this runner - // - cli := client.New( - reg.Address, - cfg.Runner.Insecure, - reg.UUID, - reg.Token, - ver.Version(), - ) - resp, err := cli.FetchTask(ctx, connect.NewRequest(&runnerv1.FetchTaskRequest{})) - assert.NoError(t, err) - assert.Nil(t, resp.Msg.Task) -} diff --git a/internal/app/cmd/daemon.go b/internal/app/cmd/daemon.go index a613546..a648d64 100644 --- a/internal/app/cmd/daemon.go +++ b/internal/app/cmd/daemon.go @@ -7,13 +7,7 @@ import ( "context" "fmt" "os" - "path" - "path/filepath" - "runtime" - "strconv" - "strings" - "connectrpc.com/connect" "github.com/mattn/go-isatty" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -29,13 +23,14 @@ import ( func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { + log.Infoln("Starting runner daemon") + cfg, err := config.LoadDefault(*configFile) if err != nil { return fmt.Errorf("invalid configuration: %w", err) } initLogging(cfg) - log.Infoln("Starting runner daemon") reg, err := config.LoadRegistration(cfg.Runner.File) if os.IsNotExist(err) { @@ -45,15 +40,8 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command, return fmt.Errorf("failed to load registration file: %w", err) } - cfg.Tune(reg.Address) - - lbls := reg.Labels - if len(cfg.Runner.Labels) > 0 { - lbls = cfg.Runner.Labels - } - ls := labels.Labels{} - for _, l := range lbls { + for _, l := range reg.Labels { label, err := labels.Parse(l) if err != nil { log.WithError(err).Warnf("ignored invalid label %q", l) @@ -66,28 +54,9 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command, } if ls.RequireDocker() { - dockerSocketPath, err := getDockerSocketPath(cfg.Container.DockerHost) - if err != nil { + if err := envcheck.CheckIfDockerRunning(ctx); err != nil { return err } - if err := envcheck.CheckIfDockerRunning(ctx, dockerSocketPath); err != nil { - return err - } - // if dockerSocketPath passes the check, override DOCKER_HOST with dockerSocketPath - os.Setenv("DOCKER_HOST", dockerSocketPath) - // empty cfg.Container.DockerHost means act_runner need to find an available docker host automatically - // and assign the path to cfg.Container.DockerHost - if cfg.Container.DockerHost == "" { - cfg.Container.DockerHost = dockerSocketPath - } - // check the scheme, if the scheme is not npipe or unix - // set cfg.Container.DockerHost to "-" because it can't be mounted to the job container - if protoIndex := strings.Index(cfg.Container.DockerHost, "://"); protoIndex != -1 { - scheme := cfg.Container.DockerHost[:protoIndex] - if !strings.EqualFold(scheme, "npipe") && !strings.EqualFold(scheme, "unix") { - cfg.Container.DockerHost = "-" - } - } } cli := client.New( @@ -99,39 +68,10 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command, ) runner := run.NewRunner(cfg, reg, cli) - // declare the labels of the runner before fetching tasks - resp, err := runner.Declare(ctx, ls.Names()) - if err != nil && connect.CodeOf(err) == connect.CodeUnimplemented { - // Gitea instance is older version. skip declare step. - log.Warn("Because the Forgejo instance is an old version, skipping declaring the labels and version.") - } else if err != nil { - log.WithError(err).Error("fail to invoke Declare") - return err - } else { - log.Infof("runner: %s, with version: %s, with labels: %v, declared successfully", - resp.Msg.Runner.Name, resp.Msg.Runner.Version, resp.Msg.Runner.Labels) - // if declared successfully, override the labels in the.runner file with valid labels in the config file (if specified) - runner.Update(ctx, ls) - reg.Labels = ls.ToStrings() - if err := config.SaveRegistration(cfg.Runner.File, reg); err != nil { - return fmt.Errorf("failed to save runner config: %w", err) - } - } - poller := poll.New(cfg, cli, runner) - go poller.Poll() + poller.Poll(ctx) - <-ctx.Done() - log.Infof("runner: %s shutdown initiated, waiting [runner].shutdown_timeout=%s for running jobs to complete before shutting down", resp.Msg.Runner.Name, cfg.Runner.ShutdownTimeout) - - ctx, cancel := context.WithTimeout(context.Background(), cfg.Runner.ShutdownTimeout) - defer cancel() - - err = poller.Shutdown(ctx) - if err != nil { - log.Warnf("runner: %s cancelled in progress jobs during shutdown", resp.Msg.Runner.Name) - } return nil } } @@ -139,11 +79,10 @@ func runDaemon(ctx context.Context, configFile *string) func(cmd *cobra.Command, // initLogging setup the global logrus logger. func initLogging(cfg *config.Config) { isTerm := isatty.IsTerminal(os.Stdout.Fd()) - format := &log.TextFormatter{ + log.SetFormatter(&log.TextFormatter{ DisableColors: !isTerm, FullTimestamp: true, - } - log.SetFormatter(format) + }) if l := cfg.Log.Level; l != "" { level, err := log.ParseLevel(l) @@ -151,58 +90,9 @@ func initLogging(cfg *config.Config) { log.WithError(err). Errorf("invalid log level: %q", l) } - - // debug level - if level == log.DebugLevel { - log.SetReportCaller(true) - format.CallerPrettyfier = func(f *runtime.Frame) (string, string) { - // get function name - s := strings.Split(f.Function, ".") - funcname := "[" + s[len(s)-1] + "]" - // get file name and line number - _, filename := path.Split(f.File) - filename = "[" + filename + ":" + strconv.Itoa(f.Line) + "]" - return funcname, filename - } - log.SetFormatter(format) - } - if log.GetLevel() != level { log.Infof("log level changed to %v", level) log.SetLevel(level) } } } - -var commonSocketPaths = []string{ - "/var/run/docker.sock", - "/run/podman/podman.sock", - "$HOME/.colima/docker.sock", - "$XDG_RUNTIME_DIR/docker.sock", - "$XDG_RUNTIME_DIR/podman/podman.sock", - `\\.\pipe\docker_engine`, - "$HOME/.docker/run/docker.sock", -} - -func getDockerSocketPath(configDockerHost string) (string, error) { - // a `-` means don't mount the docker socket to job containers - if configDockerHost != "" && configDockerHost != "-" { - return configDockerHost, nil - } - - socket, found := os.LookupEnv("DOCKER_HOST") - if found { - return socket, nil - } - - for _, p := range commonSocketPaths { - if _, err := os.Lstat(os.ExpandEnv(p)); err == nil { - if strings.HasPrefix(p, `\\.\`) { - return "npipe://" + filepath.ToSlash(os.ExpandEnv(p)), nil - } - return "unix://" + filepath.ToSlash(os.ExpandEnv(p)), nil - } - } - - return "", fmt.Errorf("daemon Docker Engine socket not found and docker_host config was invalid") -} diff --git a/internal/app/cmd/exec.go b/internal/app/cmd/exec.go index 3e111fe..d2b9f0a 100644 --- a/internal/app/cmd/exec.go +++ b/internal/app/cmd/exec.go @@ -39,7 +39,7 @@ type executeArgs struct { envs []string envfile string secrets []string - defaultActionsURL string + defaultActionsUrl string insecureSecrets bool privileged bool usernsMode string @@ -58,8 +58,6 @@ type executeArgs struct { image string cacheHandler *artifactcache.Handler network string - enableIPv6 bool - githubInstance string } // WorkflowsPath returns path to workflow file(s) @@ -253,7 +251,7 @@ func runExecList(ctx context.Context, planner model.WorkflowPlanner, execArgs *e var filterPlan *model.Plan // Determine the event name to be filtered - var filterEventName string + var filterEventName string = "" if len(execArgs.event) > 0 { log.Infof("Using chosed event for filtering: %s", execArgs.event) @@ -290,7 +288,7 @@ func runExecList(ctx context.Context, planner model.WorkflowPlanner, execArgs *e } } - _ = printList(filterPlan) + printList(filterPlan) return nil } @@ -359,24 +357,6 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command log.Infof("cache handler listens on: %v", handler.ExternalURL()) execArgs.cacheHandler = handler - if len(execArgs.artifactServerAddr) == 0 { - ip := common.GetOutboundIP() - if ip == nil { - return fmt.Errorf("unable to determine outbound IP address") - } - execArgs.artifactServerAddr = ip.String() - } - - if len(execArgs.artifactServerPath) == 0 { - tempDir, err := os.MkdirTemp("", "gitea-act-") - if err != nil { - fmt.Println(err) - } - defer os.RemoveAll(tempDir) - - execArgs.artifactServerPath = tempDir - } - // run the plan config := &runner.Config{ Workdir: execArgs.Workdir(), @@ -394,38 +374,27 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command ContainerArchitecture: execArgs.containerArchitecture, ContainerDaemonSocket: execArgs.containerDaemonSocket, UseGitIgnore: execArgs.useGitIgnore, - GitHubInstance: execArgs.githubInstance, - ContainerCapAdd: execArgs.containerCapAdd, - ContainerCapDrop: execArgs.containerCapDrop, - ContainerOptions: execArgs.containerOptions, - AutoRemove: true, - ArtifactServerPath: execArgs.artifactServerPath, - ArtifactServerPort: execArgs.artifactServerPort, - ArtifactServerAddr: execArgs.artifactServerAddr, - NoSkipCheckout: execArgs.noSkipCheckout, - // PresetGitHubContext: preset, - // EventJSON: string(eventJSON), - ContainerNamePrefix: fmt.Sprintf("FORGEJO-ACTIONS-TASK-%s", eventName), - ContainerMaxLifetime: maxLifetime, - ContainerNetworkMode: container.NetworkMode(execArgs.network), - ContainerNetworkEnableIPv6: execArgs.enableIPv6, - DefaultActionInstance: execArgs.defaultActionsURL, + // GitHubInstance: t.client.Address(), + ContainerCapAdd: execArgs.containerCapAdd, + ContainerCapDrop: execArgs.containerCapDrop, + ContainerOptions: execArgs.containerOptions, + AutoRemove: true, + ArtifactServerPath: execArgs.artifactServerPath, + ArtifactServerPort: execArgs.artifactServerPort, + NoSkipCheckout: execArgs.noSkipCheckout, + // PresetGitHubContext: preset, + // EventJSON: string(eventJSON), + ContainerNamePrefix: fmt.Sprintf("FORGEJO-ACTIONS-TASK-%s", eventName), + ContainerMaxLifetime: maxLifetime, + ContainerNetworkMode: container.NetworkMode(execArgs.network), + DefaultActionInstance: execArgs.defaultActionsUrl, PlatformPicker: func(_ []string) string { return execArgs.image }, - ValidVolumes: []string{"**"}, // All volumes are allowed for `exec` command - } - - config.Env["ACT_EXEC"] = "true" - - if t := config.Secrets["GITEA_TOKEN"]; t != "" { - config.Token = t - } else if t := config.Secrets["GITHUB_TOKEN"]; t != "" { - config.Token = t } if !execArgs.debug { - logLevel := log.InfoLevel + logLevel := log.Level(log.InfoLevel) config.JobLoggerLevel = &logLevel } @@ -434,6 +403,16 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command return err } + if len(execArgs.artifactServerPath) == 0 { + tempDir, err := os.MkdirTemp("", "forgejo-act-") + if err != nil { + fmt.Println(err) + } + defer os.RemoveAll(tempDir) + + execArgs.artifactServerPath = tempDir + } + artifactCancel := artifacts.Serve(ctx, execArgs.artifactServerPath, execArgs.artifactServerAddr, execArgs.artifactServerPort) log.Debugf("artifacts server started at %s:%s", execArgs.artifactServerPath, execArgs.artifactServerPort) @@ -480,16 +459,13 @@ func loadExecCmd(ctx context.Context) *cobra.Command { execCmd.Flags().StringArrayVarP(&execArg.containerCapDrop, "container-cap-drop", "", []string{}, "kernel capabilities to remove from the workflow containers (e.g. --container-cap-drop SYS_PTRACE)") execCmd.Flags().StringVarP(&execArg.containerOptions, "container-opts", "", "", "container options") execCmd.PersistentFlags().StringVarP(&execArg.artifactServerPath, "artifact-server-path", "", ".", "Defines the path where the artifact server stores uploads and retrieves downloads from. If not specified the artifact server will not start.") - execCmd.PersistentFlags().StringVarP(&execArg.artifactServerAddr, "artifact-server-addr", "", "", "Defines the address where the artifact server listens") execCmd.PersistentFlags().StringVarP(&execArg.artifactServerPort, "artifact-server-port", "", "34567", "Defines the port where the artifact server listens (will only bind to localhost).") - execCmd.PersistentFlags().StringVarP(&execArg.defaultActionsURL, "default-actions-url", "", "https://code.forgejo.org", "Defines the default base url of the action.") + execCmd.PersistentFlags().StringVarP(&execArg.defaultActionsUrl, "default-actions-url", "", "https://code.forgejo.org", "Defines the default url of action instance.") execCmd.PersistentFlags().BoolVarP(&execArg.noSkipCheckout, "no-skip-checkout", "", false, "Do not skip actions/checkout") execCmd.PersistentFlags().BoolVarP(&execArg.debug, "debug", "d", false, "enable debug log") execCmd.PersistentFlags().BoolVarP(&execArg.dryrun, "dryrun", "n", false, "dryrun mode") - execCmd.PersistentFlags().StringVarP(&execArg.image, "image", "i", "node:20-bullseye", "Docker image to use. Use \"-self-hosted\" to run directly on the host.") + execCmd.PersistentFlags().StringVarP(&execArg.image, "image", "i", "node:16-bullseye", "docker image to use") execCmd.PersistentFlags().StringVarP(&execArg.network, "network", "", "", "Specify the network to which the container will connect") - execCmd.PersistentFlags().BoolVarP(&execArg.enableIPv6, "enable-ipv6", "6", false, "Create network with IPv6 enabled.") - execCmd.PersistentFlags().StringVarP(&execArg.githubInstance, "gitea-instance", "", "", "Gitea instance to use.") return execCmd } diff --git a/internal/app/cmd/register.go b/internal/app/cmd/register.go index 803511a..5326512 100644 --- a/internal/app/cmd/register.go +++ b/internal/app/cmd/register.go @@ -15,7 +15,7 @@ import ( pingv1 "code.gitea.io/actions-proto-go/ping/v1" runnerv1 "code.gitea.io/actions-proto-go/runner/v1" - "connectrpc.com/connect" + "github.com/bufbuild/connect-go" "github.com/mattn/go-isatty" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -47,12 +47,12 @@ func runRegister(ctx context.Context, regArgs *registerArgs, configFile *string) } if regArgs.NoInteractive { - if err := registerNoInteractive(ctx, *configFile, regArgs); err != nil { + if err := registerNoInteractive(*configFile, regArgs); err != nil { return err } } else { go func() { - if err := registerInteractive(ctx, *configFile); err != nil { + if err := registerInteractive(*configFile); err != nil { log.Fatal(err) return } @@ -85,20 +85,23 @@ const ( StageInputInstance StageInputToken StageInputRunnerName - StageInputLabels + StageInputCustomLabels StageWaitingForRegistration StageExit ) var defaultLabels = []string{ - "docker:docker://node:20-bullseye", + "ubuntu-latest:docker://node:16-bullseye", + "ubuntu-22.04:docker://node:16-bullseye", // There's no node:16-bookworm yet + "ubuntu-20.04:docker://node:16-bullseye", + "ubuntu-18.04:docker://node:16-buster", } type registerInputs struct { InstanceAddr string Token string RunnerName string - Labels []string + CustomLabels []string } func (r *registerInputs) validate() error { @@ -108,8 +111,8 @@ func (r *registerInputs) validate() error { if r.Token == "" { return fmt.Errorf("token is empty") } - if len(r.Labels) > 0 { - return validateLabels(r.Labels) + if len(r.CustomLabels) > 0 { + return validateLabels(r.CustomLabels) } return nil } @@ -123,7 +126,7 @@ func validateLabels(ls []string) error { return nil } -func (r *registerInputs) assignToNext(stage registerStage, value string, cfg *config.Config) registerStage { +func (r *registerInputs) assignToNext(stage registerStage, value string) registerStage { // must set instance address and token. // if empty, keep current stage. if stage == StageInputInstance || stage == StageInputToken { @@ -151,40 +154,23 @@ func (r *registerInputs) assignToNext(stage registerStage, value string, cfg *co return StageInputRunnerName case StageInputRunnerName: r.RunnerName = value - // if there are some labels configured in config file, skip input labels stage - if len(cfg.Runner.Labels) > 0 { - ls := make([]string, 0, len(cfg.Runner.Labels)) - for _, l := range cfg.Runner.Labels { - _, err := labels.Parse(l) - if err != nil { - log.WithError(err).Warnf("ignored invalid label %q", l) - continue - } - ls = append(ls, l) - } - if len(ls) == 0 { - log.Warn("no valid labels configured in config file, runner may not be able to pick up jobs") - } - r.Labels = ls - return StageWaitingForRegistration - } - return StageInputLabels - case StageInputLabels: - r.Labels = defaultLabels + return StageInputCustomLabels + case StageInputCustomLabels: + r.CustomLabels = defaultLabels if value != "" { - r.Labels = strings.Split(value, ",") + r.CustomLabels = strings.Split(value, ",") } - if validateLabels(r.Labels) != nil { - log.Infoln("Invalid labels, please input again, leave blank to use the default labels (for example, ubuntu-20.04:docker://node:20-bookworm,ubuntu-18.04:docker://node:20-bookworm)") - return StageInputLabels + if validateLabels(r.CustomLabels) != nil { + log.Infoln("Invalid labels, please input again, leave blank to use the default labels (for example, ubuntu-20.04:docker://node:16-bullseye,ubuntu-18.04:docker://node:16-buster,linux_arm:host)") + return StageInputCustomLabels } return StageWaitingForRegistration } return StageUnknown } -func registerInteractive(ctx context.Context, configFile string) error { +func registerInteractive(configFile string) error { var ( reader = bufio.NewReader(os.Stdin) stage = StageInputInstance @@ -206,14 +192,15 @@ func registerInteractive(ctx context.Context, configFile string) error { if err != nil { return err } - stage = inputs.assignToNext(stage, strings.TrimSpace(cmdString), cfg) + stage = inputs.assignToNext(stage, strings.TrimSpace(cmdString)) if stage == StageWaitingForRegistration { - log.Infof("Registering runner, name=%s, instance=%s, labels=%v.", inputs.RunnerName, inputs.InstanceAddr, inputs.Labels) - if err := doRegister(ctx, cfg, inputs); err != nil { - return fmt.Errorf("Failed to register runner: %w", err) + log.Infof("Registering runner, name=%s, instance=%s, labels=%v.", inputs.RunnerName, inputs.InstanceAddr, inputs.CustomLabels) + if err := doRegister(cfg, inputs); err != nil { + log.Errorf("Failed to register runner: %v", err) + } else { + log.Infof("Runner registered successfully.") } - log.Infof("Runner registered successfully.") return nil } @@ -239,14 +226,14 @@ func printStageHelp(stage registerStage) { case StageInputRunnerName: hostname, _ := os.Hostname() log.Infof("Enter the runner name (if set empty, use hostname: %s):\n", hostname) - case StageInputLabels: - log.Infoln("Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-20.04:docker://node:20-bookworm,ubuntu-18.04:docker://node:20-bookworm):") + case StageInputCustomLabels: + log.Infoln("Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-20.04:docker://node:16-bullseye,ubuntu-18.04:docker://node:16-buster,linux_arm:host):") case StageWaitingForRegistration: log.Infoln("Waiting for registration...") } } -func registerNoInteractive(ctx context.Context, configFile string, regArgs *registerArgs) error { +func registerNoInteractive(configFile string, regArgs *registerArgs) error { cfg, err := config.LoadDefault(configFile) if err != nil { return err @@ -255,21 +242,12 @@ func registerNoInteractive(ctx context.Context, configFile string, regArgs *regi InstanceAddr: regArgs.InstanceAddr, Token: regArgs.Token, RunnerName: regArgs.RunnerName, - Labels: defaultLabels, + CustomLabels: defaultLabels, } regArgs.Labels = strings.TrimSpace(regArgs.Labels) - // command line flag. if regArgs.Labels != "" { - inputs.Labels = strings.Split(regArgs.Labels, ",") + inputs.CustomLabels = strings.Split(regArgs.Labels, ",") } - // specify labels in config file. - if len(cfg.Runner.Labels) > 0 { - if regArgs.Labels != "" { - log.Warn("Labels from command will be ignored, use labels defined in config file.") - } - inputs.Labels = cfg.Runner.Labels - } - if inputs.RunnerName == "" { inputs.RunnerName, _ = os.Hostname() log.Infof("Runner name is empty, use hostname '%s'.", inputs.RunnerName) @@ -278,14 +256,17 @@ func registerNoInteractive(ctx context.Context, configFile string, regArgs *regi log.WithError(err).Errorf("Invalid input, please re-run act command.") return nil } - if err := doRegister(ctx, cfg, inputs); err != nil { - return fmt.Errorf("Failed to register runner: %w", err) + if err := doRegister(cfg, inputs); err != nil { + log.Errorf("Failed to register runner: %v", err) + return nil } log.Infof("Runner registered successfully.") return nil } -func doRegister(ctx context.Context, cfg *config.Config, inputs *registerInputs) error { +func doRegister(cfg *config.Config, inputs *registerInputs) error { + ctx := context.Background() + // initial http client cli := client.New( inputs.InstanceAddr, @@ -301,7 +282,7 @@ func doRegister(ctx context.Context, cfg *config.Config, inputs *registerInputs) })) select { case <-ctx.Done(): - return ctx.Err() + return nil default: } if ctx.Err() != nil { @@ -322,7 +303,7 @@ func doRegister(ctx context.Context, cfg *config.Config, inputs *registerInputs) Name: inputs.RunnerName, Token: inputs.Token, Address: inputs.InstanceAddr, - Labels: inputs.Labels, + Labels: inputs.CustomLabels, } ls := make([]string, len(reg.Labels)) @@ -334,9 +315,7 @@ func doRegister(ctx context.Context, cfg *config.Config, inputs *registerInputs) resp, err := cli.Register(ctx, connect.NewRequest(&runnerv1.RegisterRequest{ Name: reg.Name, Token: reg.Token, - Version: ver.Version(), - AgentLabels: ls, // Could be removed after Gitea 1.20 - Labels: ls, + AgentLabels: ls, })) if err != nil { log.WithError(err).Error("poller: cannot register new runner") diff --git a/internal/app/poll/poller.go b/internal/app/poll/poller.go index cc89fa5..913e464 100644 --- a/internal/app/poll/poller.go +++ b/internal/app/poll/poller.go @@ -6,12 +6,10 @@ package poll import ( "context" "errors" - "fmt" "sync" - "sync/atomic" runnerv1 "code.gitea.io/actions-proto-go/runner/v1" - "connectrpc.com/connect" + "github.com/bufbuild/connect-go" log "github.com/sirupsen/logrus" "golang.org/x/time/rate" @@ -20,148 +18,64 @@ import ( "gitea.com/gitea/act_runner/internal/pkg/config" ) -const PollerID = "PollerID" - -type Poller interface { - Poll() - Shutdown(ctx context.Context) error +type Poller struct { + client client.Client + runner *run.Runner + cfg *config.Config } -type poller struct { - client client.Client - runner run.RunnerInterface - cfg *config.Config - tasksVersion atomic.Int64 // tasksVersion used to store the version of the last task fetched from the Gitea. - - pollingCtx context.Context - shutdownPolling context.CancelFunc - - jobsCtx context.Context - shutdownJobs context.CancelFunc - - done chan any +func New(cfg *config.Config, client client.Client, runner *run.Runner) *Poller { + return &Poller{ + client: client, + runner: runner, + cfg: cfg, + } } -func New(cfg *config.Config, client client.Client, runner run.RunnerInterface) Poller { - return (&poller{}).init(cfg, client, runner) -} - -func (p *poller) init(cfg *config.Config, client client.Client, runner run.RunnerInterface) Poller { - pollingCtx, shutdownPolling := context.WithCancel(context.Background()) - - jobsCtx, shutdownJobs := context.WithCancel(context.Background()) - - done := make(chan any) - - p.client = client - p.runner = runner - p.cfg = cfg - - p.pollingCtx = pollingCtx - p.shutdownPolling = shutdownPolling - - p.jobsCtx = jobsCtx - p.shutdownJobs = shutdownJobs - p.done = done - - return p -} - -func (p *poller) Poll() { +func (p *Poller) Poll(ctx context.Context) { limiter := rate.NewLimiter(rate.Every(p.cfg.Runner.FetchInterval), 1) wg := &sync.WaitGroup{} for i := 0; i < p.cfg.Runner.Capacity; i++ { wg.Add(1) - go p.poll(i, wg, limiter) + go p.poll(ctx, wg, limiter) } wg.Wait() - - // signal the poller is finished - close(p.done) } -func (p *poller) Shutdown(ctx context.Context) error { - p.shutdownPolling() - - select { - case <-p.done: - log.Trace("all jobs are complete") - return nil - - case <-ctx.Done(): - log.Trace("forcing the jobs to shutdown") - p.shutdownJobs() - <-p.done - log.Trace("all jobs have been shutdown") - return ctx.Err() - } -} - -func (p *poller) poll(id int, wg *sync.WaitGroup, limiter *rate.Limiter) { - log.Infof("[poller %d] launched", id) +func (p *Poller) poll(ctx context.Context, wg *sync.WaitGroup, limiter *rate.Limiter) { defer wg.Done() for { - if err := limiter.Wait(p.pollingCtx); err != nil { - log.Infof("[poller %d] shutdown", id) + if err := limiter.Wait(ctx); err != nil { + if ctx.Err() != nil { + log.WithError(err).Debug("limiter wait failed") + } return } - task, ok := p.fetchTask(p.pollingCtx) + task, ok := p.fetchTask(ctx) if !ok { continue } - p.runTaskWithRecover(p.jobsCtx, task) - } -} - -func (p *poller) runTaskWithRecover(ctx context.Context, task *runnerv1.Task) { - defer func() { - if r := recover(); r != nil { - err := fmt.Errorf("panic: %v", r) - log.WithError(err).Error("panic in runTaskWithRecover") + if err := p.runner.Run(ctx, task); err != nil { + log.WithError(err).Error("failed to run task") } - }() - - if err := p.runner.Run(ctx, task); err != nil { - log.WithError(err).Error("failed to run task") } } -func (p *poller) fetchTask(ctx context.Context) (*runnerv1.Task, bool) { +func (p *Poller) fetchTask(ctx context.Context) (*runnerv1.Task, bool) { reqCtx, cancel := context.WithTimeout(ctx, p.cfg.Runner.FetchTimeout) defer cancel() - // Load the version value that was in the cache when the request was sent. - v := p.tasksVersion.Load() - resp, err := p.client.FetchTask(reqCtx, connect.NewRequest(&runnerv1.FetchTaskRequest{ - TasksVersion: v, - })) + resp, err := p.client.FetchTask(reqCtx, connect.NewRequest(&runnerv1.FetchTaskRequest{})) if errors.Is(err, context.DeadlineExceeded) { - log.Trace("deadline exceeded") err = nil } if err != nil { - if errors.Is(err, context.Canceled) { - log.WithError(err).Debugf("shutdown, fetch task canceled") - } else { - log.WithError(err).Error("failed to fetch task") - } + log.WithError(err).Error("failed to fetch task") return nil, false } - if resp == nil || resp.Msg == nil { + if resp == nil || resp.Msg == nil || resp.Msg.Task == nil { return nil, false } - - if resp.Msg.TasksVersion > v { - p.tasksVersion.CompareAndSwap(v, resp.Msg.TasksVersion) - } - - if resp.Msg.Task == nil { - return nil, false - } - - // got a task, set `tasksVersion` to zero to focre query db in next request. - p.tasksVersion.CompareAndSwap(resp.Msg.TasksVersion, 0) - return resp.Msg.Task, true } diff --git a/internal/app/poll/poller_test.go b/internal/app/poll/poller_test.go deleted file mode 100644 index 04b1a84..0000000 --- a/internal/app/poll/poller_test.go +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright The Forgejo Authors. -// SPDX-License-Identifier: MIT - -package poll - -import ( - "context" - "fmt" - "testing" - "time" - - "connectrpc.com/connect" - - "code.gitea.io/actions-proto-go/ping/v1/pingv1connect" - runnerv1 "code.gitea.io/actions-proto-go/runner/v1" - "code.gitea.io/actions-proto-go/runner/v1/runnerv1connect" - "gitea.com/gitea/act_runner/internal/pkg/config" - - log "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" -) - -type mockPoller struct { - poller -} - -func (o *mockPoller) Poll() { - o.poller.Poll() -} - -type mockClient struct { - pingv1connect.PingServiceClient - runnerv1connect.RunnerServiceClient - - sleep time.Duration - cancel bool - err error - noTask bool -} - -func (o mockClient) Address() string { - return "" -} - -func (o mockClient) Insecure() bool { - return true -} - -func (o *mockClient) FetchTask(ctx context.Context, req *connect.Request[runnerv1.FetchTaskRequest]) (*connect.Response[runnerv1.FetchTaskResponse], error) { - if o.sleep > 0 { - select { - case <-ctx.Done(): - log.Trace("fetch task done") - return nil, context.DeadlineExceeded - case <-time.After(o.sleep): - log.Trace("slept") - return nil, fmt.Errorf("unexpected") - } - } - if o.cancel { - return nil, context.Canceled - } - if o.err != nil { - return nil, o.err - } - task := &runnerv1.Task{} - if o.noTask { - task = nil - o.noTask = false - } - - return connect.NewResponse(&runnerv1.FetchTaskResponse{ - Task: task, - TasksVersion: int64(1), - }), nil -} - -type mockRunner struct { - cfg *config.Runner - log chan string - panics bool - err error -} - -func (o *mockRunner) Run(ctx context.Context, task *runnerv1.Task) error { - o.log <- "runner starts" - if o.panics { - log.Trace("panics") - o.log <- "runner panics" - o.panics = false - panic("whatever") - } - if o.err != nil { - log.Trace("error") - o.log <- "runner error" - err := o.err - o.err = nil - return err - } - for { - select { - case <-ctx.Done(): - log.Trace("shutdown") - o.log <- "runner shutdown" - return nil - case <-time.After(o.cfg.Timeout): - log.Trace("after") - o.log <- "runner timeout" - return nil - } - } -} - -func setTrace(t *testing.T) { - t.Helper() - log.SetReportCaller(true) - log.SetLevel(log.TraceLevel) -} - -func TestPoller_New(t *testing.T) { - p := New(&config.Config{}, &mockClient{}, &mockRunner{}) - assert.NotNil(t, p) -} - -func TestPoller_Runner(t *testing.T) { - setTrace(t) - for _, testCase := range []struct { - name string - timeout time.Duration - noTask bool - panics bool - err error - expected string - contextTimeout time.Duration - }{ - { - name: "Simple", - timeout: 10 * time.Second, - expected: "runner shutdown", - }, - { - name: "Panics", - timeout: 10 * time.Second, - panics: true, - expected: "runner panics", - }, - { - name: "Error", - timeout: 10 * time.Second, - err: fmt.Errorf("ERROR"), - expected: "runner error", - }, - { - name: "PollTaskError", - timeout: 10 * time.Second, - noTask: true, - expected: "runner shutdown", - }, - { - name: "ShutdownTimeout", - timeout: 1 * time.Second, - contextTimeout: 1 * time.Minute, - expected: "runner timeout", - }, - } { - t.Run(testCase.name, func(t *testing.T) { - runnerLog := make(chan string, 3) - configRunner := config.Runner{ - FetchInterval: 1, - Capacity: 1, - Timeout: testCase.timeout, - } - p := &mockPoller{} - p.init( - &config.Config{ - Runner: configRunner, - }, - &mockClient{ - noTask: testCase.noTask, - }, - &mockRunner{ - cfg: &configRunner, - log: runnerLog, - panics: testCase.panics, - err: testCase.err, - }) - go p.Poll() - assert.Equal(t, "runner starts", <-runnerLog) - var ctx context.Context - var cancel context.CancelFunc - if testCase.contextTimeout > 0 { - ctx, cancel = context.WithTimeout(context.Background(), testCase.contextTimeout) - defer cancel() - } else { - ctx, cancel = context.WithCancel(context.Background()) - cancel() - } - p.Shutdown(ctx) - <-p.done - assert.Equal(t, testCase.expected, <-runnerLog) - }) - } -} - -func TestPoller_Fetch(t *testing.T) { - setTrace(t) - for _, testCase := range []struct { - name string - noTask bool - sleep time.Duration - err error - cancel bool - success bool - }{ - { - name: "Success", - success: true, - }, - { - name: "Timeout", - sleep: 100 * time.Millisecond, - }, - { - name: "Canceled", - cancel: true, - }, - { - name: "NoTask", - noTask: true, - }, - { - name: "Error", - err: fmt.Errorf("random error"), - }, - } { - t.Run(testCase.name, func(t *testing.T) { - configRunner := config.Runner{ - FetchTimeout: 1 * time.Millisecond, - } - p := &mockPoller{} - p.init( - &config.Config{ - Runner: configRunner, - }, - &mockClient{ - sleep: testCase.sleep, - cancel: testCase.cancel, - noTask: testCase.noTask, - err: testCase.err, - }, - &mockRunner{}, - ) - task, ok := p.fetchTask(context.Background()) - if testCase.success { - assert.True(t, ok) - assert.NotNil(t, task) - } else { - assert.False(t, ok) - assert.Nil(t, task) - } - }) - } -} diff --git a/internal/app/run/runner.go b/internal/app/run/runner.go index e8654b6..86b41ac 100644 --- a/internal/app/run/runner.go +++ b/internal/app/run/runner.go @@ -13,7 +13,6 @@ import ( "time" runnerv1 "code.gitea.io/actions-proto-go/runner/v1" - "connectrpc.com/connect" "github.com/docker/docker/api/types/container" "github.com/nektos/act/pkg/artifactcache" "github.com/nektos/act/pkg/common" @@ -41,10 +40,6 @@ type Runner struct { runningTasks sync.Map } -type RunnerInterface interface { - Run(ctx context.Context, task *runnerv1.Task) error -} - func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client) *Runner { ls := labels.Labels{} for _, v := range reg.Labels { @@ -64,28 +59,23 @@ func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client) envs[k] = v } if cfg.Cache.Enabled == nil || *cfg.Cache.Enabled { - if cfg.Cache.ExternalServer != "" { - envs["ACTIONS_CACHE_URL"] = cfg.Cache.ExternalServer + cacheHandler, err := artifactcache.StartHandler( + cfg.Cache.Dir, + cfg.Cache.Host, + cfg.Cache.Port, + log.StandardLogger().WithField("module", "cache_request"), + ) + if err != nil { + log.Errorf("cannot init cache server, it will be disabled: %v", err) + // go on } else { - cacheHandler, err := artifactcache.StartHandler( - cfg.Cache.Dir, - cfg.Cache.Host, - cfg.Cache.Port, - log.StandardLogger().WithField("module", "cache_request"), - ) - if err != nil { - log.Errorf("cannot init cache server, it will be disabled: %v", err) - // go on - } else { - envs["ACTIONS_CACHE_URL"] = cacheHandler.ExternalURL() + "/" - } + envs["ACTIONS_CACHE_URL"] = cacheHandler.ExternalURL() + "/" } } // set artifact gitea api artifactGiteaAPI := strings.TrimSuffix(cli.Address(), "/") + "/api/actions_pipeline/" envs["ACTIONS_RUNTIME_URL"] = artifactGiteaAPI - envs["ACTIONS_RESULTS_URL"] = strings.TrimSuffix(cli.Address(), "/") // Set specific environments to distinguish between Gitea and GitHub envs["GITEA_ACTIONS"] = "true" @@ -103,13 +93,14 @@ func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client) func (r *Runner) Run(ctx context.Context, task *runnerv1.Task) error { if _, ok := r.runningTasks.Load(task.Id); ok { return fmt.Errorf("task %d is already running", task.Id) + } else { + r.runningTasks.Store(task.Id, struct{}{}) + defer r.runningTasks.Delete(task.Id) } - r.runningTasks.Store(task.Id, struct{}{}) - defer r.runningTasks.Delete(task.Id) ctx, cancel := context.WithTimeout(ctx, r.cfg.Runner.Timeout) defer cancel() - reporter := report.NewReporter(ctx, cancel, r.client, task, r.cfg.Runner.ReportInterval) + reporter := report.NewReporter(ctx, cancel, r.client, task) var runErr error defer func() { lastWords := "" @@ -174,12 +165,8 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report. preset.Token = t } - giteaRuntimeToken := taskContext["gitea_runtime_token"].GetStringValue() - if giteaRuntimeToken == "" { - // use task token to action api token for previous Gitea Server Versions - giteaRuntimeToken = preset.Token - } - r.envs["ACTIONS_RUNTIME_TOKEN"] = giteaRuntimeToken + // use task token to action api token + r.envs["ACTIONS_RUNTIME_TOKEN"] = preset.Token eventJSON, err := json.Marshal(preset.Event) if err != nil { @@ -191,45 +178,32 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report. maxLifetime = time.Until(deadline) } - var inputs map[string]string - if preset.EventName == "workflow_dispatch" { - if inputsRaw, ok := preset.Event["inputs"]; ok { - inputs, _ = inputsRaw.(map[string]string) - } - } - runnerConfig := &runner.Config{ // On Linux, Workdir will be like "///" // On Windows, Workdir will be like "\\\" - Workdir: filepath.FromSlash(filepath.Clean(fmt.Sprintf("/%s/%s", r.cfg.Container.WorkdirParent, preset.Repository))), - BindWorkdir: false, - ActionCacheDir: filepath.FromSlash(r.cfg.Host.WorkdirParent), + Workdir: filepath.FromSlash(fmt.Sprintf("/%s/%s", r.cfg.Container.WorkdirParent, preset.Repository)), + BindWorkdir: false, - ReuseContainers: false, - ForcePull: r.cfg.Container.ForcePull, - ForceRebuild: false, - LogOutput: true, - JSONLogger: false, - Env: r.envs, - Secrets: task.Secrets, - GitHubInstance: strings.TrimSuffix(r.client.Address(), "/"), - AutoRemove: true, - NoSkipCheckout: true, - PresetGitHubContext: preset, - EventJSON: string(eventJSON), - ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id), - ContainerMaxLifetime: maxLifetime, - ContainerNetworkMode: container.NetworkMode(r.cfg.Container.Network), - ContainerNetworkEnableIPv6: r.cfg.Container.EnableIPv6, - ContainerOptions: r.cfg.Container.Options, - ContainerDaemonSocket: r.cfg.Container.DockerHost, - Privileged: r.cfg.Container.Privileged, - DefaultActionInstance: taskContext["gitea_default_actions_url"].GetStringValue(), - PlatformPicker: r.labels.PickPlatform, - Vars: task.Vars, - ValidVolumes: r.cfg.Container.ValidVolumes, - InsecureSkipTLS: r.cfg.Runner.Insecure, - Inputs: inputs, + ReuseContainers: false, + ForcePull: false, + ForceRebuild: false, + LogOutput: true, + JSONLogger: false, + Env: r.envs, + Secrets: task.Secrets, + GitHubInstance: r.client.Address(), + AutoRemove: true, + NoSkipCheckout: true, + PresetGitHubContext: preset, + EventJSON: string(eventJSON), + ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id), + ContainerMaxLifetime: maxLifetime, + ContainerNetworkMode: container.NetworkMode(r.cfg.Container.Network), + ContainerOptions: r.cfg.Container.Options, + Privileged: r.cfg.Container.Privileged, + DefaultActionInstance: taskContext["gitea_default_actions_url"].GetStringValue(), + PlatformPicker: r.labels.PickPlatform, + Vars: task.Vars, } rr, err := runner.New(runnerConfig) @@ -247,14 +221,3 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report. reporter.SetOutputs(job.Outputs) return execErr } - -func (r *Runner) Declare(ctx context.Context, labels []string) (*connect.Response[runnerv1.DeclareResponse], error) { - return r.client.Declare(ctx, connect.NewRequest(&runnerv1.DeclareRequest{ - Version: ver.Version(), - Labels: labels, - })) -} - -func (r *Runner) Update(ctx context.Context, labels labels.Labels) { - r.labels = labels -} diff --git a/internal/app/run/runner_test.go b/internal/app/run/runner_test.go deleted file mode 100644 index 0145c70..0000000 --- a/internal/app/run/runner_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package run - -import ( - "context" - "testing" - - "gitea.com/gitea/act_runner/internal/pkg/labels" - "github.com/stretchr/testify/assert" -) - -func TestLabelUpdate(t *testing.T) { - ctx := context.Background() - ls := labels.Labels{} - - initialLabel, err := labels.Parse("testlabel:docker://alpine") - assert.NoError(t, err) - ls = append(ls, initialLabel) - - newLs := labels.Labels{} - - newLabel, err := labels.Parse("next label:host") - assert.NoError(t, err) - newLs = append(newLs, initialLabel) - newLs = append(newLs, newLabel) - - runner := Runner{ - labels: ls, - } - - assert.Contains(t, runner.labels, initialLabel) - assert.NotContains(t, runner.labels, newLabel) - - runner.Update(ctx, newLs) - - assert.Contains(t, runner.labels, initialLabel) - assert.Contains(t, runner.labels, newLabel) -} diff --git a/internal/app/run/workflow_test.go b/internal/app/run/workflow_test.go index 4ab31b1..c7598db 100644 --- a/internal/app/run/workflow_test.go +++ b/internal/app/run/workflow_test.go @@ -19,7 +19,7 @@ func Test_generateWorkflow(t *testing.T) { tests := []struct { name string args args - assert func(t *testing.T, wf *model.Workflow, err error) + assert func(t *testing.T, wf *model.Workflow) want1 string wantErr bool }{ @@ -56,41 +56,19 @@ jobs: }, }, }, - assert: func(t *testing.T, wf *model.Workflow, err error) { + assert: func(t *testing.T, wf *model.Workflow) { assert.DeepEqual(t, wf.GetJob("job9").Needs(), []string{"job1", "job2"}) }, want1: "job9", wantErr: false, }, - { - name: "valid YAML syntax in top level env but wrong value type", - args: args{ - task: &runnerv1.Task{ - WorkflowPayload: []byte(` -on: push - -env: - value: {{ }} -`), - }, - }, - assert: func(t *testing.T, wf *model.Workflow, err error) { - require.Nil(t, wf) - assert.ErrorContains(t, err, "cannot unmarshal") - }, - wantErr: true, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, got1, err := generateWorkflow(tt.args.task) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - assert.Equal(t, got1, tt.want1) - } - tt.assert(t, got, err) + require.NoError(t, err) + tt.assert(t, got) + assert.Equal(t, got1, tt.want1) }) } } diff --git a/internal/pkg/client/header.go b/internal/pkg/client/header.go index 24844fa..df8627a 100644 --- a/internal/pkg/client/header.go +++ b/internal/pkg/client/header.go @@ -4,8 +4,7 @@ package client const ( - UUIDHeader = "x-runner-uuid" - TokenHeader = "x-runner-token" - // Deprecated: could be removed after Gitea 1.20 released + UUIDHeader = "x-runner-uuid" + TokenHeader = "x-runner-token" VersionHeader = "x-runner-version" ) diff --git a/internal/pkg/client/http.go b/internal/pkg/client/http.go index d365a77..cc0c44e 100644 --- a/internal/pkg/client/http.go +++ b/internal/pkg/client/http.go @@ -11,10 +11,10 @@ import ( "code.gitea.io/actions-proto-go/ping/v1/pingv1connect" "code.gitea.io/actions-proto-go/runner/v1/runnerv1connect" - "connectrpc.com/connect" + "github.com/bufbuild/connect-go" ) -func getHTTPClient(endpoint string, insecure bool) *http.Client { +func getHttpClient(endpoint string, insecure bool) *http.Client { if strings.HasPrefix(endpoint, "https://") && insecure { return &http.Client{ Transport: &http.Transport{ @@ -39,7 +39,6 @@ func New(endpoint string, insecure bool, uuid, token, version string, opts ...co if token != "" { req.Header().Set(TokenHeader, token) } - // TODO: version will be removed from request header after Gitea 1.20 released. if version != "" { req.Header().Set(VersionHeader, version) } @@ -49,12 +48,12 @@ func New(endpoint string, insecure bool, uuid, token, version string, opts ...co return &HTTPClient{ PingServiceClient: pingv1connect.NewPingServiceClient( - getHTTPClient(endpoint, insecure), + getHttpClient(endpoint, insecure), baseURL, opts..., ), RunnerServiceClient: runnerv1connect.NewRunnerServiceClient( - getHTTPClient(endpoint, insecure), + getHttpClient(endpoint, insecure), baseURL, opts..., ), diff --git a/internal/pkg/client/mocks/Client.go b/internal/pkg/client/mocks/Client.go index a8bfdb1..a689c54 100644 --- a/internal/pkg/client/mocks/Client.go +++ b/internal/pkg/client/mocks/Client.go @@ -5,7 +5,7 @@ package mocks import ( context "context" - connect "connectrpc.com/connect" + connect "github.com/bufbuild/connect-go" mock "github.com/stretchr/testify/mock" @@ -33,32 +33,6 @@ func (_m *Client) Address() string { return r0 } -// Declare provides a mock function with given fields: _a0, _a1 -func (_m *Client) Declare(_a0 context.Context, _a1 *connect.Request[runnerv1.DeclareRequest]) (*connect.Response[runnerv1.DeclareResponse], error) { - ret := _m.Called(_a0, _a1) - - var r0 *connect.Response[runnerv1.DeclareResponse] - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *connect.Request[runnerv1.DeclareRequest]) (*connect.Response[runnerv1.DeclareResponse], error)); ok { - return rf(_a0, _a1) - } - if rf, ok := ret.Get(0).(func(context.Context, *connect.Request[runnerv1.DeclareRequest]) *connect.Response[runnerv1.DeclareResponse]); ok { - r0 = rf(_a0, _a1) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*connect.Response[runnerv1.DeclareResponse]) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *connect.Request[runnerv1.DeclareRequest]) error); ok { - r1 = rf(_a0, _a1) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // FetchTask provides a mock function with given fields: _a0, _a1 func (_m *Client) FetchTask(_a0 context.Context, _a1 *connect.Request[runnerv1.FetchTaskRequest]) (*connect.Response[runnerv1.FetchTaskResponse], error) { ret := _m.Called(_a0, _a1) diff --git a/internal/pkg/config/config.example.yaml b/internal/pkg/config/config.example.yaml index 32dfb68..96fa0d1 100644 --- a/internal/pkg/config/config.example.yaml +++ b/internal/pkg/config/config.example.yaml @@ -1,8 +1,5 @@ # Example configuration file, it's safe to copy this as the default config file without any modification. -# You don't have to copy this file to your instance, -# just run `./act_runner generate-config > config.yaml` to generate a config file. - log: # The level of logging, can be trace, debug, info, warn, error, fatal level: info @@ -23,25 +20,12 @@ runner: # Please note that the Forgejo instance also has a timeout (3h by default) for the job. # So the job could be stopped by the Forgejo instance if it's timeout is shorter than this. timeout: 3h - # The timeout for the runner to wait for running jobs to finish when - # shutting down because a TERM or INT signal has been received. Any - # running jobs that haven't finished after this timeout will be - # cancelled. - # If unset or zero the jobs will be cancelled immediately. - shutdown_timeout: 3h - # Whether skip verifying the TLS certificate of the instance. + # Whether skip verifying the TLS certificate of the Forgejo instance. insecure: false # The timeout for fetching the job from the Forgejo instance. fetch_timeout: 5s # The interval for fetching the job from the Forgejo instance. fetch_interval: 2s - # The interval for reporting the job status and logs to the Forgejo instance. - report_interval: 1s - # The labels of a runner are used to determine which jobs the runner can run, and how to run them. - # Like: ["macos-arm64:host", "ubuntu-latest:docker://node:20-bookworm", "ubuntu-22.04:docker://node:20-bookworm"] - # If it's empty when registering, it will ask for inputting labels. - # If it's empty when execute `deamon`, will use labels in `.runner` file. - labels: [] cache: # Enable cache server to use actions/cache. @@ -56,19 +40,12 @@ cache: # The port of the cache server. # 0 means to use a random available port. port: 0 - # The external cache server URL. Valid only when enable is true. - # If it's specified, act_runner will use this URL as the ACTIONS_CACHE_URL rather than start a server by itself. - # The URL should generally end with "/". - external_server: "" container: # Specifies the network to which the container will connect. # Could be host, bridge or the name of a custom network. # If it's empty, create a network automatically. network: "" - # Whether to create networks with IPv6 enabled. Requires the Docker daemon to be set up accordingly. - # Only takes effect if "network" is set to "". - enable_ipv6: false # Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker). privileged: false # And other options to be used when the container is started (eg, --add-host=my.forgejo.url:host-gateway). @@ -76,25 +53,3 @@ container: # The parent directory of a job's working directory. # If it's empty, /workspace will be used. workdir_parent: - # Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob - # You can specify multiple volumes. If the sequence is empty, no volumes can be mounted. - # For example, if you only allow containers to mount the `data` volume and all the json files in `/src`, you should change the config to: - # valid_volumes: - # - data - # - /src/*.json - # If you want to allow any volume, please use the following configuration: - # valid_volumes: - # - '**' - valid_volumes: [] - # overrides the docker client host with the specified one. - # If it's empty, act_runner will find an available docker host automatically. - # If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers. - # If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work. - docker_host: "" - # Pull docker image(s) even if already present - force_pull: false - -host: - # The parent directory of a job's working directory. - # If it's empty, $HOME/.cache/act/ will be used. - workdir_parent: diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index a1536b3..4edf1d6 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -14,70 +14,33 @@ import ( "gopkg.in/yaml.v3" ) -// Log represents the configuration for logging. -type Log struct { - Level string `yaml:"level"` // Level indicates the logging level. -} - -// Runner represents the configuration for the runner. -type Runner struct { - File string `yaml:"file"` // File specifies the file path for the runner. - Capacity int `yaml:"capacity"` // Capacity specifies the capacity of the runner. - Envs map[string]string `yaml:"envs"` // Envs stores environment variables for the runner. - EnvFile string `yaml:"env_file"` // EnvFile specifies the path to the file containing environment variables for the runner. - Timeout time.Duration `yaml:"timeout"` // Timeout specifies the duration for runner timeout. - ShutdownTimeout time.Duration `yaml:"shutdown_timeout"` // ShutdownTimeout specifies the duration to wait for running jobs to complete during a shutdown of the runner. - Insecure bool `yaml:"insecure"` // Insecure indicates whether the runner operates in an insecure mode. - FetchTimeout time.Duration `yaml:"fetch_timeout"` // FetchTimeout specifies the timeout duration for fetching resources. - FetchInterval time.Duration `yaml:"fetch_interval"` // FetchInterval specifies the interval duration for fetching resources. - ReportInterval time.Duration `yaml:"report_interval"` // ReportInterval specifies the interval duration for reporting status and logs of a running job. - Labels []string `yaml:"labels"` // Labels specify the labels of the runner. Labels are declared on each startup -} - -// Cache represents the configuration for caching. -type Cache struct { - Enabled *bool `yaml:"enabled"` // Enabled indicates whether caching is enabled. It is a pointer to distinguish between false and not set. If not set, it will be true. - Dir string `yaml:"dir"` // Dir specifies the directory path for caching. - Host string `yaml:"host"` // Host specifies the caching host. - Port uint16 `yaml:"port"` // Port specifies the caching port. - ExternalServer string `yaml:"external_server"` // ExternalServer specifies the URL of external cache server -} - -// Container represents the configuration for the container. -type Container struct { - Network string `yaml:"network"` // Network specifies the network for the container. - NetworkMode string `yaml:"network_mode"` // Deprecated: use Network instead. Could be removed after Gitea 1.20 - EnableIPv6 bool `yaml:"enable_ipv6"` // EnableIPv6 indicates whether the network is created with IPv6 enabled. - Privileged bool `yaml:"privileged"` // Privileged indicates whether the container runs in privileged mode. - Options string `yaml:"options"` // Options specifies additional options for the container. - WorkdirParent string `yaml:"workdir_parent"` // WorkdirParent specifies the parent directory for the container's working directory. - ValidVolumes []string `yaml:"valid_volumes"` // ValidVolumes specifies the volumes (including bind mounts) can be mounted to containers. - DockerHost string `yaml:"docker_host"` // DockerHost specifies the Docker host. It overrides the value specified in environment variable DOCKER_HOST. - ForcePull bool `yaml:"force_pull"` // Pull docker image(s) even if already present -} - -// Host represents the configuration for the host. -type Host struct { - WorkdirParent string `yaml:"workdir_parent"` // WorkdirParent specifies the parent directory for the host's working directory. -} - -// Config represents the overall configuration. type Config struct { - Log Log `yaml:"log"` // Log represents the configuration for logging. - Runner Runner `yaml:"runner"` // Runner represents the configuration for the runner. - Cache Cache `yaml:"cache"` // Cache represents the configuration for caching. - Container Container `yaml:"container"` // Container represents the configuration for the container. - Host Host `yaml:"host"` // Host represents the configuration for the host. -} - -// Tune the config settings accordingly to the Forgejo instance that will be used. -func (c *Config) Tune(instanceURL string) { - if instanceURL == "https://codeberg.org" { - if c.Runner.FetchInterval < 30*time.Second { - log.Info("The runner is configured to be used by a public instance, fetch interval is set to 30 seconds.") - c.Runner.FetchInterval = 30 * time.Second - } - } + Log struct { + Level string `yaml:"level"` + } `yaml:"log"` + Runner struct { + File string `yaml:"file"` + Capacity int `yaml:"capacity"` + Envs map[string]string `yaml:"envs"` + EnvFile string `yaml:"env_file"` + Timeout time.Duration `yaml:"timeout"` + Insecure bool `yaml:"insecure"` + FetchTimeout time.Duration `yaml:"fetch_timeout"` + FetchInterval time.Duration `yaml:"fetch_interval"` + } `yaml:"runner"` + Cache struct { + Enabled *bool `yaml:"enabled"` // pointer to distinguish between false and not set, and it will be true if not set + Dir string `yaml:"dir"` + Host string `yaml:"host"` + Port uint16 `yaml:"port"` + } `yaml:"cache"` + Container struct { + Network string `yaml:"network"` + NetworkMode string `yaml:"network_mode"` // Deprecated: use Network instead. Could be removed after Gitea 1.20 + Privileged bool `yaml:"privileged"` + Options string `yaml:"options"` + WorkdirParent string `yaml:"workdir_parent"` + } `yaml:"container"` } // LoadDefault returns the default configuration. @@ -85,12 +48,14 @@ func (c *Config) Tune(instanceURL string) { func LoadDefault(file string) (*Config, error) { cfg := &Config{} if file != "" { - content, err := os.ReadFile(file) + f, err := os.Open(file) if err != nil { - return nil, fmt.Errorf("open config file %q: %w", file, err) + return nil, err } - if err := yaml.Unmarshal(content, cfg); err != nil { - return nil, fmt.Errorf("parse config file %q: %w", file, err) + defer f.Close() + decoder := yaml.NewDecoder(f) + if err := decoder.Decode(&cfg); err != nil { + return nil, err } } compatibleWithOldEnvs(file != "", cfg) @@ -101,9 +66,6 @@ func LoadDefault(file string) (*Config, error) { if err != nil { return nil, fmt.Errorf("read env file %q: %w", cfg.Runner.EnvFile, err) } - if cfg.Runner.Envs == nil { - cfg.Runner.Envs = map[string]string{} - } for k, v := range envs { cfg.Runner.Envs[k] = v } @@ -135,19 +97,12 @@ func LoadDefault(file string) (*Config, error) { if cfg.Container.WorkdirParent == "" { cfg.Container.WorkdirParent = "workspace" } - if cfg.Host.WorkdirParent == "" { - home, _ := os.UserHomeDir() - cfg.Host.WorkdirParent = filepath.Join(home, ".cache", "act") - } if cfg.Runner.FetchTimeout <= 0 { cfg.Runner.FetchTimeout = 5 * time.Second } if cfg.Runner.FetchInterval <= 0 { cfg.Runner.FetchInterval = 2 * time.Second } - if cfg.Runner.ReportInterval <= 0 { - cfg.Runner.ReportInterval = time.Second - } // although `container.network_mode` will be deprecated, but we have to be compatible with it for now. if cfg.Container.NetworkMode != "" && cfg.Container.Network == "" { diff --git a/internal/pkg/config/config_test.go b/internal/pkg/config/config_test.go deleted file mode 100644 index d2ddf2f..0000000 --- a/internal/pkg/config/config_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2024 The Forgejo Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package config - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestConfigTune(t *testing.T) { - c := &Config{ - Runner: Runner{}, - } - - t.Run("Public instance tuning", func(t *testing.T) { - c.Runner.FetchInterval = 60 * time.Second - c.Tune("https://codeberg.org") - assert.EqualValues(t, 60*time.Second, c.Runner.FetchInterval) - - c.Runner.FetchInterval = 2 * time.Second - c.Tune("https://codeberg.org") - assert.EqualValues(t, 30*time.Second, c.Runner.FetchInterval) - }) - - t.Run("Non-public instance tuning", func(t *testing.T) { - c.Runner.FetchInterval = 60 * time.Second - c.Tune("https://example.com") - assert.EqualValues(t, 60*time.Second, c.Runner.FetchInterval) - - c.Runner.FetchInterval = 2 * time.Second - c.Tune("https://codeberg.com") - assert.EqualValues(t, 2*time.Second, c.Runner.FetchInterval) - }) -} diff --git a/internal/pkg/envcheck/docker.go b/internal/pkg/envcheck/docker.go index f115bc7..841ca23 100644 --- a/internal/pkg/envcheck/docker.go +++ b/internal/pkg/envcheck/docker.go @@ -10,16 +10,9 @@ import ( "github.com/docker/docker/client" ) -func CheckIfDockerRunning(ctx context.Context, configDockerHost string) error { - opts := []client.Opt{ - client.FromEnv, - } - - if configDockerHost != "" { - opts = append(opts, client.WithHost(configDockerHost)) - } - - cli, err := client.NewClientWithOpts(opts...) +func CheckIfDockerRunning(ctx context.Context) error { + // TODO: if runner support configures to use docker, we need config.Config to pass in + cli, err := client.NewClientWithOpts(client.FromEnv) if err != nil { return err } @@ -27,7 +20,7 @@ func CheckIfDockerRunning(ctx context.Context, configDockerHost string) error { _, err = cli.Ping(ctx) if err != nil { - return fmt.Errorf("cannot ping the docker daemon. is it running? %w", err) + return fmt.Errorf("cannot ping the docker daemon, does it running? %w", err) } return nil diff --git a/internal/pkg/labels/labels.go b/internal/pkg/labels/labels.go index f448fdf..0848222 100644 --- a/internal/pkg/labels/labels.go +++ b/internal/pkg/labels/labels.go @@ -11,7 +11,6 @@ import ( const ( SchemeHost = "host" SchemeDocker = "docker" - SchemeLXC = "lxc" ) type Label struct { @@ -33,7 +32,7 @@ func Parse(str string) (*Label, error) { if len(splits) >= 3 { label.Arg = splits[2] } - if label.Schema != SchemeHost && label.Schema != SchemeDocker && label.Schema != SchemeLXC { + if label.Schema != SchemeHost && label.Schema != SchemeDocker { return nil, fmt.Errorf("unsupported schema: %s", label.Schema) } return label, nil @@ -56,11 +55,10 @@ func (l Labels) PickPlatform(runsOn []string) string { switch label.Schema { case SchemeDocker: // "//" will be ignored + // TODO maybe we should use 'ubuntu-18.04:docker:node:16-buster' instead platforms[label.Name] = strings.TrimPrefix(label.Arg, "//") case SchemeHost: platforms[label.Name] = "-self-hosted" - case SchemeLXC: - platforms[label.Name] = "lxc:" + strings.TrimPrefix(label.Arg, "//") default: // It should not happen, because Parse has checked it. continue @@ -82,28 +80,5 @@ func (l Labels) PickPlatform(runsOn []string) string { // So the runner receives a task with a label that the runner doesn't have, // it happens when the user have edited the label of the runner in the web UI. // TODO: it may be not correct, what if the runner is used as host mode only? - return "node:20-bullseye" -} - -func (l Labels) Names() []string { - names := make([]string, 0, len(l)) - for _, label := range l { - names = append(names, label.Name) - } - return names -} - -func (l Labels) ToStrings() []string { - ls := make([]string, 0, len(l)) - for _, label := range l { - lbl := label.Name - if label.Schema != "" { - lbl += ":" + label.Schema - if label.Arg != "" { - lbl += ":" + label.Arg - } - } - ls = append(ls, lbl) - } - return ls + return "node:16-bullseye" } diff --git a/internal/pkg/labels/labels_test.go b/internal/pkg/labels/labels_test.go index e46a27b..dbef1ef 100644 --- a/internal/pkg/labels/labels_test.go +++ b/internal/pkg/labels/labels_test.go @@ -55,8 +55,9 @@ func TestParse(t *testing.T) { if tt.wantErr { require.Error(t, err) return + } else { + require.NoError(t, err) } - require.NoError(t, err) assert.DeepEqual(t, got, tt.want) }) } diff --git a/internal/pkg/report/reporter.go b/internal/pkg/report/reporter.go index cee5062..7e9a2d5 100644 --- a/internal/pkg/report/reporter.go +++ b/internal/pkg/report/reporter.go @@ -12,8 +12,8 @@ import ( "time" runnerv1 "code.gitea.io/actions-proto-go/runner/v1" - "connectrpc.com/connect" retry "github.com/avast/retry-go/v4" + "github.com/bufbuild/connect-go" log "github.com/sirupsen/logrus" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/timestamppb" @@ -29,11 +29,10 @@ type Reporter struct { client client.Client clientM sync.Mutex - logOffset int - logRows []*runnerv1.LogRow - logReplacer *strings.Replacer - oldnew []string - reportInterval time.Duration + logOffset int + logRows []*runnerv1.LogRow + logReplacer *strings.Replacer + oldnew []string state *runnerv1.TaskState stateMu sync.RWMutex @@ -43,25 +42,21 @@ type Reporter struct { stopCommandEndToken string } -func NewReporter(ctx context.Context, cancel context.CancelFunc, client client.Client, task *runnerv1.Task, reportInterval time.Duration) *Reporter { +func NewReporter(ctx context.Context, cancel context.CancelFunc, client client.Client, task *runnerv1.Task) *Reporter { var oldnew []string if v := task.Context.Fields["token"].GetStringValue(); v != "" { oldnew = append(oldnew, v, "***") } - if v := task.Context.Fields["gitea_runtime_token"].GetStringValue(); v != "" { - oldnew = append(oldnew, v, "***") - } for _, v := range task.Secrets { oldnew = append(oldnew, v, "***") } rv := &Reporter{ - ctx: ctx, - cancel: cancel, - client: client, - oldnew: oldnew, - reportInterval: reportInterval, - logReplacer: strings.NewReplacer(oldnew...), + ctx: ctx, + cancel: cancel, + client: client, + oldnew: oldnew, + logReplacer: strings.NewReplacer(oldnew...), state: &runnerv1.TaskState{ Id: task.Id, }, @@ -116,9 +111,6 @@ func (r *Reporter) Fire(entry *log.Entry) error { for _, s := range r.state.Steps { if s.Result == runnerv1.Result_RESULT_UNSPECIFIED { s.Result = runnerv1.Result_RESULT_CANCELLED - if jobResult == runnerv1.Result_RESULT_SKIPPED { - s.Result = runnerv1.Result_RESULT_SKIPPED - } } } } @@ -182,7 +174,7 @@ func (r *Reporter) RunDaemon() { _ = r.ReportLog(false) _ = r.ReportState() - time.AfterFunc(r.reportInterval, r.RunDaemon) + time.AfterFunc(time.Second, r.RunDaemon) } func (r *Reporter) Logf(format string, a ...interface{}) { @@ -394,13 +386,12 @@ func (r *Reporter) handleCommand(originalContent, command, parameters, value str // Not implemented yet, so just return the original content. return &originalContent case "group": - // Rewriting into ##[] syntax which the frontend understands - content := "##[group]" + value - return &content + // Returning the original content, because I think the frontend + // will use it when rendering the output. + return &originalContent case "endgroup": // Ditto - content := "##[endgroup]" - return &content + return &originalContent case "stop-commands": r.stopCommandEndToken = value return nil @@ -427,7 +418,7 @@ func (r *Reporter) parseLogRow(entry *log.Entry) *runnerv1.LogRow { return &runnerv1.LogRow{ Time: timestamppb.New(entry.Time), - Content: strings.ToValidUTF8(content, "?"), + Content: content, } } diff --git a/internal/pkg/report/reporter_test.go b/internal/pkg/report/reporter_test.go index 524e972..d3d4c12 100644 --- a/internal/pkg/report/reporter_test.go +++ b/internal/pkg/report/reporter_test.go @@ -7,10 +7,9 @@ import ( "context" "strings" "testing" - "time" runnerv1 "code.gitea.io/actions-proto-go/runner/v1" - connect_go "connectrpc.com/connect" + connect_go "github.com/bufbuild/connect-go" log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -97,8 +96,8 @@ func TestReporter_parseLogRow(t *testing.T) { "::endgroup::", }, []string{ - "##[group]", - "##[endgroup]", + "::group::", + "::endgroup::", }, }, { @@ -174,7 +173,7 @@ func TestReporter_Fire(t *testing.T) { require.NoError(t, err) reporter := NewReporter(ctx, cancel, client, &runnerv1.Task{ Context: taskCtx, - }, time.Second) + }) defer func() { assert.NoError(t, reporter.Close("")) }() diff --git a/renovate.json b/renovate.json deleted file mode 100644 index 31da118..0000000 --- a/renovate.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["local>forgejo/renovate-config"], - "packageRules": [ - { - "description": "Disable nektos/act, it's replaced", - "matchDepNames": ["github.com/nektos/act"], - "enabled": false - } - ] -} diff --git a/scripts/run.sh b/run.sh similarity index 68% rename from scripts/run.sh rename to run.sh index 89626b4..8317b2d 100755 --- a/scripts/run.sh +++ b/run.sh @@ -10,10 +10,6 @@ CONFIG_ARG="" if [[ ! -z "${CONFIG_FILE}" ]]; then CONFIG_ARG="--config ${CONFIG_FILE}" fi -EXTRA_ARGS="" -if [[ ! -z "${GITEA_RUNNER_LABELS}" ]]; then - EXTRA_ARGS="${EXTRA_ARGS} --labels ${GITEA_RUNNER_LABELS}" -fi # Use the same ENV variable names as https://github.com/vegardit/docker-gitea-act-runner @@ -21,16 +17,19 @@ if [[ ! -s .runner ]]; then try=$((try + 1)) success=0 - # The point of this loop is to make it simple, when running both forgejo-runner and gitea in docker, - # for the forgejo-runner to wait a moment for gitea to become available before erroring out. Within + # The point of this loop is to make it simple, when running both act_runner and gitea in docker, + # for the act_runner to wait a moment for gitea to become available before erroring out. Within # the context of a single docker-compose, something similar could be done via healthchecks, but # this is more flexible. while [[ $success -eq 0 ]] && [[ $try -lt ${GITEA_MAX_REG_ATTEMPTS:-10} ]]; do - forgejo-runner register \ + act_runner register \ --instance "${GITEA_INSTANCE_URL}" \ --token "${GITEA_RUNNER_REGISTRATION_TOKEN}" \ --name "${GITEA_RUNNER_NAME:-`hostname`}" \ - ${CONFIG_ARG} ${EXTRA_ARGS} --no-interactive 2>&1 | tee /tmp/reg.log + --labels "${GITEA_RUNNER_LABELS}" \ + ${CONFIG_ARG} --no-interactive > /tmp/reg.log 2>&1 + + cat /tmp/reg.log cat /tmp/reg.log | grep 'Runner registered successfully' > /dev/null if [[ $? -eq 0 ]]; then @@ -42,7 +41,7 @@ if [[ ! -s .runner ]]; then fi done fi -# Prevent reading the token from the forgejo-runner process +# Prevent reading the token from the act_runner process unset GITEA_RUNNER_REGISTRATION_TOKEN -forgejo-runner daemon ${CONFIG_ARG} +act_runner daemon ${CONFIG_ARG} diff --git a/scripts/rootless.sh b/scripts/rootless.sh deleted file mode 100755 index 310a03b..0000000 --- a/scripts/rootless.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -# wait for docker daemon -while ! nc -z localhost 2376