From 9e46213454ea62a21044e026eeb47505e066511e Mon Sep 17 00:00:00 2001 From: Dimo Karaivanov Date: Mon, 13 Feb 2023 11:17:16 +0200 Subject: [PATCH] Full CI validation (#183) * validateDictionaries gradle task now makes use of caching for much faster builds * lowered the severity of missing translations linting rule * fixed some more errors in the translations * added linting task to the GitHub CI validation workflow * enabled GitHub CI validation on push to master --- .github/workflows/build.yml | 12 ++- build.gradle | 157 +++++++++++++++++++----------------- lint.xml | 4 + res/values-bg/strings.xml | 2 +- res/values-fr/strings.xml | 2 +- res/values-ru/strings.xml | 2 +- res/values-uk/strings.xml | 2 +- res/values/strings.xml | 2 +- 8 files changed, 104 insertions(+), 79 deletions(-) create mode 100644 lint.xml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6cd79fcf..16084aff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,12 @@ name: Build the Project -on: [pull_request] +on: + pull_request: + branches: + - "**" + push: + branches: + - master jobs: build: @@ -15,5 +21,7 @@ jobs: # validation - name: Validate Dictionaries run: ./gradlew validateDictionaries + - name: Lint + run: ./gradlew lint - name: Build Release APK - run: ./gradlew assemble + run: ./gradlew build diff --git a/build.gradle b/build.gradle index cbdbf9b8..d34fcad8 100644 --- a/build.gradle +++ b/build.gradle @@ -81,6 +81,89 @@ def getReleaseVersion = { -> return "${getVersionName()} (${getCurrentGitHash()})" } +task validateDictionaries { + inputs.dir fileTree(dir:'assets', excludes:['dict.properties']) + outputs.file "${project.buildDir}/dict.validation.txt" + + doLast { + final String csvDelimiter = ' ' // TAB + + String errors = "" + int errorCount = 0 + final MAX_ERRORS = 50 + + outputs.files.singleFile.text = "" + + inputs.getFiles().each {File file -> + if (errorCount >= MAX_ERRORS) { + return + } + + println "Validating dictionary: " + file.name + + def geographicalName = ~"[A-Z]\\w+-[^\\n]+" + def uniqueWords = [:] + + int lineNumber = 0 + boolean isFileValid = true + + file.eachLine {line -> + if (errorCount >= MAX_ERRORS) { + return + } + + lineNumber++ + + String[] parts = line.split(csvDelimiter, 2) + String word = parts[0] + String frequency = parts.length > 1 ? parts[1] : "" + + if (frequency.length() > 0 && !frequency.matches("^\\d+\$")) { + isFileValid = false + errorCount++ + errors += "Dictionary '" + file.name + "' is invalid. Found out-of-range word frequency: '" + frequency + "' on line " + lineNumber + ". Frequency must be a non-negative integer. \n" + } + + if (word.matches("(\\d.+?|.+?\\d|\\d)")) { + isFileValid = false + errorCount++ + errors += "Dictionary '" + file.name + "' is invalid. Found numbers on line " + lineNumber + ". Please, remove all numbers.\n" + } + + if (word.matches("^\\P{L}+\$")) { + isFileValid = false + errorCount++ + errors += "Dictionary '" + file.name + "' is invalid. Found a garbage word: '" + word + "' on line " + lineNumber + ".\n" + } + + if (word.matches("^.\$") && !Character.isUpperCase(word.charAt(0))) { + isFileValid = false + errorCount++ + errors += "Dictionary '" + file.name + "' is invalid. Found a single letter: '" + word + "' on line " + lineNumber + ". Only uppercase single letters are allowed. The rest of the alphabet will be added automatically.\n" + } + + String uniqueWordKey = word ==~ geographicalName ? word : word.toLowerCase() + if (uniqueWords[uniqueWordKey] != null && uniqueWords[uniqueWordKey] == true) { + isFileValid = false + errorCount++ + errors += "Dictionary '" + file.name + "' is invalid. Found a repeating word: '" + word + "' on line " + lineNumber + ". Ensure all words appear only once.\n" + } else { + uniqueWords[uniqueWordKey] = true + } + + if (errorCount >= MAX_ERRORS ) { + errors += "Too many errors! Aborting.\n" + } + } + + outputs.files.singleFile.text += file.name + " " + (isFileValid ? "OK" : "INVALID") + "\n" + } + + if (errors != "") { + throw new GradleException(errors) + } + } +} android { buildToolsVersion "33.0.0" @@ -143,78 +226,8 @@ android { // signingConfig android.signingConfigs.release } } -} -task validateDictionaries { - inputs.dir fileTree(dir:'assets', excludes:['dict.properties']) - - doLast { - final String csvDelimiter = ' ' - - String errors = "" - int errorCount = 0 - final MAX_ERRORS = 50 - - inputs.getFiles().each {File file -> - if (errorCount >= MAX_ERRORS) { - return - } - println "Validating dictionary: " + file.name - - def geographicalName = ~"[A-Z]\\w+-[^\\n]+" - def uniqueWords = [:] - - int lineNumber = 0 - file.eachLine {line -> - if (errorCount >= MAX_ERRORS) { - return - } - - lineNumber++ - - String[] parts = line.split(csvDelimiter, 2) - String word = parts[0] - String frequency = parts.length > 1 ? parts[1] : "" - - if (frequency.length() > 0 && !frequency.matches("^\\d+\$")) { - errorCount++ - errors += "Dictionary '" + file.name + "' is invalid. Found out-of-range word frequency: '" + frequency + "' on line " + lineNumber + ". Frequency must be a non-negative integer. \n" - } - - if (word.matches("(\\d.+?|.+?\\d|\\d)")) { - errorCount++ - errors += "Dictionary '" + file.name + "' is invalid. Found numbers on line " + lineNumber + ". Please, remove all numbers.\n" - } - - if (word.matches("^\\P{L}+\$")) { - errorCount++ - errors += "Dictionary '" + file.name + "' is invalid. Found a garbage word: '" + word + "' on line " + lineNumber + ".\n" - } - - if (word.matches("^.\$") && !Character.isUpperCase(word.charAt(0))) { - errorCount++ - errors += "Dictionary '" + file.name + "' is invalid. Found a single letter: '" + word + "' on line " + lineNumber + ". Only uppercase single letters are allowed. The rest of the alphabet will be added automatically.\n" - } - - String uniqueWordKey = word ==~ geographicalName ? word : word.toLowerCase() - if (uniqueWords[uniqueWordKey] != null && uniqueWords[uniqueWordKey] == true) { - errorCount++ - errors += "Dictionary '" + file.name + "' is invalid. Found a repeating word: '" + word + "' on line " + lineNumber + ". Ensure all words appear only once.\n" - } else { - uniqueWords[uniqueWordKey] = true - } - - if (errorCount >= MAX_ERRORS ) { - errors += "Too many errors! Aborting.\n" - } - } - } - - if (errors != "") { - throw new GradleException(errors) - } + applicationVariants.all { variant -> + tasks["merge${variant.name.capitalize()}Assets"].dependsOn(validateDictionaries) } } - -preBuild.dependsOn validateDictionaries -preBuild.mustRunAfter validateDictionaries diff --git a/lint.xml b/lint.xml new file mode 100644 index 00000000..d121ef63 --- /dev/null +++ b/lint.xml @@ -0,0 +1,4 @@ + + + + diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index a102776f..21152d10 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -49,5 +49,5 @@ Символ при многократно натисната \"0\" Нов ред Интервал - Напишете дума... + Напишете дума… diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index c3620aed..1ee02445 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -40,5 +40,5 @@ Espace Nouvelle ligne Caractère lorsque «0» est appuyé plusieurs fois - Tapez un mot... + Tapez un mot… diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index fbb246cb..144967b2 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -49,5 +49,5 @@ (зажать) Назад Позвонить - Введите слово... + Введите слово… diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index e24847d5..6c57552b 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -49,5 +49,5 @@ Словник успішно очищено. Немає словника для мови «%1$s». Перейдіть до Налаштувань, щоб завантажити його. Помилка завантаження. Недійсне слово «%1$s» в рядку %2$d мови «%3$s». - Введіть слово... + Введіть слово… diff --git a/res/values/strings.xml b/res/values/strings.xml index e77bbcb6..bb0fcb02 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -11,7 +11,7 @@ Word \"%1$s\" already in the dictionary. Cannot add a word when no language is selected. Add Word - Type a word... + Type a word… About Appearance