Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/arc-publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ jobs:

- name: Install tools
run: |
curl -L -O https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.2.0/kubebuilder_2.2.0_linux_amd64.tar.gz
tar zxvf kubebuilder_2.2.0_linux_amd64.tar.gz
sudo mv kubebuilder_2.2.0_linux_amd64 /usr/local/kubebuilder

curl -s https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh | bash
sudo mv kustomize /usr/local/bin
curl -L -O https://github.com/tcnksm/ghr/releases/download/v0.13.0/ghr_v0.13.0_linux_amd64.tar.gz
Expand Down
10 changes: 4 additions & 6 deletions .github/workflows/go.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,11 @@ jobs:
- run: make manifests
- name: Check diff
run: git diff --exit-code
- name: Install kubebuilder
- name: Setup envtest
run: |
curl -D headers.txt -fsL "https://storage.googleapis.com/kubebuilder-tools/kubebuilder-tools-1.30.0-linux-amd64.tar.gz" -o kubebuilder-tools
echo "$(grep -i etag headers.txt -m 1 | cut -d'"' -f2) kubebuilder-tools" > sum
md5sum -c sum
tar -zvxf kubebuilder-tools
sudo mv kubebuilder /usr/local/
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@$(go list -m -f '{{ .Version }}' sigs.k8s.io/controller-runtime | awk -F'[v.]' '{printf "release-%d.%d", $2, $3}')
ENVTEST_K8S_VERSION=$(go list -m -f '{{ .Version }}' k8s.io/api | awk -F'[v.]' '{printf "1.%d", $3}')
echo "KUBEBUILDER_ASSETS=$(setup-envtest use ${ENVTEST_K8S_VERSION} -p path)" >> $GITHUB_ENV
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GitHub workflow setup-envtest command uses setup-envtest use ${ENVTEST_K8S_VERSION} -p path without the --bin-dir parameter that's used in the Makefile (line 72-75 of Makefile). While this isn't necessarily wrong, it creates an inconsistency between local development and CI. The Makefile explicitly specifies --bin-dir $(GOBIN) to ensure binaries are stored in a known location. Without this parameter in the workflow, setup-envtest will use its default location, which should still work but creates an unnecessary difference between environments.

Suggested change
echo "KUBEBUILDER_ASSETS=$(setup-envtest use ${ENVTEST_K8S_VERSION} -p path)" >> $GITHUB_ENV
echo "KUBEBUILDER_ASSETS=$(setup-envtest use ${ENVTEST_K8S_VERSION} --bin-dir=$(go env GOBIN) -p path)" >> $GITHUB_ENV

Copilot uses AI. Check for mistakes.
- name: Run go tests
run: |
go test -short `go list ./... | grep -v ./test_e2e_arc`
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ bin
# OS
.DS_STORE

/test-assets

/.tools
29 changes: 29 additions & 0 deletions .mockery.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
all: false
packages:
github.com/actions/actions-runner-controller/github/actions:
config:
inpackage: true
interfaces:
ActionsService:
SessionService:

github.com/actions/actions-runner-controller/cmd/ghalistener/metrics:
config:
dir: "{{.InterfaceDir}}/mocks"
pkgname: mocks
filename: "{{.InterfaceName|snakecase}}.go"
interfaces:
Publisher:
ServerExporter:
config:
structname: ServerPublisher
filename: server_publisher.go

github.com/actions/actions-runner-controller/cmd/ghalistener/app:
config:
dir: "{{.InterfaceDir}}/mocks"
pkgname: mocks
filename: "{{.InterfaceName|snakecase}}.go"
interfaces:
Listener:
Worker:
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mockery configuration file is incomplete. It's missing the configuration for the cmd/ghalistener/listener package which has two interfaces (Client and Handler) that have //go:generate mockery directives. Without this configuration, running go generate may not generate the expected mocks for these interfaces, or the mocks may be generated with incorrect settings.

Suggested change
Worker:
Worker:
github.com/actions/actions-runner-controller/cmd/ghalistener/listener:
config:
dir: "{{.InterfaceDir}}/mocks"
pkgname: mocks
filename: "{{.InterfaceName|snakecase}}.go"
interfaces:
Client:
Handler:

Copilot uses AI. Check for mistakes.
11 changes: 4 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,19 @@ A set of example pipelines (./acceptance/pipelines) are provided in this reposit
When raising a PR please run the relevant suites to prove your change hasn't broken anything.

#### Running Ginkgo Tests

You can run the integration test suite that is written in Ginkgo with:

```shell
make test-with-deps
```

This will firstly install a few binaries required to setup the integration test environment and then runs `go test` to start the Ginkgo test.
This will install `setup-envtest`, download the required envtest binaries (etcd, kube-apiserver, kubectl), and then run `go test`.

If you don't want to use `make`, like when you're running tests from your IDE, install required binaries to `/usr/local/kubebuilder/bin`.
That's the directory in which controller-runtime's `envtest` framework locates the binaries.
If you don't want to use `make`, install the envtest binaries using `setup-envtest`:

```shell
sudo mkdir -p /usr/local/kubebuilder/bin
make kube-apiserver etcd
sudo mv test-assets/{etcd,kube-apiserver} /usr/local/kubebuilder/bin/
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
export KUBEBUILDER_ASSETS=$(setup-envtest use -p path)
go test -v -run TestAPIs github.com/actions/actions-runner-controller/controllers/actions.summerwind.net
```

Expand Down
110 changes: 33 additions & 77 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,15 @@ else
GOBIN=$(shell go env GOBIN)
endif

TEST_ASSETS=$(PWD)/test-assets
TOOLS_PATH=$(PWD)/.tools

OS_NAME := $(shell uname -s | tr A-Z a-z)

# The etcd packages that coreos maintain use different extensions for each *nix OS on their github release page.
# ETCD_EXTENSION: the storage format file extension listed on the release page.
# EXTRACT_COMMAND: the appropriate CLI command for extracting this file format.
ifeq ($(OS_NAME), darwin)
ETCD_EXTENSION:=zip
EXTRACT_COMMAND:=unzip
else
ETCD_EXTENSION:=tar.gz
EXTRACT_COMMAND:=tar -xzf
endif
# ENVTEST_VERSION is the version of controller-runtime release branch to fetch the envtest setup script
ENVTEST_VERSION ?= $(shell go list -m -f "{{ .Version }}" sigs.k8s.io/controller-runtime | awk -F'[v.]' '{printf "release-%d.%d", $$2, $$3}')
# ENVTEST_K8S_VERSION is the version of Kubernetes to use for setting up ENVTEST binaries
ENVTEST_K8S_VERSION ?= $(shell go list -m -f "{{ .Version }}" k8s.io/api | awk -F'[v.]' '{printf "1.%d", $$3}')
ENVTEST ?= $(GOBIN)/setup-envtest

# default list of platforms for which multiarch image is built
ifeq (${PLATFORMS}, )
Expand All @@ -72,18 +66,19 @@ lint:

GO_TEST_ARGS ?= -short


# Run tests
test: generate fmt vet manifests shellcheck
go test $(GO_TEST_ARGS) `go list ./... | grep -v ./test_e2e_arc` -coverprofile cover.out
go test -fuzz=Fuzz -fuzztime=10s -run=Fuzz* ./controllers/actions.summerwind.net

test-with-deps: kube-apiserver etcd kubectl
# See https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest#pkg-constants
TEST_ASSET_KUBE_APISERVER=$(KUBE_APISERVER_BIN) \
TEST_ASSET_ETCD=$(ETCD_BIN) \
TEST_ASSET_KUBECTL=$(KUBECTL_BIN) \
test: generate fmt vet manifests shellcheck setup-envtest
KUBEBUILDER_ASSETS="$$($(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(GOBIN) -p path)" \
go test $(GO_TEST_ARGS) `go list ./... | grep -v ./test_e2e_arc` -coverprofile cover.out
KUBEBUILDER_ASSETS="$$($(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(GOBIN) -p path)" \
go test -fuzz=Fuzz -fuzztime=10s -run=Fuzz* ./controllers/actions.summerwind.net

test-with-deps: setup-envtest
KUBEBUILDER_ASSETS="$$($(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(GOBIN) -p path)" \
make test


# Build manager binary
manager: generate fmt vet
go build -o bin/manager main.go
Expand Down Expand Up @@ -364,68 +359,29 @@ ifeq (, $(wildcard $(TOOLS_PATH)/shellcheck))
endif
SHELLCHECK=$(TOOLS_PATH)/shellcheck

# find or download etcd
etcd:
ifeq (, $(shell which etcd))
ifeq (, $(wildcard $(TEST_ASSETS)/etcd))
# find or download envtest
envtest:
ifeq (, $(shell which setup-envtest))
ifeq (, $(wildcard $(GOBIN)/setup-envtest))
@{ \
set -xe ;\
INSTALL_TMP_DIR=$$(mktemp -d) ;\
cd $$INSTALL_TMP_DIR ;\
wget https://github.com/coreos/etcd/releases/download/v3.4.22/etcd-v3.4.22-$(OS_NAME)-amd64.$(ETCD_EXTENSION);\
mkdir -p $(TEST_ASSETS) ;\
$(EXTRACT_COMMAND) etcd-v3.4.22-$(OS_NAME)-amd64.$(ETCD_EXTENSION) ;\
mv etcd-v3.4.22-$(OS_NAME)-amd64/etcd $(TEST_ASSETS)/etcd ;\
rm -rf $$INSTALL_TMP_DIR ;\
set -e ;\
ENVTEST_TMP_DIR=$$(mktemp -d) ;\
cd $$ENVTEST_TMP_DIR ;\
go mod init tmp ;\
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@$(ENVTEST_VERSION) ;\
rm -rf $$ENVTEST_TMP_DIR ;\
}
ETCD_BIN=$(TEST_ASSETS)/etcd
else
ETCD_BIN=$(TEST_ASSETS)/etcd
endif
ENVTEST=$(GOBIN)/setup-envtest
else
ETCD_BIN=$(shell which etcd)
ENVTEST=$(shell which setup-envtest)
endif

# find or download kube-apiserver
kube-apiserver:
ifeq (, $(shell which kube-apiserver))
ifeq (, $(wildcard $(TEST_ASSETS)/kube-apiserver))
@{ \
set -xe ;\
INSTALL_TMP_DIR=$$(mktemp -d) ;\
cd $$INSTALL_TMP_DIR ;\
wget https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.3.2/kubebuilder_2.3.2_$(OS_NAME)_amd64.tar.gz ;\
mkdir -p $(TEST_ASSETS) ;\
tar zxvf kubebuilder_2.3.2_$(OS_NAME)_amd64.tar.gz ;\
mv kubebuilder_2.3.2_$(OS_NAME)_amd64/bin/kube-apiserver $(TEST_ASSETS)/kube-apiserver ;\
rm -rf $$INSTALL_TMP_DIR ;\
.PHONY: setup-envtest
setup-envtest: envtest
@echo "Setting up envtest binaries for Kubernetes version $(ENVTEST_K8S_VERSION)..."
@$(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(GOBIN) -p path || { \
echo "Error: Failed to set up envtest binaries for version $(ENVTEST_K8S_VERSION)."; \
exit 1; \
}
KUBE_APISERVER_BIN=$(TEST_ASSETS)/kube-apiserver
else
KUBE_APISERVER_BIN=$(TEST_ASSETS)/kube-apiserver
endif
else
KUBE_APISERVER_BIN=$(shell which kube-apiserver)
endif

# find or download kubectl
kubectl:
ifeq (, $(shell which kubectl))
ifeq (, $(wildcard $(TEST_ASSETS)/kubectl))
@{ \
set -xe ;\
INSTALL_TMP_DIR=$$(mktemp -d) ;\
cd $$INSTALL_TMP_DIR ;\
wget https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.3.2/kubebuilder_2.3.2_$(OS_NAME)_amd64.tar.gz ;\
mkdir -p $(TEST_ASSETS) ;\
tar zxvf kubebuilder_2.3.2_$(OS_NAME)_amd64.tar.gz ;\
mv kubebuilder_2.3.2_$(OS_NAME)_amd64/bin/kubectl $(TEST_ASSETS)/kubectl ;\
rm -rf $$INSTALL_TMP_DIR ;\
}
KUBECTL_BIN=$(TEST_ASSETS)/kubectl
else
KUBECTL_BIN=$(TEST_ASSETS)/kubectl
endif
else
KUBECTL_BIN=$(shell which kubectl)
endif
4 changes: 2 additions & 2 deletions cmd/ghalistener/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ type App struct {
metrics metrics.ServerExporter
}

//go:generate mockery --name Listener --output ./mocks --outpkg mocks --case underscore
//go:generate mockery
type Listener interface {
Listen(ctx context.Context, handler listener.Handler) error
}

//go:generate mockery --name Worker --output ./mocks --outpkg mocks --case underscore
//go:generate mockery
type Worker interface {
HandleJobStarted(ctx context.Context, jobInfo *actions.JobStarted) error
HandleDesiredRunnerCount(ctx context.Context, count int, jobsCompleted int) (int, error)
Expand Down
12 changes: 6 additions & 6 deletions cmd/ghalistener/app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func TestApp_Run(t *testing.T) {
})

t.Run("ExitsOnListenerError", func(t *testing.T) {
listener := appmocks.NewListener(t)
worker := appmocks.NewWorker(t)
listener := appmocks.NewMockListener(t)
worker := appmocks.NewMockWorker(t)

listener.On("Listen", mock.Anything, mock.Anything).Return(errors.New("listener error")).Once()

Expand All @@ -44,8 +44,8 @@ func TestApp_Run(t *testing.T) {
})

t.Run("ExitsOnListenerNil", func(t *testing.T) {
listener := appmocks.NewListener(t)
worker := appmocks.NewWorker(t)
listener := appmocks.NewMockListener(t)
worker := appmocks.NewMockWorker(t)

listener.On("Listen", mock.Anything, mock.Anything).Return(nil).Once()

Expand All @@ -59,8 +59,8 @@ func TestApp_Run(t *testing.T) {
})

t.Run("CancelListenerOnMetricsServerError", func(t *testing.T) {
listener := appmocks.NewListener(t)
worker := appmocks.NewWorker(t)
listener := appmocks.NewMockListener(t)
worker := appmocks.NewMockWorker(t)
metrics := metricsMocks.NewServerPublisher(t)
ctx := context.Background()

Expand Down
Loading