Add smoke test infrastructure #8
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Smoke Tests | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| types: | |
| - opened | |
| - reopened | |
| - synchronize | |
| jobs: | |
| smoke: | |
| name: Run Smoke Tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Download dependencies | |
| run: go mod download | |
| - name: Create kind cluster | |
| uses: helm/kind-action@v1 | |
| with: | |
| cluster_name: stackrox-mcp-smoke | |
| - name: Clone StackRox repository | |
| run: git clone --depth 1 https://github.com/stackrox/stackrox.git stackrox-repo | |
| - name: Deploy StackRox Central | |
| env: | |
| MAIN_IMAGE_TAG: latest | |
| SENSOR_HELM_DEPLOY: "true" | |
| ROX_SCANNER_V4: "false" | |
| run: | | |
| cd stackrox-repo | |
| ./deploy/k8s/deploy-local.sh | |
| - name: Deploy vulnerable workload | |
| run: kubectl apply -f smoke/testdata/vulnerable-deployment.yaml | |
| - name: Wait for vulnerable deployment | |
| run: kubectl wait --for=condition=available --timeout=120s deployment/vulnerable-app -n vulnerable-apps | |
| - name: Wait for Central pods ready | |
| run: kubectl wait --for=condition=ready --timeout=180s pod -l app=central -n stackrox | |
| - name: Extract Central password | |
| id: extract-password | |
| run: | | |
| PASSWORD="$(kubectl get secret -n stackrox central-htpasswd -o json | jq -r '.data.password' | base64 -d)" | |
| echo "::add-mask::${PASSWORD}" | |
| echo "password=${PASSWORD}" >> "$GITHUB_OUTPUT" | |
| - name: Wait for Central API and generate token | |
| id: generate-token | |
| run: | | |
| set -e | |
| echo "Waiting for Central API to be ready at localhost:8000..." | |
| echo "Note: deploy-local.sh automatically set up port-forwarding" | |
| PASSWORD="${{ steps.extract-password.outputs.password }}" | |
| # Poll for API readiness with exponential backoff | |
| MAX_ATTEMPTS=12 | |
| ATTEMPT=0 | |
| while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do | |
| echo "Attempt $((ATTEMPT + 1))/${MAX_ATTEMPTS} to check API readiness..." | |
| if curl -k -s -f --max-time 5 -u "admin:${PASSWORD}" \ | |
| https://localhost:8000/v1/ping > /dev/null 2>&1; then | |
| echo "Central API is ready" | |
| break | |
| fi | |
| ATTEMPT=$((ATTEMPT + 1)) | |
| if [ $ATTEMPT -ge $MAX_ATTEMPTS ]; then | |
| echo "ERROR: Central API did not become ready after ${MAX_ATTEMPTS} attempts" | |
| echo "Checking if port-forward is running..." | |
| netstat -tlnp 2>/dev/null | grep :8000 || echo "Port 8000 not listening" | |
| exit 1 | |
| fi | |
| # Exponential backoff: 2, 4, 8, 16... seconds (max 30) | |
| SLEEP_TIME=$((2 ** ATTEMPT)) | |
| if [ $SLEEP_TIME -gt 30 ]; then | |
| SLEEP_TIME=30 | |
| fi | |
| echo "Waiting ${SLEEP_TIME} seconds before retry..." | |
| sleep $SLEEP_TIME | |
| done | |
| echo "Generating API token..." | |
| TOKEN_RESPONSE=$(curl -k -s -w "\n%{http_code}" -u "admin:${PASSWORD}" \ | |
| -X POST \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"name":"smoke-test-token","role":"Admin"}' \ | |
| https://localhost:8000/v1/apitokens) | |
| HTTP_CODE=$(echo "${TOKEN_RESPONSE}" | tail -n1) | |
| TOKEN_BODY=$(echo "${TOKEN_RESPONSE}" | sed '$d') | |
| echo "API response status: ${HTTP_CODE}" | |
| if [ "${HTTP_CODE}" != "200" ]; then | |
| echo "ERROR: Failed to generate token. HTTP status: ${HTTP_CODE}" | |
| echo "Response: ${TOKEN_BODY}" | |
| exit 1 | |
| fi | |
| if ! echo "${TOKEN_BODY}" | jq -e . > /dev/null 2>&1; then | |
| echo "ERROR: Invalid JSON response from token generation" | |
| echo "Response: ${TOKEN_BODY}" | |
| exit 1 | |
| fi | |
| API_TOKEN=$(echo "${TOKEN_BODY}" | jq -r '.token') | |
| if [ -z "${API_TOKEN}" ] || [ "${API_TOKEN}" = "null" ]; then | |
| echo "ERROR: Generated token is null or empty" | |
| echo "Response: ${TOKEN_BODY}" | |
| exit 1 | |
| fi | |
| echo "Token generated successfully" | |
| echo "::add-mask::${API_TOKEN}" | |
| echo "token=${API_TOKEN}" >> "$GITHUB_OUTPUT" | |
| - name: Install go-junit-report | |
| run: go install github.com/jstemmer/go-junit-report/v2@v2.1.0 | |
| - name: Run smoke tests with JUnit output | |
| env: | |
| ROX_ENDPOINT: localhost:8000 | |
| ROX_API_TOKEN: ${{ steps.generate-token.outputs.token }} | |
| run: | | |
| go test -v -tags=smoke -cover -race -coverprofile=coverage-smoke.out -timeout=20m ./smoke 2>&1 | \ | |
| tee /dev/stderr | \ | |
| go-junit-report -set-exit-code -out junit-smoke.xml | |
| - name: Upload JUnit test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: junit-smoke-results | |
| path: junit-smoke.xml | |
| if-no-files-found: error | |
| - name: Upload test results to Codecov | |
| if: always() | |
| uses: codecov/test-results-action@v1 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: junit-smoke.xml | |
| - name: Upload coverage to Codecov | |
| if: always() | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| files: ./coverage-smoke.out | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| fail_ci_if_error: false | |
| flags: smoke | |
| name: smoke-tests | |
| - name: Collect logs | |
| if: always() | |
| run: | | |
| mkdir -p logs | |
| kubectl get pods -A > logs/pods.txt || true | |
| kubectl get events -A --sort-by='.lastTimestamp' > logs/events.txt || true | |
| kubectl logs -n vulnerable-apps deployment/vulnerable-app --all-containers=true > logs/vulnerable-app.log || true | |
| kubectl logs -n stackrox deployment/central > logs/central.log || true | |
| kubectl logs -n stackrox deployment/scanner > logs/scanner.log || true | |
| kubectl describe pod -n vulnerable-apps > logs/vulnerable-app-describe.txt || true | |
| - name: Upload logs | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: smoke-test-logs | |
| path: logs/ | |
| if-no-files-found: ignore |