diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7b6d2b2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +Dockerfile +forgejo-runner diff --git a/.forgejo/workflows/integration.yml b/.forgejo/workflows/integration.yml new file mode 100644 index 0000000..025fc3d --- /dev/null +++ b/.forgejo/workflows/integration.yml @@ -0,0 +1,55 @@ +name: Integration tests for the release process + +on: + push: + paths: + - go.mod + - .forgejo/workflows/release.yml + - .forgejo/workflows/integration.yml + +jobs: + release-simulation: + runs-on: self-hosted + 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 + diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml new file mode 100644 index 0000000..f917cb1 --- /dev/null +++ b/.forgejo/workflows/release.yml @@ -0,0 +1,131 @@ +name: Publish release + +on: + push: + tags: 'v*' + +jobs: + release: + runs-on: self-hosted + steps: + - uses: actions/checkout@v3 + + - 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" + echo "shell=set -x" >> "$GITHUB_OUTPUT" + + - id: registry + run: | + ${{ steps.verbose.outputs.shell }} + url="${{ env.GITHUB_SERVER_URL }}" + hostport=${url##http*://} + hostport=${hostport%%/} + echo "host-port=${hostport}" >> "$GITHUB_OUTPUT" + if ! [[ $url =~ ^http:// ]] ; then + exit 0 + fi + cat >> "$GITHUB_OUTPUT" <> "$GITHUB_OUTPUT" + echo "doer=${doer}" >> "$GITHUB_OUTPUT" + + - 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 > 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/actions/forgejo-release@v1 + with: + direction: upload + release-dir: release + release-notes: "RELEASE-NOTES#${{ steps.build.outputs.tag }}" + token: ${{ steps.secrets.outputs.token }} + verbose: ${{ steps.verbose.outputs.value }} + + - name: publish release (when TOKEN secret is set) + if: ${{ secrets.TOKEN != '' }} + uses: https://code.forgejo.org/actions/forgejo-release@v1 + with: + 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/test.yml b/.forgejo/workflows/test.yml new file mode 100644 index 0000000..3ce0323 --- /dev/null +++ b/.forgejo/workflows/test.yml @@ -0,0 +1,23 @@ +name: checks +on: + - pull_request + - push + +env: + GOPROXY: https://goproxy.io,direct + +jobs: + lint: + name: check and test + runs-on: ubuntu-latest + steps: + - uses: actions/setup-go@v3 + with: + 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/.gitignore b/.gitignore index d9d87a5..25903d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ -act_runner +*~ + +forgejo-runner .env .runner coverage.txt diff --git a/Dockerfile b/Dockerfile index e530655..0fdae4a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,15 @@ -FROM golang:1.20-alpine3.17 as builder -RUN apk add --no-cache make=4.3-r1 git=2.38.5-r0 +#Build stage +FROM golang:1.20-alpine3.17 AS build-env -COPY . /opt/src/act_runner -WORKDIR /opt/src/act_runner +RUN apk --no-cache add build-base git -RUN make clean && make build +COPY . /srv +WORKDIR /srv +RUN make build FROM alpine:3.17 -RUN apk add --no-cache \ - git=2.38.5-r0 bash=5.2.15-r0 \ - && rm -rf /var/cache/apk/* +LABEL maintainer="contact@forgejo.org" -COPY --from=builder /opt/src/act_runner/act_runner /usr/local/bin/act_runner -COPY run.sh /opt/act/run.sh +COPY --from=build-env /srv/forgejo-runner /bin/forgejo-runner -ENTRYPOINT ["/opt/act/run.sh"] +ENTRYPOINT ["/bin/forgejo-runner"] diff --git a/Makefile b/Makefile index a72fdeb..2848c03 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ DIST := dist -EXECUTABLE := act_runner +EXECUTABLE := forgejo-runner GOFMT ?= gofumpt -l DIST := dist DIST_DIRS := $(DIST)/binaries $(DIST)/release @@ -20,11 +20,7 @@ DOCKER_IMAGE ?= gitea/act_runner DOCKER_TAG ?= nightly DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG) -ifneq ($(shell uname), Darwin) - EXTLDFLAGS = -extldflags "-static" $(null) -else - EXTLDFLAGS = -endif +EXTLDFLAGS = -extldflags "-static" $(null) ifeq ($(HAS_GO), GO) GOPATH ?= $(shell $(GO) env GOPATH) @@ -113,7 +109,7 @@ install: $(GOFILES) build: go-check $(EXECUTABLE) $(EXECUTABLE): $(GOFILES) - $(GO) build -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o $@ + $(GO) build -v -tags 'netgo osusergo $(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o $@ .PHONY: deps-backend deps-backend: diff --git a/go.mod b/go.mod index 6a7b421..91338b5 100644 --- a/go.mod +++ b/go.mod @@ -110,4 +110,4 @@ require ( modernc.org/token v1.1.0 // indirect ) -replace github.com/nektos/act => gitea.com/gitea/act v0.243.3-0.20230420082431-e12252a43a3f +replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.5.1 diff --git a/go.sum b/go.sum index b1cbeda..e94cc8a 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,11 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +code.forgejo.org/forgejo/act v1.5.1 h1:ROOxFmG4EtXh3lJ2Qrrtn4nCw4lxsgzc2A8yUu9lgqk= +code.forgejo.org/forgejo/act v1.5.1/go.mod h1:mabw6AZAiDgxGlK83orWLrNERSPvgBJzEUS3S7u2bHI= 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= -gitea.com/gitea/act v0.243.3-0.20230420082431-e12252a43a3f h1:Tbel/BObxGRyvx2q5GwBVg9IaJldhtVoonjwaQAARHU= -gitea.com/gitea/act v0.243.3-0.20230420082431-e12252a43a3f/go.mod h1:mabw6AZAiDgxGlK83orWLrNERSPvgBJzEUS3S7u2bHI= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE= diff --git a/internal/app/cmd/exec.go b/internal/app/cmd/exec.go index b6f27f7..9c9ea8f 100644 --- a/internal/app/cmd/exec.go +++ b/internal/app/cmd/exec.go @@ -440,7 +440,7 @@ func loadExecCmd(ctx context.Context) *cobra.Command { execCmd.Flags().BoolVarP(&execArg.runList, "list", "l", false, "list workflows") execCmd.Flags().StringVarP(&execArg.job, "job", "j", "", "run a specific job ID") execCmd.Flags().StringVarP(&execArg.event, "event", "E", "", "run a event name") - execCmd.PersistentFlags().StringVarP(&execArg.workflowsPath, "workflows", "W", "./.gitea/workflows/", "path to workflow file(s)") + execCmd.PersistentFlags().StringVarP(&execArg.workflowsPath, "workflows", "W", "./.forgejo/workflows/", "path to workflow file(s)") execCmd.PersistentFlags().StringVarP(&execArg.workdir, "directory", "C", ".", "working directory") execCmd.PersistentFlags().BoolVarP(&execArg.noWorkflowRecurse, "no-recurse", "", false, "Flag to disable running workflows from subdirectories of specified path in '--workflows'/'-W' flag") execCmd.Flags().BoolVarP(&execArg.autodetectEvent, "detect-event", "", false, "Use first event type from workflow as event that triggered the workflow") @@ -461,7 +461,7 @@ func loadExecCmd(ctx context.Context) *cobra.Command { 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.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://gitea.com", "Defines the default url of action instance.") + 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") diff --git a/internal/app/run/runner.go b/internal/app/run/runner.go index 79b0620..0bbe7e5 100644 --- a/internal/app/run/runner.go +++ b/internal/app/run/runner.go @@ -46,6 +46,13 @@ func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client) ls = append(ls, l) } } + + if cfg.Runner.Envs == nil { + cfg.Runner.Envs = make(map[string]string, 10) + } + + cfg.Runner.Envs["GITHUB_SERVER_URL"] = reg.Address + envs := make(map[string]string, len(cfg.Runner.Envs)) for k, v := range cfg.Runner.Envs { envs[k] = v