├── .github └── workflows │ ├── build.yml │ ├── release.yml │ └── trigger-release.yml ├── .gitignore ├── .java-version ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── LICENSE ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml ├── renovate.json └── src ├── main └── java │ └── io │ └── dropwizard │ └── flyway │ ├── FlywayBundle.java │ ├── FlywayConfiguration.java │ ├── FlywayFactory.java │ └── cli │ ├── AbstractFlywayCommand.java │ ├── DbCleanCommand.java │ ├── DbCommand.java │ ├── DbInfoCommand.java │ ├── DbInitCommand.java │ ├── DbMigrateCommand.java │ ├── DbRepairCommand.java │ ├── DbValidateCommand.java │ └── NoOptionsFlywayCommand.java ├── site └── site.xml └── test └── java └── io └── dropwizard └── flyway ├── FlywayFactoryTest.java └── cli ├── AbstractCommandTest.java ├── DbMigrateCommandTest.java └── DbValidateCommandTest.java /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build 3 | # yamllint disable-line rule:truthy 4 | on: 5 | push: 6 | branches: 7 | - release/* 8 | pull_request: 9 | jobs: 10 | yamllint: 11 | uses: dropwizard/workflows/.github/workflows/yamllint.yml@main 12 | build: 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | java-version: ['17', '21'] 17 | uses: dropwizard/workflows/.github/workflows/maven.yml@main 18 | secrets: inherit 19 | with: 20 | java-version: ${{ matrix.java-version }} 21 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Release 3 | # yamllint disable-line rule:truthy 4 | on: 5 | push: 6 | tags: 7 | - dropwizard-flyway-* 8 | jobs: 9 | release: 10 | uses: dropwizard/workflows/.github/workflows/release.yml@main 11 | secrets: inherit 12 | -------------------------------------------------------------------------------- /.github/workflows/trigger-release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # yamllint disable rule:comments rule:line-length 3 | name: Trigger Release 4 | # yamllint disable-line rule:truthy 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | releaseVersion: 9 | description: Version of the next release 10 | required: true 11 | type: string 12 | developmentVersion: 13 | description: Version of the next development cycle (must end in "-SNAPSHOT") 14 | required: true 15 | type: string 16 | jobs: 17 | release: 18 | uses: dropwizard/workflows/.github/workflows/trigger-release.yml@main 19 | secrets: inherit 20 | with: 21 | releaseVersion: ${{ inputs.releaseVersion }} 22 | developmentVersion: ${{ inputs.developmentVersion }} 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | 3 | # IntelliJ IDEA 4 | *.iml 5 | *.ipr 6 | *.iws 7 | .idea/ 8 | out/ 9 | 10 | # Eclipse 11 | .settings/ 12 | .classpath 13 | .project 14 | -------------------------------------------------------------------------------- /.java-version: -------------------------------------------------------------------------------- 1 | 17 -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dropwizard/dropwizard-flyway/67092e080e4788cdd97547159bad2d3457517d9e/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2011 Coda Hale and Yammer, Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Dropwizard Flyway 2 | ================= 3 | 4 | [![Build](https://github.com/dropwizard/dropwizard-flyway/actions/workflows/build.yml/badge.svg)](https://github.com/dropwizard/dropwizard-flyway/actions/workflows/build.yml) 5 | [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=dropwizard_dropwizard-flyway&metric=alert_status)](https://sonarcloud.io/dashboard?id=dropwizard_dropwizard-flyway) 6 | [![Maven Central](https://img.shields.io/maven-central/v/io.dropwizard.modules/dropwizard-flyway.svg)](https://search.maven.org/artifact/io.dropwizard.modules/dropwizard-flyway) 7 | 8 | `dropwizard-flyway` is a set of commands using [Flyway](http://www.flywaydb.org/) for database migrations in [Dropwizard](http://dropwizard.io/) applications. 9 | 10 | 11 | Usage 12 | ----- 13 | 14 | Just add the `FlywayBundle` to your Dropwizard application inside the [`Application#initialize`](https://javadoc.io/static/io.dropwizard/dropwizard-core/4.0.0/io/dropwizard/core/Application.html#initialize(io.dropwizard.core.setup.Bootstrap) method. 15 | 16 | @Override 17 | public void initialize(Bootstrap bootstrap) { 18 | // ... 19 | bootstrap.addBundle(new FlywayBundle() { 20 | @Override 21 | public DataSourceFactory getDataSourceFactory(MyConfiguration configuration) { 22 | return configuration.getDataSourceFactory(); 23 | } 24 | 25 | @Override 26 | public FlywayFactory getFlywayFactory(MyConfiguration configuration) { 27 | return configuration.getFlywayFactory(); 28 | } 29 | }); 30 | } 31 | 32 | 33 | After that you can use one of the following Flyway commands: 34 | 35 | | Command | Description | 36 | | ------------- | ---------------------------------------------------------------------------- | 37 | | `db migrate` | Migrates the database | 38 | | `db clean` | Drops all objects in the configured schemas | 39 | | `db info` | Prints the details and status information about all the migrations | 40 | | `db validate` | Validates the applied migrations against the ones available on the classpath | 41 | | `db init` | Creates and initializes the metadata table (existing database) | 42 | | `db repair` | Repairs the metadata table | 43 | 44 | The [Flyway migrations](http://flywaydb.org/documentation/migration/) must be accessible in the classpath under `db/migration` (or any other path configured with the `locations` parameter, see [FlywayFactory](https://dropwizard.github.io/dropwizard-flyway/2.0.0-1/apidocs/io/dropwizard/flyway/FlywayFactory.html)). 45 | 46 | 47 | Configuration 48 | ------------- 49 | 50 | `dropwizard-flyway` is using the standard [DataSourceFactory](https://javadoc.io/static/io.dropwizard/dropwizard-db/4.0.0/io/dropwizard/db/DataSourceFactory.html) from [`dropwizard-db`](https://javadoc.io/doc/io.dropwizard/dropwizard-db/4.0.0/index.html) for configuring its [DataSource](http://docs.oracle.com/javase/8/docs/api/javax/sql/DataSource.html). 51 | 52 | Additionally, you can override the following configuration settings of Flyway using [FlywayFactory](https://dropwizard.github.io/dropwizard-flyway/2.0.0-1/apidocs/io/dropwizard/flyway/FlywayFactory.html): 53 | 54 | flyway: 55 | # The encoding of SQL migrations. (default: UTF-8) 56 | encoding: UTF-8 57 | 58 | # The maximum number of retries when attempting to connect to the database. (default: 0) 59 | connectRetries: 0 60 | 61 | # The maximum time between retries when attempting to connect to the database in seconds. (default: 120) 62 | connectRetriesInterval: 120 63 | 64 | # The default schema managed by Flyway. (default: the first schema listed in schemas) 65 | defaultSchema: 66 | 67 | # The schemas managed by Flyway. (default: default schema of the connection) 68 | schemas: 69 | 70 | # The fully qualified class names of the callbacks for lifecycle notifications. (default: empty list) 71 | callbacks: 72 | 73 | # The name of the schema metadata table that will be used by Flyway. (default: flyway_schema_history) 74 | metaDataTableName: flyway_schema_history 75 | 76 | # The file name prefix for sql migrations (default: V) 77 | sqlMigrationPrefix: V 78 | 79 | # The file name separator for sql migrations (default: __) 80 | sqlMigrationSeparator: __ 81 | 82 | # The file name suffixes for sql migrations (default: .sql) 83 | sqlMigrationSuffixes: 84 | - .sql 85 | 86 | # The prefix of every placeholder. (default: ${ ) 87 | placeholderPrefix: ${ 88 | 89 | # The suffix of every placeholder. (default: } ) 90 | placeholderSuffix: } 91 | 92 | # The map of to apply to sql migration scripts. (default: empty map) 93 | placeholders: 94 | 95 | # Locations to scan recursively for migrations. (default: db/migration) 96 | locations: 97 | - db/migration 98 | 99 | # The fully qualified class names of the custom MigrationResolvers to be used in addition to the built-in ones for resolving Migrations to apply. (default: empty list) 100 | resolvers: 101 | 102 | # Allows migrations to be run "out of order". If you already have versions 1 and 3 applied, and now a version 2 is found, it will be applied too instead of being ignored. (default: false) 103 | outOfOrder: false 104 | 105 | # The description to tag an existing schema with when executing baseline. (default: << Flyway Baseline >>) 106 | baselineDescription: "<< Flyway Baseline >>" 107 | 108 | # Whether to automatically call baseline when migrate is executed against a non-empty schema with no metadata table. (default: false) 109 | # Be careful when enabling this as it removes the safety net that ensures Flyway does not migrate the wrong database in case of a configuration mistake! 110 | baselineOnMigrate: false 111 | 112 | # Whether to automatically call validate or not when running migrate. (default: true) 113 | validateOnMigrate: true 114 | 115 | # The version to tag an existing schema with when executing baseline. (default: 1) 116 | baselineVersion: 1 117 | 118 | # Whether to disabled clean. (default: false) 119 | # This is especially useful for production environments where running clean can be quite a career limiting move. 120 | cleanDisabled: false 121 | 122 | # Whether to group all pending migrations together in the same transaction when applying them 123 | # (only recommended for databases with support for DDL transactions). 124 | # true if migrations should be grouped. false if they should be applied individually instead. (default: false) 125 | group: false 126 | 127 | # Ignore migrations that match this list of patterns when validating migrations. 128 | # Each pattern is of the form described type:status with * matching type or status. 129 | # Please refer to https://documentation.red-gate.com/fd/flyway-cli-and-api/configuration/parameters/flyway/ignore-migration-patterns for details. 130 | # Example: repeatable:missing,versioned:pending,*:failed (default: *:future) 131 | ignoreMigrationPatterns: 132 | - "*:future" 133 | 134 | # The username that will be recorded in the schema history table as having applied the migration. 135 | # <> for the current database user of the connection. (default: <>). 136 | installedBy: 137 | 138 | # Whether to allow mixing transactional and non-transactional statements within the same migration. 139 | # true if mixed migrations should be allowed. false if an error should be thrown instead. (default: false) 140 | mixed: false 141 | 142 | # Whether placeholders should be replaced. (default: true) 143 | placeholderReplacement: true 144 | 145 | # If set to true, default built-in callbacks (sql) are skipped and only custom callback as 146 | # defined by 'callbacks' are used. (default: false) 147 | skipDefaultCallbacks: false 148 | 149 | # If set to true, default built-in resolvers (jdbc, spring-jdbc and sql) are skipped and only custom resolvers as 150 | # defined by 'resolvers' are used. (default: false) 151 | skipDefaultResolvers: false 152 | 153 | # The map of to overwrite any existing configuration. (default: empty map) 154 | # Properties are documented here: https://documentation.red-gate.com/fd/parameters-224919673.html 155 | configuration: 156 | 157 | #### COMMERCIAL FEATURES 158 | # (Flyway Pro and Flyway Enterprise only) 159 | 160 | # Whether to batch SQL statements when executing them. (default: false) 161 | batch: false 162 | 163 | # The file where to output the SQL statements of a migration dry run. If the file specified is in a non-existent 164 | # directory, Flyway will create all directories and parent directories as needed. 165 | # <> to execute the SQL statements directly against the database. (default: <>) 166 | #dryRunOutputFile: 167 | 168 | # Comma-separated list of the fully qualified class names of handlers for errors and warnings that occur during a 169 | # migration. This can be used to customize Flyway's behavior by for example throwing another runtime exception, 170 | # outputting a warning or suppressing the error instead of throwing a FlywayException. 171 | # ErrorHandlers are invoked in order until one reports to have successfully handled the errors or warnings. 172 | # If none do, or if none are present, Flyway falls back to its default handling of errors and warnings. 173 | # <> to use the default internal handler (default: <>) 174 | #errorHandlers: 175 | 176 | # Rules for the built-in error handler that lets you override specific SQL states and errors codes from error to 177 | # warning or from warning to error. 178 | # Each error override has the following format: STATE:12345:W. It is a 5 character SQL state, a colon, the SQL 179 | # error code, a colon and finally the desired behavior that should override the initial one. The following 180 | # behaviors are accepted: W to force a warning and E to force an error. 181 | # For example, to force Oracle stored procedure compilation issues to produce errors instead of warnings, 182 | # the following errorOverride can be used: 99999:17110:E 183 | #errorOverrides: 184 | 185 | # Whether to stream SQL migrations when executing them. (default: false) 186 | stream: false 187 | 188 | # Target version up to which Flyway should consider migrations. 189 | # The special value 'current' designates the current version of the schema. (default: <>) 190 | #target: 191 | 192 | 193 | Maven Artifacts 194 | --------------- 195 | 196 | ![dropwizard-flyway 2.1.x](https://img.shields.io/maven-central/v/io.dropwizard.modules/dropwizard-flyway/2.1) 197 | ![dropwizard-flyway 3.0.x](https://img.shields.io/maven-central/v/io.dropwizard.modules/dropwizard-flyway/3.0) 198 | ![dropwizard-flyway 4.0.x](https://img.shields.io/maven-central/v/io.dropwizard.modules/dropwizard-flyway/4.0) 199 | 200 | This project is available on Maven Central. To add it to your project simply add the following dependencies to your `pom.xml`: 201 | 202 | 203 | io.dropwizard.modules 204 | dropwizard-flyway 205 | ${dropwizard-flyway.version} 206 | 207 | 208 | Please note that you will need to add the respective Flyway database support artifacts and configure them via the `flyway.configuration` map. 209 | 210 | Example: 211 | 212 | Add Flyway PostgreSQL dependency to your POM: 213 | 214 | 215 | org.flywaydb 216 | flyway-database-postgresql 217 | ${flyway.version} 218 | 219 | 220 | Add the configuration setting to your `flyway.configuration` block: 221 | 222 | flyway: 223 | configuration: 224 | # PostgreSQL Transactional Lock, see https://documentation.red-gate.com/fd/postgresql-transactional-lock-224919738.html 225 | flyway.postgresql.transactional.lock: false 226 | 227 | Support 228 | ------- 229 | 230 | Please file bug reports and feature requests in [GitHub issues](https://github.com/dropwizard/dropwizard-flyway/issues). 231 | 232 | 233 | License 234 | ------- 235 | 236 | Copyright (c) 2014-2024 Jochen Schalanda, Dropwizard Team 237 | 238 | This library is licensed under the Apache License, Version 2.0. 239 | 240 | See http://www.apache.org/licenses/LICENSE-2.0.html or the LICENSE file in this repository for the full license text. 241 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # 58 | # Look for the Apple JDKs first to preserve the existing behaviour, and then look 59 | # for the new JDKs provided by Oracle. 60 | # 61 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then 62 | # 63 | # Apple JDKs 64 | # 65 | export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home 66 | fi 67 | 68 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then 69 | # 70 | # Apple JDKs 71 | # 72 | export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 73 | fi 74 | 75 | if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then 76 | # 77 | # Oracle JDKs 78 | # 79 | export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 80 | fi 81 | 82 | if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then 83 | # 84 | # Apple JDKs 85 | # 86 | export JAVA_HOME=`/usr/libexec/java_home` 87 | fi 88 | ;; 89 | esac 90 | 91 | if [ -z "$JAVA_HOME" ] ; then 92 | if [ -r /etc/gentoo-release ] ; then 93 | JAVA_HOME=`java-config --jre-home` 94 | fi 95 | fi 96 | 97 | if [ -z "$M2_HOME" ] ; then 98 | ## resolve links - $0 may be a link to maven's home 99 | PRG="$0" 100 | 101 | # need this for relative symlinks 102 | while [ -h "$PRG" ] ; do 103 | ls=`ls -ld "$PRG"` 104 | link=`expr "$ls" : '.*-> \(.*\)$'` 105 | if expr "$link" : '/.*' > /dev/null; then 106 | PRG="$link" 107 | else 108 | PRG="`dirname "$PRG"`/$link" 109 | fi 110 | done 111 | 112 | saveddir=`pwd` 113 | 114 | M2_HOME=`dirname "$PRG"`/.. 115 | 116 | # make it fully qualified 117 | M2_HOME=`cd "$M2_HOME" && pwd` 118 | 119 | cd "$saveddir" 120 | # echo Using m2 at $M2_HOME 121 | fi 122 | 123 | # For Cygwin, ensure paths are in UNIX format before anything is touched 124 | if $cygwin ; then 125 | [ -n "$M2_HOME" ] && 126 | M2_HOME=`cygpath --unix "$M2_HOME"` 127 | [ -n "$JAVA_HOME" ] && 128 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 129 | [ -n "$CLASSPATH" ] && 130 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 131 | fi 132 | 133 | # For Migwn, ensure paths are in UNIX format before anything is touched 134 | if $mingw ; then 135 | [ -n "$M2_HOME" ] && 136 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 137 | [ -n "$JAVA_HOME" ] && 138 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 139 | # TODO classpath? 140 | fi 141 | 142 | if [ -z "$JAVA_HOME" ]; then 143 | javaExecutable="`which javac`" 144 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 145 | # readlink(1) is not available as standard on Solaris 10. 146 | readLink=`which readlink` 147 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 148 | if $darwin ; then 149 | javaHome="`dirname \"$javaExecutable\"`" 150 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 151 | else 152 | javaExecutable="`readlink -f \"$javaExecutable\"`" 153 | fi 154 | javaHome="`dirname \"$javaExecutable\"`" 155 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 156 | JAVA_HOME="$javaHome" 157 | export JAVA_HOME 158 | fi 159 | fi 160 | fi 161 | 162 | if [ -z "$JAVACMD" ] ; then 163 | if [ -n "$JAVA_HOME" ] ; then 164 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 165 | # IBM's JDK on AIX uses strange locations for the executables 166 | JAVACMD="$JAVA_HOME/jre/sh/java" 167 | else 168 | JAVACMD="$JAVA_HOME/bin/java" 169 | fi 170 | else 171 | JAVACMD="`which java`" 172 | fi 173 | fi 174 | 175 | if [ ! -x "$JAVACMD" ] ; then 176 | echo "Error: JAVA_HOME is not defined correctly." >&2 177 | echo " We cannot execute $JAVACMD" >&2 178 | exit 1 179 | fi 180 | 181 | if [ -z "$JAVA_HOME" ] ; then 182 | echo "Warning: JAVA_HOME environment variable is not set." 183 | fi 184 | 185 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 186 | 187 | # For Cygwin, switch paths to Windows format before running java 188 | if $cygwin; then 189 | [ -n "$M2_HOME" ] && 190 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 191 | [ -n "$JAVA_HOME" ] && 192 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 193 | [ -n "$CLASSPATH" ] && 194 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 195 | fi 196 | 197 | # traverses directory structure from process work directory to filesystem root 198 | # first directory with .mvn subdirectory is considered project base directory 199 | find_maven_basedir() { 200 | local basedir=$(pwd) 201 | local wdir=$(pwd) 202 | while [ "$wdir" != '/' ] ; do 203 | if [ -d "$wdir"/.mvn ] ; then 204 | basedir=$wdir 205 | break 206 | fi 207 | wdir=$(cd "$wdir/.."; pwd) 208 | done 209 | echo "${basedir}" 210 | } 211 | 212 | # concatenates all lines of a file 213 | concat_lines() { 214 | if [ -f "$1" ]; then 215 | echo "$(tr -s '\n' ' ' < "$1")" 216 | fi 217 | } 218 | 219 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} 220 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 221 | 222 | # Provide a "standardized" way to retrieve the CLI args that will 223 | # work with both Windows and non-Windows executions. 224 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 225 | export MAVEN_CMD_LINE_ARGS 226 | 227 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 228 | 229 | exec "$JAVACMD" \ 230 | $MAVEN_OPTS \ 231 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 232 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 233 | ${WRAPPER_LAUNCHER} $MAVEN_CMD_LINE_ARGS 234 | 235 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%MAVEN_CONFIG% %* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR=""%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% 146 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | io.dropwizard.modules 6 | module-parent 7 | 4.0.4 8 | 9 | dropwizard-flyway 10 | 4.0.1-3-SNAPSHOT 11 | jar 12 | 13 | Dropwizard Flyway Bundle 14 | Addon bundle for Dropwizard to support Flyway for database migrations 15 | 16 | 17 | 18 | dropwizard-flyway 19 | http://dropwizard.github.io/dropwizard-flyway/${project.version} 20 | 21 | 22 | 23 | 24 | 25 | j.schalanda 26 | Jochen Schalanda 27 | jochen@schalanda.name 28 | 29 | 30 | 31 | 32 | dropwizard_dropwizard-flyway 33 | 34 | 11.8.2 35 | 36 | 37 | 38 | 39 | io.dropwizard 40 | dropwizard-core 41 | 42 | 43 | io.dropwizard 44 | dropwizard-db 45 | 46 | 47 | io.dropwizard 48 | dropwizard-util 49 | 50 | 51 | org.flywaydb 52 | flyway-core 53 | ${flyway.version} 54 | 55 | 56 | org.checkerframework 57 | checker-qual 58 | 59 | 60 | net.sourceforge.argparse4j 61 | argparse4j 62 | 63 | 64 | org.slf4j 65 | slf4j-api 66 | 67 | 68 | com.fasterxml.jackson.core 69 | jackson-annotations 70 | 71 | 72 | org.junit.jupiter 73 | junit-jupiter 74 | test 75 | 76 | 77 | org.mockito 78 | mockito-core 79 | test 80 | 81 | 82 | org.mockito 83 | mockito-junit-jupiter 84 | test 85 | 86 | 87 | org.flywaydb 88 | flyway-database-postgresql 89 | ${flyway.version} 90 | test 91 | 92 | 93 | com.h2database 94 | h2 95 | 2.3.232 96 | test 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "local>dropwizard/renovate-config" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/FlywayBundle.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway; 2 | 3 | import io.dropwizard.core.Configuration; 4 | import io.dropwizard.core.ConfiguredBundle; 5 | import io.dropwizard.core.setup.Bootstrap; 6 | import io.dropwizard.db.DatabaseConfiguration; 7 | import io.dropwizard.flyway.cli.DbCommand; 8 | import io.dropwizard.util.Generics; 9 | 10 | public abstract class FlywayBundle 11 | implements ConfiguredBundle, DatabaseConfiguration, FlywayConfiguration { 12 | @Override 13 | public final void initialize(final Bootstrap bootstrap) { 14 | final Class klass = Generics.getTypeParameter(getClass(), Configuration.class); 15 | bootstrap.addCommand(new DbCommand(name(), this, this, klass)); 16 | } 17 | 18 | @Override 19 | public FlywayFactory getFlywayFactory(T configuration) { 20 | // Default Flyway configuration 21 | return new FlywayFactory(); 22 | } 23 | 24 | protected String name() { 25 | return "db"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/FlywayConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway; 2 | 3 | import io.dropwizard.core.Configuration; 4 | 5 | public interface FlywayConfiguration { 6 | FlywayFactory getFlywayFactory(T configuration); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/FlywayFactory.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import jakarta.validation.constraints.NotBlank; 6 | import jakarta.validation.constraints.NotEmpty; 7 | import jakarta.validation.constraints.NotNull; 8 | import jakarta.validation.constraints.PositiveOrZero; 9 | import org.checkerframework.checker.nullness.qual.Nullable; 10 | import org.flywaydb.core.Flyway; 11 | import org.flywaydb.core.api.configuration.FluentConfiguration; 12 | 13 | import javax.sql.DataSource; 14 | import java.io.File; 15 | import java.nio.charset.StandardCharsets; 16 | import java.util.Collections; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | @SuppressWarnings("unused") 21 | public class FlywayFactory { 22 | @JsonProperty 23 | @NotEmpty 24 | private String encoding = StandardCharsets.UTF_8.name(); 25 | @JsonProperty 26 | @PositiveOrZero 27 | private int connectRetries = 0; 28 | @JsonProperty 29 | @PositiveOrZero 30 | private int connectRetriesInterval = 120; 31 | @JsonProperty 32 | @Nullable 33 | private String defaultSchema = null; 34 | @JsonProperty 35 | @NotNull 36 | private List schemas = Collections.emptyList(); 37 | @JsonProperty 38 | @NotNull 39 | private List callbacks = Collections.emptyList(); 40 | @JsonProperty 41 | @NotEmpty 42 | private String metaDataTableName = "flyway_schema_history"; 43 | @JsonProperty 44 | @NotEmpty 45 | private String sqlMigrationPrefix = "V"; 46 | @JsonProperty 47 | @NotEmpty 48 | private String sqlMigrationSeparator = "__"; 49 | @JsonProperty 50 | @NotNull 51 | private List sqlMigrationSuffixes = Collections.singletonList(".sql"); 52 | @JsonProperty 53 | @NotEmpty 54 | private String placeholderPrefix = "${"; 55 | @JsonProperty 56 | @NotEmpty 57 | private String placeholderSuffix = "}"; 58 | @JsonProperty 59 | @NotNull 60 | private Map placeholders = Collections.emptyMap(); 61 | @JsonProperty 62 | @NotEmpty 63 | private List locations = Collections.singletonList("db/migration"); 64 | @JsonProperty 65 | @NotNull 66 | private List resolvers = Collections.emptyList(); 67 | @JsonProperty 68 | private String initSql = null; 69 | @JsonIgnore 70 | private ClassLoader classLoader = null; 71 | @JsonProperty 72 | private boolean outOfOrder = false; 73 | @JsonProperty 74 | @NotNull 75 | private String baselineDescription = "<< Flyway Baseline >>"; 76 | @JsonProperty 77 | private boolean baselineOnMigrate = false; 78 | @JsonProperty 79 | private boolean validateOnMigrate = true; 80 | @JsonProperty 81 | @NotBlank 82 | private String baseLineVersion = "1"; 83 | @JsonProperty 84 | private boolean cleanDisabled = false; 85 | @JsonProperty 86 | private boolean cleanOnValidationError = false; 87 | @JsonProperty 88 | private boolean group = false; 89 | @JsonProperty 90 | private List ignoreMigrationPatterns = Collections.singletonList("*:future"); 91 | @JsonProperty 92 | @NotNull 93 | private String installedBy = ""; 94 | @JsonProperty 95 | private boolean mixed = false; 96 | @JsonProperty 97 | private boolean placeholderReplacement = true; 98 | @JsonProperty 99 | private boolean skipDefaultCallbacks = false; 100 | @JsonProperty 101 | private boolean skipDefaultResolvers = false; 102 | 103 | // Commercial Features 104 | @JsonProperty 105 | @Nullable 106 | private Boolean batch; 107 | @JsonProperty 108 | @Nullable 109 | private File dryRunOutputFile; 110 | @JsonProperty 111 | @Nullable 112 | private List errorOverrides; 113 | @JsonProperty 114 | @Nullable 115 | private Boolean stream; 116 | @JsonProperty 117 | @Nullable 118 | private String target; 119 | @JsonProperty 120 | @NotNull 121 | Map configuration = Collections.emptyMap(); 122 | 123 | /** 124 | * @see FluentConfiguration#getEncoding() 125 | */ 126 | public String getEncoding() { 127 | return encoding; 128 | } 129 | 130 | /** 131 | * @see FluentConfiguration#encoding(String) 132 | */ 133 | public void setEncoding(final String encoding) { 134 | this.encoding = encoding; 135 | } 136 | 137 | /** 138 | * @see FluentConfiguration#getConnectRetries() 139 | */ 140 | public int getConnectRetries() { 141 | return connectRetries; 142 | } 143 | 144 | /** 145 | * @see FluentConfiguration#connectRetries(int) 146 | */ 147 | public void setConnectRetries(int connectRetries) { 148 | this.connectRetries = connectRetries; 149 | } 150 | 151 | /** 152 | * @see FluentConfiguration#getConnectRetriesInterval() 153 | */ 154 | public int getConnectRetriesInterval() { 155 | return connectRetriesInterval; 156 | } 157 | 158 | /** 159 | * @see FluentConfiguration#connectRetriesInterval(int) 160 | */ 161 | public void setConnectRetriesInterval(int connectRetriesInterval) { 162 | this.connectRetriesInterval = connectRetriesInterval; 163 | } 164 | 165 | /** 166 | * @see FluentConfiguration#getDefaultSchema() 167 | */ 168 | @Nullable 169 | public String getDefaultSchema() { 170 | return defaultSchema; 171 | } 172 | 173 | /** 174 | * @see FluentConfiguration#defaultSchema(String) 175 | */ 176 | public void setDefaultSchema(@Nullable final String defaultSchema) { 177 | this.defaultSchema = defaultSchema; 178 | } 179 | 180 | /** 181 | * @see FluentConfiguration#getSchemas() 182 | */ 183 | public List getSchemas() { 184 | return schemas; 185 | } 186 | 187 | /** 188 | * @see FluentConfiguration#schemas(String...) 189 | */ 190 | public void setSchemas(final List schemas) { 191 | this.schemas = schemas; 192 | } 193 | 194 | /** 195 | * @see FluentConfiguration#getCallbacks() 196 | */ 197 | public List getCallbacks() { 198 | return callbacks; 199 | } 200 | 201 | /** 202 | * @see FluentConfiguration#callbacks(String...) 203 | */ 204 | public void setCallbacks(final List callbacks) { 205 | this.callbacks = callbacks; 206 | } 207 | 208 | /** 209 | * @see FluentConfiguration#getTable() 210 | */ 211 | public String getMetaDataTableName() { 212 | return metaDataTableName; 213 | } 214 | 215 | /** 216 | * @see FluentConfiguration#table(String) 217 | */ 218 | public void setMetaDataTableName(final String metaDataTableName) { 219 | this.metaDataTableName = metaDataTableName; 220 | } 221 | 222 | /** 223 | * @see FluentConfiguration#getSqlMigrationPrefix() 224 | */ 225 | public String getSqlMigrationPrefix() { 226 | return sqlMigrationPrefix; 227 | } 228 | 229 | /** 230 | * @see FluentConfiguration#sqlMigrationPrefix(String) 231 | */ 232 | public void setSqlMigrationPrefix(final String sqlMigrationPrefix) { 233 | this.sqlMigrationPrefix = sqlMigrationPrefix; 234 | } 235 | 236 | /** 237 | * @see FluentConfiguration#getSqlMigrationPrefix() 238 | */ 239 | public List getSqlMigrationSuffixes() { 240 | return sqlMigrationSuffixes; 241 | } 242 | 243 | /** 244 | * @see FluentConfiguration#sqlMigrationSuffixes(String...) 245 | */ 246 | public void setSqlMigrationSuffixes(final List sqlMigrationSuffixes) { 247 | this.sqlMigrationSuffixes = sqlMigrationSuffixes; 248 | } 249 | 250 | /** 251 | * @see FluentConfiguration#getSqlMigrationSeparator() 252 | */ 253 | public String getSqlMigrationSeparator() { 254 | return sqlMigrationSeparator; 255 | } 256 | 257 | /** 258 | * @see FluentConfiguration#sqlMigrationSeparator(String) 259 | */ 260 | public void setSqlMigrationSeparator(final String sqlMigrationSeparator) { 261 | this.sqlMigrationSeparator = sqlMigrationSeparator; 262 | } 263 | 264 | /** 265 | * @see FluentConfiguration#getPlaceholderPrefix() 266 | */ 267 | public String getPlaceholderPrefix() { 268 | return placeholderPrefix; 269 | } 270 | 271 | /** 272 | * @see FluentConfiguration#placeholderPrefix(String) 273 | */ 274 | public void setPlaceholderPrefix(final String placeholderPrefix) { 275 | this.placeholderPrefix = placeholderPrefix; 276 | } 277 | 278 | /** 279 | * @see FluentConfiguration#getPlaceholderSuffix() 280 | */ 281 | public String getPlaceholderSuffix() { 282 | return placeholderSuffix; 283 | } 284 | 285 | /** 286 | * @see FluentConfiguration#placeholderSuffix(String) 287 | */ 288 | public void setPlaceholderSuffix(final String placeholderSuffix) { 289 | this.placeholderSuffix = placeholderSuffix; 290 | } 291 | 292 | /** 293 | * @see FluentConfiguration#getPlaceholders() 294 | */ 295 | public Map getPlaceholders() { 296 | return placeholders; 297 | } 298 | 299 | /** 300 | * @see FluentConfiguration#placeholders(Map) 301 | */ 302 | public void setPlaceholders(final Map placeholders) { 303 | this.placeholders = placeholders; 304 | } 305 | 306 | /** 307 | * @see FluentConfiguration#getLocations() 308 | */ 309 | public List getLocations() { 310 | return locations; 311 | } 312 | 313 | /** 314 | * @see FluentConfiguration#locations(String...) 315 | */ 316 | public void setLocations(final List locations) { 317 | this.locations = locations; 318 | } 319 | 320 | /** 321 | * @see FluentConfiguration#getResolvers() 322 | */ 323 | public List getResolvers() { 324 | return resolvers; 325 | } 326 | 327 | /** 328 | * @see FluentConfiguration#resolvers(String...) 329 | */ 330 | public void setResolvers(final List resolvers) { 331 | this.resolvers = resolvers; 332 | } 333 | 334 | /** 335 | * @see FluentConfiguration#getInitSql() 336 | */ 337 | public String getInitSql() { 338 | return initSql; 339 | } 340 | 341 | /** 342 | * @see FluentConfiguration#initSql(String) 343 | */ 344 | public void setInitSql(String initSql) { 345 | this.initSql = initSql; 346 | } 347 | 348 | /** 349 | * @see FluentConfiguration#getClassLoader() 350 | */ 351 | public ClassLoader getClassLoader() { 352 | return classLoader; 353 | } 354 | 355 | /** 356 | * @see FluentConfiguration#FluentConfiguration(ClassLoader) 357 | */ 358 | public void setClassLoader(ClassLoader classLoader) { 359 | this.classLoader = classLoader; 360 | } 361 | 362 | /** 363 | * @see FluentConfiguration#isOutOfOrder() 364 | */ 365 | public boolean isOutOfOrder() { 366 | return outOfOrder; 367 | } 368 | 369 | /** 370 | * @see FluentConfiguration#outOfOrder(boolean) 371 | */ 372 | public void setOutOfOrder(boolean outOfOrder) { 373 | this.outOfOrder = outOfOrder; 374 | } 375 | 376 | /** 377 | * @see FluentConfiguration#getBaselineDescription() 378 | */ 379 | public String getBaselineDescription() { 380 | return baselineDescription; 381 | } 382 | 383 | /** 384 | * @see FluentConfiguration#baselineDescription(String) 385 | */ 386 | public void setBaselineDescription(String baselineDescription) { 387 | this.baselineDescription = baselineDescription; 388 | } 389 | 390 | /** 391 | * @see FluentConfiguration#isBaselineOnMigrate() 392 | */ 393 | public boolean isBaselineOnMigrate() { 394 | return baselineOnMigrate; 395 | } 396 | 397 | /** 398 | * @see FluentConfiguration#baselineOnMigrate(boolean) 399 | */ 400 | public void setBaselineOnMigrate(boolean baselineOnMigrate) { 401 | this.baselineOnMigrate = baselineOnMigrate; 402 | } 403 | 404 | /** 405 | * @see FluentConfiguration#isValidateOnMigrate() 406 | */ 407 | public boolean isValidateOnMigrate() { 408 | return validateOnMigrate; 409 | } 410 | 411 | /** 412 | * @see FluentConfiguration#validateOnMigrate(boolean) 413 | */ 414 | public void setValidateOnMigrate(boolean validateOnMigrate) { 415 | this.validateOnMigrate = validateOnMigrate; 416 | } 417 | 418 | /** 419 | * @see FluentConfiguration#getBaselineVersion() 420 | */ 421 | public String getBaseLineVersion() { 422 | return baseLineVersion; 423 | } 424 | 425 | /** 426 | * @see FluentConfiguration#baselineVersion(String) 427 | */ 428 | public void setBaseLineVersion(String baseLineVersion) { 429 | this.baseLineVersion = baseLineVersion; 430 | } 431 | 432 | /** 433 | * @see FluentConfiguration#isCleanDisabled() 434 | */ 435 | public boolean isCleanDisabled() { 436 | return cleanDisabled; 437 | } 438 | 439 | /** 440 | * @see FluentConfiguration#cleanDisabled(boolean) 441 | */ 442 | public void setCleanDisabled(boolean cleanDisabled) { 443 | this.cleanDisabled = cleanDisabled; 444 | } 445 | 446 | /** 447 | * @see FluentConfiguration#isCleanOnValidationError() 448 | */ 449 | public boolean isCleanOnValidationError() { 450 | return cleanOnValidationError; 451 | } 452 | 453 | /** 454 | * @see FluentConfiguration#cleanOnValidationError(boolean) 455 | */ 456 | public void setCleanOnValidationError(boolean cleanOnValidationError) { 457 | this.cleanOnValidationError = cleanOnValidationError; 458 | } 459 | 460 | /** 461 | * @see FluentConfiguration#isGroup() 462 | */ 463 | public boolean isGroup() { 464 | return group; 465 | } 466 | 467 | /** 468 | * @see FluentConfiguration#group(boolean) 469 | */ 470 | public void setGroup(boolean group) { 471 | this.group = group; 472 | } 473 | 474 | /** 475 | * @see FluentConfiguration#getIgnoreMigrationPatterns() 476 | */ 477 | public List getIgnoreMigrationPatterns() { 478 | return ignoreMigrationPatterns; 479 | } 480 | 481 | /** 482 | * @see FluentConfiguration#ignoreMigrationPatterns(String...) 483 | */ 484 | public void setIgnoreMigrationPatterns(final List ignoreMigrationPatterns) { 485 | this.ignoreMigrationPatterns = ignoreMigrationPatterns; 486 | } 487 | 488 | /** 489 | * @see FluentConfiguration#getInstalledBy() 490 | */ 491 | public String getInstalledBy() { 492 | return installedBy; 493 | } 494 | 495 | /** 496 | * @see FluentConfiguration#installedBy(String) 497 | */ 498 | public void setInstalledBy(String installedBy) { 499 | this.installedBy = installedBy; 500 | } 501 | 502 | /** 503 | * @see FluentConfiguration#isMixed() 504 | */ 505 | public boolean isMixed() { 506 | return mixed; 507 | } 508 | 509 | /** 510 | * @see FluentConfiguration#mixed(boolean) 511 | */ 512 | public void setMixed(boolean mixed) { 513 | this.mixed = mixed; 514 | } 515 | 516 | /** 517 | * @see FluentConfiguration#isPlaceholderReplacement() 518 | */ 519 | public boolean isPlaceholderReplacement() { 520 | return placeholderReplacement; 521 | } 522 | 523 | /** 524 | * @see FluentConfiguration#placeholderReplacement(boolean) 525 | */ 526 | public void setPlaceholderReplacement(boolean placeholderReplacement) { 527 | this.placeholderReplacement = placeholderReplacement; 528 | } 529 | 530 | /** 531 | * @see FluentConfiguration#isSkipDefaultCallbacks() 532 | */ 533 | public boolean isSkipDefaultCallbacks() { 534 | return skipDefaultCallbacks; 535 | } 536 | 537 | /** 538 | * @see FluentConfiguration#skipDefaultCallbacks(boolean) 539 | */ 540 | public void setSkipDefaultCallbacks(boolean skipDefaultCallbacks) { 541 | this.skipDefaultCallbacks = skipDefaultCallbacks; 542 | } 543 | 544 | /** 545 | * @see FluentConfiguration#isSkipDefaultResolvers() 546 | */ 547 | public boolean isSkipDefaultResolvers() { 548 | return skipDefaultResolvers; 549 | } 550 | 551 | /** 552 | * @see FluentConfiguration#skipDefaultResolvers(boolean) 553 | */ 554 | public void setSkipDefaultResolvers(boolean skipDefaultResolvers) { 555 | this.skipDefaultResolvers = skipDefaultResolvers; 556 | } 557 | 558 | // Commercial Features 559 | 560 | /** 561 | * @see FluentConfiguration#isBatch() 562 | */ 563 | @Nullable 564 | public Boolean isBatch() { 565 | return batch; 566 | } 567 | 568 | /** 569 | * @see FluentConfiguration#batch(boolean) 570 | */ 571 | public void setBatch(@Nullable Boolean batch) { 572 | this.batch = batch; 573 | } 574 | 575 | /** 576 | * @see FluentConfiguration#getDryRunOutput() 577 | */ 578 | @Nullable 579 | public File getDryRunOutputFile() { 580 | return dryRunOutputFile; 581 | } 582 | 583 | /** 584 | * @see FluentConfiguration#dryRunOutput(File) 585 | */ 586 | public void setDryRunOutputFile(@Nullable File dryRunOutputFile) { 587 | this.dryRunOutputFile = dryRunOutputFile; 588 | } 589 | 590 | /** 591 | * @see FluentConfiguration#getErrorOverrides() 592 | */ 593 | @Nullable 594 | public List getErrorOverrides() { 595 | return errorOverrides; 596 | } 597 | 598 | /** 599 | * @see FluentConfiguration#errorOverrides(String...) 600 | */ 601 | public void setErrorOverrides(@Nullable List errorOverrides) { 602 | this.errorOverrides = errorOverrides; 603 | } 604 | 605 | /** 606 | * @see FluentConfiguration#isStream() 607 | */ 608 | @Nullable 609 | public Boolean isStream() { 610 | return stream; 611 | } 612 | 613 | /** 614 | * @see FluentConfiguration#stream(boolean) 615 | */ 616 | public void setStream(@Nullable Boolean stream) { 617 | this.stream = stream; 618 | } 619 | 620 | /** 621 | * @see FluentConfiguration#getTarget() 622 | */ 623 | @Nullable 624 | public String getTarget() { 625 | return target; 626 | } 627 | 628 | /** 629 | * @see FluentConfiguration#target(String) 630 | */ 631 | public void setTarget(@Nullable String target) { 632 | this.target = target; 633 | } 634 | 635 | /** 636 | * @see FluentConfiguration#configuration(Map) 637 | */ 638 | public Map getConfiguration() { 639 | return configuration; 640 | } 641 | 642 | /** 643 | * Configures Flyway with these properties. 644 | * This overwrites any existing configuration. 645 | * 646 | * @see Configuration parameters 647 | */ 648 | public void setConfiguration(Map configuration) { 649 | this.configuration = configuration; 650 | } 651 | 652 | public Flyway build(final String url, final String user, final String password) { 653 | return createConfiguration().dataSource(url, user, password).load(); 654 | } 655 | 656 | public Flyway build(final DataSource dataSource) { 657 | return createConfiguration().dataSource(dataSource).load(); 658 | } 659 | 660 | private FluentConfiguration createConfiguration() { 661 | final String[] emptyStringArray = new String[0]; 662 | FluentConfiguration flyway = classLoader == null ? Flyway.configure() : Flyway.configure(classLoader); 663 | flyway = flyway 664 | .baselineOnMigrate(baselineOnMigrate) 665 | .baselineVersion(baseLineVersion) 666 | .callbacks(callbacks.toArray(emptyStringArray)) 667 | .cleanDisabled(cleanDisabled) 668 | .cleanOnValidationError(cleanOnValidationError) 669 | .configuration(configuration) 670 | .connectRetries(connectRetries) 671 | .connectRetriesInterval(connectRetriesInterval) 672 | .encoding(encoding) 673 | .group(group) 674 | .ignoreMigrationPatterns(ignoreMigrationPatterns.toArray(emptyStringArray)) 675 | .installedBy(installedBy) 676 | .locations(locations.toArray(emptyStringArray)) 677 | .mixed(mixed) 678 | .outOfOrder(outOfOrder) 679 | .placeholderPrefix(placeholderPrefix) 680 | .placeholderReplacement(placeholderReplacement) 681 | .placeholderSuffix(placeholderSuffix) 682 | .placeholders(placeholders) 683 | .resolvers(resolvers.toArray(emptyStringArray)) 684 | .initSql(initSql) 685 | .schemas(schemas.toArray(emptyStringArray)) 686 | .skipDefaultCallbacks(skipDefaultCallbacks) 687 | .skipDefaultResolvers(skipDefaultResolvers) 688 | .sqlMigrationPrefix(sqlMigrationPrefix) 689 | .sqlMigrationSeparator(sqlMigrationSeparator) 690 | .sqlMigrationSuffixes(sqlMigrationSuffixes.toArray(emptyStringArray)) 691 | .table(metaDataTableName) 692 | .validateOnMigrate(validateOnMigrate); 693 | 694 | if (defaultSchema != null) { 695 | flyway.defaultSchema(defaultSchema); 696 | } 697 | 698 | // Commercial features 699 | if (batch != null) { 700 | flyway.batch(batch); 701 | } 702 | if (dryRunOutputFile != null) { 703 | flyway.dryRunOutput(dryRunOutputFile); 704 | } 705 | if (errorOverrides != null) { 706 | flyway.errorOverrides(errorOverrides.toArray(emptyStringArray)); 707 | } 708 | if (stream != null) { 709 | flyway.stream(stream); 710 | } 711 | if (target != null) { 712 | flyway.target(target); 713 | } 714 | 715 | return flyway; 716 | } 717 | } 718 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/AbstractFlywayCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.core.Configuration; 4 | import io.dropwizard.core.cli.ConfiguredCommand; 5 | import io.dropwizard.core.setup.Bootstrap; 6 | import io.dropwizard.db.DatabaseConfiguration; 7 | import io.dropwizard.db.PooledDataSourceFactory; 8 | import io.dropwizard.flyway.FlywayConfiguration; 9 | import io.dropwizard.flyway.FlywayFactory; 10 | import net.sourceforge.argparse4j.inf.Namespace; 11 | import org.flywaydb.core.Flyway; 12 | import org.flywaydb.core.api.FlywayException; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | abstract class AbstractFlywayCommand extends ConfiguredCommand { 17 | private static final Logger LOG = LoggerFactory.getLogger(AbstractFlywayCommand.class); 18 | private final DatabaseConfiguration databaseConfiguration; 19 | private final FlywayConfiguration flywayConfiguration; 20 | private final Class configurationClass; 21 | 22 | AbstractFlywayCommand(final String name, 23 | final String description, 24 | final DatabaseConfiguration databaseConfiguration, 25 | final FlywayConfiguration flywayConfiguration, 26 | final Class configurationClass) { 27 | super(name, description); 28 | this.databaseConfiguration = databaseConfiguration; 29 | this.flywayConfiguration = flywayConfiguration; 30 | this.configurationClass = configurationClass; 31 | } 32 | 33 | @Override 34 | protected Class getConfigurationClass() { 35 | return configurationClass; 36 | } 37 | 38 | @Override 39 | protected void run(final Bootstrap bootstrap, final Namespace namespace, final T configuration) throws Exception { 40 | final PooledDataSourceFactory datasourceFactory = databaseConfiguration.getDataSourceFactory(configuration); 41 | final FlywayFactory flywayFactory = flywayConfiguration.getFlywayFactory(configuration); 42 | 43 | // Give subclasses an option to set additional config flags for flyway. 44 | setAdditionalOptions(flywayFactory, namespace); 45 | 46 | final Flyway flyway = flywayFactory.build(datasourceFactory.build(bootstrap.getMetricRegistry(), "Flyway")); 47 | 48 | try { 49 | run(namespace, flyway); 50 | } catch (FlywayException e) { 51 | LOG.error("Error while running database command", e); 52 | throw e; 53 | } 54 | } 55 | 56 | protected abstract void setAdditionalOptions(FlywayFactory flywayFactory, Namespace namespace); 57 | protected abstract void run(final Namespace namespace, final Flyway flyway) throws Exception; 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbCleanCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.flyway.FlywayConfiguration; 4 | import io.dropwizard.core.Configuration; 5 | import io.dropwizard.db.DatabaseConfiguration; 6 | import net.sourceforge.argparse4j.inf.Namespace; 7 | import org.flywaydb.core.Flyway; 8 | 9 | public class DbCleanCommand extends NoOptionsFlywayCommand { 10 | public DbCleanCommand(final DatabaseConfiguration databaseConfiguration, 11 | final FlywayConfiguration flywayConfiguration, 12 | final Class configurationClass) { 13 | super("clean", "Drops all objects in the configured schemas.", 14 | databaseConfiguration, flywayConfiguration, configurationClass); 15 | } 16 | 17 | @Override 18 | protected void run(final Namespace namespace, final Flyway flyway) throws Exception { 19 | flyway.clean(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.flyway.FlywayConfiguration; 4 | import io.dropwizard.core.Configuration; 5 | import io.dropwizard.db.DatabaseConfiguration; 6 | import io.dropwizard.flyway.FlywayFactory; 7 | import net.sourceforge.argparse4j.inf.Namespace; 8 | import net.sourceforge.argparse4j.inf.Subparser; 9 | import org.flywaydb.core.Flyway; 10 | 11 | import java.util.SortedMap; 12 | import java.util.TreeMap; 13 | 14 | public class DbCommand extends AbstractFlywayCommand { 15 | private static final String COMMAND_NAME_ATTR = "subCommand"; 16 | private final SortedMap> subCommands = new TreeMap<>(); 17 | 18 | public DbCommand(final String name, final DatabaseConfiguration databaseConfiguration, 19 | final FlywayConfiguration flywayConfiguration, 20 | final Class configurationClass) { 21 | super(name, "Run database migration tasks", 22 | databaseConfiguration, flywayConfiguration, configurationClass); 23 | 24 | addSubCommand(new DbMigrateCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 25 | addSubCommand(new DbCleanCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 26 | addSubCommand(new DbInitCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 27 | addSubCommand(new DbValidateCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 28 | addSubCommand(new DbInfoCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 29 | addSubCommand(new DbRepairCommand<>(databaseConfiguration, flywayConfiguration, configurationClass)); 30 | } 31 | 32 | private void addSubCommand(final AbstractFlywayCommand subCommand) { 33 | subCommands.put(subCommand.getName(), subCommand); 34 | } 35 | 36 | @Override 37 | public void configure(final Subparser subparser) { 38 | for (AbstractFlywayCommand subCommand : subCommands.values()) { 39 | final Subparser cmdParser = subparser.addSubparsers() 40 | .addParser(subCommand.getName()) 41 | .setDefault(COMMAND_NAME_ATTR, subCommand.getName()) 42 | .description(subCommand.getDescription()); 43 | subCommand.configure(cmdParser); 44 | } 45 | } 46 | 47 | @Override 48 | protected void setAdditionalOptions(FlywayFactory flywayFactory, Namespace namespace) { 49 | subCommands.get(namespace.getString(COMMAND_NAME_ATTR)).setAdditionalOptions(flywayFactory, namespace); 50 | } 51 | 52 | @Override 53 | public void run(final Namespace namespace, final Flyway flyway) throws Exception { 54 | subCommands.get(namespace.getString(COMMAND_NAME_ATTR)).run(namespace, flyway); 55 | } 56 | } -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbInfoCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.flyway.FlywayConfiguration; 4 | import io.dropwizard.core.Configuration; 5 | import io.dropwizard.db.DatabaseConfiguration; 6 | import net.sourceforge.argparse4j.inf.Namespace; 7 | import org.flywaydb.core.Flyway; 8 | 9 | import static org.flywaydb.core.internal.info.MigrationInfoDumper.dumpToAsciiTable; 10 | 11 | public class DbInfoCommand extends NoOptionsFlywayCommand { 12 | public DbInfoCommand(final DatabaseConfiguration databaseConfiguration, 13 | final FlywayConfiguration flywayConfiguration, 14 | final Class configurationClass) { 15 | super("info", "Prints the details and status information about all the migrations.", 16 | databaseConfiguration, flywayConfiguration, configurationClass); 17 | } 18 | 19 | @Override 20 | public void run(final Namespace namespace, final Flyway flyway) throws Exception { 21 | System.out.println(dumpToAsciiTable(flyway.info().all())); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbInitCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.flyway.FlywayConfiguration; 4 | import org.flywaydb.core.Flyway; 5 | import io.dropwizard.core.Configuration; 6 | import io.dropwizard.db.DatabaseConfiguration; 7 | import net.sourceforge.argparse4j.inf.Namespace; 8 | 9 | public class DbInitCommand extends NoOptionsFlywayCommand { 10 | public DbInitCommand(final DatabaseConfiguration databaseConfiguration, 11 | final FlywayConfiguration flywayConfiguration, 12 | final Class configurationClass) { 13 | super("init", "Creates and initializes the metadata table (existing database).", 14 | databaseConfiguration, flywayConfiguration, configurationClass); 15 | } 16 | 17 | @Override 18 | protected void run(final Namespace namespace, final Flyway flyway) throws Exception { 19 | flyway.baseline(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbMigrateCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.core.Configuration; 4 | import io.dropwizard.db.DatabaseConfiguration; 5 | import io.dropwizard.flyway.FlywayConfiguration; 6 | import io.dropwizard.flyway.FlywayFactory; 7 | import net.sourceforge.argparse4j.impl.Arguments; 8 | import net.sourceforge.argparse4j.inf.Namespace; 9 | import net.sourceforge.argparse4j.inf.Subparser; 10 | import org.flywaydb.core.Flyway; 11 | import org.flywaydb.core.api.output.MigrateResult; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | public class DbMigrateCommand extends AbstractFlywayCommand { 16 | 17 | private static final Logger LOG = LoggerFactory.getLogger(DbMigrateCommand.class); 18 | private static final String OUT_OF_ORDER = "outOfOrder"; 19 | private static final String VALIDATE_ON_MIGRATE = "validateOnMigrate"; 20 | private static final String CLEAN_ON_VALIDATION_ERROR = "cleanOnValidationError"; 21 | private static final String INIT_ON_MIGRATE = "initOnMigrate"; 22 | 23 | public DbMigrateCommand(final DatabaseConfiguration databaseConfiguration, 24 | final FlywayConfiguration flywayConfiguration, 25 | final Class configurationClass) { 26 | super("migrate", "Migrates the database.", 27 | databaseConfiguration, flywayConfiguration, configurationClass); 28 | } 29 | 30 | @Override 31 | public void configure(Subparser subparser) { 32 | super.configure(subparser); 33 | 34 | subparser.addArgument("--" + OUT_OF_ORDER) 35 | .dest(OUT_OF_ORDER) 36 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 37 | .help("Allows migrations to be run \"out of order\". " + 38 | "If you already have versions 1 and 3 applied, and now a version 2 is found, it will be applied too instead of being ignored."); 39 | 40 | subparser.addArgument("--" + VALIDATE_ON_MIGRATE) 41 | .dest(VALIDATE_ON_MIGRATE) 42 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 43 | .help("Whether to automatically call validate or not when running migrate. " + 44 | "For each sql migration a CRC32 checksum is calculated when the sql script is executed. " + 45 | "The validate mechanism checks if the sql migration in the classpath still has the same checksum as the sql migration already executed in the database."); 46 | 47 | subparser.addArgument("--" + CLEAN_ON_VALIDATION_ERROR) 48 | .dest(CLEAN_ON_VALIDATION_ERROR) 49 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 50 | .help("Whether to automatically call clean or not when a validation error occurs. " + 51 | "This is exclusively intended as a convenience for development. " + 52 | "Even tough we strongly recommend not to change migration scripts once they have been checked into SCM and run, this provides a way of dealing with this case in a smooth manner. " + 53 | "The database will be wiped clean automatically, ensuring that the next migration will bring you back to the state checked into SCM. " + 54 | "Warning! Do not enable in production !"); 55 | 56 | subparser.addArgument("--" + INIT_ON_MIGRATE) 57 | .dest(INIT_ON_MIGRATE) 58 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 59 | .help("Whether to automatically call init when migrate is executed against a non-empty schema with no metadata table. " + 60 | "This schema will then be initialized with the initVersion before executing the migrations. " + 61 | "Only migrations above initVersion will then be applied. " + 62 | "This is useful for initial Flyway production deployments on projects with an existing DB. " + 63 | "Be careful when enabling this as it removes the safety net that ensures Flyway does not migrate the wrong database in case of a configuration mistake!"); 64 | } 65 | 66 | @Override 67 | protected void setAdditionalOptions(FlywayFactory flywayFactory, Namespace namespace) { 68 | final Boolean outOfOrder = namespace.getBoolean(OUT_OF_ORDER); 69 | final Boolean validateOnMigrate = namespace.getBoolean(VALIDATE_ON_MIGRATE); 70 | final Boolean cleanOnValidationError = namespace.getBoolean(CLEAN_ON_VALIDATION_ERROR); 71 | final Boolean baselineOnMigrate = namespace.getBoolean(INIT_ON_MIGRATE); 72 | 73 | if (outOfOrder != null) { 74 | flywayFactory.setOutOfOrder(outOfOrder); 75 | } 76 | 77 | if (validateOnMigrate != null) { 78 | flywayFactory.setValidateOnMigrate(validateOnMigrate); 79 | } 80 | 81 | if (cleanOnValidationError != null) { 82 | flywayFactory.setCleanOnValidationError(cleanOnValidationError); 83 | } 84 | 85 | if (baselineOnMigrate != null) { 86 | flywayFactory.setBaselineOnMigrate(baselineOnMigrate); 87 | } 88 | } 89 | 90 | @Override 91 | public void run(final Namespace namespace, final Flyway flyway) throws Exception { 92 | final MigrateResult migrateResult = flyway.migrate(); 93 | LOG.debug("Executed {} migrations to migrate {} in database {} from schema {} -> {}", 94 | migrateResult.migrationsExecuted, migrateResult.schemaName, migrateResult.database, 95 | migrateResult.initialSchemaVersion, migrateResult.targetSchemaVersion); 96 | 97 | if (!migrateResult.warnings.isEmpty()) { 98 | LOG.warn("{} warnings when migrating {} in database {} from schema {} -> {}: {}", 99 | migrateResult.warnings.size(), migrateResult.schemaName, migrateResult.database, 100 | migrateResult.initialSchemaVersion, migrateResult.targetSchemaVersion, 101 | migrateResult.warnings 102 | ); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbRepairCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.flyway.FlywayConfiguration; 4 | import io.dropwizard.core.Configuration; 5 | import io.dropwizard.db.DatabaseConfiguration; 6 | import net.sourceforge.argparse4j.inf.Namespace; 7 | import org.flywaydb.core.Flyway; 8 | 9 | public class DbRepairCommand extends NoOptionsFlywayCommand { 10 | public DbRepairCommand(final DatabaseConfiguration databaseConfiguration, 11 | final FlywayConfiguration flywayConfiguration, 12 | final Class configurationClass) { 13 | super("repair", "Repairs the metadata table.", 14 | databaseConfiguration, flywayConfiguration, configurationClass); 15 | } 16 | 17 | @Override 18 | public void run(final Namespace namespace, final Flyway flyway) throws Exception { 19 | flyway.repair(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/DbValidateCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.core.Configuration; 4 | import io.dropwizard.db.DatabaseConfiguration; 5 | import io.dropwizard.flyway.FlywayConfiguration; 6 | import io.dropwizard.flyway.FlywayFactory; 7 | import net.sourceforge.argparse4j.impl.Arguments; 8 | import net.sourceforge.argparse4j.inf.Namespace; 9 | import net.sourceforge.argparse4j.inf.Subparser; 10 | import org.flywaydb.core.Flyway; 11 | import org.flywaydb.core.api.configuration.FluentConfiguration; 12 | 13 | import static net.sourceforge.argparse4j.impl.Arguments.storeTrue; 14 | 15 | public class DbValidateCommand extends AbstractFlywayCommand { 16 | 17 | private static final String OUT_OF_ORDER = "outOfOrder"; 18 | private static final String CLEAN_ON_VALIDATION_ERROR = "cleanOnValidationError"; 19 | 20 | public DbValidateCommand(final DatabaseConfiguration databaseConfiguration, 21 | final FlywayConfiguration flywayConfiguration, 22 | final Class configurationClass) { 23 | super("validate", "Validates the applied migrations against the ones available on the classpath.", 24 | databaseConfiguration, flywayConfiguration, configurationClass); 25 | } 26 | 27 | @Override 28 | public void configure(Subparser subparser) { 29 | super.configure(subparser); 30 | 31 | subparser.addArgument("--" + OUT_OF_ORDER) 32 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 33 | .dest(OUT_OF_ORDER) 34 | .help("Allows migrations to be run \"out of order\". " + 35 | "If you already have versions 1 and 3 applied, and now a version 2 is found, it will be applied too instead of being ignored."); 36 | 37 | subparser.addArgument("--" + CLEAN_ON_VALIDATION_ERROR) 38 | .action(Arguments.storeConst()).setConst(Boolean.TRUE) 39 | .dest(CLEAN_ON_VALIDATION_ERROR) 40 | .help("Whether to automatically call clean or not when a validation error occurs. " + 41 | "This is exclusively intended as a convenience for development. " + 42 | "Even tough we strongly recommend not to change migration scripts once they have been checked into SCM and run, this provides a way of dealing with this case in a smooth manner. " + 43 | "The database will be wiped clean automatically, ensuring that the next migration will bring you back to the state checked into SCM. " + 44 | "Warning! Do not enable in production !"); 45 | } 46 | 47 | @Override 48 | protected void setAdditionalOptions(FlywayFactory flywayFactory, Namespace namespace) { 49 | final Boolean outOfOrder = namespace.getBoolean(OUT_OF_ORDER); 50 | final Boolean cleanOnValidationError = namespace.getBoolean(CLEAN_ON_VALIDATION_ERROR); 51 | 52 | if (outOfOrder != null) { 53 | flywayFactory.setOutOfOrder(outOfOrder); 54 | } 55 | 56 | if (cleanOnValidationError != null) { 57 | flywayFactory.setCleanOnValidationError(cleanOnValidationError); 58 | } 59 | 60 | } 61 | 62 | @Override 63 | protected void run(final Namespace namespace, final Flyway flyway) throws Exception { 64 | flyway.validate(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/dropwizard/flyway/cli/NoOptionsFlywayCommand.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.core.Configuration; 4 | import io.dropwizard.db.DatabaseConfiguration; 5 | import io.dropwizard.flyway.FlywayConfiguration; 6 | import io.dropwizard.flyway.FlywayFactory; 7 | import net.sourceforge.argparse4j.inf.Namespace; 8 | 9 | public abstract class NoOptionsFlywayCommand extends AbstractFlywayCommand { 10 | 11 | NoOptionsFlywayCommand(String name, String description, DatabaseConfiguration databaseConfiguration, 12 | FlywayConfiguration flywayConfiguration, Class configurationClass) { 13 | super(name, description, databaseConfiguration, flywayConfiguration, configurationClass); 14 | } 15 | 16 | @Override 17 | protected void setAdditionalOptions(FlywayFactory flywayFactory, Namespace namespace) { 18 | // Empty on purpose 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/site/site.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | org.apache.maven.skins 6 | maven-fluido-skin 7 | 1.7 8 | 9 | 10 | 11 | 12 | dropwizard/dropwizard-flyway 13 | right 14 | red 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/flyway/FlywayFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import jakarta.validation.constraints.NotNull; 5 | import org.flywaydb.core.Flyway; 6 | import org.flywaydb.database.postgresql.PostgreSQLConfigurationExtension; 7 | import org.h2.jdbcx.JdbcDataSource; 8 | import org.junit.jupiter.api.BeforeEach; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import java.nio.charset.StandardCharsets; 12 | import java.sql.SQLException; 13 | import java.util.Map; 14 | 15 | import static org.junit.jupiter.api.Assertions.assertEquals; 16 | import static org.junit.jupiter.api.Assertions.assertNotNull; 17 | import static org.junit.jupiter.api.Assertions.assertSame; 18 | 19 | public class FlywayFactoryTest { 20 | 21 | private JdbcDataSource dataSource; 22 | 23 | @BeforeEach 24 | void setUp() throws SQLException { 25 | dataSource = new JdbcDataSource(); 26 | dataSource.setURL("jdbc:h2:mem:testdb"); 27 | dataSource.setUser("sa"); 28 | } 29 | 30 | @Test 31 | public void defaultConfigurationShouldBeValid() { 32 | final FlywayFactory factory = new FlywayFactory(); 33 | 34 | final Flyway flyway = factory.build(dataSource); 35 | 36 | assertNotNull(flyway); 37 | assertSame(dataSource, flyway.getConfiguration().getDataSource()); 38 | assertEquals(StandardCharsets.UTF_8, flyway.getConfiguration().getEncoding()); 39 | assertEquals("flyway_schema_history", flyway.getConfiguration().getTable()); 40 | assertEquals(0, flyway.getConfiguration().getSchemas().length); 41 | } 42 | 43 | @Test 44 | public void checkConfigurationWithOverridedSetting() { 45 | Flyway flyway = new FlywayFactory().build(dataSource); 46 | assertNotNull(flyway); 47 | 48 | boolean transactionalLockDefault = getPostgresTransactionLockSettings(flyway); 49 | boolean transactionalLockOverrided = !transactionalLockDefault; 50 | 51 | final FlywayFactory factory = new FlywayFactory(); 52 | Map configuration = ImmutableMap.of("flyway.postgresql.transactional.lock", String.valueOf(transactionalLockOverrided)); 53 | factory.setConfiguration(configuration); 54 | flyway = factory.build(dataSource); 55 | 56 | assertNotNull(flyway); 57 | assertEquals(StandardCharsets.UTF_8, flyway.getConfiguration().getEncoding()); // default value 58 | assertEquals(0, flyway.getConfiguration().getSchemas().length); // default value 59 | assertEquals("flyway_schema_history", flyway.getConfiguration().getTable()); // default value 60 | assertEquals(transactionalLockOverrided, getPostgresTransactionLockSettings(flyway)); // overrided value 61 | } 62 | 63 | private static boolean getPostgresTransactionLockSettings(@NotNull final Flyway flyway) { 64 | return flyway.getConfiguration().getPluginRegister().getPlugin(PostgreSQLConfigurationExtension.class).isTransactionalLock(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/flyway/cli/AbstractCommandTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import io.dropwizard.core.Application; 4 | import io.dropwizard.core.Configuration; 5 | import io.dropwizard.core.cli.Cli; 6 | import io.dropwizard.core.setup.Bootstrap; 7 | import io.dropwizard.core.setup.Environment; 8 | import io.dropwizard.db.DatabaseConfiguration; 9 | import io.dropwizard.db.PooledDataSourceFactory; 10 | import io.dropwizard.flyway.FlywayConfiguration; 11 | import io.dropwizard.flyway.FlywayFactory; 12 | import io.dropwizard.util.JarLocation; 13 | import org.flywaydb.core.Flyway; 14 | import org.junit.jupiter.api.BeforeEach; 15 | 16 | import java.util.Optional; 17 | 18 | import static org.mockito.ArgumentMatchers.any; 19 | import static org.mockito.Mockito.mock; 20 | import static org.mockito.Mockito.when; 21 | 22 | public class AbstractCommandTest { 23 | protected Cli cli; 24 | 25 | protected FlywayFactory mockFlywayFactory; 26 | protected Flyway mockFlyway; 27 | 28 | private static class TestApplication extends Application { 29 | @Override 30 | public void run(TestConfiguration configuration, Environment environment) throws Exception { 31 | } 32 | } 33 | 34 | public static class TestConfiguration extends Configuration { 35 | } 36 | 37 | @BeforeEach 38 | public void setUp() throws Exception { 39 | // Setup necessary mock 40 | final JarLocation location = mock(JarLocation.class); 41 | when(location.getVersion()).thenReturn(Optional.of("1.0.0")); 42 | 43 | final DatabaseConfiguration dbConfiguration = mock(DatabaseConfiguration.class); 44 | when(dbConfiguration.getDataSourceFactory(any())).thenReturn(mock(PooledDataSourceFactory.class)); 45 | 46 | final FlywayConfiguration flywayConfiguration = mock(FlywayConfiguration.class); 47 | mockFlywayFactory = mock(FlywayFactory.class); 48 | when(flywayConfiguration.getFlywayFactory(any())).thenReturn(mockFlywayFactory); 49 | 50 | mockFlyway = mock(Flyway.class); 51 | when(mockFlywayFactory.build(any())).thenReturn(mockFlyway); 52 | 53 | // Add commands you want to test 54 | final Bootstrap bootstrap = new Bootstrap<>(new TestApplication()); 55 | bootstrap.addCommand(new DbCommand("db", dbConfiguration, flywayConfiguration, TestConfiguration.class)); 56 | 57 | // Build what'll run the command and interpret arguments 58 | cli = new Cli(location, bootstrap, System.out, System.err); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/flyway/cli/DbMigrateCommandTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import org.flywaydb.core.api.output.MigrateResult; 4 | import org.flywaydb.core.internal.license.VersionPrinter; 5 | import org.junit.jupiter.api.BeforeEach; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import static org.mockito.ArgumentMatchers.anyBoolean; 9 | import static org.mockito.Mockito.never; 10 | import static org.mockito.Mockito.verify; 11 | import static org.mockito.Mockito.when; 12 | 13 | public class DbMigrateCommandTest extends AbstractCommandTest { 14 | private MigrateResult migrateResult; 15 | 16 | @BeforeEach 17 | void setUpFlyway() { 18 | migrateResult = new MigrateResult(VersionPrinter.getVersion(), "db", "schema", "PostgreSQL"); 19 | migrateResult.initialSchemaVersion = "initial"; 20 | migrateResult.targetSchemaVersion = "target"; 21 | migrateResult.migrationsExecuted = 23; 22 | 23 | when(mockFlyway.migrate()).thenReturn(migrateResult); 24 | } 25 | 26 | @Test 27 | public void testDefaultArguments() { 28 | cli.run("db", "migrate"); 29 | 30 | verify(mockFlywayFactory, never()).setBaselineOnMigrate(anyBoolean()); 31 | verify(mockFlywayFactory, never()).setOutOfOrder(anyBoolean()); 32 | verify(mockFlywayFactory, never()).setValidateOnMigrate(anyBoolean()); 33 | verify(mockFlywayFactory, never()).setCleanOnValidationError(anyBoolean()); 34 | verify(mockFlyway).migrate(); 35 | } 36 | 37 | @Test 38 | public void testDefaultArgumentsWithWarnings() { 39 | migrateResult.warnings.add("warning1"); 40 | migrateResult.warnings.add("warning2"); 41 | 42 | cli.run("db", "migrate"); 43 | 44 | verify(mockFlyway).migrate(); 45 | } 46 | 47 | @Test 48 | public void testInitOnMigrate() { 49 | cli.run("db", "migrate", "--initOnMigrate"); 50 | 51 | verify(mockFlywayFactory).setBaselineOnMigrate(true); 52 | verify(mockFlyway).migrate(); 53 | } 54 | 55 | @Test 56 | public void testValidateOMigrate() { 57 | cli.run("db", "migrate", "--validateOnMigrate"); 58 | 59 | verify(mockFlywayFactory).setValidateOnMigrate(true); 60 | verify(mockFlyway).migrate(); 61 | } 62 | 63 | @Test 64 | public void testOutOfOrder() { 65 | cli.run("db", "migrate", "--outOfOrder"); 66 | 67 | verify(mockFlywayFactory).setOutOfOrder(true); 68 | verify(mockFlyway).migrate(); 69 | } 70 | 71 | @Test 72 | public void testCleanOnValidationError() { 73 | cli.run("db", "migrate", "--cleanOnValidationError"); 74 | 75 | verify(mockFlywayFactory).setCleanOnValidationError(true); 76 | verify(mockFlyway).migrate(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/io/dropwizard/flyway/cli/DbValidateCommandTest.java: -------------------------------------------------------------------------------- 1 | package io.dropwizard.flyway.cli; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.mockito.ArgumentMatchers.anyBoolean; 6 | import static org.mockito.Mockito.never; 7 | import static org.mockito.Mockito.verify; 8 | 9 | public class DbValidateCommandTest extends AbstractCommandTest { 10 | 11 | @Test 12 | public void testDefaultArguments() { 13 | cli.run("db", "validate"); 14 | 15 | verify(mockFlywayFactory, never()).setOutOfOrder(anyBoolean()); 16 | verify(mockFlywayFactory, never()).setCleanOnValidationError(anyBoolean()); 17 | verify(mockFlyway).validate(); 18 | } 19 | 20 | @Test 21 | public void testOutOfOrder() { 22 | cli.run("db", "validate", "--outOfOrder"); 23 | 24 | verify(mockFlywayFactory).setOutOfOrder(true); 25 | verify(mockFlyway).validate(); 26 | } 27 | 28 | @Test 29 | public void testCleanOnValidationError() { 30 | cli.run("db", "validate", "--cleanOnValidationError"); 31 | 32 | verify(mockFlywayFactory).setCleanOnValidationError(true); 33 | verify(mockFlyway).validate(); 34 | } 35 | } 36 | --------------------------------------------------------------------------------