Custom Policy Checks
Custom Policy Checks are Python scripts that allow you run advanced policies using the Liquibase Policy Checks framework. Custom policy checks allow you to enforce compliance for a wide array of security, code standards, data quality, and more.
While it's possible to configure the behavior of many built-in Liquibase policy checks using regular expressions, those checks only work for predefined use-cases. Sometimes, they might not be robust enough for your needs. In contrast, you can use custom policy checks to create unique checks for any situation in your Liquibase workflow.
Note: This is a Liquibase Pro feature, so you need a Liquibase Pro License Key to use it.
Quickstart: Create a custom policy check
For a step-by-step tutorial, see Create a Custom Policy Check.
Liquibase checks framework
The logic of a custom policy check is stored in a Python (.py
) script file in your Liquibase working directory. You can write and modify that script without using Liquibase commands: it's just a Python file. You should keep the logic for different checks in different Python files.
You can integrate your Python file into Liquibase by using the same Policy Checks Commands you would use to copy a built-in policy check. Specifically, there is a built-in policy check called CustomChecksTemplate
that you can copy and customize to specify your own logic. In the CLI, you specify a short name for your custom check in Liquibase, the Python script containing the check logic to run, and other configurations like the check's severity level.
Since a custom policy check runs in the Liquibase policy checks framework, you can deploy custom policy checks into your CI/CD automation the same way as built-in checks. This allows your code to be robust but keeps your processes simple.
Python script looping
Liquibase always runs every enabled policy check against every object the check targets. This works the same for custom policy checks. For example, Liquibase runs any custom policy check with a scope of:
changelog
: once per changeset in that changelog. If the changelog usesinclude
orincludeAll
to reference child changelogs, the script also runs once per changeset in each of those changelogs.database
: once per database object.
Warning: If you write a custom policy check that is individually performance-heavy, and you have a very large changelog or database, Liquibase may take a long time to run your custom check iteratively.
Python helper scripts
Liquibase has a public API that you can import in your Python scripts in order to access a library of Liquibase helper scripts. For example, there are helper scripts to find the author of a changeset and to determine whether a database object is a table.
Using helper scripts makes it easier to access information in Liquibase resources and your database. This way, you can keep your Python scripts concise.
Python script pseudocode
Your Python script contains:
- Imports of useful Liquibase helper scripts to access the Liquibase API
- Clearly named variables that call on functions in the helper scripts (for ease of use)
- The logic of your custom check. The code for Liquibase to run against your changelog or database.
- A default return code (
False
)
import helpers
some_variable = helpers.get_useful_object()
particular_changeset = helpers.other_function()
for change_type in particular_changeset:
if some condition is met, then do the following:
tell liquibase: the check triggered!
send this message: "NOOOOO"
exit script with return code 1
otherwise, return false
Note: Remember that your Python script should test a single changeset. Liquibase then iterates it across your entire changelog.
import helpers
some_variable = helpers.get_useful_object()
database_object = helpers.get_database_object()
if some condition is met, then do the following:
tell liquibase: the check triggered!
send this message: "NOOOOO"
exit script with return code 1
otherwise, return false
Note: Remember that your Python script should test a single database object. Liquibase then iterates it across your entire database.