Skip to content

Conversation

@b-gyula
Copy link
Contributor

@b-gyula b-gyula commented Nov 3, 2025

Impact

  • Bug fix (non-breaking change which fixes expected existing functionality)
  • Enhancement/New feature (adds functionality without impacting existing logic)
  • Breaking change (fix or feature that would cause existing functionality to change)

Description

Starting include@file, includeAll@path, property@file with . sets relativeToChangelogFile true by default

Improved error handling for theses attributes:

  • missing file, value or name for 'property' resulted in NullPointerException: Cannot invoke "String.equalsIgnoreCase(String)" because the return value of "liquibase.changelog.ChangeLogParameters$ChangeLogParameter.getKey()" is null.

    new error message: Either 'file' or 'name' + 'value' must be set for 'property'

  • Warning if 'file' is set for 'property', then 'value' and 'name' are ignored

<databaseChangeLog>
  <property file='a' name='n' />
  • Empty name attribute for property created a property with no name silently, which of course could not be used. Now results error message: 'value' is required for 'property' when 'name' is set
<databaseChangeLog>
  <property name='' />
  • empty file attribute for include and property results a nice error message 'file' is empty for 'include' instead of a cryptic error listing all files on the search path
<databaseChangeLog>
  <property file: ''/>
  • Add ' character around both the field and the tag in validation error messages like 'file' is empty for 'include'

Things to be aware of

The same ValidationErrors is used in DatabaseChangeLog as everywhere else.

Things to worry about

Additional Context

Summary by CodeRabbit

  • Bug Fixes

    • Error messages now display quoted field and change names for improved readability
    • Strengthened validation for property files and include/includeAll changelog operations
    • Improved relative path resolution for changelog file references
  • Chores

    • Updated test suite patterns and validation error handling

…uired for 'includeAll' instead of: Unexpected error running Liquibase: Error parsing inc.yml : null

- missing `file`, `value` or `name` resulted in NullPointerException:  Cannot invoke "String.equalsIgnoreCase(String)" because the return value of "liquibase.changelog.ChangeLogParameters$ChangeLogParameter.getKey()" is null new : Either 'file' or 'name' + 'value' must be set for 'property'
- empty `file` attribute for `include` results a nice error message `'file' is empty for 'include'` instead of a cryptic error listing all files on the search path
- starting `include@file`, `includeAll@path`, `property@file` with `.` sets `relativeToChangelogFile` true by default
- Warning if 'file' is set for 'property', then 'value' and 'name' are ignored
- Add ' character around both the field and the tag in validation error messages like `'file' is empty for 'include'`
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link

coderabbitai bot commented Nov 3, 2025

Walkthrough

DatabaseChangeLog refactored to use Lombok for generated setters on multiple fields. New helper methods introduced for validation and relative path resolution. ValidationErrors updated with Lombok @Getter annotations. New constructor added for DatabaseChangeLog. Error message formatting updated to quote identifiers. Tests updated to align with new validation behavior.

Changes

Cohort / File(s) Change Summary
Core DatabaseChangeLog Refactoring
liquibase-standard/src/main/java/liquibase/changelog/DatabaseChangeLog.java
Added Lombok @Setter to: physicalFilePath, rootChangeLog, parentChangeLog, contextFilter, includeContextFilter, includeIgnore, runtimeEnvironment, logicalFilePath. Added @Accessors(chain = true) to changeLogParameters. Introduced helper methods throwIf(ValidationErrors) and getRelativeToChangelog(ParsedNode, String). Added constructor DatabaseChangeLog(String, ChangeLogParameters). Updated property and include handling logic.
ValidationErrors Lombok Upgrade
liquibase-standard/src/main/java/liquibase/exception/ValidationErrors.java
Replaced explicit getErrorMessages() and getWarningMessages() with Lombok @Getter annotations. Updated error message formatting to quote field names and change identifiers (e.g., "'field' is required for 'change'").
Path Normalization Utility
liquibase-standard/src/main/java/liquibase/sdk/resource/MockResourceAccessor.java
Added static import and usage of normalizePath from DatabaseChangeLog for consistent path handling in getAll() method.
Test Updates - Core Changelog
liquibase-standard/src/test/groovy/liquibase/changelog/DatabaseChangeLogTest.groovy
Removed explicit ChangeLogParameters initializations. Added tests for include/includeAll relative path behavior, property file handling, and error scenarios. Added ParsedNodeException import.
Test Updates - Error Messages
liquibase-standard/src/test/groovy/liquibase/change/AbstractChangeTest.groovy, liquibase-standard/src/test/groovy/liquibase/change/core/LoadDataChangeTest.groovy
Updated expected error messages to reflect new quoting format for field and change identifiers.
Test Updates - ValidationErrors
liquibase-standard/src/test/groovy/liquibase/exception/ValidationErrorsTests.groovy
Updated test expectations for new quoted error message format. Added test methods checkRequiredField_nullValue() and hasErrors(). Added static imports for assertion utilities.
Removed Test File
liquibase-standard/src/test/java/liquibase/exception/ValidatorErrorsTest.java
Deleted Java test file; functionality migrated to Groovy test equivalent ValidationErrorsTests.groovy.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • DatabaseChangeLog.java: Requires careful review of Lombok annotation placement, new helper methods (throwIf, getRelativeToChangelog), updated property/include handling logic, and the new constructor. The refactored context resolution and path handling merit close attention.
  • Error message formatting changes: Verify that all quoted identifier patterns are consistently applied across ValidationErrors and dependent test updates.
  • Test coverage expansion: Ensure new include/includeAll and property file tests are comprehensive and cover error paths.
  • Cross-file consistency: Confirm Lombok-generated setters are properly leveraged throughout and that path normalization via MockResourceAccessor integrates correctly.

Poem

🐰 Hop, hop, hooray! New setters bloom,
Lombok enchantments chase the gloom,
Validation speaks in quoted rhyme,
Helper methods keeping paths sublime,
From constructor dreams to test delight—
This changelog changelog shines so bright! ✨

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main behavior changes: include(All) and property file/path attributes starting with '.' now set relativeToChangelogFile true by default, which is the primary feature being introduced.
Description check ✅ Passed The description covers the main impact (Enhancement/New feature), describes the feature and improved error handling with concrete examples, mentions technical considerations, and includes test updates. However, it lacks specific GitHub issue references (no 'Fixes #XXXX').
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

@jnewton03
Copy link
Contributor

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Nov 4, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
liquibase-standard/src/test/groovy/liquibase/exception/ValidationErrorsTests.groovy (1)

6-8: Remove duplicate import.

Line 7 and line 8 both import assertTrue, creating a duplicate import statement.

Apply this diff to remove the duplicate:

 import static org.junit.Assert.assertFalse
 import static org.junit.Assert.assertTrue
-import static org.junit.Assert.assertTrue
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c5bacdf and d54631d.

📒 Files selected for processing (8)
  • liquibase-standard/src/main/java/liquibase/changelog/DatabaseChangeLog.java (16 hunks)
  • liquibase-standard/src/main/java/liquibase/exception/ValidationErrors.java (4 hunks)
  • liquibase-standard/src/main/java/liquibase/sdk/resource/MockResourceAccessor.java (2 hunks)
  • liquibase-standard/src/test/groovy/liquibase/change/AbstractChangeTest.groovy (1 hunks)
  • liquibase-standard/src/test/groovy/liquibase/change/core/LoadDataChangeTest.groovy (1 hunks)
  • liquibase-standard/src/test/groovy/liquibase/changelog/DatabaseChangeLogTest.groovy (3 hunks)
  • liquibase-standard/src/test/groovy/liquibase/exception/ValidationErrorsTests.groovy (4 hunks)
  • liquibase-standard/src/test/java/liquibase/exception/ValidatorErrorsTest.java (0 hunks)
💤 Files with no reviewable changes (1)
  • liquibase-standard/src/test/java/liquibase/exception/ValidatorErrorsTest.java
🔇 Additional comments (17)
liquibase-standard/src/test/groovy/liquibase/change/AbstractChangeTest.groovy (1)

256-256: LGTM!

The test correctly reflects the new error message format with quoted field and change names, aligning with the ValidationErrors updates.

liquibase-standard/src/test/groovy/liquibase/change/core/LoadDataChangeTest.groovy (1)

932-932: LGTM!

The test correctly reflects the new error message format with quoted identifiers.

liquibase-standard/src/test/groovy/liquibase/changelog/DatabaseChangeLogTest.groovy (5)

643-655: LGTM!

The test validates that properties can be loaded from a file specified with a relative path starting with './', correctly verifying the new default behavior for relative path resolution.


1151-1161: LGTM!

The test confirms that include files with paths starting with './' are correctly resolved relative to the changelog.


1162-1171: LGTM!

The test confirms that includeAll paths starting with './' are correctly resolved relative to the changelog.


1173-1185: LGTM!

The test validates that properties can be loaded from a relative properties file, confirming the feature works end-to-end.


1187-1220: LGTM!

Comprehensive error case testing for property definitions and include/includeAll tags. The tests validate:

  • Missing required fields
  • Empty field values
  • Clear, quoted error messages
liquibase-standard/src/test/groovy/liquibase/exception/ValidationErrorsTests.groovy (2)

22-27: LGTM!

The tests correctly reflect the new error message format with quoted field and change names.

Also applies to: 41-45


58-77: LGTM!

The new tests add valuable coverage for checkRequiredField and hasErrors methods, validating the expected behavior.

liquibase-standard/src/main/java/liquibase/exception/ValidationErrors.java (2)

19-22: LGTM!

Lombok @Getter annotations appropriately replace explicit getter methods, reducing boilerplate while maintaining the same public API.


76-90: LGTM!

The error message updates consistently quote field names and change names, improving readability and clarity for end users.

liquibase-standard/src/main/java/liquibase/changelog/DatabaseChangeLog.java (6)

167-170: LGTM!

The new constructor provides a convenient way to initialize both the physical file path and change log parameters together, maintaining backward compatibility with the existing single-argument constructor.


489-497: LGTM!

The new helper methods improve code clarity:

  • throwIf centralizes validation error handling
  • getRelativeToChangelog implements the PR's core feature: defaulting to relativeToChangelogFile=true when the path starts with '.'

581-613: LGTM!

The refactored handleIncludeAll method:

  • Uses throwIf for validation (line 584)
  • Applies getRelativeToChangelog for relative path resolution (line 602)
  • Uses determineContextExpression for consistent context handling (line 606)

The changes align with the PR objectives and improve code consistency.


616-638: LGTM!

The refactored handleInclude method:

  • Uses throwIf for validation (line 619)
  • Applies getRelativeToChangelog for relative path resolution (line 626)
  • Maintains backward compatibility while adding the new default behavior

640-646: LGTM!

The determineContextExpression helper method centralizes context expression resolution logic, checking contextFilter first and falling back to context. This improves code maintainability.


499-564: No issues found—the warning logic is correctly guarded.

The condition at line 521 (if(null != value || null != name)) correctly ensures the warning logs only when at least one of name or value is provided. When only file is specified (both name and value are null), the warning is properly suppressed. The property handling for this edge case is already correct as implemented.

Comment on lines 29 to 31
public List<Resource> getAll(String path) throws IOException {
path = path.replace("\\", "/");
path = normalizePath(path);
String content = contentByFileName.get(path);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify consistent path normalization across methods.

The getAll method now uses DatabaseChangeLog.normalizePath, but the search method (line 45) still uses the old path.replace("\\", "/") approach. This inconsistency could lead to different path resolution behavior between these methods.


🏁 Script executed:

#!/bin/bash
# Check if search method in MockResourceAccessor should also use normalizePath
rg -n "def search|public.*search" liquibase-standard/src/main/java/liquibase/sdk/resource/MockResourceAccessor.java -A 10

Length of output: 561



🏁 Script executed:

#!/bin/bash
# Get complete MockResourceAccessor.java to see all path handling
cat liquibase-standard/src/main/java/liquibase/sdk/resource/MockResourceAccessor.java

Length of output: 1927


🏁 Script executed:

#!/bin/bash
# Check what normalizePath does in DatabaseChangeLog
rg -n "public.*static.*normalizePath|private.*static.*normalizePath" -A 5 -B 2

Length of output: 1798


🏁 Script executed:

#!/bin/bash
# Check if there are other path manipulations in MockResourceAccessor
rg -n "replace.*\\\\\\\\" liquibase-standard/src/main/java/liquibase/sdk/resource/MockResourceAccessor.java

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Check what imports are at the top of MockResourceAccessor
head -30 liquibase-standard/src/main/java/liquibase/sdk/resource/MockResourceAccessor.java

Length of output: 775


Replace path normalization in search() method to use normalizePath().

The inconsistency is confirmed. The search() method at line 45 still uses path.replace("\\", "/") while getAll() uses normalizePath(). Since normalizePath() handles null values and protocol prefixes (like classpath protocol), the simple string replacement is insufficient. This causes search() to potentially fail to match paths that are stored with protocol handling. Change line 45 to use normalizePath(path) for consistency with the rest of the class.

🤖 Prompt for AI Agents
In
liquibase-standard/src/main/java/liquibase/sdk/resource/MockResourceAccessor.java
around lines 29 to 31 (and specifically the search() call at line 45), the
search() method currently normalizes paths with path.replace("\\", "/") which is
inconsistent with getAll() that uses normalizePath(); update search() to call
normalizePath(path) instead so nulls and protocol prefixes (e.g., classpath:)
are handled consistently; ensure you replace the simple replace call with
normalizePath(path) and use the returned normalized value for matching.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants