mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-19 16:57:40 +03:00
Check trigger dao migrations digests (#7908)
* Check the trigger dao migrations digest Following the example of the corresponding ledger on SQL tests. The digests had to be updated as both of them had gone out of sync. The init digest presumably due to the change in #7226 and the one for adding the access token during review of #7890. changelog_begin changelog_end * define abstract migrations test * Use abstract migrations test in trigger service tests * use abstract migrations test in ledger on SQL * Retain check for number of .sql resources * Factor out the hash-migrations script * Consistent shell settings Addressing review comment Co-authored-by: Andreas Herrmann <andreas.herrmann@tweag.io>
This commit is contained in:
parent
08e1dc34ef
commit
9758b2f85b
@ -216,6 +216,7 @@ da_scala_test_suite(
|
||||
"//ledger/participant-state/kvutils",
|
||||
"//ledger/participant-state/kvutils:kvutils-tests-lib",
|
||||
"//libs-scala/contextualized-logging",
|
||||
"//libs-scala/flyway-testing",
|
||||
"//libs-scala/postgresql-testing",
|
||||
"//libs-scala/resources",
|
||||
"@maven//:com_typesafe_akka_akka_actor_2_12",
|
||||
|
@ -3,11 +3,10 @@
|
||||
# Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -e
|
||||
set -u
|
||||
set -eou pipefail
|
||||
shopt -s globstar
|
||||
|
||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
|
||||
for file in "$DIR"/src/main/resources/com/daml/ledger/on/sql/migrations/**/*.sql; do
|
||||
shasum -a 256 "$file" | awk '{ print $1 }' > "$file.sha256"
|
||||
done
|
||||
"$DIR"/../../libs-scala/flyway-testing/hash-migrations.sh \
|
||||
"$DIR"/src/main/resources/com/daml/ledger/on/sql/migrations/**/*.sql
|
||||
|
@ -3,76 +3,10 @@
|
||||
|
||||
package com.daml.ledger.on.sql
|
||||
|
||||
import java.io.{BufferedReader, FileNotFoundException}
|
||||
import java.math.BigInteger
|
||||
import java.nio.charset.Charset
|
||||
import java.security.MessageDigest
|
||||
import java.util
|
||||
import com.daml.flyway.AbstractImmutableMigrationsSpec
|
||||
|
||||
import com.daml.ledger.on.sql.ImmutableMigrationsSpec._
|
||||
import org.flywaydb.core.Flyway
|
||||
import org.flywaydb.core.api.configuration.FluentConfiguration
|
||||
import org.flywaydb.core.internal.resource.LoadableResource
|
||||
import org.flywaydb.core.internal.scanner.{LocationScannerCache, ResourceNameCache, Scanner}
|
||||
import org.scalatest.Matchers._
|
||||
import org.scalatest.WordSpec
|
||||
|
||||
import scala.collection.JavaConverters._
|
||||
|
||||
class ImmutableMigrationsSpec extends WordSpec {
|
||||
"migration files" should {
|
||||
"never change, according to their accompanying digest file" in {
|
||||
val configuration = Flyway
|
||||
.configure()
|
||||
.locations(s"classpath:/$migrationsResourcePath")
|
||||
val resourceScanner = flywayScanner(configuration)
|
||||
val resources = resourceScanner.getResources("", ".sql").asScala.toSeq
|
||||
resources.size should be >= 3
|
||||
|
||||
resources.foreach { resource =>
|
||||
val migrationFile = resource.getRelativePath
|
||||
val digestFile = migrationFile + ".sha256"
|
||||
val expectedDigest = readExpectedDigest(digestFile, resourceScanner)
|
||||
val currentDigest = computeCurrentDigest(resource, configuration.getEncoding)
|
||||
assert(
|
||||
currentDigest == expectedDigest,
|
||||
s"""The contents of the migration file "$migrationFile" have changed! Migrations are immutable; you must not change their contents or their digest.""",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ImmutableMigrationsSpec {
|
||||
private val migrationsResourcePath = "com/daml/ledger/on/sql/migrations"
|
||||
private val hashMigrationsScriptPath = "ledger/ledger-on-sql/hash-migrations.sh"
|
||||
|
||||
private def flywayScanner(configuration: FluentConfiguration) =
|
||||
new Scanner(
|
||||
classOf[Object],
|
||||
util.Arrays.asList(configuration.getLocations: _*),
|
||||
getClass.getClassLoader,
|
||||
configuration.getEncoding,
|
||||
new ResourceNameCache,
|
||||
new LocationScannerCache,
|
||||
)
|
||||
|
||||
private def readExpectedDigest(
|
||||
digestFile: String,
|
||||
resourceScanner: Scanner[_],
|
||||
): String = {
|
||||
val resource = Option(resourceScanner.getResource(digestFile))
|
||||
.getOrElse(throw new FileNotFoundException(
|
||||
s"""\"$digestFile\" is missing. If you are introducing a new Flyway migration step, you need to create an SHA-256 digest file by running $hashMigrationsScriptPath."""))
|
||||
new BufferedReader(resource.read()).readLine()
|
||||
}
|
||||
|
||||
private def computeCurrentDigest(resource: LoadableResource, encoding: Charset): String = {
|
||||
val sha256 = MessageDigest.getInstance("SHA-256")
|
||||
new BufferedReader(resource.read())
|
||||
.lines()
|
||||
.forEach(line => sha256.update((line + "\n").getBytes(encoding)))
|
||||
val digest = sha256.digest()
|
||||
String.format(s"%0${digest.length * 2}x", new BigInteger(1, digest))
|
||||
}
|
||||
class ImmutableMigrationsSpec extends AbstractImmutableMigrationsSpec {
|
||||
protected override val migrationsResourcePath = "com/daml/ledger/on/sql/migrations"
|
||||
protected override val migrationsMinSize = 3
|
||||
protected override val hashMigrationsScriptPath = "ledger/ledger-on-sql/hash-migrations.sh"
|
||||
}
|
||||
|
16
libs-scala/flyway-testing/BUILD.bazel
Normal file
16
libs-scala/flyway-testing/BUILD.bazel
Normal file
@ -0,0 +1,16 @@
|
||||
# Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
load("//bazel_tools:scala.bzl", "da_scala_library")
|
||||
|
||||
da_scala_library(
|
||||
name = "flyway-testing",
|
||||
srcs = glob(["src/main/scala/**/*.scala"]),
|
||||
tags = ["maven_coordinates=com.daml:flyway-testing:__VERSION__"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"@maven//:org_flywaydb_flyway_core",
|
||||
"@maven//:org_scalactic_scalactic_2_12",
|
||||
"@maven//:org_scalatest_scalatest_2_12",
|
||||
],
|
||||
)
|
10
libs-scala/flyway-testing/hash-migrations.sh
Executable file
10
libs-scala/flyway-testing/hash-migrations.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -eou pipefail
|
||||
|
||||
for file in "$@"; do
|
||||
shasum -a 256 "$file" | awk '{ print $1 }' > "$file.sha256"
|
||||
done
|
@ -0,0 +1,76 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.flyway
|
||||
|
||||
import java.io.{BufferedReader, FileNotFoundException}
|
||||
import java.math.BigInteger
|
||||
import java.nio.charset.Charset
|
||||
import java.security.MessageDigest
|
||||
import java.util
|
||||
|
||||
import org.flywaydb.core.Flyway
|
||||
import org.flywaydb.core.api.configuration.FluentConfiguration
|
||||
import org.flywaydb.core.internal.resource.LoadableResource
|
||||
import org.flywaydb.core.internal.scanner.{LocationScannerCache, ResourceNameCache, Scanner}
|
||||
import org.scalatest.Matchers._
|
||||
import org.scalatest.WordSpec
|
||||
|
||||
import scala.collection.JavaConverters._
|
||||
|
||||
abstract class AbstractImmutableMigrationsSpec extends WordSpec {
|
||||
protected def migrationsResourcePath: String
|
||||
protected def migrationsMinSize: Int
|
||||
protected def hashMigrationsScriptPath: String
|
||||
|
||||
private def flywayScanner(configuration: FluentConfiguration) =
|
||||
new Scanner(
|
||||
classOf[Object],
|
||||
util.Arrays.asList(configuration.getLocations: _*),
|
||||
getClass.getClassLoader,
|
||||
configuration.getEncoding,
|
||||
new ResourceNameCache,
|
||||
new LocationScannerCache,
|
||||
)
|
||||
|
||||
private def readExpectedDigest(
|
||||
digestFile: String,
|
||||
resourceScanner: Scanner[_],
|
||||
): String = {
|
||||
val resource = Option(resourceScanner.getResource(digestFile))
|
||||
.getOrElse(throw new FileNotFoundException(
|
||||
s"""\"$digestFile\" is missing. If you are introducing a new Flyway migration step, you need to create an SHA-256 digest file by running $hashMigrationsScriptPath."""))
|
||||
new BufferedReader(resource.read()).readLine()
|
||||
}
|
||||
|
||||
private def computeCurrentDigest(resource: LoadableResource, encoding: Charset): String = {
|
||||
val sha256 = MessageDigest.getInstance("SHA-256")
|
||||
new BufferedReader(resource.read())
|
||||
.lines()
|
||||
.forEach(line => sha256.update((line + "\n").getBytes(encoding)))
|
||||
val digest = sha256.digest()
|
||||
String.format(s"%0${digest.length * 2}x", new BigInteger(1, digest))
|
||||
}
|
||||
|
||||
"migration files" should {
|
||||
"never change, according to their accompanying digest file" in {
|
||||
val configuration = Flyway
|
||||
.configure()
|
||||
.locations(s"classpath:/$migrationsResourcePath")
|
||||
val resourceScanner = flywayScanner(configuration)
|
||||
val resources = resourceScanner.getResources("", ".sql").asScala.toSeq
|
||||
resources.size should be >= migrationsMinSize
|
||||
|
||||
resources.foreach { resource =>
|
||||
val migrationFile = resource.getRelativePath
|
||||
val digestFile = migrationFile + ".sha256"
|
||||
val expectedDigest = readExpectedDigest(digestFile, resourceScanner)
|
||||
val currentDigest = computeCurrentDigest(resource, configuration.getEncoding)
|
||||
assert(
|
||||
currentDigest == expectedDigest,
|
||||
s"""The contents of the migration file "$migrationFile" have changed! Migrations are immutable; you must not change their contents or their digest.""",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -115,6 +115,7 @@ da_scala_test(
|
||||
"//ledger/participant-state",
|
||||
"//ledger/sandbox-classic",
|
||||
"//ledger/sandbox-common",
|
||||
"//libs-scala/flyway-testing",
|
||||
"//libs-scala/ports",
|
||||
"//libs-scala/postgresql-testing",
|
||||
"//libs-scala/resources",
|
||||
@ -127,6 +128,7 @@ da_scala_test(
|
||||
"@maven//:com_typesafe_akka_akka_parsing_2_12",
|
||||
"@maven//:eu_rekawek_toxiproxy_toxiproxy_java_2_1_3",
|
||||
"@maven//:io_spray_spray_json_2_12",
|
||||
"@maven//:org_flywaydb_flyway_core",
|
||||
"@maven//:org_scalatest_scalatest_2_12",
|
||||
"@maven//:org_scalaz_scalaz_core_2_12",
|
||||
],
|
||||
|
12
triggers/service/hash-migrations.sh
Executable file
12
triggers/service/hash-migrations.sh
Executable file
@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -eou pipefail
|
||||
shopt -s globstar
|
||||
|
||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
|
||||
"$DIR"/../../libs-scala/flyway-testing/hash-migrations.sh \
|
||||
"$DIR"/src/main/resources/com/daml/lf/engine/trigger/db/migration/**/*.sql
|
@ -1 +0,0 @@
|
||||
cbac336e1d253707f6ef4dd866b7ed107be3dd908906c446202f5dc7f8594c48
|
@ -0,0 +1 @@
|
||||
9e3bad4ec8947cea838aaabaffeaa81c0084fffd3f1f930caa9d43309c9bb7fa
|
@ -1 +0,0 @@
|
||||
6762d275f249330869111253545121673c09faf31fb032b78654106380d167fa
|
@ -0,0 +1 @@
|
||||
774600d1fcdab326edc840421da21d42ed2022d15fdbdb10e319364a2a1de7ba
|
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.lf.engine.trigger
|
||||
|
||||
import com.daml.flyway.AbstractImmutableMigrationsSpec
|
||||
|
||||
class ImmutableMigrationsSpec extends AbstractImmutableMigrationsSpec {
|
||||
protected override val migrationsResourcePath = "com/daml/lf/engine/trigger/db/migration/postgres"
|
||||
protected override val migrationsMinSize = 2
|
||||
protected override val hashMigrationsScriptPath = "trigger/service/hash-migrations.sh"
|
||||
}
|
Loading…
Reference in New Issue
Block a user