CI/CD Integration
Integrate Olytix Core tests into your CI/CD pipeline to catch data quality issues before they reach production. This guide covers automated testing with GitHub Actions.
Overview
A robust CI/CD pipeline for Olytix Core projects includes:
┌─────────────────────────────────────────────────────────────────────┐
│ Olytix Core CI/CD Pipeline │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Code Push │
│ ┌──────────┐ │
│ │ Git │ │
│ │ Push │ │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ CI Pipeline │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
│ │ │ Lint │─►│Compile │─►│ Test │─►│ Deploy │ │ │
│ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │
│ │ │ │ │
│ │ ┌─────────┴─────────┐ │ │
│ │ ▼ ▼ │ │
│ │ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Data │ │ Schema │ │ │
│ │ │ Tests │ │ Tests │ │ │
│ │ └──────────┘ └──────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
GitHub Actions Workflow
Create a workflow file to automate Olytix Core testing on every pull request and push.
Basic Workflow
# .github/workflows/olytix-core-ci.yml
name: Olytix Core CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
env:
PYTHON_VERSION: "3.11"
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
pip install -e ".[dev]"
- name: Run ruff linter
run: ruff check src/
- name: Run ruff formatter check
run: ruff format --check src/
- name: Run mypy type checker
run: mypy src/
compile:
name: Compile Project
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install Olytix Core
run: pip install -e ".[dev]"
- name: Compile Olytix Core project
run: olytix-core compile --validate-schema
env:
OLYTIX_DATABASE__HOST: ${{ secrets.DATABASE_HOST }}
OLYTIX_DATABASE__USER: ${{ secrets.DATABASE_USER }}
OLYTIX_DATABASE__PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
OLYTIX_DATABASE__NAME: ${{ secrets.DATABASE_NAME }}
- name: Upload manifest artifact
uses: actions/upload-artifact@v4
with:
name: manifest
path: target/manifest.json
test:
name: Run Tests
runs-on: ubuntu-latest
needs: compile
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install Olytix Core
run: pip install -e ".[dev]"
- name: Download manifest
uses: actions/download-artifact@v4
with:
name: manifest
path: target/
- name: Run data tests
run: olytix-core test --verbose
env:
OLYTIX_DATABASE__HOST: ${{ secrets.DATABASE_HOST }}
OLYTIX_DATABASE__USER: ${{ secrets.DATABASE_USER }}
OLYTIX_DATABASE__PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
OLYTIX_DATABASE__NAME: ${{ secrets.DATABASE_NAME }}
- name: Run schema tests
run: olytix-core test --schema-only --verbose
env:
OLYTIX_DATABASE__HOST: ${{ secrets.DATABASE_HOST }}
OLYTIX_DATABASE__USER: ${{ secrets.DATABASE_USER }}
OLYTIX_DATABASE__PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
OLYTIX_DATABASE__NAME: ${{ secrets.DATABASE_NAME }}
deploy:
name: Deploy to Production
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install Olytix Core
run: pip install -e ".[dev]"
- name: Deploy models
run: olytix-core run --target prod
env:
OLYTIX_DATABASE__HOST: ${{ secrets.PROD_DATABASE_HOST }}
OLYTIX_DATABASE__USER: ${{ secrets.PROD_DATABASE_USER }}
OLYTIX_DATABASE__PASSWORD: ${{ secrets.PROD_DATABASE_PASSWORD }}
OLYTIX_DATABASE__NAME: ${{ secrets.PROD_DATABASE_NAME }}
Advanced Workflow with Matrix Testing
Test against multiple warehouse types:
# .github/workflows/olytix-core-matrix.yml
name: Olytix Core Matrix CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
name: Test (${{ matrix.warehouse }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
warehouse: [postgresql, snowflake, bigquery]
include:
- warehouse: postgresql
connection_env: OLYTIX_WAREHOUSE_POSTGRESQL
- warehouse: snowflake
connection_env: OLYTIX_WAREHOUSE_SNOWFLAKE
- warehouse: bigquery
connection_env: OLYTIX_WAREHOUSE_BIGQUERY
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install Olytix Core
run: pip install -e ".[dev]"
- name: Configure warehouse connection
run: |
echo "OLYTIX_WAREHOUSE__TYPE=${{ matrix.warehouse }}" >> $GITHUB_ENV
env:
CONNECTION_SECRET: ${{ secrets[matrix.connection_env] }}
- name: Compile project
run: olytix-core compile --target ${{ matrix.warehouse }}
- name: Run tests
run: olytix-core test --target ${{ matrix.warehouse }}
Pull Request Checks
Add status checks to require passing tests before merge:
# .github/workflows/pr-checks.yml
name: PR Checks
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
data-quality:
name: Data Quality Gates
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install Olytix Core
run: pip install -e ".[dev]"
- name: Get changed models
id: changed
run: |
CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD -- 'models/**' 'cubes/**' | xargs)
echo "models=$CHANGED" >> $GITHUB_OUTPUT
- name: Compile changed models
if: steps.changed.outputs.models != ''
run: olytix-core compile --select ${{ steps.changed.outputs.models }}
- name: Test changed models
if: steps.changed.outputs.models != ''
run: olytix-core test --select ${{ steps.changed.outputs.models }}
- name: Post test results
if: always()
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const results = fs.readFileSync('target/test_results.json', 'utf8');
const parsed = JSON.parse(results);
const summary = `## Test Results
| Status | Count |
|--------|-------|
| Passed | ${parsed.passed} |
| Failed | ${parsed.failed} |
| Warnings | ${parsed.warnings} |
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: summary
});
Environment Configuration
GitHub Secrets Setup
Configure repository secrets for database connections:
Settings > Secrets and variables > Actions > New repository secret
Required secrets:
| Secret Name | Description |
|---|---|
DATABASE_HOST | Database hostname |
DATABASE_USER | Database username |
DATABASE_PASSWORD | Database password |
DATABASE_NAME | Database name |
PROD_DATABASE_HOST | Production database host |
PROD_DATABASE_USER | Production database user |
PROD_DATABASE_PASSWORD | Production database password |
PROD_DATABASE_NAME | Production database name |
Environment Variables
Olytix Core uses environment variables with the OLYTIX_ prefix:
env:
# Database connection
OLYTIX_DATABASE__HOST: ${{ secrets.DATABASE_HOST }}
OLYTIX_DATABASE__PORT: 5432
OLYTIX_DATABASE__USER: ${{ secrets.DATABASE_USER }}
OLYTIX_DATABASE__PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
OLYTIX_DATABASE__NAME: ${{ secrets.DATABASE_NAME }}
# Project settings
OLYTIX_PROJECT__NAME: my-analytics
OLYTIX_TARGET: ci
# Test settings
OLYTIX_TEST__FAIL_FAST: true
OLYTIX_TEST__STORE_FAILURES: true
Staging Environment Testing
Test in a staging environment before production:
# .github/workflows/staging.yml
name: Staging Deployment
on:
push:
branches: [develop]
jobs:
deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install Olytix Core
run: pip install -e ".[dev]"
- name: Compile for staging
run: olytix-core compile --target staging
- name: Run models in staging
run: olytix-core run --target staging
- name: Run all tests
run: |
olytix-core test --target staging
olytix-core test --schema-only --target staging
- name: Run integration tests
run: pytest tests/integration/ -v
- name: Validate cube queries
run: olytix-core query --validate-only --cube orders
Test Reporting
Generate and publish test reports:
- name: Run tests with JUnit output
run: olytix-core test --output-format junit --output-file test-results.xml
- name: Publish Test Results
uses: dorny/test-reporter@v1
if: always()
with:
name: Olytix Core Test Results
path: test-results.xml
reporter: java-junit
- name: Upload test artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-failures
path: |
target/test_results.json
target/failed_tests/
Scheduled Testing
Run tests on a schedule to catch data drift:
# .github/workflows/scheduled-tests.yml
name: Scheduled Data Quality Checks
on:
schedule:
- cron: '0 6 * * *' # Daily at 6 AM UTC
workflow_dispatch: # Allow manual trigger
jobs:
daily-tests:
name: Daily Data Quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install Olytix Core
run: pip install -e ".[dev]"
- name: Run full test suite
run: olytix-core test --verbose
env:
OLYTIX_DATABASE__HOST: ${{ secrets.PROD_DATABASE_HOST }}
OLYTIX_DATABASE__USER: ${{ secrets.PROD_DATABASE_USER }}
OLYTIX_DATABASE__PASSWORD: ${{ secrets.PROD_DATABASE_PASSWORD }}
OLYTIX_DATABASE__NAME: ${{ secrets.PROD_DATABASE_NAME }}
- name: Notify on failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
channel-id: 'data-alerts'
slack-message: 'Daily data quality tests failed. Check workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
Best Practices
1. Fail Fast on Critical Tests
Configure critical tests to fail the pipeline immediately:
- name: Run critical tests
run: olytix-core test --select tag:critical --fail-fast
2. Cache Dependencies
Speed up workflows with dependency caching:
- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
3. Use Branch Protection
Require tests to pass before merging:
Settings > Branches > Branch protection rules
- Require status checks to pass
- Select: lint, compile, test
4. Separate Test Environments
Use dedicated test databases to avoid impacting production:
env:
OLYTIX_DATABASE__NAME: analytics_ci_${{ github.run_id }}
5. Clean Up Resources
Remove temporary resources after tests:
- name: Cleanup test database
if: always()
run: |
olytix-core run --select tag:cleanup
psql -c "DROP SCHEMA IF EXISTS ci_${{ github.run_id }} CASCADE"
Next Steps
With CI/CD integration complete:
- Data Tests - Configure data quality tests
- Schema Tests - Add schema validation
- Lineage - Track data flow