postgresqlgithub-actionsliquibasechangelog

Can you use property subsitution in liquibase changelog?


I am using github actions to run my liquibase deployments. I have variables that I want to substitute into my liquibase script during deployment the liquibase article here states that this should be possible. I have a changelog.json that simply includes the sql files like so:

"databaseChangeLog": [
    {
           "include":{"file": "path-to-sql/my_file.sql"}
    }
]

now in my_file.sql I have:

--changeset author:1
create user my-user with password ${MY_ENV};

However, I receive the error:

Unexpected error running Liquibase: Migration failed for changeset my_file.sql:
    Reason: liquibase.exception.DatabaseException: ERROR: syntax error at or near "$"...

Any one come across this specific error with variable substitution? Is this just a syntax error? Thanks.


Solution

  • You can use the -d parameter,

    -D<property.name>=<property.value> Pass a name/value pair for substitution of ${} blocks in the changelogs.

    For example:

    --liquibase formatted sql
    
    --changeset your.name:1 labels:example-label context:example-context
    --comment: example comment
    create table ${daTableName} (
        id int primary key auto_increment not null,
        name varchar(50) not null,
        address1 varchar(50),
        address2 varchar(50),
        city varchar(30)
    )
    --rollback DROP TABLE ${daTableName};
    

    And the command:

    liquibase update -DdaTableName=MySofExampleTable
    

    Did work for me

    h2 example

    Note that this approach will log your variables in Github actions, and in your case the value represents a password so be carful with that, or you add this value to your liquibase.properties file, for example

    parameter.daTableName=SomeTable
    

    then you just run your liquibase commands without passing the -d parameter.

    From Github actions side, you would fetch the secret, and ammend it to your properties file, for example:

    jobs:
      foo:
        runs-on: ubuntu-latest
        steps:
          - run: echo "liquibase.MY_ENV=${{ secrets.MY_SECRET }}" >> liquibase.properties
    

    Or as a plan-B for some use-cases, you can use envsubst to replace your environment variables, for example:

    jobs:
      foo:
        runs-on: ubuntu-latest
        steps:
          - run: echo "create user my-user with password \${MY_ENV};" > my-migration.template.sql
          - run: envsubst < my-migration.template.sql > my-migration.sql
            env:
             MY_ENV: bob
          - run: cat my-migration.sql 
    

    Result:

    jobs screenshot

    So you basically create actions (or scripts) that replace your environment variables, if you have multiple files you may do something like:

    for f in $(find ./lqb-src -regex '.*\.sql'); do envsubst < $f > "./lqb-out/$(basename $f)"; done