10ba4f0a0c
Rescope OOBE claims with permitted ALTER operations and make deployment smoke validation require every migration through V28.
96 lines
4.5 KiB
Kotlin
96 lines
4.5 KiB
Kotlin
package com.osglab.account.config
|
|
|
|
import io.kotest.core.spec.style.FunSpec
|
|
import io.kotest.matchers.collections.shouldContainExactly
|
|
import io.kotest.matchers.shouldBe
|
|
import io.kotest.matchers.string.shouldContain
|
|
import io.kotest.matchers.string.shouldNotContain
|
|
import java.nio.file.Files
|
|
import java.nio.file.Path
|
|
|
|
class SmokeDeploymentTest : FunSpec({
|
|
val root = Path.of(System.getProperty("user.dir"))
|
|
|
|
test("smoke Compose builds locally and publishes only loopback ports") {
|
|
val compose = root.read("compose.smoke.yaml")
|
|
|
|
compose shouldContain "image: mysql:8.4"
|
|
compose shouldContain "build:"
|
|
compose shouldContain "dockerfile: Dockerfile"
|
|
compose shouldContain "127.0.0.1:\${SMOKE_APP_PORT"
|
|
compose shouldContain "internal: true"
|
|
compose shouldContain "network_mode: none"
|
|
compose shouldContain "read_only: true"
|
|
compose shouldContain "no-new-privileges:true"
|
|
compose shouldNotContain "SMOKE_MYSQL_PORT"
|
|
compose shouldNotContain "0.0.0.0:"
|
|
compose shouldNotContain "ghcr.io/"
|
|
}
|
|
|
|
test("smoke runner isolates secrets providers and cleanup") {
|
|
val runner = root.read("deploy/smoke-local.sh")
|
|
|
|
runner shouldContain "set -euo pipefail"
|
|
runner shouldContain "mktemp -d"
|
|
runner shouldContain "trap cleanup EXIT INT TERM"
|
|
runner shouldContain "down --volumes --remove-orphans --rmi local"
|
|
runner shouldContain "APPLE_JWKS_URL=http://127.0.0.1:9/"
|
|
runner shouldContain "VOLCENGINE_ASR_ENDPOINT=ws://127.0.0.1:9/"
|
|
runner shouldContain "DEEPSEEK_ENDPOINT=http://127.0.0.1:9/"
|
|
runner shouldContain "Flyway history was not exactly successful V1-V28"
|
|
runner shouldContain "default referral rewards were not 1000 credits for both accounts"
|
|
runner shouldContain "active smaller credit rates did not match the V10 contract"
|
|
runner shouldContain "first ledger page omitted nextCursor"
|
|
runner shouldContain "DELETE FROM admin_sessions WHERE expires_at < UTC_TIMESTAMP()"
|
|
runner shouldContain "UPDATE storekit_credit_purchases SET credits_granted = credits_granted"
|
|
runner shouldContain "DELETE FROM storekit_credit_purchases WHERE 1 = 0"
|
|
runner shouldNotContain "appleid.apple.com"
|
|
runner shouldNotContain "api.deepseek.com"
|
|
runner shouldNotContain "openspeech.bytedance.com"
|
|
}
|
|
|
|
test("runtime grants cover every migrated table without mutable history privileges") {
|
|
val grants = root.read("deploy/smoke/runtime-grants.sql")
|
|
val migrationTables = Files.list(root.resolve("src/main/resources/db/migration")).use { paths ->
|
|
paths.filter { MIGRATION_FILE.matches(it.fileName.toString()) }
|
|
.flatMap { migration ->
|
|
CREATE_TABLE.findAll(Files.readString(migration))
|
|
.map { it.groupValues[1] }
|
|
.toList()
|
|
.stream()
|
|
}
|
|
.toList()
|
|
}
|
|
.toSet()
|
|
val grantedTables = GRANTED_TABLE.findAll(grants)
|
|
.map { it.groupValues[1] }
|
|
.toSet()
|
|
|
|
grantedTables.sorted() shouldContainExactly migrationTables.sorted()
|
|
grants shouldContain "GRANT INSERT, UPDATE, DELETE ON osg_account_smoke.admin_sessions"
|
|
grants shouldContain
|
|
"GRANT INSERT, UPDATE, DELETE ON osg_account_smoke.gateway_complimentary_requests"
|
|
grants shouldNotContain "UPDATE ON osg_account_smoke.credit_ledger"
|
|
grants shouldNotContain "DELETE ON osg_account_smoke.credit_ledger"
|
|
grants shouldNotContain "UPDATE ON osg_account_smoke.admin_audit_log"
|
|
grants shouldNotContain "DELETE ON osg_account_smoke.admin_audit_log"
|
|
grants shouldNotContain "UPDATE ON osg_account_smoke.admin_credit_grants"
|
|
grants shouldNotContain "DELETE ON osg_account_smoke.admin_credit_grants"
|
|
}
|
|
|
|
test("fixture forces the ledger cursor boundary") {
|
|
val fixture = root.read("deploy/smoke/fixture.sql")
|
|
|
|
fixture shouldContain "WHERE value < 101"
|
|
fixture shouldContain "INSERT INTO credit_ledger"
|
|
fixture shouldNotContain "osg_account"
|
|
}
|
|
})
|
|
|
|
private fun Path.read(relativePath: String): String =
|
|
Files.readString(resolve(relativePath))
|
|
|
|
private val CREATE_TABLE = Regex("""CREATE TABLE\s+([a-z0-9_]+)""", RegexOption.IGNORE_CASE)
|
|
private val GRANTED_TABLE = Regex("""ON osg_account_smoke\.([a-z0-9_]+)""")
|
|
private val MIGRATION_FILE = Regex("""V\d+__.+\.sql""")
|