Skip to content

Commit 59f2c6f

Browse files
authored
chore: replace k3s, reduce log level, update deps, multi-arch builds (#662)
* chore: reduce log level on metrics Metrics reporter is spamming the logs even in production flavor because it logs as info when reporting metrics for each scheduler * chore(github): update deprecated ubuntu img * fix(runtime): retry pdb update Sometimes, PDB update can fail due to conflicts of changing the resource (in-memory copy vs runtime). To fix, k8s provides and API to use retry on conflicts * feat(forwarder): add dial options Optional parameter that the caller can add specifying dial parameters such as WithBlock(), that blocks grpc.Dial() until connection is established rather than doing in background. This is useful in tests * chore: update to go 1.23 * fix(runtime): avoid race condition in GR watcher * chore: enable multi-arch images Build images based on platform, by default we always publish to linux/amd64 and linux/arm64 - whereas locally we rely on the hosting OS arch * refactor: replace k3s with k3d K3d is a newer tool to bring up a Kubernetes mock cluster. Previous K3S tool is deprecated and did not support CI runners anymore, thus refactoring the application setup and tests to use k3d. Also adjusted docs and Makefile commands to bring up the k3d/up when starting Maestro or running integration tests * chore: redis 8 and postgres 17 Update local setup to use latest redis and postgres version available * chore(ci): fix test yaml with k3d * fix(runtime): indempotent Stop with nil check * chore(ci): fix build on CI for multi-arch * fix(test): flaky test assert only room in terminating * fix(forwarder): type assertion on cache * fix: simplify Makefile and test setup
1 parent 5528782 commit 59f2c6f

32 files changed

+983
-571
lines changed

.github/workflows/lint.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
- name: Set up Go
99
uses: actions/setup-go@v1
1010
with:
11-
go-version: '1.22'
11+
go-version: '1.23'
1212
- name: Checkout
1313
uses: actions/checkout@v2
1414
- name: Restore cache

.github/workflows/mkdocs.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,13 @@ jobs:
1919
with:
2020
python-version: 3.x
2121
- run: cp proto/apidocs.swagger.json docs/reference/apidocs.json
22-
- run: pip install mkdocs-material
22+
- run: pip install mkdocs-material
2323
- run: pip install mkdocs-git-revision-date-plugin
2424
- run: pip install mkdocs-render-swagger-plugin
2525
- run: pip install mkdocs-mermaid2-plugin
2626
- run: git config user.name 'github-actions[bot]' && git config user.email 'github-actions[bot]@users.noreply.github.com'
2727
- name: Publish docs
2828
run: mkdocs gh-deploy --force
29-
3029
update-docs:
3130
runs-on: ubuntu-latest
3231
steps:

.github/workflows/publish.yaml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,23 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- name: Checkout
13-
uses: actions/checkout@v2
13+
uses: actions/checkout@v4
1414
- name: Get the version (release tag)
1515
run: echo "IMAGE_VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
16+
- name: Set up QEMU
17+
uses: docker/setup-qemu-action@v3
1618
- name: Set up Docker Buildx
17-
uses: docker/setup-buildx-action@v1
19+
uses: docker/setup-buildx-action@v3
1820
- name: Login to DockerHub
19-
uses: docker/login-action@v1
21+
uses: docker/login-action@v3
2022
with:
2123
username: ${{ secrets.DOCKERHUB_USERNAME }}
2224
password: ${{ secrets.DOCKERHUB_TOKEN }}
2325
- name: Build and push
24-
uses: docker/build-push-action@v2
26+
uses: docker/build-push-action@v5
2527
with:
2628
context: ./
2729
file: ./Dockerfile
30+
platforms: linux/amd64,linux/arm64
2831
push: true
2932
tags: tfgco/maestro:${{ env.IMAGE_VERSION }}

.github/workflows/test.yaml

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ on: push
33
jobs:
44
unit:
55
name: Unit tests
6-
runs-on: ubuntu-20.04
6+
runs-on: ubuntu-22.04
77
steps:
88
- name: Set up Go
9-
uses: actions/setup-go@v1
9+
uses: actions/setup-go@v5
1010
with:
11-
go-version: '1.22'
11+
go-version: '1.23'
1212
- name: Checkout
13-
uses: actions/checkout@v2
13+
uses: actions/checkout@v4
1414
- name: Restore cache
1515
uses: actions/cache@v4
1616
with:
@@ -23,46 +23,54 @@ jobs:
2323
run: bash <(curl -s https://codecov.io/bash)
2424
integration:
2525
name: Integration tests
26-
runs-on: ubuntu-20.04
26+
runs-on: ubuntu-22.04
2727
steps:
2828
- name: Set up Go
29-
uses: actions/setup-go@v1
29+
uses: actions/setup-go@v5
3030
with:
31-
go-version: '1.22'
31+
go-version: '1.23'
3232
- name: Checkout
33-
uses: actions/checkout@v2
33+
uses: actions/checkout@v4
3434
- name: Restore cache
3535
uses: actions/cache@v4
3636
with:
3737
path: ~/go/pkg/mod
3838
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
39+
- name: Set up KinD cluster
40+
uses: helm/kind-action@v1.10.0
41+
with:
42+
node_image: kindest/node:v1.27.3
3943
- name: Run tests
4044
run: |
41-
make run/integration-tests
45+
echo "INFO: Running integration tests (using KUBECONFIG from kind-action)..."
46+
go test -tags=integration -count=1 -timeout 20m -coverprofile=coverage.out -covermode=atomic ./...
4247
- name: Upload coverage to Codecov
4348
run: bash <(curl -s https://codecov.io/bash)
4449

4550
runtime-integration:
4651
name: Runtime Integration tests
47-
runs-on: ubuntu-20.04
52+
runs-on: ubuntu-22.04
4853
strategy:
4954
fail-fast: false
5055
matrix:
51-
k3s-version: [v1.19.11, v1.20.7, v1.21.1]
52-
env:
53-
K3S_VERSION: ${{ matrix.k3s-version }}
56+
k8s-version: [v1.25.11, v1.26.6, v1.27.3]
5457
steps:
5558
- name: Set up Go
56-
uses: actions/setup-go@v1
59+
uses: actions/setup-go@v5
5760
with:
58-
go-version: '1.22'
61+
go-version: '1.23'
5962
- name: Checkout
60-
uses: actions/checkout@v2
63+
uses: actions/checkout@v4
6164
- name: Restore cache
6265
uses: actions/cache@v4
6366
with:
6467
path: ~/go/pkg/mod
6568
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
69+
- name: Set up KinD cluster
70+
uses: helm/kind-action@v1.10.0
71+
with:
72+
node_image: kindest/node:${{ matrix.k8s-version }}
6673
- name: Run tests
6774
run: |
68-
make run/runtime-integration-tests
75+
echo "INFO: Running runtime integration tests (using KUBECONFIG from kind-action for k8s ${{ matrix.k8s-version }} )..."
76+
go test -tags=integration -count=1 -timeout 20m ./internal/adapters/runtime/kubernetes/...

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ env
5151

5252
# K3S files
5353
kubeconfig.yaml
54-
e2e/framework/maestro/kubeconfig.yaml
54+
e2e/framework/maestro/.k3d-kubeconfig.yaml
5555

5656
# MkDocs
5757
site/

.golangci.yaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1+
version: "2"
12
run:
23
timeout: 5m
34
build-tags:
45
- unit
56
- integration
67
- wireinject
7-
skip-dirs:
8-
- ".*/mock/.*"
9-
skip-files:
8+
9+
linters:
10+
exclusions:
11+
paths:
12+
- "mock"
1013
- "_gen.go$"
1114
- "pb.go$"
1215
- "pb.gw.go$"
13-
14-
linters:
1516
enable:
1617
- goimports

Dockerfile

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@
1919
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2020
#
2121

22-
FROM golang:1.22-alpine AS build-env
22+
FROM golang:1.23-alpine AS build-env
23+
24+
# TARGETARCH and TARGETOS are automatically set by buildx
25+
ARG TARGETARCH
26+
ARG TARGETOS
2327

2428
WORKDIR /build
2529

@@ -30,13 +34,12 @@ COPY . /build
3034

3135
RUN mkdir -p /app
3236

33-
RUN apk add --update make
34-
35-
RUN cd /build && \
36-
make build-linux-x86_64 && \
37-
mv ./bin/maestro-linux-x86_64 /app/maestro && \
38-
mv internal/service/migrations /app/migrations && \
39-
mv ./config /app/config
37+
# Instead of 'make build', compile directly for the target platform
38+
# Output the binary directly to /app/maestro
39+
RUN echo "Building for $TARGETOS/$TARGETARCH" && \
40+
CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -a -installsuffix cgo -o /app/maestro ./ && \
41+
mv /build/internal/service/migrations /app/migrations && \
42+
mv /build/config /app/config
4043

4144

4245
FROM alpine
@@ -49,4 +52,4 @@ COPY --from=build-env /app/config /app/config
4952

5053
EXPOSE 8080 8081
5154

52-
CMD /app/maestro
55+
CMD ["/app/maestro"]

Makefile

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ lint: lint/go lint/protobuf ## Execute linters.
3434

3535
.PHONY: lint/go
3636
lint/go: ## Execute golangci-lint.
37-
@go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.0 run
37+
@go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.5 run
3838

3939
.PHONY: lint/protobuf
4040
lint/protobuf: ## Execute buf linter.
@@ -48,35 +48,63 @@ run/unit-tests: ## Execute unit tests.
4848
@go test -count=1 -tags=unit -coverprofile=coverage.out -covermode=atomic $(OPTS) ./...
4949

5050
.PHONY: run/integration-tests
51-
run/integration-tests: ## Execute integration tests.
52-
@go test -tags=integration -count=1 -timeout 20m -coverprofile=coverage.out -covermode=atomic $(OPTS) ./...
51+
run/integration-tests: k3d/up ## Execute integration tests.
52+
@KUBECONFIG_PATH="$(shell pwd)/e2e/framework/maestro/.k3d-kubeconfig.yaml"; \
53+
echo "INFO: Checking for Kubeconfig at $$KUBECONFIG_PATH for integration tests..."; \
54+
if [ -f "$$KUBECONFIG_PATH" ] && [ -s "$$KUBECONFIG_PATH" ]; then \
55+
echo "INFO: Using kubeconfig from $$KUBECONFIG_PATH for integration tests..."; \
56+
KUBECONFIG="$$KUBECONFIG_PATH" go test -tags=integration -count=1 -timeout 20m -coverprofile=coverage.out -covermode=atomic $(OPTS) ./... ; \
57+
else \
58+
echo "ERROR: Kubeconfig $$KUBECONFIG_PATH not found or is empty. Please ensure 'make k3d/up' completed successfully before running integration tests."; \
59+
exit 1; \
60+
fi
5361

5462
.PHONY: run/runtime-integration-tests
55-
run/runtime-integration-tests: ## Execute runtime integration tests.
56-
@go test -tags=integration -count=1 -timeout 20m ./internal/adapters/runtime/kubernetes/...
63+
run/runtime-integration-tests: k3d/up ## Execute runtime integration tests.
64+
@KUBECONFIG_PATH="$(shell pwd)/e2e/framework/maestro/.k3d-kubeconfig.yaml"; \
65+
echo "INFO: Checking for Kubeconfig at $$KUBECONFIG_PATH for runtime integration tests..."; \
66+
if [ -f "$$KUBECONFIG_PATH" ] && [ -s "$$KUBECONFIG_PATH" ]; then \
67+
echo "INFO: Using kubeconfig from $$KUBECONFIG_PATH for runtime integration tests..."; \
68+
KUBECONFIG="$$KUBECONFIG_PATH" go test -tags=integration -count=1 -timeout 20m ./internal/adapters/runtime/kubernetes/... ; \
69+
else \
70+
echo "ERROR: Kubeconfig $$KUBECONFIG_PATH not found or is empty. Please ensure 'make k3d/up' completed successfully before running runtime integration tests."; \
71+
exit 1; \
72+
fi
5773

5874
.PHONY: license-check
5975
license-check: ## Execute license check.
6076
@go run github.com/google/addlicense -skip yaml -skip yml -skip proto -check .
6177

6278
.PHONY: run/e2e-tests
63-
run/e2e-tests: build-linux-x86_64 setup/e2e deps/stop ## Execute end-to-end tests.
79+
run/e2e-tests: k3d/up build setup/e2e deps/stop ## Execute end-to-end tests.
6480
@cd e2e; go test -count=1 -v $(OPTS) ./suites/...
6581

6682
#-------------------------------------------------------------------------------
6783
# Build and run
6884
#-------------------------------------------------------------------------------
6985

7086
.PHONY: build
71-
build: build-linux-x86_64 ## Build the project and generates a binary.
72-
@rm -f ./bin/maestro || true
73-
@go build -o ./bin/maestro ./
87+
build: ## Build the project and generates a binary.
88+
ifeq ($(shell go env GOARCH),amd64)
89+
@$(MAKE) build-linux-x86_64
90+
@ln -sf ./bin/maestro-linux-x86_64 ./bin/maestro
91+
else ifeq ($(shell go env GOARCH),arm64)
92+
@$(MAKE) build-linux-arm64
93+
@ln -sf ./bin/maestro-linux-arm64 ./bin/maestro
94+
else
95+
@echo "Unsupported architecture: $(shell go env GOARCH)"
96+
@exit 1
97+
endif
7498

7599
.PHONY: build-linux-x86_64
76100
build-linux-x86_64: ## Build the project and generates a binary for x86_64 architecture.
77101
@rm -f ./bin/maestro-linux-x86_64 || true
78102
@env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -o ./bin/maestro-linux-x86_64 ./
79103

104+
.PHONY: build-linux-arm64
105+
build-linux-arm64: ## Build the project and generates a binary for arm64 architecture.
106+
@rm -f ./bin/maestro-linux-arm64 || true
107+
@env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -a -installsuffix cgo -o ./bin/maestro-linux-arm64 ./
80108

81109
.PHONY: run/worker
82110
run/worker: ## Runs maestro worker.
@@ -150,15 +178,56 @@ deps/down: ## Delete containers dependencies.
150178
# Easily start Maestro
151179
#-------------------------------------------------------------------------------
152180
.PHONY: maestro/start
153-
maestro/start: build-linux-x86_64 ## Start Maestro with all of its dependencies.
181+
maestro/start: k3d/up build ## Start Maestro with all of its dependencies.
154182
@echo "Starting maestro..."
155183
@cd ./e2e/framework/maestro; docker compose up --build -d
156184
@MAESTRO_MIGRATION_PATH="file://internal/service/migrations" go run main.go migrate;
157185
@cd ./e2e/framework/maestro; docker compose up --build -d worker runtime-watcher #Worker and watcher do not work before migration, so we start them after it.
158186
@echo "Maestro is up and running!"
159187

160188
.PHONY: maestro/down
161-
maestro/down: ## Delete Maestro and all of its dependencies.
189+
maestro/down: k3d/down ## Delete Maestro and all of its dependencies.
162190
@echo "Deleting maestro..."
163191
@cd ./e2e/framework/maestro; docker compose down
192+
@$(MAKE) k3d/down
164193
@echo "Maestro was deleted with success!"
194+
195+
#-------------------------------------------------------------------------------
196+
# Local Kubernetes cluster (k3d)
197+
#-------------------------------------------------------------------------------
198+
199+
K3D_CLUSTER_NAME ?= maestro-dev
200+
201+
.PHONY: k3d/up
202+
k3d/up: ## Create/Start the k3d cluster via docker-compose.
203+
@echo "INFO: Ensuring k3d service is up and cluster '$(K3D_CLUSTER_NAME)' is created via docker-compose..."
204+
@docker-compose up -d k3d
205+
@echo "INFO: Waiting for k3d cluster and kubeconfig file at ./e2e/framework/maestro/.k3d-kubeconfig.yaml..."
206+
@timeout=120; \
207+
interval=5; \
208+
elapsed=0; \
209+
until [ -f ./e2e/framework/maestro/.k3d-kubeconfig.yaml ] && [ -s ./e2e/framework/maestro/.k3d-kubeconfig.yaml ]; do \
210+
if [ $$elapsed -ge $$timeout ]; then \
211+
echo "ERROR: Timeout waiting for kubeconfig file."; \
212+
exit 1; \
213+
fi; \
214+
echo "INFO: Waiting for ./e2e/framework/maestro/.k3d-kubeconfig.yaml to be created and populated by k3d service (elapsed $$elapsed sec)..."; \
215+
sleep $$interval; \
216+
elapsed=$$((elapsed + interval)); \
217+
done
218+
@echo "INFO: k3d cluster '$(K3D_CLUSTER_NAME)' should be ready and kubeconfig exported."
219+
@echo "To use with kubectl, run: export KUBECONFIG=$(shell pwd)/e2e/framework/maestro/.k3d-kubeconfig.yaml"
220+
221+
.PHONY: k3d/down
222+
k3d/down: ## Delete the local k3d cluster and stop the k3d docker-compose service.
223+
@echo "INFO: Attempting to delete k3d cluster '$(K3D_CLUSTER_NAME)' via k3d service (if running)..."
224+
@if docker-compose ps k3d | grep -q "k3d"; then \
225+
docker-compose exec k3d k3d cluster delete $(K3D_CLUSTER_NAME) || echo "INFO: k3d cluster delete command failed or cluster was not found."; \
226+
else \
227+
echo "INFO: k3d service not running, skipping cluster deletion command."; \
228+
fi
229+
@echo "INFO: Stopping and removing k3d service..."
230+
@docker-compose rm -sf k3d
231+
@echo "INFO: Removing k3d kubeconfig file..."
232+
@rm -f ./e2e/framework/maestro/.k3d-kubeconfig.yaml
233+
@echo "INFO: k3d cluster and service are down."

0 commit comments

Comments
 (0)