Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changelog is found twice in classpath #2818

Closed
dbyron-sf opened this issue May 3, 2022 · 27 comments · Fixed by #3006
Closed

changelog is found twice in classpath #2818

dbyron-sf opened this issue May 3, 2022 · 27 comments · Fixed by #3006

Comments

@dbyron-sf
Copy link

Environment

This is potentially a duplicate of #1916 / #1916 (comment), but since that's closed, I'm opening a new issue.

Liquibase Version: 4.0.0, 4.1.0, 4.3.2, 4.3.3, 4.3.4, 4.3.5, 4.4.0, 4.4.1, 4.4.2, 4.4.3, 4.5.0, 4.6.0, 4.6.1, 4.6.2, 4.7.0, 4.7.1, 4.8.0, 4.9.0, and 4.9.1
Liquibase Integration & Version: gradle, spring boot 2.2.13, 2.3.12

Liquibase Extension(s) & Version:

Database Vendor & Version:

Operating System Type & Version:

Description

liquibase throws an exception that a changelog file is on the classpath twice. Here's the stacktrace from liquibase 4.9.1:

Caused by: liquibase.exception.ChangeLogParseException: Error parsing classpath:db/healthcheck.yml
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:89)
	at liquibase.Liquibase.getDatabaseChangeLog(Liquibase.java:369)
	at liquibase.Liquibase.lambda$update$1(Liquibase.java:224)
	at liquibase.Scope.lambda$child$0(Scope.java:180)
	at liquibase.Scope.child(Scope.java:189)
	at liquibase.Scope.child(Scope.java:179)
	at liquibase.Scope.child(Scope.java:158)
	at liquibase.Liquibase.runInScope(Liquibase.java:2405)
	at liquibase.Liquibase.update(Liquibase.java:211)
	at liquibase.Liquibase.update(Liquibase.java:197)
	at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:314)
	at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:269)
	at com.netflix.spinnaker.kork.sql.migration.SpringLiquibaseProxy.afterPropertiesSet(SpringLiquibaseProxy.kt:65)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1858)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1795)
	... 87 more
Caused by: java.io.IOException: Found 2 files that match classpath:db/healthcheck.yml: file:/Users/dbyron/src/spinnaker/kork/kork-sql/build/resources/main/db/healthcheck.yml, jar:file:/Users/dbyron/src/spinnaker/kork/kork-sql/build/libs/kork-sql.jar!/db/healthcheck.yml
	at liquibase.resource.AbstractResourceAccessor.openStream(AbstractResourceAccessor.java:25)
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:25)
	... 101 more

Steps To Reproduce

This happens in kork, with:

$ ./gradlew kork-sql:test

I tried adding a test to SpringResourceAccessorTest.groovy, but I'm not familiar enough with mvn to get a test to run after packaging the jar, so it passes. I believe the mvn terminology for the kind of test I'm looking for is an integration test.

    def "openStreams for a file in src/main/resources"() {
        when:
        def list = resourceAccessor.openStreams(null, "classpath:/liquibase/examples/yaml/example-changelog.yaml")

        then:
        list.size() == 1
    }

I believe this commit is the one that made this stop working in 4.3.2, when it worked in 4.3.1, specifically the change to finalizeSearchPath that unconditionally prepends classpath*:.

I single-stepped through SpringResourceAccessor.openStreams. In 4.3.1, the return value from

ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources(searchPath);

is an array with one classpath resource element. searchPath in this case is classpath:db/healthcheck.yml. In 4.3.2 though, searchPath is classpath*:/db/healthcheck.yml and the return value is (perhaps obviously) an array with two elements:

          URL [file:/Users/dbyron/src/spinnaker/kork/kork-sql/build/resources/main/db/healthcheck.yml]
          URL [jar:file:/Users/dbyron/src/spinnaker/kork/kork-sql/build/libs/kork-sql.jar!/db/healthcheck.yml]
@dbyron-sf
Copy link
Author

@nvoxland Hope it's OK to ping you since I believe the commit I mentioned above is yours.

@ghynx
Copy link

ghynx commented May 13, 2022

Have the same behaviour that appears suddenly with 4.2.2 , mind that we are using 4.2.2 for a long time without issues (and nothing changed in our code ) ,

Note : we are using ant to execute liquibase changelog ( ;-)

checked with 4.2.2 , 4.3.1, 4.8.0 , 4.10.0

There is something weird here ..
tested with the same build for our product on a local pc, and on 2 vm server (Windows 2019)

  • works on local pc and one server
  • fail on another server
  • checked with jdk 11,jdk 8 , jdk 16 but seems that 's not related .

@luispollo
Copy link

luispollo commented Jun 7, 2022

Ran into the same issue today. Any updates?

Versions:

  • gradle 7.4.2
  • liquibase-core 4.5.0

@kataggart kataggart added the field label Jun 7, 2022
@kataggart
Copy link
Contributor

@luispollo I am checking with @nvoxland -- I know he is looking at it. Thanks for the nudge.

@luispollo
Copy link

BTW, if this helps, unlike @dbyron-sf, locking liquibase-core to 4.3.1 does not fix the issue for me.

@mamtananavati
Copy link

We have the same issue as well with liquibase 4.9.1

@JanCizmar
Copy link

+1

@JanCizmar
Copy link

It would be nice to be able to at least provide the absolute path to the changelog. I tried to debug the whole thing and I haven't found any hack how to force it to get single changelog.

@kevin-atx kevin-atx added this to the NEXT milestone Jun 13, 2022
@kataggart kataggart modified the milestone: NEXT Jun 13, 2022
@nvoxland
Copy link
Contributor

The change from classpath: to classpath*: was intentional. We look up files via the classpath, but sometimes multiple files stored with the same path across the classpath and just randomly picking one lead to errors.

So the change was to make sure we use classpath* so that we can correctly detect that there are multiple files with the same path and force that to get fixed.

In the case of the original description on this issue, there is a file db/healthcheck.yml in both /Users/dbyron/src/spinnaker/kork/kork-sql/build/resources/main/ and in the /Users/dbyron/src/spinnaker/kork/kork-sql/build/libs/kork-sql.jar dir. Perhaps the are the same? Perhaps they are not? We've found the safest thing to do is to stop execution and list out those locations so you can handle that as you need. For example, if that file is already bundled in the kork-sql.jar file it shouldn't be in the build directory also? Or maybe they are actually different and one should be renamed so you can correctly distinguish between them?

Liquibase gets configured with a set of locations to search for files in. We don't support absolute paths out of the box, because absolute paths often change between machines and over time, so we separate the list of search base locations from the paths within those locations. How those search paths get set will depend on how Liquibase is being set up, and usually "file found twice" errors come from those how those search paths getting set up incorrectly. Sometimes that setup is wrong in the library calling liquibase, sometimes in configuration passed to gradle/spring/whatever.

In the case of Kork, how is the project being set up so that it has db/healthcheck.yml in multiple places?

In the case of the other people seeing a similar issue: look at the paths Liquibase lists as the duplicate locations. Does your classpath/configuration setup explain why Liquibase is getting them as separate paths? Or is the listed locations out of your control and/or not making sense?

Related to that, we are working on #2917 which is looking to introduce better terminology for this to help make it easier to explain. Feel free to comment on that PR as well with what could help make it more understandable.

@nvoxland nvoxland removed this from the NEXT milestone Jun 13, 2022
@dbyron-sf
Copy link
Author

Thanks for the information @nvoxland . Let me try to answer the specific question you asked.

In the case of Kork, how is the project being set up so that it has db/healthcheck.yml in multiple places?

db/healthcheck.yml exists in src/main/resources in what I think is "the normal way" here. It's part of the kork-sql module/subproject. Also, in what I think is the normal way of things:

  • gradle copies the file to kork-sql/build/resources/main/db/healthcheck.yml as part of the kork-sql:processResources task from gradle's java plugin.
  • As part of gradle's kork-sql:jar task, gradle creates kork-sql/build/libs/kork-sql.jar which (of course) contains db/healthcheck.yml, identical to the one in kork-sql/build/resources/main/db/healthcheck.yml
  • gradle runs the kork-sql:test task with both kork-sql/build/resources/main/db/healthcheck.yml and kork-sql/build/libs/kork-sql.jar are on the classpath.

I think the notion of searchPath specific to changelog files helps make things easier to understand. Doesn't seem like by itself it would fix this issue though.

@JanCizmar
Copy link

I run to the same issue as @dbyron-sf. The only workaround I can think of now (haven't tried yet) is moving tests to other module, which will have only the jar changelog in classpath.

@kataggart
Copy link
Contributor

@nvoxland noting our conversation from this morning, idea:

  • identify what duplicates were found and where they were found
  • provide option for user to configure exclusion logic when duplicate is found (use first first, exclude where .jar file, exclude file paths)

@mamtananavati
Copy link

@nvoxland noting our conversation from this morning, idea:

  • identify what duplicates were found and where they were found
  • provide option for user to configure exclusion logic when duplicate is found (use first first, exclude where .jar file, exclude file paths)

Being able to configure exclusion regex would be super helpful. Is there somewhere this work can be tracked?

@kataggart
Copy link
Contributor

@mamtananavati we haven't started working on this yet; for now this ticket is the best place to track any product improvements we do to help better handle configuration issues that lead to duplicate found files.

@nvoxland
Copy link
Contributor

Thanks for the details, @dbyron-sf. So it sounds like you have a gradle setup where both the original compiled dir and a jar'ed up version of that both end up in the project classpath. From liquibase's standpoint, that gets confusing but I get how it ends up happening.

I'll look a bit at what we could do to handle that better

@kataggart kataggart linked a pull request Jun 27, 2022 that will close this issue
3 tasks
@dbyron-sf
Copy link
Author

Thanks @nvoxland . #3006 looks promising!

@nvoxland
Copy link
Contributor

Thanks. In looking at ways to address this, I made both #3006 and #2917 as possible options.

The problem we're trying to solve with the "duplicate" error is that sometimes people use a generic path like dbchangelog.xml which has multiple completely separate files that they don't realize all get found and we want to protect them from that. Or sometimes they include both a "source" path and also the "compiled" filtered/modified path and we don't know which is which.

I thought a bit on trying to do a checksum or something to determine if the files are the same or not, but that adds a lot of overhead and may not even be possible to read twice depending on the implementation of how the content is read (we make not assumptions on where the resource input comes from).

So there will be two options when the default way your Liquibase runner (gradle-plugin in your case) is setting up the search path has duplicate copies of files:

  1. Set duplicateFileMode=WARN. Then we don't fail and it's on you to make sure there is not actually differences between the copies we found
  2. Set the searchPath to have only one location. This will replace the runner's default search path with whatever you gave it so you can ensure only the jar or only the build dir or whatever is in there

I think between those two options, this issue will be addressed. Anyone disagree?

@dbyron-sf
Copy link
Author

Good point that setting searchPath to have one location would also work, though doing that correctly feels like it may be harder than setting duplicateFileMode to WARN.

Conditioning++ automation moved this from To Do to Done Jun 30, 2022
@kataggart
Copy link
Contributor

@dbyron-sf @mamtananavati @JanCizmar 4.13 is out https://github.com/liquibase/liquibase/releases/tag/v4.13.0

@dbyron-sf
Copy link
Author

Thanks much @kataggart !

dbyron-sf added a commit to dbyron-sf/kork that referenced this issue Jul 20, 2022
…022-0839

introduce SqlMigrationProperty.duplicateFileMode to prevent test failures in
SpringStartupTests.  See liquibase/liquibase#2818 for
background.
@mamtananavati
Copy link

Tried using the DuplicateFileMode setting on liquibase-maven-plugin but it seems to not be recognized , do any of you have examples of the setting working?

@kataggart
Copy link
Contributor

@mamtananavati I will double check to make sure it was added there and if it wasn't, open a new issue to get it resolved. Thanks!

@kataggart
Copy link
Contributor

@mamtananavati we accidentally forgot to add to maven; @nvoxland is adding a PR and we will push that through. Sorry about that.

@marcelstoer
Copy link

marcelstoer commented Sep 15, 2022

I am seeing the same behavior for updates invoked through the Liquibase Maven plugin (stuck at 4.9.1, upgrading from 3.7). Even worse, I am setting liquibase.changeLogDirectory explicitly and it seems to get ignored or overruled:

mvn org.liquibase:liquibase-maven-plugin:$LIQUIBASE_VERSION:update \
-Dliquibase.changeLogFile="$db_changelog" \
-Dliquibase.changeLogDirectory="$resources_folder" \
-Dliquibase.driver=org.postgresql.Driver \
...

[ERROR] Error Reading Changelog File: Found 2 files that match db/changelog/db.changelog-master.xml:
file:/some-dir/target/classes/db/changelog/db.changelog-master.xml,
file:/some-dir/src/main/resources/db/changelog/db.changelog-master.xml

P.S. liquibase.changeLogDirectory maps to org.liquibase.maven.plugins.AbstractLiquibaseChangeLogMojo#changeLogDirectory.

P.P.S. The/one ugly remedy is to use an absolute path for liquibase.changeLogFile, combining $resources_folder/$db_changelog in my case. liquibase.changeLogDirectory doesn't need to be set anymore.

@kataggart
Copy link
Contributor

kataggart commented Sep 16, 2022

@marcelstoer would you mind filing a new issue with the details? Since this issue is closed I don't want your problem to get lost.

Also, not sure if you saw, but the duplicateFileMode was added to the maven plugin here #3119, so that will likely help.

Thanks.

@marcelstoer
Copy link

@kataggart thanks, had planned on doing so anyway: #3282. Also stated there why #3119 is not applicable.

dbyron-sf added a commit to dbyron-sf/kork that referenced this issue Jan 20, 2023
…022-0839

introduce SqlMigrationProperty.duplicateFileMode to prevent test failures in
SpringStartupTests.  See liquibase/liquibase#2818 for
background.
j-sandy added a commit to j-sandy/kork that referenced this issue Mar 21, 2023
 While upgrading spring boot 2.5.x, liquibase version transitively upgrades to 4.3.5. The liquibase version starting from 4.0.0 till 4.12.0 has an [issue](liquibase/liquibase#2818) w.r.t parsing the changelog file, if found at multiple places within the classpath and encounter the below error:
 ```
 Caused by: liquibase.exception.ChangeLogParseException: Error parsing classpath:db/healthcheck.yml
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:89)
	at liquibase.Liquibase.getDatabaseChangeLog(Liquibase.java:369)
	at liquibase.Liquibase.lambda$update$1(Liquibase.java:224)
	at liquibase.Scope.lambda$child$0(Scope.java:180)
	at liquibase.Scope.child(Scope.java:189)
	at liquibase.Scope.child(Scope.java:179)
	at liquibase.Scope.child(Scope.java:158)
	at liquibase.Liquibase.runInScope(Liquibase.java:2405)
	at liquibase.Liquibase.update(Liquibase.java:211)
	at liquibase.Liquibase.update(Liquibase.java:197)
	at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:314)
	at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:269)
	at com.netflix.spinnaker.kork.sql.migration.SpringLiquibaseProxy.afterPropertiesSet(SpringLiquibaseProxy.kt:65)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1858)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1795)
	... 87 more
Caused by: java.io.IOException: Found 2 files that match classpath:db/healthcheck.yml: file:/spinnaker/kork/kork-sql/build/resources/main/db/healthcheck.yml, jar:file:/spinnaker/kork/kork-sql/build/libs/kork-sql.jar!/db/healthcheck.yml
	at liquibase.resource.AbstractResourceAccessor.openStream(AbstractResourceAccessor.java:25)
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:25)
	... 101 more
 ```
 This duplicate changelog issue is fixed in 4.13.0, but identified another issue that gets introduced in 4.13.0. This [issue](liquibase/liquibase#3091) hinders the migration of sql scripts available in [orca](https://github.com/spinnaker/orca/tree/master/orca-sql/src/main/resources/db/changelog), containing `afterColumn`, with a validation error for postgresql.
 The efforts to resolve the issue are in progress, so pinning the version of org.liquibase:liquibase-core to 3.10.3 (latest of 3.x series).
j-sandy added a commit to j-sandy/kork that referenced this issue Mar 30, 2023
 While upgrading spring boot 2.5.x, liquibase version transitively upgrades to 4.3.5. The liquibase version starting from 4.0.0 till 4.12.0 has an [issue](liquibase/liquibase#2818) w.r.t parsing the changelog file, if found at multiple places within the classpath and encounter the below error:
 ```
 Caused by: liquibase.exception.ChangeLogParseException: Error parsing classpath:db/healthcheck.yml
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:89)
	at liquibase.Liquibase.getDatabaseChangeLog(Liquibase.java:369)
	at liquibase.Liquibase.lambda$update$1(Liquibase.java:224)
	at liquibase.Scope.lambda$child$0(Scope.java:180)
	at liquibase.Scope.child(Scope.java:189)
	at liquibase.Scope.child(Scope.java:179)
	at liquibase.Scope.child(Scope.java:158)
	at liquibase.Liquibase.runInScope(Liquibase.java:2405)
	at liquibase.Liquibase.update(Liquibase.java:211)
	at liquibase.Liquibase.update(Liquibase.java:197)
	at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:314)
	at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:269)
	at com.netflix.spinnaker.kork.sql.migration.SpringLiquibaseProxy.afterPropertiesSet(SpringLiquibaseProxy.kt:65)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1858)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1795)
	... 87 more
Caused by: java.io.IOException: Found 2 files that match classpath:db/healthcheck.yml: file:/spinnaker/kork/kork-sql/build/resources/main/db/healthcheck.yml, jar:file:/spinnaker/kork/kork-sql/build/libs/kork-sql.jar!/db/healthcheck.yml
	at liquibase.resource.AbstractResourceAccessor.openStream(AbstractResourceAccessor.java:25)
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:25)
	... 101 more
 ```
 This duplicate changelog issue is fixed in 4.13.0, but identified another issue that gets introduced in 4.13.0. This [issue](liquibase/liquibase#3091) hinders the migration of sql scripts available in [orca](https://github.com/spinnaker/orca/tree/master/orca-sql/src/main/resources/db/changelog), containing `afterColumn`, with a validation error for postgresql.
 The efforts to resolve the issue are in progress, so pinning the version of org.liquibase:liquibase-core to 3.10.3 (latest of 3.x series).
j-sandy added a commit to j-sandy/kork that referenced this issue Mar 31, 2023
 While upgrading spring boot 2.5.x, liquibase version transitively upgrades to 4.3.5. The liquibase version starting from 4.0.0 till 4.12.0 has an [issue](liquibase/liquibase#2818) w.r.t parsing the changelog file, if found at multiple places within the classpath and encounter the below error:
 ```
 Caused by: liquibase.exception.ChangeLogParseException: Error parsing classpath:db/healthcheck.yml
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:89)
	at liquibase.Liquibase.getDatabaseChangeLog(Liquibase.java:369)
	at liquibase.Liquibase.lambda$update$1(Liquibase.java:224)
	at liquibase.Scope.lambda$child$0(Scope.java:180)
	at liquibase.Scope.child(Scope.java:189)
	at liquibase.Scope.child(Scope.java:179)
	at liquibase.Scope.child(Scope.java:158)
	at liquibase.Liquibase.runInScope(Liquibase.java:2405)
	at liquibase.Liquibase.update(Liquibase.java:211)
	at liquibase.Liquibase.update(Liquibase.java:197)
	at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:314)
	at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:269)
	at com.netflix.spinnaker.kork.sql.migration.SpringLiquibaseProxy.afterPropertiesSet(SpringLiquibaseProxy.kt:65)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1858)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1795)
	... 87 more
Caused by: java.io.IOException: Found 2 files that match classpath:db/healthcheck.yml: file:/spinnaker/kork/kork-sql/build/resources/main/db/healthcheck.yml, jar:file:/spinnaker/kork/kork-sql/build/libs/kork-sql.jar!/db/healthcheck.yml
	at liquibase.resource.AbstractResourceAccessor.openStream(AbstractResourceAccessor.java:25)
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:25)
	... 101 more
 ```
 This duplicate changelog issue is fixed in 4.13.0, but identified another issue that gets introduced in 4.13.0. This [issue](liquibase/liquibase#3091) hinders the migration of sql scripts available in [orca](https://github.com/spinnaker/orca/tree/master/orca-sql/src/main/resources/db/changelog), containing `afterColumn`, with a validation error for postgresql.
 The efforts to resolve the issue are in progress, so pinning the version of org.liquibase:liquibase-core to 3.10.3 (latest of 3.x series).
j-sandy added a commit to j-sandy/kork that referenced this issue Mar 31, 2023
 While upgrading spring boot 2.5.x, liquibase version transitively upgrades to 4.3.5. The liquibase version starting from 4.0.0 till 4.12.0 has an [issue](liquibase/liquibase#2818) w.r.t parsing the changelog file, if found at multiple places within the classpath and encounter the below error:
 ```
 Caused by: liquibase.exception.ChangeLogParseException: Error parsing classpath:db/healthcheck.yml
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:89)
	at liquibase.Liquibase.getDatabaseChangeLog(Liquibase.java:369)
	at liquibase.Liquibase.lambda$update$1(Liquibase.java:224)
	at liquibase.Scope.lambda$child$0(Scope.java:180)
	at liquibase.Scope.child(Scope.java:189)
	at liquibase.Scope.child(Scope.java:179)
	at liquibase.Scope.child(Scope.java:158)
	at liquibase.Liquibase.runInScope(Liquibase.java:2405)
	at liquibase.Liquibase.update(Liquibase.java:211)
	at liquibase.Liquibase.update(Liquibase.java:197)
	at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:314)
	at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:269)
	at com.netflix.spinnaker.kork.sql.migration.SpringLiquibaseProxy.afterPropertiesSet(SpringLiquibaseProxy.kt:65)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1858)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1795)
	... 87 more
Caused by: java.io.IOException: Found 2 files that match classpath:db/healthcheck.yml: file:/spinnaker/kork/kork-sql/build/resources/main/db/healthcheck.yml, jar:file:/spinnaker/kork/kork-sql/build/libs/kork-sql.jar!/db/healthcheck.yml
	at liquibase.resource.AbstractResourceAccessor.openStream(AbstractResourceAccessor.java:25)
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:25)
	... 101 more
 ```
 This duplicate changelog issue is fixed in 4.13.0, but identified another issue that gets introduced in 4.13.0. This [issue](liquibase/liquibase#3091) hinders the migration of sql scripts available in [orca](https://github.com/spinnaker/orca/tree/master/orca-sql/src/main/resources/db/changelog), containing `afterColumn`, with a validation error for postgresql.
 The efforts to resolve the issue are in progress, so pinning the version of org.liquibase:liquibase-core to 3.10.3 (latest of 3.x series).
mergify bot pushed a commit to spinnaker/kork that referenced this issue Mar 31, 2023
* chore(dependencies): Upgrade Spring Boot to 2.5.14

* fix(dependency): Issue with kork-jedis while upgrading spring-boot to 2.5.14

While upgrading the spring-boot, the compilation of kork-jedis module failed with following error:
```
> Task :kork-jedis:compileJava FAILED
/kork/kork-jedis/src/main/java/com/netflix/spinnaker/kork/jedis/telemetry/InstrumentedJedis.java:2652: error: slowlogGetBinary(long) in InstrumentedJedis cannot implement slowlogGetBinary(long) in AdvancedBinaryJedisCommands
  public List<byte[]> slowlogGetBinary(long entries) {
                      ^
  return type List<byte[]> is not compatible with List<Object>
/kork/kork-jedis/src/main/java/com/netflix/spinnaker/kork/jedis/telemetry/InstrumentedJedis.java:2646: error: slowlogGetBinary() in InstrumentedJedis cannot implement slowlogGetBinary() in AdvancedBinaryJedisCommands
  public List<byte[]> slowlogGetBinary() {
                      ^
  return type List<byte[]> is not compatible with List<Object>
/kork/kork-jedis/src/main/java/com/netflix/spinnaker/kork/jedis/telemetry/InstrumentedJedis.java:2645: error: method does not override or implement a method from a supertype
  @OverRide
  ^
/kork/kork-jedis/src/main/java/com/netflix/spinnaker/kork/jedis/telemetry/InstrumentedJedis.java:2648: error: incompatible types: inference variable T has incompatible bounds
    return instrumented(command, () -> delegated.slowlogGetBinary());
                       ^
    lower bounds: List<byte[]>,Object
    lower bounds: List<Object>
  where T is a type-variable:
    T extends Object declared in method <T>instrumented(String,Callable<T>)
/kork/kork-jedis/src/main/java/com/netflix/spinnaker/kork/jedis/telemetry/InstrumentedJedis.java:2651: error: method does not override or implement a method from a supertype
  @OverRide
  ^
/kork/kork-jedis/src/main/java/com/netflix/spinnaker/kork/jedis/telemetry/InstrumentedJedis.java:2654: error: incompatible types: inference variable T has incompatible bounds
    return instrumented(command, () -> delegated.slowlogGetBinary(entries));
                       ^
    lower bounds: List<byte[]>,Object
    lower bounds: List<Object>
  where T is a type-variable:
    T extends Object declared in method <T>instrumented(String,Callable<T>)
```

```
> Task :kork-jedis:compileJava FAILED
/kork/kork-jedis/src/main/java/com/netflix/spinnaker/kork/jedis/telemetry/InstrumentedJedisPool.java:84: error: name clash: initPool(GenericObjectPoolConfig,PooledObjectFactory<Jedis>) in InstrumentedJedisPool and initPool(GenericObjectPoolConfig<Jedis>,PooledObjectFactory<Jedis>) in Pool have the same erasure, yet neither overrides the other
  public void initPool(GenericObjectPoolConfig poolConfig, PooledObjectFactory<Jedis> factory) {
              ^
/kork/kork-jedis/src/main/java/com/netflix/spinnaker/kork/jedis/telemetry/InstrumentedJedisPool.java:83: error: method does not override or implement a method from a supertype
  @OverRide
```

The root cause is the upgrade of redis.clients:jedis from 3.3.0 to 3.6.3 as transitive dependency of spring-boot, that brings the breaking changes in APIs as mentioned below:
redis/jedis#2084
redis/jedis#2361

Fixed the issue with required code changes.

* fix(dependency): Issue with kork-web while upgrading spring-boot to 2.5.14

While upgrading the spring-boot, the compilation of kork-web module failed with following error:
```
> Task :kork-web:compileGroovy FAILED
/kork/kork-web/src/main/java/com/netflix/spinnaker/kork/web/controllers/GenericErrorController.java:41: error: incompatible types: Boolean cannot be converted to ErrorAttributeOptions
        errorAttributes.getErrorAttributes(webRequest, includeStackTrace);
                                                       ^
```

```
/kork/kork-web/src/main/java/com/netflix/spinnaker/kork/web/controllers/GenericErrorController.java:51: error: method does not override or implement a method from a supertype
  @OverRide
  ^
```

```
> Task :kork-web:compileGroovy
/kork/kork-web/src/main/java/com/netflix/spinnaker/kork/web/selector/v2/SelectableService.java uses unchecked or unsafe operations.
startup failed:
/kork/kork-web/src/main/groovy/com/netflix/spinnaker/config/ErrorConfiguration.groovy: 37: Method 'getErrorAttributes' from class 'com.netflix.spinnaker.config.ErrorConfiguration$1' does not override method from its superclass or interfaces but is annotated with @OverRide.
 @ line 37, column 7.
         @OverRide
         ^
```
The root cause is the deprecation of following methods in Spring boot 2.3.x and now removal of code from spring boot 2.5.x:

ErrorAttributes.getErrorAttributes(ServerRequest, boolean)
spring-projects/spring-boot@158933c    spring-projects/spring-boot#21324

ErrorController.getErrorPath()
spring-projects/spring-boot#19844

Fixed the issue with required code changes.

* chore (dependency): pinning the io.rest-assured to 4.2.0

Spring boot 2.5.14 upgrade brings io.rest-assured 4.3.3 as transitive dependency.
io.rest-assured 4.3.x require groovy 3.0.2. So, pinning the nearest version using groovy 2.x. After upgrading the groovy to 3.x, pin can be removed. [https://github.com/rest-assured/rest-assured/blob/9b683130c93188cabdef850e89d0c9417d847a17/changelog.txt#L200]

* chore(dependency): pinning ch.qos.logback to 1.2.10

Spring boot 2.5.14 upgrade brings ch.qos.logback 1.2.11 as transitive dependency.
A bug is reported in 1.2.11 [https://jira.qos.ch/browse/LOGBACK-1623] and it is fixed in 1.2.12.
However the 1.2.12 package has not been released yet. So, pinning the version to 1.2.10 untill required package is released.

* chore(dependency): Pinning groovy to 2.5.15 with spring boot 2.5.x upgrade

Spring boot 2.5.x brings groovy 3.x as its transitive dependency.
https://docs.spring.io/spring-boot/docs/2.5.14/reference/html/dependency-versions.html#appendix.dependency-versions

Currently spinnaker services use gradle 6.x, that does not support groovy 3.x.
https://docs.gradle.org/6.8.1/userguide/compatibility.html

Restricting groovy to 2.5.x, till upgrade of gradle to 7.x.
https://docs.gradle.org/current/userguide/resolution_rules.html#sec:denying_version
To avoid transitive upgrade of groovy, pinning it with enforcedPlatform() closure.
It forces version for internal submodules of kork as well as for all the consumer spinnaker services.

* chore(dependency): pin org.liquibase to 3.10.3

 While upgrading spring boot 2.5.x, liquibase version transitively upgrades to 4.3.5. The liquibase version starting from 4.0.0 till 4.12.0 has an [issue](liquibase/liquibase#2818) w.r.t parsing the changelog file, if found at multiple places within the classpath and encounter the below error:
 ```
 Caused by: liquibase.exception.ChangeLogParseException: Error parsing classpath:db/healthcheck.yml
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:89)
	at liquibase.Liquibase.getDatabaseChangeLog(Liquibase.java:369)
	at liquibase.Liquibase.lambda$update$1(Liquibase.java:224)
	at liquibase.Scope.lambda$child$0(Scope.java:180)
	at liquibase.Scope.child(Scope.java:189)
	at liquibase.Scope.child(Scope.java:179)
	at liquibase.Scope.child(Scope.java:158)
	at liquibase.Liquibase.runInScope(Liquibase.java:2405)
	at liquibase.Liquibase.update(Liquibase.java:211)
	at liquibase.Liquibase.update(Liquibase.java:197)
	at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:314)
	at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:269)
	at com.netflix.spinnaker.kork.sql.migration.SpringLiquibaseProxy.afterPropertiesSet(SpringLiquibaseProxy.kt:65)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1858)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1795)
	... 87 more
Caused by: java.io.IOException: Found 2 files that match classpath:db/healthcheck.yml: file:/spinnaker/kork/kork-sql/build/resources/main/db/healthcheck.yml, jar:file:/spinnaker/kork/kork-sql/build/libs/kork-sql.jar!/db/healthcheck.yml
	at liquibase.resource.AbstractResourceAccessor.openStream(AbstractResourceAccessor.java:25)
	at liquibase.parser.core.yaml.YamlChangeLogParser.parse(YamlChangeLogParser.java:25)
	... 101 more
 ```
 This duplicate changelog issue is fixed in 4.13.0, but identified another issue that gets introduced in 4.13.0. This [issue](liquibase/liquibase#3091) hinders the migration of sql scripts available in [orca](https://github.com/spinnaker/orca/tree/master/orca-sql/src/main/resources/db/changelog), containing `afterColumn`, with a validation error for postgresql.
 The efforts to resolve the issue are in progress, so pinning the version of org.liquibase:liquibase-core to 3.10.3 (latest of 3.x series).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment