Back to skills
SKILL.md
Snowflake Ci Integration
ASecurity'Configure Snowflake CI/CD with GitHub Actions, SchemaChange, and Terraform. Use when setting up automated schema migrations, CI pipelines for Snowflake, or integrating SchemaChange/Terraform into your deployment workflow. Trigger with phrases like \"snowflake CI\", \"snowflake GitHub Actions\", \"snowflake SchemaChange\", \"snowflake terraform\", \"snowflake CI/CD\". '
- 3 stars
- 0 votes
- 0 copies
- 2 views
- Added September 12, 2026
Security analysis
96/100- Installs packages at runtime which could introduce malicious dependencies
npx -y skills add thedixitjain/the-mega-skill-library --skill snowflake-ci-integration --agent claude-codeAre you the author of Snowflake Ci Integration?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/thedixitjain-snowflake-ci-integration)---
name: snowflake-ci-integration
description: "'Configure Snowflake CI/CD with GitHub Actions, SchemaChange, and Terraform. Use when setting up automated schema migrations, CI pipelines for Snowflake, or integrating SchemaChange/Terraform into your deployment workflow. Trigger with phrases like \"snowflake CI\", \"snowflake GitHub Actions\", \"snowflake SchemaChange\", \"snowflake terraform\", \"snowflake CI/CD\". '"
allowed-tools: "Read, Write, Edit, Bash(gh:*)"
category: backend-and-data
source_repo: jeremylongshore/claude-code-plugins-plus-skills
source_path: "plugins/saas-packs/snowflake-pack/skills/snowflake-ci-integration/SKILL.md"
source_url: https://github.com/jeremylongshore/claude-code-plugins-plus-skills/blob/HEAD/plugins/saas-packs/snowflake-pack/skills/snowflake-ci-integration/SKILL.md
---
# Snowflake CI Integration
## Overview
Set up CI/CD for Snowflake using SchemaChange for migrations, GitHub Actions for automation, and Terraform for infrastructure.
## Prerequisites
- GitHub repository with Actions enabled
- Snowflake service account with key pair auth
- SchemaChange or Terraform installed
## Instructions
### Step 1: SchemaChange for Database Migrations
```bash
# Install SchemaChange
pip install schemachange
# Directory structure
migrations/
├── V1.0.0__initial_schema.sql # Versioned (run once, in order)
├── V1.1.0__add_orders_table.sql
├── V1.2.0__add_customer_segments.sql
├── R__views.sql # Repeatable (re-run on every change)
├── R__stored_procedures.sql
└── A__cleanup_temp_tables.sql # Always run
```
```sql
-- V1.0.0__initial_schema.sql
CREATE DATABASE IF NOT EXISTS {{database}};
CREATE SCHEMA IF NOT EXISTS {{database}}.{{schema}};
CREATE TABLE IF NOT EXISTS {{database}}.{{schema}}.users (
id INTEGER AUTOINCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
created_at TIMESTAMP_NTZ DEFAULT CURRENT_TIMESTAMP()
);
-- V1.1.0__add_orders_table.sql
CREATE TABLE IF NOT EXISTS {{database}}.{{schema}}.orders (
order_id INTEGER AUTOINCREMENT,
user_id INTEGER REFERENCES {{database}}.{{schema}}.users(id),
amount DECIMAL(12,2),
order_date TIMESTAMP_NTZ DEFAULT CURRENT_TIMESTAMP()
);
```
```bash
# Run migrations locally
schemachange deploy \
--root-folder migrations \
--snowflake-account $SNOWFLAKE_ACCOUNT \
--snowflake-user $SNOWFLAKE_USER \
--snowflake-private-key-path ./rsa_key.p8 \
--snowflake-warehouse DEV_WH_XS \
--snowflake-database DEV_DB \
--snowflake-schema PUBLIC \
--change-history-table SCHEMACHANGE.CHANGE_HISTORY \
--create-change-history-table \
--vars '{"database": "DEV_DB", "schema": "PUBLIC"}'
```
### Step 2: GitHub Actions Workflow
```yaml
# .github/workflows/snowflake-deploy.yml
name: Snowflake Deploy
on:
push:
branches: [main]
paths: ['migrations/**']
pull_request:
branches: [main]
paths: ['migrations/**']
env:
SNOWFLAKE_ACCOUNT: ${{ secrets.SNOWFLAKE_ACCOUNT }}
SNOWFLAKE_USER: ${{ secrets.SNOWFLAKE_USER }}
jobs:
validate:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install schemachange
- name: Dry-run migrations against staging
env:
SNOWFLAKE_PRIVATE_KEY: ${{ secrets.SNOWFLAKE_PRIVATE_KEY }}
run: |
echo "$SNOWFLAKE_PRIVATE_KEY" > /tmp/rsa_key.p8
schemachange deploy \
--root-folder migrations \
--snowflake-account $SNOWFLAKE_ACCOUNT \
--snowflake-user $SNOWFLAKE_USER \
--snowflake-private-key-path /tmp/rsa_key.p8 \
--snowflake-warehouse CI_WH_XS \
--snowflake-database STAGING_DB \
--dry-run \
--vars '{"database": "STAGING_DB", "schema": "PUBLIC"}'
deploy:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install schemachange
- name: Deploy to production
env:
SNOWFLAKE_PRIVATE_KEY: ${{ secrets.SNOWFLAKE_PRIVATE_KEY_PROD }}
run: |
echo "$SNOWFLAKE_PRIVATE_KEY" > /tmp/rsa_key.p8
schemachange deploy \
--root-folder migrations \
--snowflake-account $SNOWFLAKE_ACCOUNT \
--snowflake-user $SNOWFLAKE_USER \
--snowflake-private-key-path /tmp/rsa_key.p8 \
--snowflake-warehouse PROD_ETL_WH \
--snowflake-database PROD_DB \
--change-history-table SCHEMACHANGE.CHANGE_HISTORY \
--create-change-history-table \
--vars '{"database": "PROD_DB", "schema": "PUBLIC"}'
```
### Step 3: Configure GitHub Secrets
```bash
# Store credentials
gh secret set SNOWFLAKE_ACCOUNT --body "myorg-myaccount"
gh secret set SNOWFLAKE_USER --body "svc_github_ci"
gh secret set SNOWFLAKE_PRIVATE_KEY < rsa_key.p8
gh secret set SNOWFLAKE_PRIVATE_KEY_PROD < rsa_key_prod.p8
```
### Step 4: Terraform for Infrastructure
```hcl
# snowflake.tf
terraform {
required_providers {
snowflake = {
source = "Snowflake-Labs/snowflake"
version = "~> 0.90"
}
}
}
provider "snowflake" {
account = var.snowflake_account
user = var.snowflake_user
private_key = file(var.private_key_path)
role = "SYSADMIN"
}
resource "snowflake_database" "analytics" {
name = "ANALYTICS_DB"
data_retention_time_in_days = 14
}
resource "snowflake_warehouse" "etl" {
name = "ETL_WH"
warehouse_size = "LARGE"
auto_suspend = 120
auto_resume = true
}
resource "snowflake_role" "analyst" {
name = "ANALYST_ROLE"
}
resource "snowflake_grant_privileges_to_role" "analyst_usage" {
role_name = snowflake_role.analyst.name
privileges = ["USAGE"]
on_account_object {
object_type = "WAREHOUSE"
object_name = snowflake_warehouse.etl.name
}
}
```
### Step 5: Integration Tests in CI
```yaml
# Add to GitHub Actions workflow
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- name: Run Snowflake integration tests
env:
SNOWFLAKE_ACCOUNT: ${{ secrets.SNOWFLAKE_ACCOUNT }}
SNOWFLAKE_USER: ${{ secrets.SNOWFLAKE_USER }}
SNOWFLAKE_PRIVATE_KEY: ${{ secrets.SNOWFLAKE_PRIVATE_KEY }}
run: |
echo "$SNOWFLAKE_PRIVATE_KEY" > /tmp/rsa_key.p8
SNOWFLAKE_PRIVATE_KEY_PATH=/tmp/rsa_key.p8 npm test
```
## Error Handling
| Issue | Cause | Solution |
|-------|-------|----------|
| `Duplicate script` | SchemaChange already ran it | Versioned scripts run once; check CHANGE_HISTORY |
| `Permission denied` | CI user lacks privileges | Grant required roles to CI service account |
| `Terraform drift` | Manual changes in Snowflake | Run `terraform plan` to detect, `terraform import` to sync |
| `Secret not found` | Missing GitHub secret | `gh secret set SNOWFLAKE_*` |
## Resources
- [SchemaChange](https://github.com/Snowflake-Labs/schemachange)
- [Snowflake Terraform Provider](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest)
- [GitHub Actions](https://docs.github.com/en/actions)
## Next Steps
For deployment patterns, see `snowflake-deploy-integration`.
---
**Source:** [`jeremylongshore/claude-code-plugins-plus-skills`](https://github.com/jeremylongshore/claude-code-plugins-plus-skills) → `plugins/saas-packs/snowflake-pack/skills/snowflake-ci-integration/SKILL.md`
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.