These actions allow you to safely deploy database schema changes to your databases using Redgate Flyway. Supports 50+ databases including PostgreSQL, MySQL, SQL Server, and Oracle.
These actions can be used both for database deployment pipelines, and for validation of your PRs.
| Action | Description |
|---|---|
setup-flyway |
Install Flyway CLI in your GitHub Actions workflow |
migrations/checks |
Run pre-deployment checks on migrations and target database |
migrations/deploy |
Deploy pending migrations against target database |
migrations/undo |
Undo migrations on target database |
state/prepare |
Generate deployment script and run pre-deployment checks |
state/deploy |
Deploy state-based changes to target database |
name: Deploy to test
on:
push:
branches: [main]
jobs:
automated-deploy:
runs-on: ubuntu-latest
environment: test
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Flyway
uses: red-gate/setup-flyway@v3
with:
edition: enterprise
i-agree-to-the-eula: true
email: "${{ secrets.FLYWAY_EMAIL }}"
token: "${{ secrets.FLYWAY_TOKEN }}"
- name: Run deployment checks and generate reports
uses: red-gate/flyway-actions/migrations/checks@v2
with:
target-environment: test
target-user: "${{ secrets.FLYWAY_USER }}"
target-password: "${{ secrets.FLYWAY_PASSWORD }}"
build-environment: build
build-user: "${{ secrets.FLYWAY_BUILD_USER }}"
build-password: "${{ secrets.FLYWAY_BUILD_PASSWORD }}"
working-directory: my-flyway-project
- name: Run migrations deployment
uses: red-gate/flyway-actions/migrations/deploy@v2
with:
target-environment: test
target-user: "${{ secrets.FLYWAY_USER }}"
target-password: "${{ secrets.FLYWAY_PASSWORD }}"
working-directory: my-flyway-projectSplit checks and deployment into separate jobs and use a GitHub environment with required reviewers on the 'deploy' job. The deployment will pause until a reviewer approves it.
name: Deploy to production
on:
push:
branches: [main]
jobs:
checks:
runs-on: ubuntu-latest
environment: production-read-only
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Flyway
uses: red-gate/setup-flyway@v3
with:
edition: enterprise
i-agree-to-the-eula: true
email: "${{ secrets.FLYWAY_EMAIL }}"
token: "${{ secrets.FLYWAY_TOKEN }}"
- name: Run checks
uses: red-gate/flyway-actions/migrations/checks@v2
with:
target-environment: production
target-user: "${{ secrets.FLYWAY_USER }}"
target-password: "${{ secrets.FLYWAY_PASSWORD }}"
build-environment: build
build-user: "${{ secrets.FLYWAY_BUILD_USER }}"
build-password: "${{ secrets.FLYWAY_BUILD_PASSWORD }}"
working-directory: my-flyway-project
deploy:
needs: checks
runs-on: ubuntu-latest
environment: production-write # requires reviewer approval before running
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Flyway
uses: red-gate/setup-flyway@v3
with:
edition: enterprise
i-agree-to-the-eula: true
email: "${{ secrets.FLYWAY_EMAIL }}"
token: "${{ secrets.FLYWAY_TOKEN }}"
- name: Run migrations deployment
uses: red-gate/flyway-actions/migrations/deploy@v2
with:
target-environment: production
target-user: "${{ secrets.FLYWAY_USER }}"
target-password: "${{ secrets.FLYWAY_PASSWORD }}"
working-directory: my-flyway-projectThe manual review workflow uses two GitHub environments to separate read-only checks from write access deployment:
-
production-read-only— used by thechecksjob. Go to Settings > Environments > New environment, name itproduction-read-only, and add the following secrets:FLYWAY_USER,FLYWAY_PASSWORD— database credentials with read-only access to the production databaseFLYWAY_BUILD_USER,FLYWAY_BUILD_PASSWORD— credentials for the build database
This environment does not need protection rules since it only performs read-only checks. Using a read-only database user here ensures the checks job cannot modify production data.
-
production-write— used by thedeployjob. Create a second environment namedproduction-writeand add the following secrets:FLYWAY_USER,FLYWAY_PASSWORD— database credentials with write access to the production database
Under Protection rules, enable Required reviewers and add the team members who should approve deployments. You can also restrict which branches can deploy by enabling Deployment branches and tags and limiting it to
main.
The deploy job will wait for reviewer approval after the checks job passes, giving reviewers a chance to inspect the check results and uploaded report before the migration runs.
State-based deployments use state/prepare to generate a deployment script by comparing your schema model against the target database, then state/deploy to apply it. This approach is ideal when you manage your database schema as a set of object definitions rather than ordered migration files.
name: Deploy to production
on:
push:
branches: [main]
jobs:
automated-deploy:
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Flyway
uses: red-gate/setup-flyway@v3
with:
edition: enterprise
i-agree-to-the-eula: true
email: "${{ secrets.FLYWAY_EMAIL }}"
token: "${{ secrets.FLYWAY_TOKEN }}"
- name: Prepare deployment script
uses: red-gate/flyway-actions/state/prepare@v2
with:
target-environment: production
target-user: "${{ secrets.FLYWAY_USER }}"
target-password: "${{ secrets.FLYWAY_PASSWORD }}"
working-directory: my-flyway-project
- name: Deploy changes
uses: red-gate/flyway-actions/state/deploy@v2
with:
target-environment: production
target-user: "${{ secrets.FLYWAY_USER }}"
target-password: "${{ secrets.FLYWAY_PASSWORD }}"
working-directory: my-flyway-projectSplit the prepare and deploy steps into separate jobs. Use a GitHub environment with required reviewers on the deploy job so a reviewer can inspect the pre-deployment report and generated deployment script before approving.
name: Deploy to production
on:
push:
branches: [main]
jobs:
prepare:
runs-on: ubuntu-latest
environment: production-read-only
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Flyway
uses: red-gate/setup-flyway@v3
with:
edition: enterprise
i-agree-to-the-eula: true
email: "${{ secrets.FLYWAY_EMAIL }}"
token: "${{ secrets.FLYWAY_TOKEN }}"
- name: Prepare deployment script
uses: red-gate/flyway-actions/state/prepare@v2
with:
target-environment: production
target-user: "${{ secrets.FLYWAY_USER }}"
target-password: "${{ secrets.FLYWAY_PASSWORD }}"
working-directory: my-flyway-project
deploy:
needs: prepare
runs-on: ubuntu-latest
environment: production-write # requires reviewer approval before running
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Flyway
uses: red-gate/setup-flyway@v3
with:
edition: enterprise
i-agree-to-the-eula: true
email: "${{ secrets.FLYWAY_EMAIL }}"
token: "${{ secrets.FLYWAY_TOKEN }}"
- name: Deploy changes
uses: red-gate/flyway-actions/state/deploy@v2
with:
target-environment: production
target-user: "${{ secrets.FLYWAY_USER }}"
target-password: "${{ secrets.FLYWAY_PASSWORD }}"
working-directory: my-flyway-projectThe environment setup is the same as described in Setting up the environments above. The prepare job runs drift detection, code review, and generates reports and the deployment script — all using read-only access. Reviewers can inspect the uploaded pre-deployment report and deployment script artifacts before approving the deploy job.
name: Deploy to production
on:
push:
branches: [ main ]
jobs:
automated-deploy:
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Flyway
uses: red-gate/setup-flyway@v3
with:
edition: community
i-agree-to-the-eula: true
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install SQLFluff
run: pip install sqlfluff
- name: Run checks
uses: red-gate/flyway-actions/migrations/checks@v2
with:
target-environment: production
target-user: "${{ secrets.FLYWAY_USER }}"
target-password: "${{ secrets.FLYWAY_PASSWORD }}"
working-directory: my-flyway-project
- name: Run migrations deployment
uses: red-gate/flyway-actions/migrations/deploy@v2
with:
target-environment: production
target-user: "${{ secrets.FLYWAY_USER }}"
target-password: "${{ secrets.FLYWAY_PASSWORD }}"
working-directory: my-flyway-projectGitHub Actions secrets keep sensitive values like database credentials and license tokens out of your workflow files and logs.
- Use repository or organization secrets — navigate to Settings > Secrets and variables > Actions to add secrets. Organization-level secrets can be shared across repositories.
- Use environment secrets for sensitive targets — for production databases, store credentials under a GitHub environment (e.g.
production). This scopes secrets to that environment and enables protection rules like required reviewers. - Never hardcode credentials — keep database URLs, usernames, passwords, and Flyway license tokens in secrets rather than in workflow files,
flyway.toml, or source code. - Rotate secrets regularly — update secrets when team members leave or if a credential may have been exposed.
Reference secrets using the ${{ secrets.SECRET_NAME }} syntax:
- name: Run migrations deployment
uses: red-gate/flyway-actions/migrations/deploy@v2
with:
target-environment: production
target-user: "${{ secrets.FLYWAY_USER }}"
target-password: "${{ secrets.FLYWAY_PASSWORD }}"- Secrets are masked in logs — GitHub automatically redacts secret values from workflow output, but avoid echoing or writing them to files.
- Limit secret scope with environments — attach secrets to environments that have protection rules (e.g. required reviewers, branch restrictions) to control who can trigger deployments that use those secrets.
- Pass secrets explicitly — GitHub does not inject secrets automatically. Each step that needs a secret must reference it via
withorenv.
The scripts and documentation in this project are released under the MIT License.
Contributions are welcome! See Code of Conduct
See Breaking Changes for a list of breaking changes.
Find a security issue? Please review our Security Policy.
For support, please see the Support Policy.