Skip to content
Open
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
6 changes: 6 additions & 0 deletions .github/workflows/style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,9 @@ jobs:

- name: Run chart-testing (lint)
run: ct lint charts/stackrox-mcp --validate-maintainers=false --all

- name: Run shellcheck
run: make shell-lint

- name: Run actionlint
run: make actionlint
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ jobs:
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
file: ./coverage.out
files: ./coverage.out
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
9 changes: 9 additions & 0 deletions .shellcheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Follow external sources (equivalent to -x flag)
external-sources=true

# Enable all optional checks
enable=all

# Exclude checks that are too noisy
# SC2312: Consider invoking this command separately to avoid masking its return value
exclude=SC2312
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ lint: ## Run golangci-lint
go install -v "github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.6"
golangci-lint run

.PHONY: shell-lint
shell-lint: ## Run shellcheck on shell scripts
@echo "Running shellcheck..."
@shellcheck scripts/*.sh e2e-tests/scripts/*.sh

.PHONY: actionlint
actionlint: ## Run actionlint on GitHub Actions workflows
@echo "Running actionlint..."
@cd e2e-tests/tools && go build -o ../../bin/actionlint github.com/rhysd/actionlint/cmd/actionlint
@./bin/actionlint -color

##############
## Protobuf ##
##############
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -409,3 +409,23 @@ Common commands:
- `make test` - Run tests
- `make fmt` - Format code
- `make lint` - Run linter

### Code Style Checks

The project enforces several code style checks:

- **Go formatting**: `make fmt-check` (or `make fmt` to auto-fix)
- **Go linting**: `make lint`
- **Shell scripts**: `make shell-lint`
- **GitHub Actions workflows**: `make actionlint`
- **Dockerfile**: `make dockerfile-lint`
- **Helm charts**: `make helm-lint`

All checks run automatically in CI on pull requests.

#### Shell Script Guidelines

- All scripts must pass `shellcheck` with no errors
- Use `set -e` for error handling
- Use `SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"` for directory detection
- Include cleanup traps for temporary resources (see existing scripts for examples)
4 changes: 2 additions & 2 deletions e2e-tests/scripts/build-mcpchecker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ set -e
E2E_DIR="$(cd "$(dirname "$0")/.." && pwd)"

echo "Building mcpchecker from tool dependencies..."
cd "$E2E_DIR/tools"
cd "${E2E_DIR}/tools"
go build -o ../bin/mcpchecker github.com/mcpchecker/mcpchecker/cmd/mcpchecker

echo "mcpchecker built successfully"
cd "$E2E_DIR"
cd "${E2E_DIR}"
./bin/mcpchecker help
36 changes: 18 additions & 18 deletions e2e-tests/scripts/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
E2E_DIR="$(dirname "$SCRIPT_DIR")"
ROOT_DIR="$(dirname "$E2E_DIR")"
E2E_DIR="$(dirname "${SCRIPT_DIR}")"
ROOT_DIR="$(dirname "${E2E_DIR}")"

# Cleanup function
WIREMOCK_WAS_STARTED=false
cleanup() {
if [ "$WIREMOCK_WAS_STARTED" = true ]; then
if [[ "${WIREMOCK_WAS_STARTED}" = true ]]; then
echo "Stopping WireMock..."
cd "$ROOT_DIR"
cd "${ROOT_DIR}"
make mock-stop > /dev/null 2>&1 || true
fi
}
Expand All @@ -23,16 +23,16 @@ echo "════════════════════════
echo ""

# Load environment variables
if [ -f "$E2E_DIR/.env" ]; then
if [[ -f "${E2E_DIR}/.env" ]]; then
echo "Loading environment variables from .env..."
# shellcheck source=/dev/null
set -a && source "$E2E_DIR/.env" && set +a
set -a && source "${E2E_DIR}/.env" && set +a
fi

# Check if WireMock is already running
if ! curl -skf https://localhost:8081/__admin/mappings > /dev/null 2>&1; then
echo "Starting WireMock mock service..."
cd "$ROOT_DIR"
cd "${ROOT_DIR}"
make mock-start
WIREMOCK_WAS_STARTED=true
else
Expand All @@ -45,15 +45,15 @@ export STACKROX_MCP__CENTRAL__API_TOKEN="test-token-admin"
export STACKROX_MCP__CENTRAL__INSECURE_SKIP_TLS_VERIFY="true"

# Check OpenAI API key for judge
if [ -z "$OPENAI_API_KEY" ]; then
if [[ -z "${OPENAI_API_KEY}" ]]; then
echo "Warning: OPENAI_API_KEY is not set (needed for LLM judge)"
echo "Note: mcpchecker only supports OpenAI-compatible APIs for the judge"
fi

# Build mcpchecker if not present
if [ ! -f "$E2E_DIR/bin/mcpchecker" ]; then
if [[ ! -f "${E2E_DIR}/bin/mcpchecker" ]]; then
echo "mcpchecker binary not found. Building..."
"$SCRIPT_DIR/build-mcpchecker.sh"
"${SCRIPT_DIR}/build-mcpchecker.sh"
echo ""
fi

Expand All @@ -63,34 +63,34 @@ export AGENT_MODEL_NAME="${AGENT_MODEL_NAME:-claude-sonnet-4-5}"

# Set judge environment variables (use OpenAI)
export JUDGE_BASE_URL="${JUDGE_BASE_URL:-https://api.openai.com/v1}"
export JUDGE_API_KEY="${JUDGE_API_KEY:-$OPENAI_API_KEY}"
export JUDGE_API_KEY="${JUDGE_API_KEY:-${OPENAI_API_KEY}}"
export JUDGE_MODEL_NAME="${JUDGE_MODEL_NAME:-gpt-5-nano}"

echo "Configuration:"
echo " Central URL: $STACKROX_MCP__CENTRAL__URL (WireMock)"
echo " Judge: $JUDGE_MODEL_NAME (OpenAI)"
echo " Central URL: ${STACKROX_MCP__CENTRAL__URL} (WireMock)"
echo " Judge: ${JUDGE_MODEL_NAME} (OpenAI)"
echo " MCP Server: stackrox-mcp (via go run)"
echo ""

# Run mcpchecker
cd "$E2E_DIR/mcpchecker"
cd "${E2E_DIR}/mcpchecker"
echo "Running mcpchecker tests..."
echo ""

EVAL_FILE="eval.yaml"
echo "Using eval file: $EVAL_FILE"
"$E2E_DIR/bin/mcpchecker" check "$EVAL_FILE"
echo "Using eval file: ${EVAL_FILE}"
"${E2E_DIR}/bin/mcpchecker" check "${EVAL_FILE}"

EXIT_CODE=$?

echo ""
if [ $EXIT_CODE -eq 0 ]; then
if [[ "${EXIT_CODE}" -eq 0 ]]; then
echo "══════════════════════════════════════════════════════════"
echo " Tests Completed Successfully!"
echo "══════════════════════════════════════════════════════════"
else
echo "══════════════════════════════════════════════════════════"
echo " Tests Failed"
echo "══════════════════════════════════════════════════════════"
exit $EXIT_CODE
exit "${EXIT_CODE}"
fi
20 changes: 10 additions & 10 deletions e2e-tests/scripts/smoke-test-mock.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
E2E_DIR="$(dirname "$SCRIPT_DIR")"
ROOT_DIR="$(dirname "$E2E_DIR")"
E2E_DIR="$(dirname "${SCRIPT_DIR}")"
ROOT_DIR="$(dirname "${E2E_DIR}")"

echo "══════════════════════════════════════════════════════════"
echo " WireMock Integration Smoke Test"
Expand All @@ -12,14 +12,14 @@ echo ""

# Start WireMock
echo "1. Starting WireMock..."
cd "$ROOT_DIR"
cd "${ROOT_DIR}"
make mock-stop > /dev/null 2>&1 || true
make mock-start

# Wait for WireMock to be ready
echo ""
echo "2. Waiting for WireMock to be ready..."
for i in {1..10}; do
for _ in {1..10}; do
if nc -z localhost 8081 2>/dev/null; then
echo "✓ WireMock is ready"
break
Expand All @@ -30,7 +30,7 @@ done
# Test MCP server can connect
echo ""
echo "3. Testing MCP server connection..."
cd "$ROOT_DIR"
cd "${ROOT_DIR}"

# Run MCP server and test a simple tool call
timeout 10 bash -c '
Expand All @@ -50,29 +50,29 @@ echo "4. Testing WireMock responses..."
AUTH_RESULT=$(grpcurl -insecure -H "Authorization: Bearer test-token-admin" \
-d '{}' localhost:8081 v1.ClustersService/GetClusters 2>&1 || true)

if echo "$AUTH_RESULT" | grep -q "clusters"; then
if echo "${AUTH_RESULT}" | grep -q "clusters"; then
echo "✓ Authentication works"
else
echo "✗ Authentication failed"
echo "$AUTH_RESULT"
echo "${AUTH_RESULT}"
fi

# Test CVE query
CVE_RESULT=$(grpcurl -insecure -H "Authorization: Bearer test-token-admin" \
-d '{"query": "CVE:\"CVE-2021-44228\""}' \
localhost:8081 v1.DeploymentService/ListDeployments 2>&1 || true)

if echo "$CVE_RESULT" | grep -q "deployments"; then
if echo "${CVE_RESULT}" | grep -q "deployments"; then
echo "✓ CVE query returns data"
else
echo "✗ CVE query failed"
echo "$CVE_RESULT"
echo "${CVE_RESULT}"
fi

# Cleanup
echo ""
echo "5. Cleaning up..."
cd "$ROOT_DIR"
cd "${ROOT_DIR}"
make mock-stop

echo ""
Expand Down
8 changes: 4 additions & 4 deletions e2e-tests/scripts/smoke-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
E2E_DIR="$(dirname "$SCRIPT_DIR")"
E2E_DIR="$(dirname "${SCRIPT_DIR}")"

echo "══════════════════════════════════════════════════════════"
echo " E2E Tests Smoke Test"
Expand All @@ -11,15 +11,15 @@ echo ""

# Step 1: Build mcpchecker binary
echo "Step 1/2: Building mcpchecker binary..."
cd "$E2E_DIR/tools"
cd "${E2E_DIR}/tools"
go build -o ../bin/mcpchecker github.com/mcpchecker/mcpchecker/cmd/mcpchecker
echo "✓ mcpchecker built successfully"
echo ""

# Step 2: Verify mcpchecker binary works
echo "Step 2/2: Verifying mcpchecker binary works..."
"$E2E_DIR/bin/mcpchecker" --version > /dev/null 2>&1 || true
"$E2E_DIR/bin/mcpchecker" help > /dev/null
"${E2E_DIR}/bin/mcpchecker" --version > /dev/null 2>&1 || true
"${E2E_DIR}/bin/mcpchecker" help > /dev/null
echo "✓ mcpchecker binary works correctly"
echo ""

Expand Down
7 changes: 7 additions & 0 deletions e2e-tests/tools/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.25.5
require (
github.com/fullstorydev/grpcurl v1.9.3
github.com/mcpchecker/mcpchecker v0.0.4
github.com/rhysd/actionlint v1.7.11
)

require (
Expand All @@ -13,6 +14,7 @@ require (
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
github.com/bufbuild/protocompile v0.14.1 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
Expand Down Expand Up @@ -64,12 +66,16 @@ require (
github.com/mailru/easyjson v0.9.1 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.17 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/modelcontextprotocol/go-sdk v1.2.0 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/openai/openai-go/v2 v2.7.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.10.0 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/sigstore/protobuf-specs v0.5.0 // indirect
Expand Down Expand Up @@ -97,6 +103,7 @@ require (
go.opentelemetry.io/otel/trace v1.39.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
go.yaml.in/yaml/v4 v4.0.0-rc.3 // indirect
golang.org/x/crypto v0.47.0 // indirect
golang.org/x/exp/event v0.0.0-20260112195511-716be5621a96 // indirect
golang.org/x/exp/jsonrpc2 v0.0.0-20260112195511-716be5621a96 // indirect
Expand Down
15 changes: 15 additions & 0 deletions e2e-tests/tools/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPn
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs=
github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw=
github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
Expand Down Expand Up @@ -266,6 +268,10 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
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.17 h1:78v8ZlW0bP43XfmAfPsdXcoNCelfMHsDmd/pkENfrjQ=
github.com/mattn/go-runewidth v0.0.17/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mcpchecker/mcpchecker v0.0.4 h1:xpnFI/NRSkEZB6ofixo4dyWurf2RjAlsRCeUkyXQEYs=
github.com/mcpchecker/mcpchecker v0.0.4/go.mod h1:IIvKxkVxHN6kOOPe+Hah/oG84Xei5inFRAq3ycshaew=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
Expand All @@ -290,6 +296,13 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgm
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rhysd/actionlint v1.7.11 h1:m+aSuCpCIClS8X02xMG4Z8s87fCHPsAtYkAoWGQZgEE=
github.com/rhysd/actionlint v1.7.11/go.mod h1:8n50YougV9+50niD7oxgDTZ1KbN/ZnKiQ2xpLFeVhsI=
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.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
Expand Down Expand Up @@ -399,6 +412,8 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go=
go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/exp/event v0.0.0-20260112195511-716be5621a96 h1:l+bY+u9cx/1NImWfu0OVcMmlK19fFvQEXUrm3c/qj/o=
Expand Down
1 change: 1 addition & 0 deletions e2e-tests/tools/tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ package tools
import (
_ "github.com/fullstorydev/grpcurl/cmd/grpcurl"
_ "github.com/mcpchecker/mcpchecker/cmd/mcpchecker"
_ "github.com/rhysd/actionlint/cmd/actionlint"
)
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/stretchr/testify v1.11.1
golang.stackrox.io/grpc-http1 v0.5.1
google.golang.org/grpc v1.79.1
google.golang.org/protobuf v1.36.10
)

require (
Expand Down Expand Up @@ -38,7 +39,6 @@ require (
golang.org/x/text v0.32.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

Expand Down
Loading
Loading