Skip to content

Adds BDD instructions and upgrade go to 1.26.3 #461

Adds BDD instructions and upgrade go to 1.26.3

Adds BDD instructions and upgrade go to 1.26.3 #461

Workflow file for this run

name: CI
on:
push:
paths:
- '.github/workflows/ci.yml'
- 'cmd/**'
- 'internal/**'
- 'scripts/**'
- 'test/**'
- 'go.mod'
- 'go.sum'
workflow_dispatch:
env:
GO_VERSION: '1.26.3'
jobs:
# Build the binary once and share it across all jobs
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Download dependencies
run: |
go mod download
go mod verify
- name: Build cqlai binary
run: |
go build -v -o cqlai cmd/cqlai/main.go
chmod +x cqlai
- name: Upload binary artifact
uses: actions/upload-artifact@v4
with:
name: cqlai-binary
path: cqlai
retention-days: 1
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Download dependencies
run: |
go mod download
go mod vendor
- name: Install and run golangci-lint
run: |
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b /tmp v2.11.4
/tmp/golangci-lint run --timeout=5m
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Run unit tests
run: |
# Run tests excluding integration tests (which require Cassandra).
# test/bdd is in-process godog and is run by the dedicated bdd-tests
# job below — keep it out of the unit suite so coverage only counts
# the production packages.
go test -v -race -coverprofile=coverage.out -covermode=atomic $(go list ./... | grep -v /test/)
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.out
flags: unittests
fail_ci_if_error: false
bdd-tests:
name: BDD Tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Download dependencies
run: |
go mod download
go mod tidy
- name: Run godog BDD suites
run: |
# Pure in-process godog scenarios — no Cassandra required.
# Covers test/bdd/steps (validation, splitter, save, ai, ssl-flags)
# plus internal/router (COPY options, in-package so it can see
# unexported helpers).
go test -v -count=1 -run BDD ./test/bdd/... ./internal/router/...
parquet-tests:
name: Parquet Tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Download dependencies
run: |
go mod download
go mod tidy
- name: Run Parquet tests
run: |
echo "Running Parquet COPY TO/FROM tests"
go test -v -timeout 60s ./test/parquet/...
env:
CI: true
- name: Run Parquet test suite with script
run: |
chmod +x ./test/parquet/run_tests.sh
./test/parquet/run_tests.sh
env:
CI: true
# Cassandra integration tests using the pre-built binary
cassandra-tests:
name: Cassandra ${{ matrix.cassandra.version }}
needs: build # Wait for binary to be built
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
cassandra:
- { version: "2.1", image: "cassandra:2.1" }
- { version: "3.0", image: "cassandra:3.0" }
- { version: "3.11", image: "cassandra:3.11" }
- { version: "4.0", image: "cassandra:4.0" }
- { version: "4.1", image: "cassandra:4.1" }
- { version: "5.0", image: "cassandra:5.0" }
services:
cassandra:
image: ${{ matrix.cassandra.image }}
ports:
- 9042:9042
options: >-
--health-cmd "cqlsh -e 'describe cluster'"
--health-interval 30s
--health-timeout 10s
--health-retries 10
--health-start-period 60s
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download pre-built binary
uses: actions/download-artifact@v4
with:
name: cqlai-binary
- name: Make binary executable
run: chmod +x ./cqlai
- name: Wait for Cassandra to be fully ready
run: |
echo "Waiting for Cassandra to be fully ready..."
for i in {1..30}; do
if docker exec $(docker ps -q -f ancestor=${{ matrix.cassandra.image }}) cqlsh -e "DESCRIBE CLUSTER" 2>/dev/null; then
echo "Cassandra is ready!"
break
fi
echo "Waiting for Cassandra... ($i/30)"
sleep 5
done
- name: Create configuration file
run: |
cat > cqlai.json <<EOF
{
"host": "127.0.0.1",
"port": 9042,
"username": "",
"password": "",
"keyspace": "",
"consistency": "ONE",
"pageSize": 100,
"timeout": "10s",
"connectTimeout": "10s"
}
EOF
- name: Run basic connectivity test
run: |
echo "Running basic connectivity test..."
cat > basic_connectivity_test.cql <<EOF
CREATE KEYSPACE IF NOT EXISTS test_connectivity
WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};
USE test_connectivity;
CREATE TABLE IF NOT EXISTS test_table (
id uuid PRIMARY KEY,
data text
);
INSERT INTO test_table (id, data) VALUES (uuid(), 'test data');
SELECT * FROM test_table;
DROP KEYSPACE test_connectivity;
EOF
./cqlai -f basic_connectivity_test.cql
if [ $? -eq 0 ]; then
echo "✅ Basic connectivity test passed"
else
echo "❌ Basic connectivity test failed"
exit 1
fi
- name: Run COPY command tests
run: |
echo "Running COPY TO/FROM command tests..."
# Create test keyspace and table
./cqlai -e "CREATE KEYSPACE IF NOT EXISTS copy_test WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};"
./cqlai -k copy_test -e "CREATE TABLE IF NOT EXISTS test_copy (id int PRIMARY KEY, name text, value int, active boolean);"
# Insert test data
./cqlai -k copy_test -e "INSERT INTO test_copy (id, name, value, active) VALUES (1, 'Alice', 100, true);"
./cqlai -k copy_test -e "INSERT INTO test_copy (id, name, value, active) VALUES (2, 'Bob', 200, false);"
./cqlai -k copy_test -e "INSERT INTO test_copy (id, name, value, active) VALUES (3, 'Charlie', 300, true);"
# Test COPY TO
echo "Testing COPY TO..."
./cqlai -k copy_test -e "COPY test_copy TO '/tmp/test_export.csv' WITH HEADER=true"
if [ -f /tmp/test_export.csv ]; then
echo "✅ COPY TO created file successfully"
echo "File contents:"
head -5 /tmp/test_export.csv
else
echo "❌ COPY TO failed to create file"
exit 1
fi
# Test COPY FROM
echo "Testing COPY FROM..."
./cqlai -k copy_test -e "TRUNCATE test_copy;"
./cqlai -k copy_test -e "COPY test_copy FROM '/tmp/test_export.csv' WITH HEADER=true"
# Verify data was imported
count=$(./cqlai -k copy_test -e "SELECT COUNT(*) FROM test_copy;" | grep -o '[0-9]\+' | head -1)
if [ "$count" = "3" ]; then
echo "✅ COPY FROM imported $count rows successfully"
else
echo "❌ COPY FROM failed: expected 3 rows, got $count"
exit 1
fi
# Clean up
./cqlai -e "DROP KEYSPACE copy_test;"
rm -f /tmp/test_export.csv
echo "✅ All COPY command tests passed"
- name: Run COPY FROM benchmark (issue #63)
run: |
echo "Running COPY FROM benchmark with 100k rows (use ROWS=1000000 for full test)..."
chmod +x ./test/benchmark_copy_from.sh
CQLAI=./cqlai ROWS=100000 ./test/benchmark_copy_from.sh
- name: Run version-specific tests (if exists)
run: |
TEST_FILE="test/cassandra_${{ matrix.cassandra.version }}_test.cql"
if [ -f "$TEST_FILE" ]; then
echo "Running version-specific tests: $TEST_FILE"
./cqlai -f "$TEST_FILE"
else
echo "No version-specific tests found for Cassandra ${{ matrix.cassandra.version }}"
fi
# ------------------------------------------------------------------
# Full Go integration suite against Cassandra 5.0 only.
# These tests are gated by the `integration` build tag (see
# test/integration/*.go) and require a live cluster. Running on every
# matrix entry would multiply CI time for little extra signal — the
# logic under test is server-version-agnostic.
# ------------------------------------------------------------------
- name: Setup Go (integration suite)
if: matrix.cassandra.version == '5.0'
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Run Go integration tests against Cassandra 5
if: matrix.cassandra.version == '5.0'
run: |
go test -v -tags integration -timeout 10m -count=1 ./test/integration/...
security-scan:
name: Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@0.35.0
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
- name: Upload Trivy results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
if: always()
continue-on-error: true
with:
sarif_file: 'trivy-results.sarif'
category: 'trivy'
- name: Setup Go for gosec
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Run gosec security scanner
run: |
go install github.com/securego/gosec/v2/cmd/gosec@v2.23.0
gosec -no-fail -fmt sarif -out gosec-results.sarif ./...
- name: Upload gosec results
uses: github/codeql-action/upload-sarif@v3
if: always()
continue-on-error: true
with:
sarif_file: 'gosec-results.sarif'
category: 'gosec'
dependency-check:
name: Dependency Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Check for outdated dependencies
run: |
go list -u -m all
- name: Check for security vulnerabilities
continue-on-error: true
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck -show verbose ./...
# Summary job that runs after all tests
test-summary:
name: Test Summary
needs: [lint, unit-tests, parquet-tests, cassandra-tests, security-scan]
runs-on: ubuntu-latest
if: always()
steps:
- name: Test Summary
run: |
echo "## CI Test Summary"
echo ""
echo "All CI checks have completed."
echo ""
echo "### Tests Run:"
echo "- ✅ Linting"
echo "- ✅ Unit Tests"
echo "- ✅ Parquet Tests"
echo "- ✅ Cassandra Integration Tests (6 versions)"
echo "- ✅ Security Scans"
echo "- ✅ Dependency Checks"
echo ""
echo "Note: Cross-platform builds are verified in the release workflow"