概要
Streamlit in SnowflakeをGitで管理したい!
今回はSnowflake CLIを使って実装しました。
使ったもの
- Azure DevOps Repos/Pipelines
- Managed DevOps Pool(DevOpsエージェント)
- Snowflake CLI 3.6.0
Azure DevOpsでSnowflakeCLIを手軽に利用できる拡張機能が開発されていますが、2025/4/4現在鋭意開発中の機能ということで採用を見送りました。
デプロイパイプライン作成
YAMLを使ってパイプラインを作成しました。
Snowflake CLIはpipを使ってインストールしています。
(あまり推奨されていませんが、楽なのでつい……)
# cicd-pipeline.yaml
trigger:
- main
pool:
name: MDP
demands:
- ImageOverride -equals ubuntu-latest
variables:
- group: 'main'
stages:
- stage: Checkout_Repository
jobs:
- job: Checkout
displayName: 'Checkout Repository'
steps:
- checkout: self
displayName: 'Checkout repo'
clean: true
- stage: Deploy
jobs:
- job: Deploy
steps:
- task: DownloadSecureFile@1
inputs:
secureFile: 'rsa_key.p8'
displayName: 'Download Private_key for snowflake authentication'
- task: UsePythonVersion@0
inputs:
versionSpec: '3.11'
- script: python -m pip install --upgrade pip setuptools wheel
displayName: 'Install tools'
- script: pip install snowflake-cli
displayName: 'Install snowflake-cli'
- script: |
snow streamlit deploy --replace --project $(Build.SourcesDirectory) \
--account '$(account)' \
--user '$(user)' \
--authenticator 'SNOWFLAKE_JWT' \
--private-key-file '$(Agent.TempDirectory)/rsa_key.p8' \
--database '$(database)' \
--schema '$(schema)' \
--role '$(role)' \
--warehouse '$(warehouse)' \
--temporary-connection
displayName: 'Deploy Streamlit App'
SnowflakeのシステムユーザーはキーペアやSSOなどの認証が必要となっています。
今回はキーペア認証を採用しました。
秘密鍵はAzure DevOpsの機能であるセキュアファイルに格納しています。
ゆくゆくはプルリクのトリガーに併せて、デプロイ先を検証環境と本番環境を切り替えられるようにするためです。
リポジトリ構成
streamlit_project
├── common/
│ └── utils.py
├── page-sec1/
│ └── page1-1.py
├── page-sec2/
│ ├── page2-1.py
│ ├── page2-2.py
│ └── page2-3.py
├── .gitignore
├── cicd-pipeline.yml
├── environment.yml
├── main.py
└── snowflake.yml
今回作成したのはcicd-pipeline.ymlです。
他のファイルも簡単に説明を書きます。
- commonディレクトリ
Pyhonのモジュールです。複数ページで使用する汎用処理を入れておきます。 - page-secディレクトリ
ページを使用用途ごとに分けています。 - environment.yml
必要なPythonのモジュールなどを記載しています
# environment.yml
name: sf_env
channels:
- snowflake
dependencies:
- streamlit
- snowflake-snowpark-python
- pandas
- plotly
- main.py
アプリのエントリポイントです。
#main.py
import streamlit as st
#######################
# ページ設定
#######################
page1_1 = st.Page("./page-sec1/page1-1.py", title="test1-1", icon=":material/deployed_code_alert:")
page2_1 = st.Page("./page-sec2/page2-1.py", title="test2-1", icon=":material/dataset:")
page2_2 = st.Page("./page-sec2/page2-2.py", title="test2-2", icon=":material/dataset:")
page2_3 = st.Page("./page-sec2/page2-3.py", title="test2-3", icon=":material/dataset:")
pg = st.navigation(
{
"入力フォーム": [page1_1],
"データ確認": [page2_1, page2_2, page2_3]
}
)
def main ():
pg.run()
###################################
if __name__ == "__main__":
main()
- snowflake.yml
アプリの定義ファイルです。ソースコードを置いておく内部ステージなどを指定します。
# snowflake.yml
definition_version: '2'
entities:
streamlit_project:
type: streamlit
identifier:
name: streamlit_project
schema: TEST
database: TEST
main_file: main.py
query_warehouse: XSMALL_WH
stage: CICD_TEST
artifacts:
- main.py
- environment.yml
- page-sec1/*
- page-sec2/*
- common/*
comment: 'CICD test'
DevOpsパイプラインを実行
以下のようなメッセージが出てデプロイできました。
Streamlit successfully deployed and available under https://...
Snowflake CLIを使うと内部ステージのデプロイからStreamlitアプリのデプロイが簡単に実行できます。
やり残していること
snow streamlit deploy
コマンドは毎回内部ステージにファイル一式をアップロードする工程があります。
ステージに同一名のファイルがある場合は上書き保存されますが、リポジトリから削除したファイルが自動で削除されるわけではありません。
リポジトリのファイル構成とステージのファイル構成の同期を取るには、少し工夫が必要だな~と思い先送りにしてます。。。