Skip to content

Commit 85276bd

Browse files
feat: Add Core integration test workflow and docker setup
- Create GitHub workflow for Core integration tests based on firebolt-python-sdk - Add simplified docker-compose.yml without nginx/SSL setup - Add Core configuration file for docker container - Create Core integration test fixtures and test class - Test Core connection, authentication, and simple query execution - Verify Core connections don't require traditional credentials Co-Authored-By: [email protected] <[email protected]>
1 parent 5b08b27 commit 85276bd

File tree

5 files changed

+165
-0
lines changed

5 files changed

+165
-0
lines changed

.github/resources/core/config.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"nodes": [
3+
{
4+
"host": "firebolt-core"
5+
}
6+
]
7+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: firebolt-core
2+
3+
services:
4+
firebolt-core:
5+
image: ghcr.io/firebolt-db/firebolt-core:${IMAGE_TAG}
6+
container_name: firebolt-core
7+
command: --node 0
8+
privileged: true
9+
restart: no
10+
ulimits:
11+
memlock: 8589934592
12+
ports:
13+
- 3473:3473
14+
volumes:
15+
- ${BASE_DIR}/.github/resources/core/config.json:/firebolt-core/config.json:ro
16+
- ${BASE_DIR}/firebolt-core:/firebolt-core/data
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: Core integration tests
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag_version:
7+
description: 'The docker image tag for the firebolt core'
8+
required: false
9+
type: string
10+
default: 'preview-rc'
11+
python_version:
12+
description: 'Python version'
13+
required: false
14+
type: string
15+
default: '3.8'
16+
workflow_call:
17+
inputs:
18+
tag_version:
19+
description: 'The docker image tag for the firebolt core'
20+
required: false
21+
type: string
22+
default: 'preview-rc'
23+
python_version:
24+
description: 'Python version'
25+
required: false
26+
type: string
27+
default: '3.8'
28+
29+
jobs:
30+
run-core-integration-tests:
31+
runs-on: ubuntu-latest
32+
env:
33+
DOCKER_COMPOSE_FILE: ${{ github.workspace }}/.github/resources/core/docker-compose.yml
34+
SERVICE_PORT: 3473
35+
SERVICE_URL: http://localhost:3473
36+
MAX_RETRIES: 30
37+
RETRY_INTERVAL: 2
38+
steps:
39+
- name: Check out code
40+
uses: actions/checkout@v4
41+
42+
- name: Set up Python
43+
uses: actions/setup-python@v5
44+
with:
45+
python-version: ${{ inputs.python_version }}
46+
47+
- name: Install dependencies
48+
run: |
49+
python -m pip install --upgrade pip
50+
pip install ".[dev]"
51+
52+
- name: Log in to GitHub Container Registry
53+
uses: docker/login-action@v3
54+
with:
55+
registry: ghcr.io
56+
username: ${{ github.actor }}
57+
password: ${{ secrets.GITHUB_TOKEN }}
58+
59+
- name: Prepare docker-compose.yml
60+
run: |
61+
sed -i "s|\${IMAGE_TAG}|${{ inputs.tag_version }}|g" "$DOCKER_COMPOSE_FILE"
62+
sed -i "s|\${BASE_DIR}|${{ github.workspace }}|g" "$DOCKER_COMPOSE_FILE"
63+
64+
- name: Start service container
65+
run: |
66+
docker compose -f "$DOCKER_COMPOSE_FILE" up -d
67+
docker compose -f "$DOCKER_COMPOSE_FILE" ps
68+
69+
- name: Wait for service to be ready
70+
run: |
71+
for i in $(seq 1 $MAX_RETRIES); do
72+
if curl --silent --fail "$SERVICE_URL" --data-binary "SELECT 1" | grep -q "1"; then
73+
echo "Service is up and responding!"
74+
exit 0
75+
fi
76+
echo "Waiting for service... ($i/$MAX_RETRIES)"
77+
sleep $RETRY_INTERVAL
78+
done
79+
echo "Error: Service failed to start within timeout"
80+
docker compose -f "$DOCKER_COMPOSE_FILE" logs
81+
exit 1
82+
83+
- name: Run Core integration tests
84+
env:
85+
CORE_URL: "http://localhost:3473"
86+
run: |
87+
pytest -o log_cli=true -o log_cli_level=INFO tests/integration/test_core_integration.py
88+
89+
- name: Stop container
90+
if: always()
91+
run: |
92+
docker compose -f "$DOCKER_COMPOSE_FILE" down

tests/integration/conftest.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,19 @@ def setup_test_tables(
233233
assert not engine.dialect.has_table(connection, fact_table_name)
234234
assert not engine.dialect.has_table(connection, dimension_table_name)
235235
assert not engine.dialect.has_table(connection, type_table_name)
236+
237+
238+
@fixture(scope="session")
239+
def core_url() -> str:
240+
return environ.get("CORE_URL", "http://localhost:3473")
241+
242+
243+
@fixture(scope="session")
244+
def core_engine(core_url: str) -> Engine:
245+
return create_engine(f"firebolt://firebolt?url={core_url}")
246+
247+
248+
@fixture(scope="session")
249+
def core_connection(core_engine: Engine) -> Connection:
250+
with core_engine.connect() as c:
251+
yield c
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from sqlalchemy import text
2+
from sqlalchemy.engine.base import Connection, Engine
3+
from firebolt.client.auth import FireboltCore
4+
5+
6+
class TestFireboltCoreIntegration:
7+
def test_core_connection(self, core_connection: Connection):
8+
"""Test that Core connection can be established."""
9+
result = core_connection.execute(text("SELECT 1"))
10+
assert result.fetchall() == [(1,)]
11+
12+
def test_core_engine_auth(self, core_engine: Engine):
13+
"""Test that Core engine uses FireboltCore authentication."""
14+
connect_args = core_engine.dialect.create_connect_args(core_engine.url)
15+
auth = connect_args[1]["auth"]
16+
assert isinstance(auth, FireboltCore)
17+
18+
def test_core_simple_query(self, core_connection: Connection):
19+
"""Test executing a simple query against Core."""
20+
result = core_connection.execute(text("SELECT 'Hello Core' as message"))
21+
rows = result.fetchall()
22+
assert len(rows) == 1
23+
assert rows[0][0] == "Hello Core"
24+
25+
def test_core_no_credentials_required(self, core_engine: Engine):
26+
"""Test that Core connection doesn't require traditional credentials."""
27+
connect_args = core_engine.dialect.create_connect_args(core_engine.url)
28+
result_dict = connect_args[1]
29+
30+
assert "url" in result_dict
31+
assert result_dict["url"] == "http://localhost:3473"
32+
assert isinstance(result_dict["auth"], FireboltCore)
33+
assert result_dict["engine_name"] is None
34+
assert "account_name" not in result_dict

0 commit comments

Comments
 (0)