Skip to content

Commit f81be6e

Browse files
committed
Change the Solr rule deployment script to support the Querqy 5 rule API. The example smui2solr.sh was still using ssh based file upload to deploy Querqy rules, there is a new way with Querqy 5: the Querqy rewriter API.
* New smui2solr.sh deployment script that uses the Querqy 5 API. It is triggered with 4 parameters 1) the path to the common rules file 2) the path to the replace rules file 3) the target system, i.e. PRELIVE or LIVE 4) the Solr core or collection name (taken from the rules collection) * The script expects all other configuration as environment variables: - SMUI_QUERQY_REWRITER_COMMON_RULES: the name of the common rules rewriter the rules should be deployed to - SMUI_QUERQY_REWRITER_COMMON_RULES_DECOMPOUND: the name of the common rules rewriter for decompound rules (required, if decompound rules shall be exported separately) - SMUI_QUERQY_REWRITER_REPLACE: the name of the replace rules rewriter (required, if spelling/replacement rules are used) - SMUI_2SOLR_SOLR_HOST or SMUI_DEPLOY_LIVE_SOLR_HOST: the live Solr host - SMUI_DEPLOY_PRELIVE_SOLR_HOST: the prelive Solr host, if prelive deployment is enabled - SMUI_DEPLOY_(PRE)LIVE_SOLR_(USER|PASSWORD): the live/prelive user/password if Solr basic authentication is used - SMUI_DEPLOY_PRELIVE_SOLR_ALLOW_INSECURE: if the --insecure flag should be used when authenticating (i.e. no cert validation) * Removing all configuration related to the *target* file names of the common rules, optional decompound common rules and replace rules file names as they are no longer copied to a target. * Changing the decision to trigger a GIT based rule deployment to a dedicated toggle / environment variable SMUI_DEPLOYMENT_GIT_ENABLE which needs to be set to true. No longer relying on the magic name "GIT" as the rules file name on the deployment target. * Add jq to SMUI Docker image to facilitate JSON based Querqy request recreation in smui2solr.sh script.
1 parent 0afbf10 commit f81be6e

10 files changed

+219
-361
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ RUN --mount=target=/root/.ivy2,type=cache sbt "set assembly / test := {}" clean
2828
FROM eclipse-temurin:17-jre-focal
2929

3030
RUN apt-get update \
31-
&& apt-get install -y --no-install-recommends openssh-client sshpass bash curl git \
31+
&& apt-get install -y --no-install-recommends openssh-client sshpass bash curl git jq \
3232
&& rm -rf /var/lib/apt/lists/*
3333

3434
ARG VERSION

app/controllers/ApiController.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ class ApiController @Inject()(val controllerComponents: SecurityComponents,
326326
logger.debug("In ApiController :: updateRulesTxtForSolrIndexAndTargetPlatform")
327327

328328
// generate rules.txt(s)
329-
val rulesFiles = rulesTxtDeploymentService.generateRulesTxtContentWithFilenames(SolrIndexId(solrIndexId), targetSystem)
329+
val rulesFiles = rulesTxtDeploymentService.generateRulesTxtContentWithFilenames(SolrIndexId(solrIndexId))
330330

331331
// validate every generated rules.txt
332332
rulesTxtDeploymentService.validateCompleteRulesTxts(rulesFiles) match {

app/models/FeatureToggleModel.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ package object FeatureToggleModel extends Logging {
5050
private val FEATURE_TOGGLE_UI_LIST_LIMIT_ITEMS_TO = "toggle.ui-list.limit-items-to"
5151
private val FEATURE_TOGGLE_RULE_DEPLOYMENT_LOG_RULE_ID = "toggle.rule-deployment.log-rule-id"
5252
private val FEATURE_TOGGLE_RULE_DEPLOYMENT_SPLIT_DECOMPOUND_RULES_TXT = "toggle.rule-deployment.split-decompound-rules-txt"
53-
private val FEATURE_TOGGLE_RULE_DEPLOYMENT_SPLIT_DECOMPOUND_RULES_TXT_DST_CP_FILE_TO = "toggle.rule-deployment.split-decompound-rules-txt-DST_CP_FILE_TO"
5453
private val FEATURE_TOGGLE_RULE_DEPLOYMENT_PRE_LIVE_PRESENT = "toggle.rule-deployment.pre-live.present"
5554
private val FEATURE_TOGGLE_RULE_DEPLOYMENT_CUSTOM_SCRIPT = "toggle.rule-deployment.custom-script"
5655
private val FEATURE_TOGGLE_RULE_DEPLOYMENT_CUSTOM_SCRIPT_SMUI2SOLR_SH_PATH = "toggle.rule-deployment.custom-script-SMUI2SOLR-SH_PATH"
56+
private val FEATURE_TOGGLE_RULE_DEPLOYMENT_ENABLE_GIT = "toggle.rule-deployment.git.enable"
5757
private val FEATURE_TOGGLE_HEADLINE = "toggle.headline"
5858
private val FEATURE_TOGGLE_DEPLOYMENT_LABEL = "toggle.rule-deployment-label"
5959
private val FEATURE_TOGGLE_DEPLOYMENT_PRELIVE_LABEL = "toggle.deploy-prelive-fn-label"
@@ -173,6 +173,10 @@ package object FeatureToggleModel extends Logging {
173173
)
174174
}
175175

176+
def getToggleRuleDeploymentGitEnabled: Boolean = {
177+
appConfig.getOptional[Boolean](FEATURE_TOGGLE_RULE_DEPLOYMENT_ENABLE_GIT).getOrElse(false)
178+
}
179+
176180
def getToggleRuleDeploymentLogRuleId: Boolean = {
177181
appConfig.getOptional[Boolean](FEATURE_TOGGLE_RULE_DEPLOYMENT_LOG_RULE_ID).getOrElse(false)
178182
}
@@ -181,10 +185,6 @@ package object FeatureToggleModel extends Logging {
181185
appConfig.getOptional[Boolean](FEATURE_TOGGLE_RULE_DEPLOYMENT_SPLIT_DECOMPOUND_RULES_TXT).getOrElse(false)
182186
}
183187

184-
def getToggleRuleDeploymentSplitDecompoundRulesTxtDstCpFileTo: String = {
185-
appConfig.getOptional[String](FEATURE_TOGGLE_RULE_DEPLOYMENT_SPLIT_DECOMPOUND_RULES_TXT_DST_CP_FILE_TO).getOrElse("")
186-
}
187-
188188
def getToggleRuleDeploymentCustomScript: Boolean = {
189189
appConfig.getOptional[Boolean](FEATURE_TOGGLE_RULE_DEPLOYMENT_CUSTOM_SCRIPT).getOrElse(false)
190190
}

app/services/RulesTxtDeploymentService.scala

Lines changed: 57 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -20,98 +20,64 @@ class RulesTxtDeploymentService @Inject() (querqyRulesTxtGenerator: QuerqyRulesT
2020
environment: Environment) extends Logging {
2121

2222
case class RulesTxtsForSolrIndex(solrIndexId: SolrIndexId,
23-
regularRules: RulesTxtWithFileNames,
24-
decompoundRules: Option[RulesTxtWithFileNames],
25-
replaceRules: Option[RulesTxtWithFileNames]) {
23+
regularRules: RulesTxtWithFileName,
24+
decompoundRules: Option[RulesTxtWithFileName],
25+
replaceRules: Option[RulesTxtWithFileName]) {
2626

27-
def regularAndDecompoundFiles: List[RulesTxtWithFileNames] = List(regularRules) ++ decompoundRules
27+
def regularAndDecompoundFiles: List[RulesTxtWithFileName] = List(regularRules) ++ decompoundRules
2828

29-
def allFiles: List[RulesTxtWithFileNames] = regularAndDecompoundFiles ++ replaceRules
29+
def allFiles: List[RulesTxtWithFileName] = regularAndDecompoundFiles ++ replaceRules
3030

3131
}
3232

33-
case class RulesTxtWithFileNames(content: String,
34-
sourceFileName: String,
35-
destinationFileName: String)
33+
case class RulesTxtWithFileName(content: String,
34+
sourceFileName: String)
3635

3736
/**
3837
* Generates a list of source to destination filenames containing the rules.txt(s) according to current application settings.
3938
*
4039
* @param solrIndexId Solr Index Id to generate the output for.
4140
*/
4241
// TODO evaluate, if logDebug should be used to prevent verbose logging of the whole generated rules.txt (for zip download especially)
43-
def generateRulesTxtContentWithFilenames(solrIndexId: SolrIndexId, targetSystem: String, logDebug: Boolean = true): RulesTxtsForSolrIndex = {
42+
def generateRulesTxtContentWithFilenames(solrIndexId: SolrIndexId, logDebug: Boolean = true): RulesTxtsForSolrIndex = {
4443

45-
// SMUI config for (regular) LIVE deployment
4644
val SRC_TMP_FILE = appConfig.get[String]("smui2solr.SRC_TMP_FILE")
47-
val DST_CP_FILE_TO = appConfig.get[String]("smui2solr.DST_CP_FILE_TO")
4845
val DO_SPLIT_DECOMPOUND_RULES_TXT = featureToggleService.getToggleRuleDeploymentSplitDecompoundRulesTxt
49-
val DECOMPOUND_RULES_TXT_DST_CP_FILE_TO = featureToggleService.getToggleRuleDeploymentSplitDecompoundRulesTxtDstCpFileTo
50-
// (additional) SMUI config for PRELIVE deployment
51-
val SMUI_DEPLOY_PRELIVE_FN_RULES_TXT = appConfig.get[String]("smui2solr.deploy-prelive-fn-rules-txt")
52-
val SMUI_DEPLOY_PRELIVE_FN_DECOMPOUND_TXT = appConfig.get[String]("smui2solr.deploy-prelive-fn-decompound-txt")
53-
54-
// Replace rules (spelling)
55-
val EXPORT_REPLACE_RULES = featureToggleService.getToggleActivateSpelling
46+
val DO_EXPORT_REPLACE_RULES = featureToggleService.getToggleActivateSpelling
5647
val REPLACE_RULES_SRC_TMP_FILE = appConfig.get[String]("smui2solr.replace-rules-tmp-file")
57-
val REPLACE_RULES_DST_CP_FILE_TO = appConfig.get[String]("smui2solr.replace-rules-dst-cp-file-to")
58-
val SMUI_DEPLOY_PRELIVE_FN_REPLACE_TXT = appConfig.get[String]("smui2solr.deploy-prelive-fn-replace-txt")
5948

6049
if (logDebug) {
6150
logger.debug(
6251
s""":: generateRulesTxtContentWithFilenames config
6352
|:: SRC_TMP_FILE = $SRC_TMP_FILE
64-
|:: DST_CP_FILE_TO = $DST_CP_FILE_TO
6553
|:: DO_SPLIT_DECOMPOUND_RULES_TXT = $DO_SPLIT_DECOMPOUND_RULES_TXT
66-
|:: DECOMPOUND_RULES_TXT_DST_CP_FILE_TO = $DECOMPOUND_RULES_TXT_DST_CP_FILE_TO
67-
|:: SMUI_DEPLOY_PRELIVE_FN_RULES_TXT = $SMUI_DEPLOY_PRELIVE_FN_RULES_TXT
68-
|:: SMUI_DEPLOY_PRELIVE_FN_DECOMPOUND_TXT = $SMUI_DEPLOY_PRELIVE_FN_DECOMPOUND_TXT
69-
|:: EXPORT_REPLACE_RULES = $EXPORT_REPLACE_RULES
54+
|:: EXPORT_REPLACE_RULES = $DO_EXPORT_REPLACE_RULES
7055
|:: REPLACE_RULES_SRC_TMP_FILE = $REPLACE_RULES_SRC_TMP_FILE
71-
|:: REPLACE_RULES_DST_CP_FILE_TO = $REPLACE_RULES_DST_CP_FILE_TO
72-
|:: SMUI_DEPLOY_PRELIVE_FN_REPLACE_TXT = $SMUI_DEPLOY_PRELIVE_FN_REPLACE_TXT
7356
""".stripMargin)
7457
}
7558

7659
// generate one rules.txt by default or two separated, if decompound instructions are supposed to be split
7760

78-
// TODO test correct generation in different scenarios (one vs. two rules.txts, etc.)
79-
val dstCpFileTo = if (targetSystem == "PRELIVE")
80-
SMUI_DEPLOY_PRELIVE_FN_RULES_TXT
81-
else // targetSystem == "LIVE"
82-
DST_CP_FILE_TO
83-
84-
val replaceRulesDstCpFileTo =
85-
if (targetSystem == "PRELIVE") SMUI_DEPLOY_PRELIVE_FN_REPLACE_TXT
86-
else REPLACE_RULES_DST_CP_FILE_TO
87-
88-
val replaceRules =
89-
if (EXPORT_REPLACE_RULES) {
61+
val optReplaceRules =
62+
if (DO_EXPORT_REPLACE_RULES) {
9063
val allCanonicalSpellings = searchManagementRepository.listAllSpellingsWithAlternatives(solrIndexId)
91-
Some(RulesTxtWithFileNames(
92-
QuerqyReplaceRulesGenerator.renderAllCanonicalSpellingsToReplaceRules(allCanonicalSpellings),
93-
REPLACE_RULES_SRC_TMP_FILE,
94-
replaceRulesDstCpFileTo
95-
))
64+
val spellingsRendered = QuerqyReplaceRulesGenerator.renderAllCanonicalSpellingsToReplaceRules(allCanonicalSpellings)
65+
Some(RulesTxtWithFileName(spellingsRendered, REPLACE_RULES_SRC_TMP_FILE))
9666
} else None
9767

9868
if (!DO_SPLIT_DECOMPOUND_RULES_TXT) {
9969
RulesTxtsForSolrIndex(solrIndexId,
100-
RulesTxtWithFileNames(querqyRulesTxtGenerator.renderSingleRulesTxt(solrIndexId), SRC_TMP_FILE, dstCpFileTo),
70+
RulesTxtWithFileName(querqyRulesTxtGenerator.renderSingleRulesTxt(solrIndexId), SRC_TMP_FILE),
10171
None,
102-
replaceRules
72+
optReplaceRules
10373
)
10474
} else {
105-
val decompoundDstCpFileTo = if (targetSystem == "PRELIVE")
106-
SMUI_DEPLOY_PRELIVE_FN_DECOMPOUND_TXT
107-
else // targetSystem == "LIVE"
108-
DECOMPOUND_RULES_TXT_DST_CP_FILE_TO
75+
val rulesWithoutDecompounds = querqyRulesTxtGenerator.renderSeparatedRulesTxts(solrIndexId, renderCompoundsRulesTxt = false)
76+
val decompoundRules = querqyRulesTxtGenerator.renderSeparatedRulesTxts(solrIndexId, renderCompoundsRulesTxt = true)
10977
RulesTxtsForSolrIndex(solrIndexId,
110-
RulesTxtWithFileNames(querqyRulesTxtGenerator.renderSeparatedRulesTxts(solrIndexId, renderCompoundsRulesTxt = false), SRC_TMP_FILE, dstCpFileTo),
111-
Some(RulesTxtWithFileNames(querqyRulesTxtGenerator.renderSeparatedRulesTxts(solrIndexId, renderCompoundsRulesTxt = true),
112-
SRC_TMP_FILE + "-2", decompoundDstCpFileTo)
113-
),
114-
replaceRules
78+
RulesTxtWithFileName(rulesWithoutDecompounds, SRC_TMP_FILE),
79+
Some(RulesTxtWithFileName(decompoundRules, SRC_TMP_FILE + "-2")),
80+
optReplaceRules
11581
)
11682
}
11783
}
@@ -123,7 +89,7 @@ class RulesTxtDeploymentService @Inject() (querqyRulesTxtGenerator: QuerqyRulesT
12389
def validateCompleteRulesTxts(rulesTxts: RulesTxtsForSolrIndex, logDebug: Boolean = true): List[String] = {
12490
val rulesValidation = rulesTxts.regularAndDecompoundFiles.flatMap { rulesFile =>
12591
if (logDebug) {
126-
logger.debug(":: validateCompleteRulesTxts for src = " + rulesFile.sourceFileName + " dst = " + rulesFile.destinationFileName)
92+
logger.debug(":: validateCompleteRulesTxts for src = " + rulesFile.sourceFileName)
12793
logger.debug(":: rulesTxt = <<<" + rulesFile.content + ">>>")
12894
}
12995
val validationResult = querqyRulesTxtGenerator.validateQuerqyRulesTxtToErrMsg(rulesFile.content)
@@ -158,43 +124,34 @@ class RulesTxtDeploymentService @Inject() (querqyRulesTxtGenerator: QuerqyRulesT
158124

159125
}
160126

161-
def interfaceSmui2SolrSh(scriptPath: String, srcTmpFile: String, dstCpFileTo: String, solrHost: String,
162-
solrCoreName: String, decompoundDstCpFileTo: String, targetSystem: String,
163-
replaceRulesSrcTmpFile: String, replaceRulesDstCpFileTo: String
127+
def interfaceSmui2SolrSh(scriptPath: String,
128+
srcTmpFile: String,
129+
replaceRulesSrcTmpFile: String,
130+
targetSystem: String,
131+
solrCoreName: String
164132
): DeploymentScriptResult = {
165133

166134
logger.info(
167135
s""":: interfaceSmui2SolrSh
168136
|:: scriptPath = $scriptPath
169137
|:: srcTmpFile = $srcTmpFile
170-
|:: dstCpFileTo = $dstCpFileTo
171-
|:: solrHost = $solrHost
138+
|:: replaceRulesSrcTmpFile = $replaceRulesSrcTmpFile
172139
|:: solrCoreName = $solrCoreName
173-
|:: decompoundDstCpFileTo = $decompoundDstCpFileTo
174140
|:: targetSystem = $targetSystem
175-
|:: replaceRulesSrcTmpFile = $replaceRulesSrcTmpFile
176-
|:: replaceRulesDstCpFileTo = $replaceRulesDstCpFileTo
177141
""".stripMargin)
178142

179-
val scriptCall =
143+
val scriptCall = List(
180144
// define call for regular smui2solr (default or custom script) and add parameters to the script (in expected order, see smui2solr.sh)
181-
scriptPath + " " +
145+
scriptPath,
182146
// SRC_TMP_FILE=$1
183-
srcTmpFile + " " +
184-
// DST_CP_FILE_TO=$2
185-
dstCpFileTo + " " +
186-
// SOLR_HOST=$3
187-
solrHost + " " +
147+
srcTmpFile,
148+
// REPLACE_RULES_SRC_TMP_FILE=$2
149+
replaceRulesSrcTmpFile,
150+
// TARGET_SYSTEM=$3
151+
targetSystem,
188152
// SOLR_CORE_NAME=$4
189-
solrCoreName + " " +
190-
// DECOMPOUND_DST_CP_FILE_TO=$5
191-
decompoundDstCpFileTo + " " +
192-
// TARGET_SYSTEM=$6
193-
targetSystem + " " +
194-
// REPLACE_RULES_SRC_TMP_FILE=$7
195-
replaceRulesSrcTmpFile + " " +
196-
// REPLACE_RULES_DST_CP_FILE_TO=$8
197-
replaceRulesDstCpFileTo
153+
solrCoreName
154+
).mkString(" ")
198155

199156
interfaceDeploymentScript(scriptCall)
200157
}
@@ -233,58 +190,37 @@ class RulesTxtDeploymentService @Inject() (querqyRulesTxtGenerator: QuerqyRulesT
233190
else
234191
environment.rootPath.getAbsolutePath + "/conf/smui2solr.sh"
235192

193+
val deployToGitConfigured = featureToggleService.getToggleRuleDeploymentGitEnabled
194+
236195
val srcTmpFile = rulesTxts.regularRules.sourceFileName
237-
val dstCpFileTo = rulesTxts.regularRules.destinationFileName
238-
val decompoundDstCpFileTo = if (rulesTxts.decompoundRules.isDefined)
239-
rulesTxts.decompoundRules.get.destinationFileName
240-
else
241-
"NONE"
242-
243-
// host for (optional) core reload
244-
val SMUI_DEPLOY_PRELIVE_SOLR_HOST = appConfig.get[String]("smui2solr.deploy-prelive-solr-host")
245-
val SMUI_DEPLOY_LIVE_SOLR_HOST = appConfig.get[String]("smui2solr.SOLR_HOST")
246-
val solrHost = if (targetSystem == "PRELIVE")
247-
if (SMUI_DEPLOY_PRELIVE_SOLR_HOST.isEmpty)
248-
"NONE"
249-
else
250-
SMUI_DEPLOY_PRELIVE_SOLR_HOST
251-
else // targetSystem == "LIVE"
252-
if (SMUI_DEPLOY_LIVE_SOLR_HOST.isEmpty)
253-
"NONE"
254-
else
255-
SMUI_DEPLOY_LIVE_SOLR_HOST
256-
// core name from repo (optional, for core reload as well)
257196
val solrCoreName = searchManagementRepository.getSolrIndexName(rulesTxts.solrIndexId)
258-
259197
val replaceRulesSrcTmpFile = rulesTxts.replaceRules.map(_.sourceFileName).getOrElse("NONE")
260-
val replaceRulesDstCpFileTo = rulesTxts.replaceRules.map(_.destinationFileName).getOrElse("NONE")
261198

262199
// execute script
263200
// TODO currently only git deployment for LIVE instance available
264-
val deployToGit = targetSystem.equals("LIVE") && appConfig.get[String]("smui2solr.DST_CP_FILE_TO").equals("GIT")
265-
val result = (if(!deployToGit) {
201+
val result = if (deployToGitConfigured) {
202+
if (targetSystem == "LIVE") {
203+
logger.info(":: executeDeploymentScript :: GIT configured calling interfaceSmui2GitSh")
204+
// TODO support further rule files (decompound / replace) and maybe solrCoreName and/or targetSystem for git branch?
205+
interfaceSmui2GitSh(
206+
environment.rootPath.getAbsolutePath + "/conf/smui2git.sh",
207+
srcTmpFile,
208+
featureToggleService.getSmuiDeploymentGitRepoUrl,
209+
featureToggleService.getSmuiDeploymentGitFilenameCommonRulesTxt,
210+
)
211+
} else {
212+
DeploymentScriptResult(exitCode = -1, output = "Git deployment only support for LIVE target")
213+
}
214+
} else {
266215
logger.info(s":: executeDeploymentScript :: regular script configured calling interfaceSmui2SolrSh(scriptPath = '$scriptPath')")
267216
interfaceSmui2SolrSh(
268217
scriptPath,
269218
srcTmpFile,
270-
dstCpFileTo,
271-
solrHost,
272-
solrCoreName,
273-
decompoundDstCpFileTo,
274-
targetSystem,
275219
replaceRulesSrcTmpFile,
276-
replaceRulesDstCpFileTo
277-
)
278-
} else {
279-
logger.info(":: executeDeploymentScript :: GIT configured calling interfaceSmui2GitSh")
280-
// TODO support further rule files (decompound / replace) and maybe solrCoreName and/or targetSystem for git branch?
281-
interfaceSmui2GitSh(
282-
environment.rootPath.getAbsolutePath + "/conf/smui2git.sh",
283-
srcTmpFile,
284-
featureToggleService.getSmuiDeploymentGitRepoUrl,
285-
featureToggleService.getSmuiDeploymentGitFilenameCommonRulesTxt,
220+
targetSystem,
221+
solrCoreName
286222
)
287-
})
223+
}
288224
if (result.success) {
289225
logger.info(s"Rules.txt deployment successful:\n${result.output}")
290226
} else {
@@ -323,7 +259,7 @@ class RulesTxtDeploymentService @Inject() (querqyRulesTxtGenerator: QuerqyRulesT
323259
try {
324260
for (index <- searchManagementRepository.listAllSolrIndexes) {
325261
// TODO make targetSystem configurable from ApiController.downloadAllRulesTxtFiles ... go with "LIVE" from now (as there exist no different revisions of the search management content)!
326-
val rules = generateRulesTxtContentWithFilenames(index.id, "LIVE", logDebug = false)
262+
val rules = generateRulesTxtContentWithFilenames(index.id, logDebug = false)
327263
zipStream.putNextEntry(new ZipEntry(s"rules_${index.name}.txt"))
328264
zipStream.write(rules.regularRules.content.getBytes("UTF-8"))
329265
zipStream.closeEntry()

build.sbt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import com.typesafe.sbt.GitBranchPrompt
22

33
name := "search-management-ui"
4-
version := "4.3.1"
4+
version := "4.4.1"
55
maintainer := "Contact productful.io <[email protected]>"
66

7-
scalaVersion := "2.13.14"
7+
scalaVersion := "2.13.15"
88

99
ThisBuild / evictionErrorLevel := Level.Info
1010

0 commit comments

Comments
 (0)