Skip to main content

alt-python-boot-flyway

Language Python License: MIT

Spring Boot-style CDI auto-configuration for Flyway-inspired database migrations. Registers a ManagedFlyway CDI bean that runs migrate() synchronously during init(), reading all configuration from boot.flyway.*.

Port of @alt-javascript/boot-flyway.

Part of the alt-python/boot monorepo.

Install

uv add alt-python-boot-flyway pydbc-sqlite

Requires Python 3.12+, alt-python-boot-pydbc, and alt-python-flyway.

Quick Start

# invoke.py
import os
os.chdir(os.path.dirname(os.path.abspath(__file__)))

import pydbc_sqlite  # registers the SQLite driver
from boot import Boot
from cdi import Context, Singleton
from boot_pydbc import pydbc_auto_configuration
from boot_flyway import flyway_starter
from services import NoteRepository, Application

Boot.boot({
    'contexts': [
        Context(pydbc_auto_configuration() + flyway_starter()),
        Context([Singleton(NoteRepository), Singleton(Application)]),
    ]
})
// config/application.json
{
  "boot": {
    "datasource": {
      "url": "pydbc:sqlite::memory:",
      "pool": { "enabled": true, "max": 2 }
    },
    "flyway": {
      "locations": "db/migration"
    }
  }
}

Boot loads config, creates the datasource, runs all pending Flyway migrations during CDI startup, then starts the application. By the time any repository bean's init() is called, the schema is fully applied and seeded.

What's Included

Class / Function Description
ManagedFlyway CDI bean that runs migrate() synchronously during init()
flyway_auto_configuration(prefix, datasource_bean) Returns a Singleton list for Context()
flyway_starter(prefix, datasource_bean) Alias for flyway_auto_configuration()
DEFAULT_FLYWAY_PREFIX 'boot.flyway'

Configuration

All properties live under boot.flyway by default. Override with prefix= to use a different key root.

Property Type Default Description
boot.flyway.enabled bool true Set to false to skip migration on start
boot.flyway.locations string db/migration Comma-separated migration file paths
boot.flyway.table string flyway_schema_history History table name
boot.flyway.baseline-on-migrate bool false Run baseline() if history is empty before migrating
boot.flyway.baseline-version string '1' Version to record in the baseline entry
boot.flyway.baseline-description string 'Flyway Baseline' Baseline entry description
boot.flyway.out-of-order bool false Allow applying migrations older than the latest applied
boot.flyway.validate-on-migrate bool true Validate checksums before migrating
boot.flyway.installed-by string 'flyway' User recorded in history

CDI Lifecycle

ManagedFlyway follows the standard CDI lifecycle:

  1. set_application_context(ctx) — CDI injects the application context.
  2. init() — reads config, creates a Flyway instance, calls migrate(). The schema is fully applied before init() returns.
  3. Downstream beans start after init() completes — repositories and services can query the database immediately.

Python vs JavaScript difference. The JS port (@alt-javascript/boot-flyway) stores the migration promise and exposes a ready() method because JS CDI does not await async init(). Python CDI is synchronous — migrate() completes inside init(), so no ready() call is needed.

Accessing the Flyway Instance

ManagedFlyway.get_flyway() returns the underlying Flyway instance for info(), validate(), repair(), and clean():

managed_flyway = ctx.get('managed_flyway')
flyway = managed_flyway.get_flyway()

# Check migration status
for m in flyway.info():
    print(m['version'], m['state'], m['description'])

# Validate checksums against files on disk
flyway.validate()

# Remove failed history entries
result = flyway.repair()
print(result['removed_entries'])

Multiple Datasources

To run Flyway migrations against two independent datasources, use DataSourceBuilder and two flyway_starter() calls with different prefixes and explicit CDI bean names.

# invoke.py
from boot import Boot
from cdi import Context, Singleton
from boot_pydbc import pydbc_auto_configuration, DataSourceBuilder
from boot_flyway import flyway_starter, ManagedFlyway

# Primary datasource — uses boot.datasource.* and boot.flyway.*
# Produces: data_source, pydbc_template, managed_flyway
notes_beans = pydbc_auto_configuration() + flyway_starter()

# Secondary datasource — uses boot.datasource-tags.* and boot.flyway-tags.*
# DataSourceBuilder produces beans named tags_data_source, tags_pydbc_template, etc.
tags_ds = (
    DataSourceBuilder.create()
    .prefix('boot.datasource-tags')
    .bean_names({
        'data_source': 'tags_data_source',
        'pydbc_template': 'tags_pydbc_template',
        'named_parameter_pydbc_template': 'tags_named_pydbc_template',
        'schema_initializer': 'tags_schema_initializer',
    })
    .without_schema_initializer()
    .build()
)

# flyway_starter for the tags DB — must use a unique CDI name
tags_flyway_raw = flyway_starter(
    prefix='boot.flyway-tags',
    datasource_bean='tags_data_source',
)
# Re-create with name='managed_flyway_tags' so it coexists with managed_flyway
tags_flyway = []
for comp in tags_flyway_raw:
    if comp.name == 'managed_flyway':
        tags_flyway.append(Singleton({
            'reference': comp.reference,
            'name': 'managed_flyway_tags',
            'depends_on': 'tags_data_source',
            'properties': [{'name': 'data_source', 'reference': 'tags_data_source'}],
        }))
    else:
        tags_flyway.append(comp)

Boot.boot({
    'contexts': [
        Context(notes_beans + tags_ds + tags_flyway),
        Context([Singleton(NoteRepository), Singleton(TagRepository), Singleton(Application)]),
    ]
})

Config:

{
  "boot": {
    "datasource": {
      "url": "pydbc:sqlite::memory:",
      "pool": { "enabled": true, "max": 2 }
    },
    "datasource-tags": {
      "url": "pydbc:sqlite::memory:",
      "pool": { "enabled": true, "max": 2 }
    },
    "flyway": {
      "locations": "db/notes-migration"
    },
    "flyway-tags": {
      "locations": "db/tags-migration"
    }
  }
}

See packages/example-5-4-persistence-flyway-multidb for a complete runnable example.

Running Tests

uv run pytest packages/boot-flyway -v

Troubleshooting

KeyError: 'managed_flyway' when two Flyway runners share a context Each flyway_starter() call produces a managed_flyway bean. The second one will clash with the first. Re-create the second starter's component with a distinct name (managed_flyway_tags, etc.) as shown in the multi-datasource example above.

Migrations run but the schema is missing when the repository queries it Check that ManagedFlyway is listed before your repository beans in the CDI context, or add depends_on='managed_flyway' to the repository component. CDI initialises beans in dependency order.

boot.flyway.enabled: false does not suppress migration The enabled key must be a boolean in the config file, not a string. Use "enabled": false (JSON) or enabled: false (YAML), not "enabled": "false".

License

MIT

Metadata

Release files for alt-python-boot-flyway 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for alt-python-boot-flyway 1.1.1
File Size Uploaded Provenance
alt_python_boot_flyway-1.1.1.tar.gz 6.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for alt-python-boot-flyway 1.1.1
File Interpreter ABI Platform
alt_python_boot_flyway-1.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 12.6 kB

Release files / alt_python_boot_flyway-1.1.1.tar.gz

Download URL alt_python_boot_flyway-1.1.1.tar.gz
Size 6.4 kB
Tags Source
SHA-256 checksum
How to use checksums
c6d9f469b1fb714a410f0fec1e76c7fbdee002edb7c97b4703083fd329aa2d86
BLAKE2b-256 checksum
How to use checksums
39a7dad5f661c391befffa71fa0d45da48f9ebd9bbe592eecb0822f696aba0f6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / alt_python_boot_flyway-1.1.1-py3-none-any.whl

Download URL alt_python_boot_flyway-1.1.1-py3-none-any.whl
Size 6.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
aad5658b9137ab755552acf1a1fa1dc6d3d766168380c64cc6e5036d5d79cacd
BLAKE2b-256 checksum
How to use checksums
3bde9ea6803c10125e6ed5ac2f1cbac0ed69b530a0d6828ca4411de93b0195c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for alt-python-boot-flyway 1.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page