Snowflake CLI と GitHub Actions を使用したリポジトリ ステージ経由のオブジェクトデプロイを試してみる
はじめに
Snowflake では、リポジトリ ステージとしてアカウントを Git リポジトリに接続することでリポジトリからクローンされたファイル内のコードを実行できるようになります。これにより、バージョン管理されたファイルから SQL スクリプトを実行しオブジェクトを管理できます。
こちらの機能を試してみましたので、本記事で手順をまとめてみます。
Snowflake における DevOps については以下で解説されています。
クイックスタートも提供されています。
また、本検証にあたって特にワークフロー定義の構成情報の渡し方については、以下のリポジトリの内容を参照させていただきました。
※Apache License 2.0
検証環境
以下の環境で検証しています。
- Ubuntu 24.04LTS(WSL2上で動作)
- Snowflake CLI version: 3.4.1
事前準備
GitHub Actions 経由でデプロイするために GitHub でリポジトリを作成しておきます。続けてローカルで検証用のディレクトリを作成し GitHub リポジトリと紐づけておきます。
mkdir snowcli-practice && cd snowcli-practice
echo "# snowcli-practice" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:<GitHubアカウント名>/<リモートリポジトリ名>.git
git push -u origin main
リポジトリステージの作成
Snowflake 側でリポジトリ ステージと呼ばれる種類のステージを作成することで、リモートリポジトリを Snowflake と統合することができます。リポジトリ ステージは、ブランチ、タグ、コミットを含むリモートリポジトリの完全なクローンを持つローカルリポジトリとして機能します。
ここでは以下の手順でリポジトリステージの管理用ロール、リポジトリステージの作成を行いました。
--データベース作成
USE ROLE sysadmin;
----シークレット管理用DB・スキーマを作成
CREATE DATABASE IF NOT EXISTS governance;
CREATE SCHEMA IF NOT EXISTS integrations;
--管理用ロールを作成
USE ROLE useradmin;
CREATE ROLE IF NOT EXISTS git_admin;
--スキーマに対するシークレットの作成権限を付与
USE ROLE securityadmin;
GRANT CREATE SECRET ON SCHEMA governance.integrations TO ROLE git_admin;
--対象のデータベース・スキーマに対するUSAGE権限も必要なので付与
GRANT USAGE ON DATABASE governance TO ROLE git_admin;
GRANT USAGE ON SCHEMA governance.integrations TO ROLE git_admin;
--スキーマに対する CREATE GIT REPOSITORY 権限を付与
GRANT CREATE GIT REPOSITORY ON SCHEMA governance.integrations TO ROLE git_admin;
--ロール階層を定義
GRANT ROLE git_admin TO ROLE sysadmin;
--コンテキストの設定(シークレット作成ロールに切り替え、スキーマを指定)
USE ROLE git_admin;
USE SCHEMA governance.integrations;
--シークレットを作成
CREATE OR REPLACE SECRET git_secret
TYPE = password
USERNAME = '<GitHubアカウント名>'
PASSWORD = '<トークン>';
--API統合を作成
USE ROLE ACCOUNTADMIN;
CREATE OR REPLACE API INTEGRATION git_api_integration
API_PROVIDER = git_https_api
API_ALLOWED_PREFIXES = ('https://github.com/<GitHubアカウント名>')
ALLOWED_AUTHENTICATION_SECRETS = (governance.integrations.git_secret)
ENABLED = TRUE;
--API統合の使用権限を付与
GRANT USAGE ON INTEGRATION git_api_integration TO ROLE git_admin;
--コンテキストの設定
USE ROLE git_admin;
USE SCHEMA governance.integrations;
--GIT REPOSITORY ステージを作成
CREATE OR REPLACE GIT REPOSITORY snowflake_extensions
API_INTEGRATION = git_api_integration
GIT_CREDENTIALS = git_secret
ORIGIN = 'https://github.com/<GitHubアカウント名>/<リモートリポジトリ名>';
--確認
ls @snowflake_extensions/branches/main;
この時点では、以下のように確認できます。
リポジトリステージについては以下をご参照ください。
ローカルから実行
はじめにローカルからオブジェクトのデプロイを試してみます。具体的には dev ブランチを作成し、dev ブランチの内容をもとにデプロイします。
# main ブランチに切り替え
git checkout main
# 最新の変更を取得
git pull origin main
# devブランチを作成
git checkout -b dev
$ git branch
* dev
main
続けて SQL ファイルを作成します。
mkdir scripts
touch scripts/db_schema.sql
実行するコマンドは以下のようにしました。データベースとデータベース内にスキーマを作成するシンプルな内容です。
ポイントは{{ 変数名 }}
としている部分で、実行時に変数を与えることで、環境に応じて作成されるオブジェクト名を変更します。
--データベース・スキーマ
USE ROLE sysadmin;
CREATE OR ALTER DATABASE {{ env }}_db;
CREATE OR ALTER SCHEMA {{ env }}_db.functions_sch;
dev ブランチにプッシュします。
git add scripts/
git commit -m "added sample sql"
git push --set-upstream origin dev
リモート リポジトリに変更を反映したので、この内容をもとにオブジェクトをデプロイします。デプロイには Snowflake CLI のコマンドを使用できます。
はじめに GitHub 上の変更を Snowflake のリポジトリステージに反映します。
$ snow git fetch governance.integrations.snowflake_extensions
+------------------------+
| scope | name | result |
|--------+------+--------|
| Branch | dev | NEW |
+------------------------+
Snowflakeで確認すると下図のように追加したファイルを確認できます。
ls @snowflake_extensions/branches/dev;
ファイルの実行はsnow git execute
を使用します。ポイントはenv='dev'
としている部分でここで変数の値を渡しています。
$ snow git execute '@snowflake_extensions/branches/dev/' -D "env='dev'" --database governance --schema integrations
SUCCESS - @snowflake_extensions/branches/dev/scripts/db_schema.sql
+----------------------------------------------------------------------------+
| File | Status | Error |
|----------------------------------------------------------+---------+-------|
| @snowflake_extensions/branches/dev/scripts/db_schema.sql | SUCCESS | None |
+----------------------------------------------------------------------------+
実行後のオブジェクト
$ snow sql -q "show databases like 'dev_db'"
show databases like 'dev_db';
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| created_on | name | is_default | is_current | origin | owner | comment | options | retention_time | kind | budget | owner_role_type | object_visibility |
|----------------------------------+--------+------------+------------+--------+----------+---------+---------+----------------+----------+--------+-----------------+-------------------|
| 2025-03-22 20:56:48.198000-07:00 | DEV_DB | N | N | | SYSADMIN | | | 1 | STANDARD | None | ROLE | None |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
$ snow sql -q "show schemas in database dev_db"
show schemas in database dev_db
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| | | | | | | | | | | | classificatio | classificatio | | |
| | | | | | | | | retention_tim | owner_role_ty | | n_profile_dat | n_profile_sch | classification | object_visibi |
| created_on | name | is_default | is_current | database_name | owner | comment | options | e | pe | budget | abase | ema | _profile | lity |
|---------------+---------------+------------+------------+---------------+----------+---------------+---------+---------------+---------------+--------+---------------+---------------+----------------+---------------|
| 2025-03-22 | FUNCTIONS_SCH | N | N | DEV_DB | SYSADMIN | | | 1 | ROLE | None | None | None | None | None |
| 20:56:48.3600 | | | | | | | | | | | | | | |
| 00-07:00 | | | | | | | | | | | | | | |
| 2025-03-22 | INFORMATION_S | N | N | DEV_DB | | Views | | 1 | | None | None | None | None | None |
| 21:00:23.5610 | CHEMA | | | | | describing | | | | | | | | |
| 00-07:00 | | | | | | the contents | | | | | | | | |
| | | | | | | of schemas in | | | | | | | | |
| | | | | | | this database | | | | | | | | |
| 2025-03-22 | PUBLIC | N | N | DEV_DB | SYSADMIN | | | 1 | ROLE | None | None | None | None | None |
| 20:56:48.2270 | | | | | | | | | | | | | | |
| 00-07:00 | | | | | | | | | | | | | | |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
クエリ履歴を見ると赤枠部分のように変数に値が渡されていることが確認できます。
なお、この時点では接続情報としてローカルのデフォルトを使用しています。(Linux では~/.config/snowflake/config.toml
)
GitHub Actions 経由でデプロイ
続けて GitHub Actions 経由でオブジェクトをデプロイしてみます。
構成ファイルの作成
はじめにワークフローで使用する構成ファイルを追加します。
mkdir config
touch config/config.toml
内容は以下のようにしました。接続の名称を指定するのみで具体的な接続情報(アカウント情報、ユーザー名など)はシークレット経由で与えることとします。
default_connection_name = "workflow"
[connections.workflow]
リモートリポジトリにプッシュしておきます。
git checkout dev
git add config/config.toml
git commit -m "Added config file"
git push origin dev
シークレットを追加
Snowflake への接続情報はシークレット経由で渡します。リポジトリの「Settings > Security > Secrets and variables > Actions」から以下のシークレットを定義しました。
※ここでは簡単にパスワード認証を使用しています。
ワークフローの作成
具体的なワークフローの内容を定義します。ここでは.github/workflows/snowcli-workflow.yml
の名称でファイルを作成しました。
mkdir -p .github/workflows
touch .github/workflows/snowcli-workflow.yml
具体的な定義は以下の通りとしました。
name: SNowflake CLI WF
on:
push:
branches:
- main
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-24.04
env:
GIT_REPO_DB: governance
GIT_REPO_SCHEMA: integrations
GIT_REPO_NAME: snowflake_extensions
SNOWFLAKE_DEFAULT_CONNECTION_NAME: "workflow"
SNOWFLAKE_CONNECTIONS_WORKFLOW_ACCOUNT: ${{ secrets.SNOWFLAKE_ACCOUNT }}
SNOWFLAKE_CONNECTIONS_WORKFLOW_USER: ${{ secrets.SNOWFLAKE_USER }}
SNOWFLAKE_CONNECTIONS_WORKFLOW_PASSWORD: ${{ secrets.SNOWFLAKE_PASSWORD }}
ENV_NAME: "PROD"
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install snowflake-cli
uses: Snowflake-Labs/snowflake-cli-action@v1.5
with:
cli-version: "latest"
default-config-file-path: ${{ github.workspace }}/config/config.toml
- name: Debug environment variables
run: |
echo "Deploying to Snowflake Account: ${{ secrets.SNOWFLAKE_ACCOUNT }}"
echo "Using Snowflake User: ${{ secrets.SNOWFLAKE_USER }}"
- name: Fetch repository changes
env:
GIT_REPO_FQN: ${{ env.GIT_REPO_DB }}.${{ env.GIT_REPO_SCHEMA }}.${{env.GIT_REPO_NAME }}
run: |
set -e
snow git fetch "${GIT_REPO_FQN}"
- name: Deploy data pipeline to main
env:
GIT_REPO_FQN: ${{ env.GIT_REPO_DB }}.${{ env.GIT_REPO_SCHEMA }}.${{env.GIT_REPO_NAME }}
run: |
set -e
snow git execute "@${GIT_REPO_FQN}/branches/main/" \
--database $GIT_REPO_DB \
--schema $GIT_REPO_SCHEMA \
--variable "env='$ENV_NAME'"
ポイントは以下です。
default-config-file-path: ${{ github.workspace }}/config/config.toml
としてワークフローで使用する構成ファイルのパスを指定SNOWFLAKE_CONNECTIONS_WORKFLOW_ACCOUNT
のようにすることでアカウントやユーザー名など構成ファイルに無い設定値を指定snow git execute
の引数としてenv='$ENV_NAME'
を指定- ワークフローでの
$ENV_NAME
は PROD
- ワークフローでの
ワークフローの追加を dev ブランチにプッシュしておきます。
git checkout dev
git add .github/workflows/snowcli-workflow.yml
git commit -m "Added new workflow"
git push origin dev
GitHub Actions でワークフローを実行
プルリクエストを作成し、ワークフローが実行されることを確認します。
「Merge pull request」をクリックします。
するとワークフローが実行されます。
実行ログ
問題なく実行できたので、クエリ履歴を確認します。ワークフローではenv=’PROD’
としたのでこの値が渡されていることが確認できます。
さいごに
Snowflake CLI と GitHub Actions を連携しワークフロー経由でのオブジェクトのデプロイを試してみました。
こちらの内容が何かの参考になれば幸いです。