Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
49 changes: 49 additions & 0 deletions .github/workflows/go-testing-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Golang Unit and Integration Tests
on:
push:
branches:
- "master"
paths:
- "**.go"
- "**.golden"
pull_request:
branches:
- "master"
paths:
- "**.go"
- "**.golden"
workflow_dispatch:
inputs:
logLevel:
description: "Log level"
required: true
default: "warning"

jobs:
integration-tests:
name: Integration tests
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Install lynx for xdg-open support
run: sudo apt-get install lynx
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.23"
- name: Install Docker Compose
run: |
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create k8s Kind Cluster
uses: helm/[email protected]
with:
cluster_name: "kind-cluster"
- name: Run integration tests
run: |
make integration-test

11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,13 @@ test: check
go test -failfast --short ./... -race
## Lint check Golang
lint:
golangci-lint run ./...
golangci-lint run ./...
## Runs integration tests
## it does not start kind (neither install CRD), only starts nats
## hence to successful run you need a k8s cluster (with installed meshsync CRD);
## docker compose exposes nats on default ports to host, so they must be available
integration-test:
docker compose up -d
sleep 4
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The sleep 4 command uses a hardcoded value. It would be better to use a variable or a more dynamic approach to ensure NATS is ready before running the tests. Consider using docker compose ps and checking the status of the NATS container.

# Example using a loop and docker compose ps (untested):
# ready=false
# until $ready; do
#   status=$$(docker compose ps --services --filter "status=running" nats)
#   if [[ "$${status}" == "nats" ]]; then
#     ready=true
#   else
#     sleep 1
#   fi
# done
sleep 4

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks gemi 🤗 , the idea is good, but the suggested snippet is not working.
I briefly tried to play a little with similar ideas, but didn't succeed 😄 , so sleep 4 is the best option for now 👍

Copy link
Member

Choose a reason for hiding this comment

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

This is a good comment from Gemini. While use of sleep() is almost never desired, replacement of its use can sometimes be more trouble than it's worth.

Copy link
Contributor

Choose a reason for hiding this comment

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

You're welcome! I understand the challenges with dynamic checks in docker compose. While sleep 4 might be the most practical option for now, keep an eye on its reliability as the environment evolves. If the tests become flaky, revisiting the dynamic check might be necessary.

RUN_INTEGRATION_TESTS=true go test -v -count=1 -run Integration .
docker compose down
15 changes: 15 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: '3.8'

# this docker compose is solely for local run with main_test.go
services:
nats:
image: nats:2.11-alpine3.21
container_name: nats
ports:
- "4222:4222" # client connections
- "8222:8222" # HTTP monitoring (optional)
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8222/varz"]
interval: 5s
timeout: 3s
retries: 5
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/myntra/pipeline v0.0.0-20180618182531-2babf4864ce8
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8
golang.org/x/net v0.34.0
gorm.io/gorm v1.25.12
Expand Down Expand Up @@ -135,6 +136,7 @@ require (
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
Expand Down
69 changes: 69 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package main

import (
"os"
"testing"
"time"

"github.com/layer5io/meshkit/broker"
"github.com/layer5io/meshkit/broker/nats"
"github.com/stretchr/testify/assert"
)

var runIntegrationTest bool
var testMeshsyncTopic = "meshery.meshsync.core"
var testMeshsyncNatsURL = "localhost:4222"

func init() {
runIntegrationTest = os.Getenv("RUN_INTEGRATION_TESTS") == "true"
}

/**
* this test requires k8s cluster (with installed CRDs: broker, meshsync) and nats streaming
* could be a good idea to put a test into ci workflow:
* - start a kind cluster and nats container
* - check that the messages are received in nats
* --
* use docker compose to start nats
* ---
* TODO:
* - add starting kind cluster to docker compose
* - run all test in container to avoid port exposure to host
*/
func TestWithNatsIntegration(t *testing.T) {
if !runIntegrationTest {
t.Skip("skipping integration test")
}

br, err := nats.New(nats.Options{
URLS: []string{testMeshsyncNatsURL},
ConnectionName: "meshsync",
Username: "",
Password: "",
ReconnectWait: 2 * time.Second,
MaxReconnect: 60,
})
if err != nil {
t.Fatal("error connecting to nats", err)
}
count := 0

go func() {
out := make(chan *broker.Message)
br.SubscribeWithChannel(testMeshsyncTopic, "", out)

for range out {
count++
}
}()

os.Setenv("BROKER_URL", testMeshsyncNatsURL)
go main()

<-time.After(time.Second * 8)
// TODO some more meaningful check
assert.True(t, count > 0)

t.Logf("received %d messages from broker", count)
t.Log("done")
}
Loading