❄️

Snowflake CLIを利用したStreamlit in Snowflakeアプリの開発、GitHub Actionsを用いたCICD

2024/05/20に公開

はじめに

Streamlit in Snowflake(以下 SiS)は、Snowflake 上で Streamlit アプリを実行するための機能です。インフラ管理などなく、気軽に Streamlit アプリを Snowflake 上で実行できるため、非常に便利な機能です。
ただ、現在では Git 統合、CI/CD のサポートが不十分[1]で、アプリのデプロイが煩雑でした。実際私はSnowpark APIを利用して、stage に upload する Python コードをカスタムで書いてました。

一方、Snowflake CLI が Public Preview になり、CLI で Snowflake 上で実行されるアプリを作成、管理、更新、表示できるようになりました。
この Snowflake CLI を利用することで、SiS アプリを簡単にデプロイできるようになりました。
こちらの記事では、Snowflake CLI を利用して SiS アプリを開発、また、GitHub Actions を用いてデプロイする方法を紹介します。

ディレクトリ構成

.
├── README.md
├── Makefile
├── pyproject.toml
├── poetry.lock
├── apps
│   ├── example_streamlit
│   │   ├── .snowflake
│   │   │   ├── config_ci.json
│   │   │   └── config.json
│   │   ├── common
│   │   │   └── hello.py
│   │   ├── environment.yml
│   │   ├── snowflake.yml
│   │   └── streamlit_app.py
│   └── app2
└── .github
    └── workflows
        ├── CI.yml
        ├── CD_example_streamlit.yml
        └── CD_workflow_base.yml

このリポジトリでは、appsディレクトリに SiS アプリを格納しています。example_streamlitディレクトリには、SiS アプリの設定ファイルや Streamlit アプリのコードが格納されています。app2ディレクトリには、別の SiS アプリが格納されています。

サンプルの Streamlit のアプリコードは以下の通りです。

apps/example_streamlit/streamlit_app.py
import streamlit as st
from common.hello import say_hello

st.title(f"Example streamlit app. {say_hello()}")
apps/example_streamlit/common/hello.py
def say_hello():
    return "Hello, World!"

SiSアプリの設定ファイル

SiS アプリの設定ファイルは、snowflake.ymlenvironment.yml の 2 つです。snowflake.ymlは、SiS アプリの設定を記述するファイルで、environment.ymlは、SiS アプリの実行に必要なライブラリを記述するファイルです。

snowflake.yml
definition_version: 1
streamlit:
  name: example_streamlit
  stage: STAGE_NAME
  query_warehouse: WAREHOUSE_NAME
  main_file: streamlit_app.py
  env_file: environment.yml
  additional_source_files:
    - common/hello.py
  # 今回はシングルページアプリなので、以下の設定は不要
  # pages_dir: pages/
environment.yml
name: sf_env
channels:
  - snowflake
dependencies:
  - pandas # ここに必要なライブラリを記述

Snowflake認証情報の設定

Snowflake CLI を利用するためには、Snowflake 認証情報を設定する必要があります。認証情報は、config.tomlconfig_ci.toml の 2 つのファイルに記述します。

config.toml
default_connection_name = "snowflake"
[connections]
[connections.snowflake]
account = "ACCOUNT_NAME"
user = "USER_NAME"
role = "ROLE_NAME"
database = "DATABASE_NAME"
schema = "SCHEMA_NAME"
warehouse = "WAREHOUSE_NAME"
authenticator = "SNOWFLAKE_JWT"
private_key_path = "path/to/private_key"

以下は CI/CD 用の設定ファイルの例です。

config_ci.toml
default_connection_name = "snowflake"
[connections]
[connections.snowflake]
account = "ACCOUNT_NAME"
role = "ROLE_NAME"
database = "DATABASE_NAME"
schema = "SCHEMA_NAME"
warehouse = "WAREHOUSE_NAME"

local Python環境の設定

local で SiS アプリを実行するために、Python 環境を設定します。ここでは、Poetryを利用して Python 環境を構築します。

poetry add snowflake-connector-python==${SNOWFLAKE_CONNECTOR_PYTHON} streamlit==${STREAMLIT_VERSION}
poetry add --group dev black isort flake8 mypy snowflake-cli-labs

ついでに、Makefileの設定をします。

init:
	poetry install
	poetry run pre-commit install
	
new_streamlit_app: __require_streamlit_app_name__
	cp -r apps/example_streamlit apps/${STREAMLIT_APP_NAME}
	cd apps/${STREAMLIT_APP_NAME}

format:
	poetry run isort apps/
	poetry run black apps/

lint:
	poetry run flake8 apps/
	poetry run black --check apps/
	poetry run isort --check-only apps/
	poetry run mypy apps/

run_streamlit: __require_streamlit_app_name__
	cd apps/${STREAMLIT_APP_NAME} && \
		poetry run streamlit run streamlit_app.py

deploy_streamlit: __require_streamlit_app_name__
	cd apps/${STREAMLIT_APP_NAME} && \
		poetry run snow --config-file .snowflake/config.toml \
			streamlit deploy --replace

deploy_streamlit_ci: __require_streamlit_app_name__
	cd apps/${STREAMLIT_APP_NAME} && \
		poetry run snow --config-file .snowflake/config_ci.toml \
			streamlit deploy --replace

__require_streamlit_app_name__:
	@[ -n "$(STREAMLIT_APP_NAME)" ] || (echo "[ERROR] Parameter [STREAMLIT_APP_NAME] is requierd" 1>&2 && echo "(e.g) make xxx STREAMLIT_APP_NAME=hoge" 1>&2 && exit 1)

これで

  • make initで Python 環境を構築
  • make new_streamlit_app STREAMLIT_APP_NAME=example_streamlitで新しい SiS アプリを作成
  • make formatでコードフォーマット
  • make lintでコードの Lint
  • make run_streamlit STREAMLIT_APP_NAME=example_streamlitでローカルで SiS アプリを実行
  • make deploy_streamlit STREAMLIT_APP_NAME=example_streamlitで SiS アプリをデプロイ

ができるようになります。

GitHub Actionsを利用したCI/CD

GitHub Actions を利用して、SiS アプリの CI/CD を行います。

以下は、CI の設定ファイルです。こちらで GitHub 上で PR が作成されたときに、かつ、appsディレクトリ以下のファイルが変更された場合に、Lint を行います。

.github/workflows/CI.yml
name: CI
on:
  pull_request:
    types: [opened, synchronize]
    paths:
      - "apps/**"
    branches:
      - master
jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v4
      - name: Set up Python
        # This is the version of the action for setting up Python, not the Python version.
        uses: actions/setup-python@v5
        with:
          # Semantic version range syntax or exact version of a Python version
          python-version: '3.11'
      - name: Install poetry
        run: |
          curl -sSL https://install.python-poetry.org | python - --version 1.8.2
          echo "$HOME/.poetry/bin" >> $GITHUB_PATH
      - name: Poetry Version
        run: |
          poetry --version
      - name: Poetry Install Dependencies
        run: |
          poetry install
      - name: lint
        run: make lint

以下は、SiS アプリをデプロイするための GitHub Actions の設定ファイルです。

.github/workflows/CD_workflow_base.yml
name: Streamlit in Snowflake deploy base
on:
  workflow_call:
    inputs:
      streamlit_app_name:
        required: true
        type: string
    secrets:
      SNOWFLAKE_USER:
        required: true
        description: "Snowflake user name"
      SNOWFLAKE_PASSWORD:
        required: true
        description: "Snowflake password"
jobs:
  streamlit_deploy:
    name: SiS Deploy
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      pull-requests: write
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v4
      - name: Set up Python
        # This is the version of the action for setting up Python, not the Python version.
        uses: actions/setup-python@v5
        with:
          # Semantic version range syntax or exact version of a Python version
          python-version: '3.11'
      - name: Install poetry
        run: |
          curl -sSL https://install.python-poetry.org | python - --version 1.8.2
          echo "$HOME/.poetry/bin" >> $GITHUB_PATH
      - name: Poetry Version
        run: |
          poetry --version
      - name: Poetry Install Dependencies
        run: |
          poetry install
      - name: lint
        run: make lint
      - name: deploy Sis App
        env:
          SNOWFLAKE_USER: ${{ secrets.SNOWFLAKE_USER }}
          SNOWFLAKE_PASSWORD: ${{ secrets.SNOWFLAKE_PASSWORD }}
        run: |
          make deploy_streamlit_ci STREAMLIT_APP_NAME=${{ inputs.streamlit_app_name }}

以下は、example_streamlitアプリをデプロイするための設定ファイルです。

.github/workflows/CD_example_streamlit.yml
name: Deploy example_streamlit app
on:
  push:
    branches:
      - master
    paths:
      - 'apps/example_streamlit/**'
jobs:
  call_CD_workflow:
    uses: ./.github/workflows/CD_workflow_base.yml
    permissions:
      id-token: write
      contents: read
      pull-requests: write
    with:
      streamlit_app_name: example_streamlit
    secrets:
      SNOWFLAKE_USER: ${{ secrets.SNOWFLAKE_USER }}
      SNOWFLAKE_PASSWORD: ${{ secrets.SNOWFLAKE_PASSWORD }}

これで、PR がマージされたときに、example_streamlitアプリがデプロイされるようになります🎉

SnowflakeにデプロイされたStreamlitアプリ

おわりに

Snowflake CLI を利用することで、SiS アプリの開発、デプロイが簡単になりました。また、GitHub Actions を利用することで、CI/CD も簡単に設定できるようになりました。SiS アプリをチームで開発していく、そして設定を安全に管理していくのに便利なのでぜひお試しください!

参考文献

脚注
  1. 制限とサポートされていない機能 | Snowflake Documentation ↩︎

GitHubで編集を提案

Discussion