Update marketing examples from WebGoat to known-malicious-repo #190
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: Test | |
| on: | |
| push: | |
| branches: [main, claude/*] | |
| pull_request: | |
| branches: [main] | |
| # Pin opengrep version for consistent SARIF output | |
| # IMPORTANT: When updating this version, also update: | |
| # - internal/version/version.go | |
| # - docker/Dockerfile | |
| env: | |
| OPENGREP_VERSION: "1.15.1" | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| # Skip redundant runs: run on push, or on pull_request only if from a fork | |
| if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.22' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install opengrep (pinned version) | |
| run: | | |
| wget -O /usr/local/bin/opengrep "https://github.com/opengrep/opengrep/releases/download/v${OPENGREP_VERSION}/opengrep_manylinux_x86" | |
| chmod +x /usr/local/bin/opengrep | |
| opengrep --version | |
| - name: Build | |
| run: go build -v ./... | |
| - name: Run unit tests with coverage | |
| run: | | |
| go test -v -race -coverprofile=coverage.out -short ./... | |
| go tool cover -func=coverage.out | |
| - name: Run integration tests (with scanner) | |
| run: | | |
| go test -v -timeout 5m ./test/... | |
| - name: Upload coverage | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report | |
| path: coverage.out | |
| scanner-test: | |
| runs-on: ubuntu-latest | |
| # Skip redundant runs: run on push, or on pull_request only if from a fork | |
| if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.22' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install opengrep (pinned version) | |
| run: | | |
| wget -O /usr/local/bin/opengrep "https://github.com/opengrep/opengrep/releases/download/v${OPENGREP_VERSION}/opengrep_manylinux_x86" | |
| chmod +x /usr/local/bin/opengrep | |
| opengrep --version | |
| - name: Clone test repo and scan for fake secrets | |
| run: | | |
| # Clone this repo (contains test/fixtures/fake_secrets.go) | |
| git clone --depth 1 https://github.com/baocin/gitscan.git /tmp/test-repo | |
| # Run scanner with SARIF output to file (--sarif-output writes directly to file) | |
| # Use --quiet to suppress progress bar which can interfere with output | |
| echo "Running opengrep scanner..." | |
| opengrep scan --quiet --config auto --sarif-output=/tmp/scan-results.json /tmp/test-repo || true | |
| # Show scanner progress (from stderr) | |
| echo "=== Scanner Progress ===" | |
| cat /tmp/scan-stderr.log | head -50 | |
| # Show JSON results | |
| echo "=== Scan Results (JSON) ===" | |
| cat /tmp/scan-results.json | head -200 | |
| # Verify we got JSON output | |
| if [ ! -s /tmp/scan-results.json ]; then | |
| echo "ERROR: No scan output generated" | |
| echo "=== Stderr log ===" | |
| cat /tmp/scan-stderr.log | |
| exit 1 | |
| fi | |
| # Check for valid JSON structure | |
| if ! python3 -c "import json; json.load(open('/tmp/scan-results.json'))"; then | |
| echo "ERROR: Invalid JSON output" | |
| echo "=== Full output ===" | |
| cat /tmp/scan-results.json | |
| echo "=== Stderr log ===" | |
| cat /tmp/scan-stderr.log | |
| exit 1 | |
| fi | |
| echo "Scanner produced valid JSON output" | |
| - name: Verify SARIF parsing compatibility | |
| run: | | |
| # Test that our Go code can parse the scanner output | |
| go test -v -run TestParseSARIF ./internal/scanner/... | |
| benchmark-test: | |
| runs-on: ubuntu-latest | |
| # Skip redundant runs: run on push, or on pull_request only if from a fork | |
| if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.22' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install opengrep (pinned version) | |
| run: | | |
| wget -O /usr/local/bin/opengrep "https://github.com/opengrep/opengrep/releases/download/v${OPENGREP_VERSION}/opengrep_manylinux_x86" | |
| chmod +x /usr/local/bin/opengrep | |
| opengrep --version | |
| - name: Run OWASP NodeGoat clone test | |
| run: | | |
| go test -v -run TestCloneOWASPNodeGoatPinned ./test/... -timeout 5m | |
| - name: Run clone speed tests | |
| run: | | |
| go test -v -run TestCloneSpeed ./test/... -timeout 5m | |
| - name: Run OWASP NodeGoat scan test | |
| run: | | |
| go test -v -run TestScanOWASPNodeGoat ./test/... -timeout 10m | |
| - name: Run benchmarks (1 iteration for CI) | |
| run: | | |
| go test -bench=. -benchtime=1x -run=^$ ./test/... -timeout 10m || true | |
| integration-test: | |
| runs-on: ubuntu-latest | |
| needs: test | |
| # Skip redundant runs: run on push, or on pull_request only if from a fork | |
| if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.22' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install opengrep (pinned version) | |
| run: | | |
| wget -O /usr/local/bin/opengrep "https://github.com/opengrep/opengrep/releases/download/v${OPENGREP_VERSION}/opengrep_manylinux_x86" | |
| chmod +x /usr/local/bin/opengrep | |
| opengrep --version | |
| - name: Build server | |
| run: go build -o gitscan-server ./cmd/gitscan-server | |
| - name: Start server | |
| run: | | |
| ./gitscan-server -listen :6633 -cache-dir /tmp/gitscan-cache & | |
| sleep 3 | |
| curl -sf http://localhost:6633/health || exit 1 | |
| - name: Test health endpoint | |
| run: | | |
| curl -sf http://localhost:6633/health | |
| - name: Test version endpoint | |
| run: | | |
| curl -sf http://localhost:6633/version | jq . | |
| - name: Test homepage | |
| run: | | |
| curl -sf http://localhost:6633/ | grep -q "git.vet" | |
| - name: Test git clone (info/refs) | |
| run: | | |
| # Test that info/refs endpoint responds with git protocol | |
| curl -sf "http://localhost:6633/github.com/OWASP/NodeGoat/info/refs?service=git-upload-pack" | head -c 100 | |
| docker-test: | |
| runs-on: ubuntu-latest | |
| needs: test # Run after unit tests pass | |
| # Skip redundant runs: run on push, or on pull_request only if from a fork | |
| if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build Docker image | |
| run: | | |
| echo "Building Docker image..." | |
| docker build -f docker/Dockerfile -t gitscan:test . | |
| echo "Image built successfully" | |
| - name: Verify binary in image | |
| run: | | |
| echo "=== Checking binary exists and is executable ===" | |
| docker run --rm gitscan:test ls -la /usr/local/bin/gitscan | |
| docker run --rm gitscan:test file /usr/local/bin/gitscan | |
| echo "=== Checking shared library dependencies ===" | |
| docker run --rm gitscan:test ldd /usr/local/bin/gitscan 2>&1 || echo "Static binary or musl-linked" | |
| - name: Start container | |
| run: | | |
| docker run -d --name gitscan-test -p 6633:6633 gitscan:test | |
| echo "Container started, waiting for server..." | |
| # Wait for server to be ready (up to 30 seconds) | |
| for i in $(seq 1 15); do | |
| if curl -sf http://localhost:6633/health > /dev/null 2>&1; then | |
| echo "Server ready after $((i*2)) seconds" | |
| break | |
| fi | |
| echo "Waiting... ($i/15)" | |
| sleep 2 | |
| done | |
| - name: Test health endpoint | |
| run: | | |
| response=$(curl -sf http://localhost:6633/health) | |
| echo "Health: $response" | |
| [ "$response" = "ok" ] || [ "$response" = "OK" ] || exit 1 | |
| - name: Test version endpoint | |
| run: | | |
| curl -sf http://localhost:6633/version | jq . | |
| - name: Test homepage | |
| run: | | |
| curl -sf http://localhost:6633/ | grep -q "git.vet" | |
| echo "Homepage OK - contains git.vet" | |
| - name: Test pricing page | |
| run: | | |
| curl -sf http://localhost:6633/pricing | grep -q "Pricing" | |
| echo "Pricing page OK" | |
| # Test redirect from /pricing/ to /pricing | |
| status=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:6633/pricing/) | |
| echo "Redirect status: $status" | |
| [ "$status" = "301" ] || [ "$status" = "200" ] || exit 1 | |
| - name: Test static assets | |
| run: | | |
| # Test favicon | |
| curl -sf http://localhost:6633/static/favicon.svg > /dev/null | |
| echo "Favicon OK" | |
| - name: Test git protocol - info/refs | |
| run: | | |
| response=$(curl -sf "http://localhost:6633/github.com/OWASP/NodeGoat/info/refs?service=git-upload-pack") | |
| echo "$response" | head -c 200 | |
| echo "" | |
| # Verify git protocol response | |
| echo "$response" | grep -q "git-upload-pack" || { echo "Missing git-upload-pack in response"; exit 1; } | |
| echo "Git info/refs OK" | |
| - name: Test report page (404 for non-existent) | |
| run: | | |
| # Should return HTML even for non-existent reports | |
| curl -sf http://localhost:6633/r/nonexistent123 | grep -q "Report Not Found" | |
| echo "Report 404 page OK" | |
| - name: Show container logs | |
| if: always() | |
| run: | | |
| echo "=== Container logs ===" | |
| docker logs gitscan-test 2>&1 | tail -100 | |
| - name: Cleanup | |
| if: always() | |
| run: | | |
| docker stop gitscan-test 2>/dev/null || true | |
| docker rm gitscan-test 2>/dev/null || true |