Snowflake CLI と GitHub Actions を使用したリポジトリ ステージ経由のオブジェクトデプロイを試してみる

Snowflake CLI と GitHub Actions を使用したリポジトリ ステージ経由のオブジェクトデプロイを試してみる

Clock Icon2025.03.23

はじめに

Snowflake では、リポジトリ ステージとしてアカウントを Git リポジトリに接続することでリポジトリからクローンされたファイル内のコードを実行できるようになります。これにより、バージョン管理されたファイルから SQL スクリプトを実行しオブジェクトを管理できます。
こちらの機能を試してみましたので、本記事で手順をまとめてみます。

Snowflake における DevOps については以下で解説されています。

https://docs.snowflake.com/en/developer-guide/builders/devops

クイックスタートも提供されています。

https://quickstarts.snowflake.com/guide/getting_started_with_snowflake_devops/index.html#0

また、本検証にあたって特にワークフロー定義の構成情報の渡し方については、以下のリポジトリの内容を参照させていただきました。

https://github.com/Snowflake-Labs/snow-cli-demo

※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;

この時点では、以下のように確認できます。

image

リポジトリステージについては以下をご参照ください。

https://dev.classmethod.jp/articles/snowflake-git-stage-jinja2/

ローカルから実行

はじめにローカルからオブジェクトのデプロイを試してみます。具体的には 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;

image 1

ファイルの実行は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      |               |            |            |               |          |               |         |               |               |        |               |               |                |               |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

クエリ履歴を見ると赤枠部分のように変数に値が渡されていることが確認できます。

image 2

なお、この時点では接続情報としてローカルのデフォルトを使用しています。(Linux では~/.config/snowflake/config.toml )

参考:接続の管理|DevelopersIO

GitHub Actions 経由でデプロイ

続けて GitHub Actions 経由でオブジェクトをデプロイしてみます。

構成ファイルの作成

はじめにワークフローで使用する構成ファイルを追加します。

mkdir config
touch config/config.toml

内容は以下のようにしました。接続の名称を指定するのみで具体的な接続情報(アカウント情報、ユーザー名など)はシークレット経由で与えることとします。

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」から以下のシークレットを定義しました。
※ここでは簡単にパスワード認証を使用しています。

image 3

ワークフローの作成

具体的なワークフローの内容を定義します。ここでは.github/workflows/snowcli-workflow.ymlの名称でファイルを作成しました。

mkdir -p .github/workflows
touch .github/workflows/snowcli-workflow.yml

具体的な定義は以下の通りとしました。

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 でワークフローを実行

プルリクエストを作成し、ワークフローが実行されることを確認します。

image 4

「Merge pull request」をクリックします。

image 5

するとワークフローが実行されます。

image 6

実行ログ

image 7

問題なく実行できたので、クエリ履歴を確認します。ワークフローではenv=’PROD’としたのでこの値が渡されていることが確認できます。

image 8

image 9

さいごに

Snowflake CLI と GitHub Actions を連携しワークフロー経由でのオブジェクトのデプロイを試してみました。
こちらの内容が何かの参考になれば幸いです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.