Skip to content

Commit

Permalink
feat: add alembic
Browse files Browse the repository at this point in the history
  • Loading branch information
osoken committed Feb 22, 2025
1 parent 713e44f commit 8736b75
Show file tree
Hide file tree
Showing 7 changed files with 464 additions and 9 deletions.
42 changes: 42 additions & 0 deletions migrate/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,44 @@

# BirdXplorer Migrations

## Alembic によるマイグレーション

### 前提条件

- `birdxplorer_common` のインストールが完了していること
- `birdxplorer_migration` のインストールが完了していること
- `.env` ファイルに `BX_STORAGE_SETTINGS__PASSWORD` が設定されていること
- DB のデフォルトホスト名 `db` が解決できない場合は `BX_STORAGE_SETTINGS__HOST` も設定すること

### 現在のマイグレーションを適用する

データベースのスキーマを最新の状態にします。

`alembic.ini` があるディレクトリの場合:

```bash
alembic upgrade head
```

`alembic.ini` が別の場所にある場合:

```bash
alembic upgrade head -c /path/to/alembic.ini
```

### 新しいマイグレーションを作成する

データベースのスキーマを変更した場合、以下の手順で新しいマイグレーションを作成します。

`alembic.ini` があるディレクトリの場合:

```bash
alembic revision --autogenerate -m "マイグレーションの説明"
```

`alembic.ini` が別の場所にある場合:

```bash
alembic revision --autogenerate -m "マイグレーションの説明" -c /path/to/alembic.ini
```

36 changes: 36 additions & 0 deletions migrate/alembic.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[alembic]
script_location = %(here)s/migration

[loggers]
keys = root,sqlalchemy,alembic

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = WARNING
handlers = console
qualname =

[logger_sqlalchemy]
level = WARNING
handlers =
qualname = sqlalchemy.engine

[logger_alembic]
level = INFO
handlers =
qualname = alembic

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
2 changes: 1 addition & 1 deletion migrate/birdxplorer_migration/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.0.1"
__version__ = "0.1.0"
80 changes: 80 additions & 0 deletions migrate/migration/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import os
from logging.config import fileConfig

from alembic import context
from dotenv import load_dotenv

from birdxplorer_common.settings import GlobalSettings
from birdxplorer_common.storage import Base, gen_storage

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

# Interpret the config file for Python logging.
# This line sets up loggers basically.
if config.config_file_name is not None:
fileConfig(config.config_file_name)

work_dir = os.path.dirname(os.path.abspath(__file__))
env_file = os.path.join(os.path.dirname(os.path.dirname(work_dir)), ".env")
load_dotenv(env_file)
bx_settings = GlobalSettings()

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = Base.metadata

# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.


def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
url = bx_settings.storage_settings.sqlalchemy_database_url
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)

with context.begin_transaction():
context.run_migrations()


def run_migrations_online() -> None:
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""
storage = gen_storage(settings=bx_settings)
connectable = storage.engine

with connectable.connect() as connection:
context.configure(connection=connection, target_metadata=target_metadata)

with context.begin_transaction():
context.run_migrations()


if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
26 changes: 26 additions & 0 deletions migrate/migration/script.py.mako
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""${message}

Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
${imports if imports else ""}

# revision identifiers, used by Alembic.
revision: str = ${repr(up_revision)}
down_revision: Union[str, None] = ${repr(down_revision)}
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}


def upgrade() -> None:
${upgrades if upgrades else "pass"}


def downgrade() -> None:
${downgrades if downgrades else "pass"}
Loading

0 comments on commit 8736b75

Please sign in to comment.