在Liquibase脚本上执行检查 [英] Performing checks on Liquibase scripts

查看:143
本文介绍了在Liquibase脚本上执行检查的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Oracle上部署Liquibase脚本时,我经常遇到问题,因为在部署它们之前,我没有一种简单的方法来运行它们.它们始终可以在新的H2 DB上正常运行,但是当我在管道中进行部署时,我经常会遇到一些基本问题.

I regularly face issues when deploying my Liquibase scripts on Oracle, because I don't have an easy way to run them before I deploy them. They always run fine on a fresh H2 DB, but when I deploy in the pipeline, I often face basic issues.

我想之前对脚本进行一些质量检查,通常将其作为构建的一部分.有没有简单的方法可以做到这一点?例如,对于Oracle来说,检查列和表名的时间不太长.一些基本操作,因为我不经常这样做,所以我往往会忘记该限制,而当我在Oracle上进行部署时,我会感到非常惊讶..

I would like to implement some quality checks on my scripts before they are deployed, typically as part of the build. Is there an easy way to do that ? For example, something basic like checking that column and table names are not too long for Oracle.. Because I don't do it very often, I tend to forget about that limit, and when I deploy on Oracle, I get a bad surprise..

谢谢!

推荐答案

我找到了一种方法来解析我创建的最新Liquibase文件,并执行一些基本检查.我想可以将其扩展用于更高级的检查,但这已经非常不错了.这是4个使用AssertJ进行断言的测试

I found a way to parse the latest Liquibase files I create, and perform some basic checks. I guess this can be extended for more advanced checks, but that's already quite nice. Here are 4 tests, using AssertJ for assertions

import liquibase.change.core.AddColumnChange;
import liquibase.change.core.CreateTableChange;
import liquibase.change.core.RenameColumnChange;
import liquibase.change.core.RenameTableChange;
import liquibase.changelog.ChangeLogParameters;
import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.exception.ChangeLogParseException;
import liquibase.parser.core.yaml.YamlChangeLogParser;
import liquibase.resource.FileSystemResourceAccessor;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;

public class LiquibaseScriptsTest {

    public static final String LIQUIBASE_FILES_LOCATION = "src/main/resources/db/changelog/changes/*.yml";

    public static final int NB_LAST_FILES_TO_CHECK = 5;

    private static final int ORACLE_TABLE_NAME_MAX_LENGTH = 30;

    private static final int ORACLE_COLUMN_NAME_MAX_LENGTH = 30;

    private List<DatabaseChangeLog> scriptsToCheck;

    private final static Comparator<Resource> resourceComparator = (r1, r2) -> r1.getFilename().compareTo(r2.getFilename());

    private static YamlChangeLogParser parser = new YamlChangeLogParser();

    @Before
    public void setUp() throws IOException {

        ResourcePatternResolver resourceFinder = new PathMatchingResourcePatternResolver(this.getClass().getClassLoader());
        Resource[] resources = resourceFinder.getResources("file:" + LIQUIBASE_FILES_LOCATION);

        scriptsToCheck = Arrays.asList(resources).stream()
                //looking only at the latest files, assuming their name is indexed
                .sorted(resourceComparator.reversed())
                .limit(NB_LAST_FILES_TO_CHECK)
                .map(r -> toLiquibaseScript(r))
                .collect(toList());
    }

    @Test
    public void someScriptsAreChecked() {
        assertThat(scriptsToCheck).as("There's no script to check - are you sure you configured the path correctly ? ").isNotEmpty();
        assertThat(scriptsToCheck.size()).isLessThanOrEqualTo(NB_LAST_FILES_TO_CHECK);
    }

    @Test
    public void tableNamesShouldBeLessThanOracleMaxSize_whenCreated() {

        Stream<CreateTableChange> createTableChanges = getChangesAsStreamOf(CreateTableChange.class);

        createTableChanges.forEach(tableCreationChange -> {

            assertThat(tableCreationChange.getTableName().length())
                    .as("change " + tableCreationChange.getChangeSet().getId() + " - table name is too long - " +
                            tableCreationChange.getTableName() + " is " + tableCreationChange.getTableName().length() +
                            "char long while maximum for Oracle is " + ORACLE_TABLE_NAME_MAX_LENGTH)
                    .isLessThanOrEqualTo(ORACLE_TABLE_NAME_MAX_LENGTH);
        });
    }

    @Test
    public void tableNamesShouldBeLessThanOracleMaxSize_whenModified() {

        Stream<RenameTableChange> renameTableChanges = getChangesAsStreamOf(RenameTableChange.class);

        renameTableChanges.forEach(tableRenameChange -> {

            assertThat(tableRenameChange.getNewTableName().length())
                    .as("change " + tableRenameChange.getChangeSet().getId() + " - table name is too long - " +
                            tableRenameChange.getNewTableName() + " is " + tableRenameChange.getNewTableName().length() +
                            "char long while maximum for Oracle is " + ORACLE_TABLE_NAME_MAX_LENGTH)
                    .isLessThanOrEqualTo(ORACLE_TABLE_NAME_MAX_LENGTH);
        });
    }

    @Test
    public void columnNamesShouldBeLessThanOracleMaxSize_whenCreated() {

        Stream<AddColumnChange> addColumnChanges = getChangesAsStreamOf(AddColumnChange.class);

        addColumnChanges.flatMap(columnCreationChanges -> columnCreationChanges.getColumns().stream())
                        .forEach(columnCreationChange -> {

                    assertThat(columnCreationChange.getName().length())
                            .as("column name is too long - " + columnCreationChange.getName() + " is " + columnCreationChange.getName().length() +
                                    "char long while maximum for Oracle is " + ORACLE_COLUMN_NAME_MAX_LENGTH)
                            .isLessThanOrEqualTo(ORACLE_COLUMN_NAME_MAX_LENGTH);

                });
    }

    @Test
    public void columnNamesShouldBeLessThanOracleMaxSize_whenModified() {

        Stream<RenameColumnChange> renameColumnChanges = getChangesAsStreamOf(RenameColumnChange.class);

        renameColumnChanges.forEach(columnRenameChange -> {

                    assertThat(columnRenameChange.getNewColumnName().length())
                            .as("column name is too long - " + columnRenameChange.getNewColumnName() + " is " +
                                    columnRenameChange.getNewColumnName().length() + "char long while maximum for Oracle is " +
                                    ORACLE_COLUMN_NAME_MAX_LENGTH)
                            .isLessThanOrEqualTo(ORACLE_COLUMN_NAME_MAX_LENGTH);

                });
    }

    private <E> Stream<E> getChangesAsStreamOf(Class E) {
        Stream<Stream<ChangeSet>> changeSets = scriptsToCheck.stream().map(script -> script.getChangeSets().stream());

        Stream<ChangeSet> changeSetStream = changeSets.flatMap(changeSet -> changeSet);

        return changeSetStream.flatMap(changeSet -> changeSet.getChanges().stream())
                .filter(E::isInstance)
                .map(change -> (E) change);
    }

    private DatabaseChangeLog toLiquibaseScript(Resource r) {
        try {

            System.out.println("going to apply checks on "+r.getFilename());

            return parser.parse(r.getFile().getCanonicalPath(), new ChangeLogParameters(), new FileSystemResourceAccessor());
        } catch (ChangeLogParseException | IOException e) {
            fail("couldn't parse Liquibase script - " + r.getFilename() + " - " + e.getMessage());
        }
        return null;
    }
}

这篇关于在Liquibase脚本上执行检查的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆