COLUMN

Streamlit in Snowflake の CI/CD を GitHub Actions で構築する

Streamlit in Snowflake の CI/CD を GitHub Actions で構築する

Streamlit in Snowflake(以下 SiS)は、Snowflake上で手軽にダッシュボードや社内ツールを構築できる便利な機能です。
しかし、アプリのコードが増えてくると「誰がいつデプロイしたかわからない」「本番に反映するたびに手作業が発生する」といった課題が出てきます。

本記事では、GitHub Actions とSnowflake CLIを使ってSiSアプリのCI/CDパイプラインを構築した事例を紹介します。
OIDC(OpenID Connect)によるシークレットレスな認証も組み合わせ、セキュアかつ運用負荷の低い構成を実現しました。

1.なぜ GitHub Actions+Snowflake CLIなのか

SiSのデプロイを自動化する方法は、大きく2つあります。

項目GitHub Actions+CLINative Git Integration
用途CI/CD (推奨)デプロイ自動化
Lint/テスト可能不可
PR時の自動チェック可能不可
承認フローGitHub Pull Request
(ブランチ保護で必須化)
別途実装が必要
Streamlit対応snow streamlit deployCREATE STREAMLIT FROM

SnowflakeにはNative Git Integrationというデプロイ自動化の仕組みもあります。
ただし、これはあくまで「デプロイの自動化」であり、Lintやテストを含む「CI/CD」とは異なります。
PR時のLintチェックやマージ後の自動デプロイを一貫して行いたいなら、GitHub Actions+Snowflake CLIの構成が適しています。

技術的には「CIはGitHub Actions、CDはGit Integration」というハイブリッド構成も可能ですが、SiSのデプロイはsnow streamlit deployの1コマンドで完結するため、わざわざ分離するメリットはありません。
また、Git IntegrationはFETCH時に全ブランチ・全タグ・全コミットを Snowflake 側に同期する仕様です。 SiSのデプロイに必要なのは最新のコードだけなので、この点でも CLI 方式のほうが効率的です。

2.全体アーキテクチャ

今回構築したパイプラインの全体像です。

GitHub Actions上でCI(継続的なコード検証・統合)とCD(デプロイ)を一元管理します。
Snowflake CLI でデプロイを行います。
OIDC 認証を使うことで、長期的な秘密情報を GitHub Secrets に保存する必要がありません。

ブランチとSnowflake環境のマッピングは以下のとおりです。
今回は3ブランチ構成を採用しました。

  • feature/* — ローカル開発・PR 作成
  • dev — DEV環境へ自動デプロイ(統合テスト用)
  • main — PROD環境へ自動デプロイ(本番)

mainブランチには保護ルールを設定し、PR必須・承認必須・Force Push禁止としています。

3.認証方式: Key-pair vs OIDC

GitHub Actionsから Snowflakeに接続する認証方式は主に2つあります。

観点Key-pairOIDC
秘密鍵の管理GitHub Secretsに保存が必要不要
漏洩リスク鍵漏洩で長期アクセス可能トークンは短命で限定的
ローテーション手動で定期更新自動(都度生成)
設定の複雑さシンプルSnowflake側の初期設定が必要

今回はOIDC 認証(Workload Identity)を採用しました。
GitHub Actionsが発行する短命のOIDCトークンでSnowflakeに接続するため、GitHub Secretsに秘密鍵を保存する必要がありません。

Snowflake側ではWorkload Identity Userを作成し、特定のリポジトリ・環境からのみ認証を許可します。

-- Snowflake 側の設定例(DEV / PROD それぞれ作成)
-- DEV 環境用
CREATE OR REPLACE USER svc_cicd_dev
    TYPE = SERVICE
    DEFAULT_ROLE = cicd_role_dev
    WORKLOAD_IDENTITY = (
        TYPE = OIDC
        ISSUER = 'https://token.actions.githubusercontent.com'
        SUBJECT = 'repo:<org>/<repo>:environment:dev'
    );
GRANT ROLE cicd_role_dev TO USER svc_cicd_dev;

-- PROD 環境用
CREATE OR REPLACE USER svc_cicd_prod
    TYPE = SERVICE
    DEFAULT_ROLE = cicd_role_prod
    WORKLOAD_IDENTITY = (
        TYPE = OIDC
        ISSUER = 'https://token.actions.githubusercontent.com'
        SUBJECT = 'repo:<org>/<repo>:environment:prod'
    );
GRANT ROLE cicd_role_prod TO USER svc_cicd_prod;

SUBJECTでGitHub Environmentを指定することで、各環境のワークフローからのみ認証可能になります。
PoCや小規模プロジェクトであればKey-pair認証でも十分ですが、本番運用ではOIDCを推奨します。

GitHub Secrets/Variablesの設定

OIDC認証では秘密鍵は不要ですが、接続先の情報はGitHub Secrets/Variablesで管理します。

リポジトリ Secrets(全環境共通)

Secret説明
SNOWFLAKE_ACCOUNTSnowflake アカウント識別子

環境 Secrets(環境ごとに異なる値)*

EnvironmentSecret
devSNOWFLAKE_USERsvc_cicd_dev
prodSNOWFLAKE_USERsvc_cicd_dev

4.CI/CDパイプライン

CIパイプライン

PR 作成時に自動実行されるチェックをGitHub Actionsで定義しました。

# ci.yml
name: CI
on:
  pull_request:
  workflow_call:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
      - name: Run Ruff (lint)
        run: uv run ruff check .
      - name: Run Ruff (format check)
        run: uv run ruff format --check --diff .

RuffはPythonの高速なLinter/Formatterです。
ruff checkでコードスタイルの違反を、ruff format --checkでフォーマットの不整合を検出します。

なお、SiSはPythonアプリなので、必要に応じてpytestなどの自動テストを追加することも可能です。

CDパイプライン

ブランチへのpushをトリガーに、Snowflakeへ自動デプロイします。

  • cd_dev.ymldevブランチへpush時にDEV環境へデプロイ
  • cd_prod.ymlmainブランチへpush時にPROD環境へデプロイ

DEV環境へのデプロイでは、CI(Lint)とパッケージ検証を通過してからデプロイが実行されます。

SiS(Warehouse Runtime)ではenvironment.ymlでライブラリを管理しますが、Snowflake環境のAnacondaチャンネルで提供されていないパッケージを指定するとデプロイが失敗します。
これを防ぐため、snow snowpark package lookupで事前チェックしています。

# cd_dev.yml(抜粋)
- name: Setup Snowflake CLI
  uses: snowflakedb/snowflake-cli-action@v2.0
  with:
    use-oidc: true

# environment.yml からパッケージ名を抽出し、各パッケージを検証
- name: Validate Snowflake Anaconda packages
  run: snow snowpark package lookup <パッケージ名> -x

- name: Deploy Streamlit App
  run: snow streamlit deploy app_dev --replace --prune -x
  env:
    SNOWFLAKE_ACCOUNT: ${{ secrets.SNOWFLAKE_ACCOUNT }}
    SNOWFLAKE_USER: ${{ secrets.SNOWFLAKE_USER }}

-x(--temporary-connection)は、config.tomlの接続定義を使わず環境変数で接続する指定です。
GitHub Actionsのように設定ファイルを持たない環境では、このオプションを付ける必要があります。

環境ごとのデプロイ先はsnowflake.ymlで定義します。
同じデータベース内でスキーマを分離し、app_devdevスキーマへ、app_prodprodスキーマへデプロイされます。

# snowflake.yml
definition_version: '2'
entities:
  # DEV environment
  app_dev:
    type: streamlit
    identifier:
      name: my_app
      database: my_db
      schema: dev
    main_file: app.py
    pages_dir: pages
    query_warehouse: my_wh
    artifacts:
      - app.py
      - environment.yml
      - pages

  # PROD environment
  app_prod:
    type: streamlit
    identifier:
      name: my_app
      database: my_db
      schema: prod
    main_file: app.py
    pages_dir: pages
    query_warehouse: my_wh
    artifacts:
      - app.py
      - environment.yml
      - pages

5.おわりに

SiSのCI/CDは、GitHub Actions+Snowflake CLI+ OIDCの組み合わせで十分に構築できます。
Snowflake CLI Actionuse-oidc: trueオプションにより、シークレットレスなデプロイが数行の設定で実現できるようになりました。

最初のセットアップ、特に OIDCのWorkload Identity Userの作成にはやや手間がかかりますが、一度構築すれば運用はほぼ自動化されます。
ランニングコストもGitHub Actions の無料枠(月2,000分)で十分まかなえるため、コストが導入の障壁になることもありません。
SiSアプリの規模が小さいうちからCI/CDを整備しておくと、チームが拡大したときにもスムーズに対応できます。

SnowflakeやSiSを活用したデータ基盤の構築・運用にご興味がありましたら、ぜひシステムエグゼへお気軽にお問い合わせください。

6.参考リンク

コラム検索

連載タイトル

DOWNLOAD

資料ダウンロード

CONTACT

お問い合わせ