diff --git a/.git-hooks/commit-msg.sh b/.git-hooks/commit-msg.sh new file mode 100644 index 0000000000..f465ed4d47 --- /dev/null +++ b/.git-hooks/commit-msg.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +commit_pattern="(Merge (remote-tracking )?branch|### What's done:)" +error_msg="Your commit message doesn't match the pattern $commit_pattern. Please fix it." + +if [[ ! $( cat "$1" ) =~ $commit_pattern ]] +then + echo "$error_msg" + exit 1 +fi + +exit 0 diff --git a/.git-hooks/pre-commit.sh b/.git-hooks/pre-commit.sh new file mode 100644 index 0000000000..e683861d39 --- /dev/null +++ b/.git-hooks/pre-commit.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +branch_name="$(git rev-parse --abbrev-ref HEAD)" +branch_pattern="^(feature|bugfix|hotfix|infra)/.*$" +error_message="Your branch name doesn't match the pattern $branch_pattern. Please correct it before committing." + +if [[ ! $branch_name =~ $branch_pattern ]] +then + echo "$error_message" + exit 1 +fi + +exit 0 diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 6a06a28111..0114507fa6 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -1,7 +1,10 @@ name: Build and test on: - pull_request + pull_request: + push: + branches: + - 'master' jobs: build_and_test_with_code_coverage: @@ -31,7 +34,7 @@ jobs: run: | ARCH=$(uname -m) URL=https://storage.googleapis.com/gvisor/releases/release/latest/${ARCH} - wget ${URL}/runsc ${URL}/runsc.sha512 \ + wget -nv ${URL}/runsc ${URL}/runsc.sha512 \ ${URL}/containerd-shim-runsc-v1 ${URL}/containerd-shim-runsc-v1.sha512 sha512sum -c runsc.sha512 \ -c containerd-shim-runsc-v1.sha512 @@ -42,7 +45,7 @@ jobs: sudo systemctl reload docker - name: Gradle build run: | - ./gradlew build + ./gradlew build -x detekt - name: Upload test reports uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/detekt.yml b/.github/workflows/detekt.yml new file mode 100644 index 0000000000..b02e52b8df --- /dev/null +++ b/.github/workflows/detekt.yml @@ -0,0 +1,30 @@ +name: Run deteKT + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + detekt_check: + runs-on: ubuntu-20.04 + env: + GRADLE_OPTS: -Dorg.gradle.daemon=false + + steps: + - uses: actions/checkout@v2.3.3 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 1.11 + - name: Cache gradle caches + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches/ + ~/.gradle/wrapper/ + key: ${{ runner.os }}-gradle-detekt-${{ hashFiles('**/*.gradle*') }} + restore-keys: ${{ runner.os }}-gradle-detekt + - name: Run detekt + run: ./gradlew detektAll diff --git a/.github/workflows/diktat.yml b/.github/workflows/diktat.yml new file mode 100644 index 0000000000..10a3bdcb29 --- /dev/null +++ b/.github/workflows/diktat.yml @@ -0,0 +1,30 @@ +name: Run diKTat + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + diktat_check: + runs-on: ubuntu-20.04 + env: + GRADLE_OPTS: -Dorg.gradle.daemon=false + + steps: + - uses: actions/checkout@v2.3.3 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 1.11 + - name: Cache gradle caches + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches/ + ~/.gradle/wrapper/ + key: ${{ runner.os }}-gradle-diktat-${{ hashFiles('**/*.gradle*') }} + restore-keys: ${{ runner.os }}-gradle-diktat + - name: Run diktat + run: ./gradlew diktatCheckAll diff --git a/.github/workflows/metrics_for_master.yml b/.github/workflows/metrics_for_master.yml deleted file mode 100644 index 3025f2e3cd..0000000000 --- a/.github/workflows/metrics_for_master.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Update metrics for master branch - -on: - push: - branches: - - 'master' - -env: - GRADLE_OPTS: -Dorg.gradle.daemon=false - -jobs: - master_flow: - name: Master branch update - runs-on: ubuntu-20.04 - - steps: - - uses: actions/checkout@v2.3.3 - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 1.11 - # todo: consider using https://github.com/burrunan/gradle-cache-action instead - - name: Cache gradle caches - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches/ - ~/.gradle/wrapper/ - key: ${{ runner.os }}-gradle-build-${{ hashFiles('**/*.gradle*') }} - restore-keys: ${{ runner.os }}-gradle-build - - name: Run tests - # we need to run `install` goal here so that gradle will be able to resolve dependencies and run tests on diktat-gradle-plugin - run: ./gradlew build - - name: Generate code coverage report - uses: codecov/codecov-action@v1 - with: - flags: unittests - fail_ci_if_error: true # optional (default = false) diff --git a/build.gradle.kts b/build.gradle.kts index 08fe23fa63..25530ab80a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,12 @@ +import org.cqfn.save.buildutils.configureDetekt +import org.cqfn.save.buildutils.configureDiktat +import org.cqfn.save.buildutils.createDetektTask +import org.cqfn.save.buildutils.createDiktatTask +import org.cqfn.save.buildutils.installGitHooks + plugins { kotlin("jvm") version "1.4.21" apply false + id("com.github.ben-manes.versions") version "0.36.0" } allprojects { @@ -7,4 +14,10 @@ allprojects { jcenter() mavenCentral() } + configureDiktat() + configureDetekt() } + +createDiktatTask() +createDetektTask() +installGitHooks() \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index c39a297b0f..8ce9500966 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -4,4 +4,9 @@ plugins { repositories { jcenter() +} + +dependencies { + implementation("org.cqfn.diktat:diktat-gradle-plugin:0.4.0") + implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.15.0") } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 24a41555a3..57c9195c5e 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -1,10 +1,10 @@ object Versions { - val kotlin = "1.4.30" - val springBoot = "2.4.2" - val springSecurity = "5.4.2" - val hibernate = "5.4.2.Final" - val liquibase = "4.2.2" - val slf4j = "1.7.30" - val logback = "1.2.3" - val dockerJavaApi = "3.2.7" + const val kotlin = "1.4.30" + const val springBoot = "2.4.2" + const val springSecurity = "5.4.2" + const val hibernate = "5.4.2.Final" + const val liquibase = "4.3.0" + const val slf4j = "1.7.30" + const val logback = "1.2.3" + const val dockerJavaApi = "3.2.7" } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/org/cqfn/save/buildutils/DetektConfiguration.kt b/buildSrc/src/main/kotlin/org/cqfn/save/buildutils/DetektConfiguration.kt new file mode 100644 index 0000000000..918de729b8 --- /dev/null +++ b/buildSrc/src/main/kotlin/org/cqfn/save/buildutils/DetektConfiguration.kt @@ -0,0 +1,33 @@ +/** + * Configuration for detekt static analysis + */ + +package org.cqfn.save.buildutils + +import io.gitlab.arturbosch.detekt.DetektPlugin +import io.gitlab.arturbosch.detekt.extensions.DetektExtension +import org.gradle.api.Project +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.configure + +/** + * Configure Detekt for a single project + */ +fun Project.configureDetekt() { + apply() + configure { + config = rootProject.files("detekt.yml") + buildUponDefaultConfig = true + } +} + +/** + * Register a unified detekt task + */ +fun Project.createDetektTask() { + tasks.register("detektAll") { + allprojects { + this@register.dependsOn(tasks.getByName("detekt")) + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/org/cqfn/save/buildutils/DiktatConfiguration.kt b/buildSrc/src/main/kotlin/org/cqfn/save/buildutils/DiktatConfiguration.kt new file mode 100644 index 0000000000..d4c3317dc5 --- /dev/null +++ b/buildSrc/src/main/kotlin/org/cqfn/save/buildutils/DiktatConfiguration.kt @@ -0,0 +1,38 @@ +/** + * Configuration for diktat static analysis + */ + +package org.cqfn.save.buildutils + +import org.cqfn.diktat.plugin.gradle.DiktatExtension +import org.cqfn.diktat.plugin.gradle.DiktatGradlePlugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.configure + +/** + * Applies diktat gradle plugin and configures diktat for [this] project + */ +fun Project.configureDiktat() { + apply() + configure { + diktatConfigFile = rootProject.file("diktat-analysis.yml") + inputs = files("src/**/*.kt") + } +} + +/** + * Creates unified tasks to run diktat on all projects + */ +fun Project.createDiktatTask() { + tasks.register("diktatCheckAll") { + allprojects { + this@register.dependsOn(tasks.getByName("diktatCheck")) + } + } + tasks.register("diktatFixAll") { + allprojects { + this@register.dependsOn(tasks.getByName("diktatFix")) + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/org/cqfn/save/buildutils/GitHookInstallation.kt b/buildSrc/src/main/kotlin/org/cqfn/save/buildutils/GitHookInstallation.kt new file mode 100644 index 0000000000..2493578a41 --- /dev/null +++ b/buildSrc/src/main/kotlin/org/cqfn/save/buildutils/GitHookInstallation.kt @@ -0,0 +1,25 @@ +/** + * Gradle tasks to install git hooks as a part of the build + */ + +package org.cqfn.save.buildutils + +import org.gradle.api.Project +import org.gradle.api.tasks.Copy +import org.gradle.kotlin.dsl.register + +/** + * Task of type [Copy] that install git hooks from directory in repo to .git directory + */ +fun Project.installGitHooks() { + val installGitHooksTask = tasks.register("installGitHooks", Copy::class) { + from(file("$rootDir/.git-hooks")) + into(file("$rootDir/.git/hooks")) + } + // add git hooks installation to build by adding it as a dependency for some common task + subprojects.mapNotNull { + it.tasks.findByName("build") + } + .firstOrNull() + ?.dependsOn(installGitHooksTask) +} \ No newline at end of file diff --git a/detekt.yml b/detekt.yml new file mode 100644 index 0000000000..fc6f2f8765 --- /dev/null +++ b/detekt.yml @@ -0,0 +1,839 @@ +build: + maxIssues: 0 + excludeCorrectable: false + weights: + # complexity: 2 + # LongParameterList: 1 + # style: 1 + # comments: 1 + +config: + validation: true + # when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]' + excludes: '' + +processors: + active: true + exclude: + - 'DetektProgressListener' + # - 'FunctionCountProcessor' + # - 'PropertyCountProcessor' + # - 'ClassCountProcessor' + # - 'PackageCountProcessor' + # - 'KtFileCountProcessor' + +console-reports: + active: true + exclude: + - 'ProjectStatisticsReport' + - 'ComplexityReport' + - 'NotificationReport' + # - 'FindingsReport' + - 'FileBasedFindingsReport' + +comments: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + AbsentOrWrongFileLicense: + excludes: ['**/resources/**'] + active: false + + licenseTemplateFile: 'license.template' + CommentOverPrivateFunction: + excludes: ['**/resources/**'] + active: false + CommentOverPrivateProperty: + excludes: ['**/resources/**'] + active: false + EndOfSentenceFormat: + excludes: ['**/resources/**'] + active: false + endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)' + UndocumentedPublicClass: + excludes: ['**/resources/**'] + active: false + searchInNestedClass: true + searchInInnerClass: true + searchInInnerObject: true + searchInInnerInterface: true + UndocumentedPublicFunction: + excludes: ['**/resources/**'] + active: false + UndocumentedPublicProperty: + excludes: ['**/resources/**'] + active: false + +complexity: + active: true + ComplexCondition: + excludes: ['**/resources/**'] + active: false + threshold: 4 + ComplexInterface: + excludes: ['**/resources/**'] + active: false + threshold: 10 + includeStaticDeclarations: false + includePrivateDeclarations: false + ComplexMethod: + excludes: ['**/resources/**'] + active: true + threshold: 15 + ignoreSingleWhenExpression: false + ignoreSimpleWhenEntries: false + ignoreNestingFunctions: false + nestingFunctions: [run, let, apply, with, also, use, forEach, isNotNull, ifNull] + LabeledExpression: + excludes: ['**/resources/**'] + active: false + ignoredLabels: [] + LargeClass: + excludes: ['**/resources/**'] + active: true + threshold: 600 + LongMethod: + excludes: ['**/resources/**'] + active: true + threshold: 60 + LongParameterList: + excludes: ['**/resources/**'] + active: true + functionThreshold: 6 + constructorThreshold: 7 + ignoreDefaultParameters: false + ignoreDataClasses: true + ignoreAnnotated: [] + MethodOverloading: + excludes: ['**/resources/**'] + active: false + threshold: 6 + NestedBlockDepth: + excludes: ['**/resources/**'] + active: true + threshold: 5 + ReplaceSafeCallChainWithRun: + active: false + StringLiteralDuplication: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + threshold: 3 + ignoreAnnotation: true + excludeStringsWithLessThan5Characters: true + ignoreStringsRegex: '$^' + TooManyFunctions: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + thresholdInFiles: 11 + thresholdInClasses: 11 + thresholdInInterfaces: 11 + thresholdInObjects: 11 + thresholdInEnums: 11 + ignoreDeprecated: false + ignorePrivate: false + ignoreOverridden: false + +coroutines: + active: true + GlobalCoroutineUsage: + excludes: ['**/resources/**'] + active: false + RedundantSuspendModifier: + excludes: ['**/resources/**'] + active: false + SuspendFunWithFlowReturnType: + active: false + +empty-blocks: + active: true + EmptyCatchBlock: + excludes: ['**/resources/**'] + active: true + allowedExceptionNameRegex: '_|(ignore|expected).*' + EmptyClassBlock: + excludes: ['**/resources/**'] + active: true + EmptyDefaultConstructor: + excludes: ['**/resources/**'] + active: true + EmptyDoWhileBlock: + excludes: ['**/resources/**'] + active: true + EmptyElseBlock: + excludes: ['**/resources/**'] + active: true + EmptyFinallyBlock: + excludes: ['**/resources/**'] + active: true + EmptyForBlock: + excludes: ['**/resources/**'] + active: true + EmptyFunctionBlock: + excludes: ['**/resources/**'] + active: true + ignoreOverridden: false + EmptyIfBlock: + excludes: ['**/resources/**'] + active: true + EmptyInitBlock: + excludes: ['**/resources/**'] + active: true + EmptyKtFile: + excludes: ['**/resources/**'] + active: true + EmptySecondaryConstructor: + excludes: ['**/resources/**'] + active: true + EmptyTryBlock: + excludes: ['**/resources/**'] + active: true + EmptyWhenBlock: + excludes: ['**/resources/**'] + active: true + EmptyWhileBlock: + excludes: ['**/resources/**'] + active: true + +exceptions: + active: true + ExceptionRaisedInUnexpectedLocation: + excludes: ['**/resources/**'] + active: false + methodNames: [toString, hashCode, equals, finalize] + InstanceOfCheckForException: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + NotImplementedDeclaration: + excludes: ['**/resources/**'] + active: false + PrintStackTrace: + excludes: ['**/resources/**'] + active: false + RethrowCaughtException: + excludes: ['**/resources/**'] + active: false + ReturnFromFinally: + excludes: ['**/resources/**'] + active: false + ignoreLabeled: false + SwallowedException: + excludes: ['**/resources/**'] + active: false + ignoredExceptionTypes: + - InterruptedException + - NumberFormatException + - ParseException + - MalformedURLException + allowedExceptionNameRegex: '_|(ignore|expected).*' + ThrowingExceptionFromFinally: + excludes: ['**/resources/**'] + active: false + ThrowingExceptionInMain: + excludes: ['**/resources/**'] + active: false + ThrowingExceptionsWithoutMessageOrCause: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + exceptions: + - IllegalArgumentException + - IllegalStateException + - IOException + ThrowingNewInstanceOfSameException: + excludes: ['**/resources/**'] + active: false + TooGenericExceptionCaught: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + exceptionNames: + - ArrayIndexOutOfBoundsException + - Error + - Exception + - IllegalMonitorStateException + - NullPointerException + - IndexOutOfBoundsException + - RuntimeException + - Throwable + allowedExceptionNameRegex: '_|(ignore|expected).*' + TooGenericExceptionThrown: + excludes: ['**/resources/**'] + active: true + exceptionNames: + - Error + - Exception + - Throwable + - RuntimeException + +formatting: + active: true + android: false + autoCorrect: true + AnnotationOnSeparateLine: + excludes: ['**/resources/**'] + active: false + autoCorrect: true + AnnotationSpacing: + active: true + ArgumentListWrapping: + active: true + ChainWrapping: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + CommentSpacing: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + EnumEntryNameCase: + excludes: ['**/resources/**'] + active: false + autoCorrect: true + Filename: + excludes: ['**/resources/**'] + active: true + FinalNewline: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + insertFinalNewLine: true + ImportOrdering: + excludes: ['**/resources/**'] + active: false + autoCorrect: true + layout: 'idea' + Indentation: + excludes: ['**/resources/**'] + active: false + autoCorrect: true + indentSize: 4 + continuationIndentSize: 4 + MaximumLineLength: + excludes: ['**/resources/**'] + active: true + maxLineLength: 180 + ModifierOrdering: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + MultiLineIfElse: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + NoBlankLineBeforeRbrace: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + NoConsecutiveBlankLines: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + NoEmptyClassBody: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + NoEmptyFirstLineInMethodBlock: + excludes: ['**/resources/**'] + active: false + autoCorrect: true + NoLineBreakAfterElse: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + NoLineBreakBeforeAssignment: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + NoMultipleSpaces: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + NoSemicolons: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + NoTrailingSpaces: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + NoUnitReturn: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + NoUnusedImports: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + NoWildcardImports: + excludes: ['**/resources/**'] + active: true + PackageName: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + ParameterListWrapping: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + indentSize: 4 + SpacingAroundColon: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + SpacingAroundComma: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + SpacingAroundCurly: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + SpacingAroundDot: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + SpacingAroundDoubleColon: + excludes: ['**/resources/**'] + active: false + autoCorrect: true + SpacingAroundKeyword: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + SpacingAroundOperators: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + SpacingAroundParens: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + SpacingAroundRangeOperator: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + SpacingBetweenDeclarationsWithAnnotations: + excludes: ['**/resources/**'] + active: false + autoCorrect: true + SpacingBetweenDeclarationsWithComments: + excludes: ['**/resources/**'] + active: false + autoCorrect: true + StringTemplate: + excludes: ['**/resources/**'] + active: true + autoCorrect: true + +naming: + active: true + ClassNaming: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + classPattern: '[A-Z][a-zA-Z0-9]*' + ConstructorParameterNaming: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + parameterPattern: '[a-z][A-Za-z0-9]*' + privateParameterPattern: '[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + ignoreOverridden: true + EnumNaming: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + enumEntryPattern: '[A-Z][_a-zA-Z0-9]*' + ForbiddenClassName: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + forbiddenName: [] + FunctionMaxLength: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + maximumFunctionNameLength: 30 + FunctionMinLength: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + minimumFunctionNameLength: 3 + FunctionNaming: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + functionPattern: '([a-z][a-zA-Z0-9]*)|(`.*`)' + excludeClassPattern: '$^' + ignoreOverridden: true + ignoreAnnotated: ['Composable'] + FunctionParameterNaming: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + parameterPattern: '[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + ignoreOverridden: true + InvalidPackageDeclaration: + excludes: ['**/resources/**'] + active: false + rootPackage: '' + MatchingDeclarationName: + excludes: ['**/resources/**'] + active: true + mustBeFirst: true + MemberNameEqualsClassName: + excludes: ['**/resources/**'] + active: true + ignoreOverridden: true + NonBooleanPropertyPrefixedWithIs: + active: true + ObjectPropertyNaming: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + constantPattern: '[A-Za-z][_A-Za-z0-9]*' + propertyPattern: '[A-Za-z][_A-Za-z0-9]*' + privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*' + PackageNaming: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*' + TopLevelPropertyNaming: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + constantPattern: '[A-Z][_A-Z0-9]*' + propertyPattern: '[A-Za-z][_A-Za-z0-9]*' + privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*' + VariableMaxLength: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + maximumVariableNameLength: 64 + VariableMinLength: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + minimumVariableNameLength: 1 + VariableNaming: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + variablePattern: '[a-z][A-Za-z0-9]*' + privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + ignoreOverridden: true + +performance: + active: true + ArrayPrimitive: + excludes: ['**/resources/**'] + active: true + ForEachOnRange: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + SpreadOperator: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + UnnecessaryTemporaryInstantiation: + excludes: ['**/resources/**'] + active: true + +potential-bugs: + active: true + Deprecation: + excludes: ['**/resources/**'] + active: false + DuplicateCaseInWhenExpression: + excludes: ['**/resources/**'] + active: true + EqualsAlwaysReturnsTrueOrFalse: + excludes: ['**/resources/**'] + active: true + EqualsWithHashCodeExist: + excludes: ['**/resources/**'] + active: true + ExplicitGarbageCollectionCall: + excludes: ['**/resources/**'] + active: true + HasPlatformType: + excludes: ['**/resources/**'] + active: false + IgnoredReturnValue: + excludes: ['**/resources/**'] + active: false + restrictToAnnotatedMethods: true + returnValueAnnotations: ['*.CheckReturnValue', '*.CheckResult'] + ImplicitDefaultLocale: + excludes: ['**/resources/**'] + active: false + ImplicitUnitReturnType: + excludes: ['**/resources/**'] + active: false + allowExplicitReturnType: true + InvalidRange: + excludes: ['**/resources/**'] + active: true + IteratorHasNextCallsNextMethod: + excludes: ['**/resources/**'] + active: true + IteratorNotThrowingNoSuchElementException: + excludes: ['**/resources/**'] + active: true + LateinitUsage: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludeAnnotatedProperties: [] + ignoreOnClassesPattern: '' + MapGetWithNotNullAssertionOperator: + excludes: ['**/resources/**'] + active: false + MissingWhenCase: + excludes: ['**/resources/**'] + active: true + NullableToStringCall: + active: false + RedundantElseInWhen: + excludes: ['**/resources/**'] + active: true + UnconditionalJumpStatementInLoop: + excludes: ['**/resources/**'] + active: false + UnnecessaryNotNullOperator: + excludes: ['**/resources/**'] + active: false + UnnecessarySafeCall: + excludes: ['**/resources/**'] + active: false + UnreachableCode: + excludes: ['**/resources/**'] + active: true + UnsafeCallOnNullableType: + excludes: ['**/resources/**'] + active: true + UnsafeCast: + excludes: ['**/resources/**'] + active: false + UselessPostfixExpression: + excludes: ['**/resources/**'] + active: false + WrongEqualsTypeParameter: + excludes: ['**/resources/**'] + active: true + +style: + active: true + ClassOrdering: + active: true + CollapsibleIfStatements: + excludes: ['**/resources/**'] + active: false + DataClassContainsFunctions: + excludes: ['**/resources/**'] + active: false + conversionFunctionPrefix: 'to' + DataClassShouldBeImmutable: + excludes: ['**/resources/**'] + active: false + EqualsNullCall: + excludes: ['**/resources/**'] + active: true + EqualsOnSignatureLine: + excludes: ['**/resources/**'] + active: false + ExplicitCollectionElementAccessMethod: + excludes: ['**/resources/**'] + active: false + ExplicitItLambdaParameter: + excludes: ['**/resources/**'] + active: false + ExpressionBodySyntax: + excludes: ['**/resources/**'] + active: false + includeLineWrapping: false + ForbiddenComment: + excludes: ['**/resources/**'] + active: true + values: ['TODO:', 'STOPSHIP:'] + allowedPatterns: '' + ForbiddenImport: + excludes: ['**/resources/**'] + active: false + imports: [] + forbiddenPatterns: '' + ForbiddenMethodCall: + excludes: ['**/resources/**'] + active: false + methods: ['kotlin.io.println', 'kotlin.io.print'] + ForbiddenPublicDataClass: + excludes: ['**/resources/**'] + active: false + ignorePackages: ['*.internal', '*.internal.*'] + ForbiddenVoid: + excludes: ['**/resources/**'] + active: false + ignoreOverridden: false + ignoreUsageInGenerics: false + FunctionOnlyReturningConstant: + excludes: ['**/resources/**'] + active: true + ignoreOverridableFunction: true + excludedFunctions: 'describeContents' + excludeAnnotatedFunction: ['dagger.Provides'] + LibraryCodeMustSpecifyReturnType: + excludes: ['**/resources/**'] + active: false + LibraryEntitiesShouldNotBePublic: + active: false + LoopWithTooManyJumpStatements: + excludes: ['**/resources/**'] + active: true + maxJumpCount: 1 + MagicNumber: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + ignoreNumbers: ['-1', '0', '1', '2'] + ignoreHashCodeFunction: true + ignorePropertyDeclaration: false + ignoreLocalVariableDeclaration: false + ignoreConstantDeclaration: true + ignoreCompanionObjectPropertyDeclaration: true + ignoreAnnotation: false + ignoreNamedArgument: true + ignoreEnums: false + ignoreRanges: false + MandatoryBracesIfStatements: + excludes: ['**/resources/**'] + active: false + MandatoryBracesLoops: + excludes: ['**/resources/**'] + active: false + MaxLineLength: + excludes: ['**/resources/**'] + active: true + maxLineLength: 180 + excludePackageStatements: true + excludeImportStatements: true + excludeCommentStatements: false + MayBeConst: + excludes: ['**/resources/**'] + active: true + ModifierOrder: + excludes: ['**/resources/**'] + active: true + NestedClassesVisibility: + excludes: ['**/resources/**'] + active: false + NewLineAtEndOfFile: + excludes: ['**/resources/**'] + active: true + NoTabs: + excludes: ['**/resources/**'] + active: false + OptionalAbstractKeyword: + excludes: ['**/resources/**'] + active: true + OptionalUnit: + excludes: ['**/resources/**'] + active: false + OptionalWhenBraces: + excludes: ['**/resources/**'] + active: false + PreferToOverPairSyntax: + excludes: ['**/resources/**'] + active: false + ProtectedMemberInFinalClass: + excludes: ['**/resources/**'] + active: true + RedundantExplicitType: + excludes: ['**/resources/**'] + active: false + RedundantHigherOrderMapUsage: + active: true + RedundantVisibilityModifierRule: + excludes: ['**/resources/**'] + active: false + ReturnCount: + excludes: ['**/resources/**'] + active: false + max: 4 + excludedFunctions: 'equals' + excludeLabeled: false + excludeReturnFromLambda: true + excludeGuardClauses: false + SafeCast: + excludes: ['**/resources/**'] + active: true + SerialVersionUIDInSerializableClass: + excludes: ['**/resources/**'] + active: false + SpacingBetweenPackageAndImports: + excludes: ['**/resources/**'] + active: false + ThrowsCount: + excludes: ['**/resources/**'] + active: true + max: 2 + TrailingWhitespace: + excludes: ['**/resources/**'] + active: false + UnderscoresInNumericLiterals: + excludes: ['**/resources/**'] + active: false + acceptableDecimalLength: 5 + UnnecessaryAbstractClass: + excludes: ['**/resources/**'] + active: true + excludeAnnotatedClasses: ['dagger.Module'] + UnnecessaryAnnotationUseSiteTarget: + excludes: ['**/resources/**'] + active: false + UnnecessaryApply: + excludes: ['**/resources/**'] + active: false + UnnecessaryInheritance: + excludes: ['**/resources/**'] + active: true + UnnecessaryLet: + excludes: ['**/resources/**'] + active: false + UnnecessaryParentheses: + excludes: ['**/resources/**'] + active: false + UntilInsteadOfRangeTo: + excludes: ['**/resources/**'] + active: false + UnusedImports: + excludes: ['**/resources/**'] + active: false + UnusedPrivateClass: + excludes: ['**/resources/**'] + active: true + UnusedPrivateMember: + excludes: ['**/resources/**'] + active: false + allowedNames: '(_|ignored|expected|serialVersionUID)' + UseArrayLiteralsInAnnotations: + excludes: ['**/resources/**'] + active: false + UseCheckNotNull: + active: true + UseCheckOrError: + excludes: ['**/resources/**'] + active: false + UseDataClass: + excludes: ['**/resources/**'] + active: false + excludeAnnotatedClasses: [] + allowVars: false + UseEmptyCounterpart: + active: true + UseIfEmptyOrIfBlank: + active: true + UseIfInsteadOfWhen: + excludes: ['**/resources/**'] + active: false + UseRequire: + excludes: ['**/resources/**'] + active: false + UseRequireNotNull: + active: true + UselessCallOnNotNull: + excludes: ['**/resources/**'] + active: true + UtilityClassWithPublicConstructor: + excludes: ['**/resources/**'] + active: true + VarCouldBeVal: + excludes: ['**/resources/**'] + active: false + WildcardImport: + active: true + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**'] + excludeImports: ['java.util.*', 'kotlinx.android.synthetic.*', 'kotlinx.serialization'] \ No newline at end of file diff --git a/diktat-analysis.yml b/diktat-analysis.yml new file mode 100644 index 0000000000..e93b90fab7 --- /dev/null +++ b/diktat-analysis.yml @@ -0,0 +1,101 @@ +- name: DIKTAT_COMMON + enabled: true + configuration: + domainName: org.cqfn.save + kotlinVersion: 1.4 +- name: ENUM_VALUE + enabled: true + configuration: + enumStyle: snakeCase +- name: KDOC_CONTAINS_DATE_OR_AUTHOR + enabled: true + configuration: + versionRegex: \d+\.\d+\.\d+[-.\w\d]* +- name: HEADER_MISSING_OR_WRONG_COPYRIGHT + enabled: true + configuration: + isCopyrightMandatory: false + copyrightText: '' +- name: FILE_IS_TOO_LONG + enabled: true + configuration: + maxSize: 2000 + ignoreFolders: '' +- name: FILE_UNORDERED_IMPORTS + enabled: true + configuration: + useRecommendedImportsOrder: true +- name: FILE_WILDCARD_IMPORTS + enabled: true + configuration: + allowedWildcards: "kotlinx.serialization.*" +- name: BRACES_BLOCK_STRUCTURE_ERROR + enabled: true + configuration: + openBraceNewline: true + closeBraceNewline: true +- name: WRONG_INDENTATION + enabled: true + configuration: + # Is newline at the end of a file needed + newlineAtEnd: true + # If true: in parameter list when parameters are split by newline they are indented with two indentations instead of one + extendedIndentOfParameters: false + # If true: if first parameter in parameter list is on the same line as opening parenthesis, then other parameters can be aligned with it + alignedParameters: true + # If true: if expression is split by newline after operator like +/-/`*`, then the next line is indented with two indentations instead of one + extendedIndentAfterOperators: true + # If true: when dot qualified expression starts on a new line, this line will be indented with two indentations instead of one + extendedIndentBeforeDot: false + # The indentation size for each file + indentationSize: 4 +- name: EMPTY_BLOCK_STRUCTURE_ERROR + enabled: true + configuration: + styleEmptyBlockWithNewline: true + allowEmptyBlocks: false +- name: LONG_LINE + enabled: true + configuration: + lineLength: 180 +- name: WRONG_NEWLINES + enabled: true + configuration: + maxParametersInOneLine: 2 +- name: TOO_MANY_CONSECUTIVE_SPACES + enabled: true + configuration: + maxSpaces: 1 + saveInitialFormattingForEnums: false +- name: LONG_NUMERICAL_VALUES_SEPARATED + enabled: true + configuration: + maxNumberLength: 5 + maxBlockLength: 3 +- name: WRONG_DECLARATIONS_ORDER + enabled: true + configuration: + sortEnum: true + sortProperty: true +- name: COMMENT_WHITE_SPACE + enabled: true + configuration: + maxSpacesBeforeComment: 2 + maxSpacesInComment: 1 +- name: TYPE_ALIAS + enabled: true + configuration: + typeReferenceLength: 25 +- name: TOO_LONG_FUNCTION + enabled: true + configuration: + maxFunctionLength: 35 # max length of function + isIncludeHeader: false # count function's header +- name: TOO_MANY_PARAMETERS + enabled: true + configuration: + maxParameterListSize: 5 +- name: NESTED_BLOCK + enabled: true + configuration: + maxNestedBlockQuantity: 4 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index da9702f9e7..2a563242c1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/save-backend/src/main/kotlin/org/cqfn/save/backend/SaveApplication.kt b/save-backend/src/main/kotlin/org/cqfn/save/backend/SaveApplication.kt index f50993bb6e..de3c412d94 100644 --- a/save-backend/src/main/kotlin/org/cqfn/save/backend/SaveApplication.kt +++ b/save-backend/src/main/kotlin/org/cqfn/save/backend/SaveApplication.kt @@ -4,10 +4,13 @@ import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.web.reactive.config.EnableWebFlux +/** + * An entrypoint for spring for save-backend + */ @SpringBootApplication @EnableWebFlux open class SaveApplication fun main(args: Array) { SpringApplication.run(SaveApplication::class.java, *args) -} \ No newline at end of file +} diff --git a/save-backend/src/main/kotlin/org/cqfn/save/backend/controllers/DownloadFilesController.kt b/save-backend/src/main/kotlin/org/cqfn/save/backend/controllers/DownloadFilesController.kt index 013eeda725..c3900ddfec 100644 --- a/save-backend/src/main/kotlin/org/cqfn/save/backend/controllers/DownloadFilesController.kt +++ b/save-backend/src/main/kotlin/org/cqfn/save/backend/controllers/DownloadFilesController.kt @@ -11,24 +11,30 @@ import org.springframework.web.bind.annotation.RestController import reactor.core.publisher.Mono import java.io.File +/** + * A Spring controller for file downloading + */ @RestController class DownloadFilesController { private val logger = LoggerFactory.getLogger("org.cqfn.save.logback") + /** + * @return [Mono] with file contents + */ @GetMapping(value = ["/download"], produces = [MediaType.APPLICATION_OCTET_STREAM_VALUE]) - fun download(): Mono { - return Mono.fromCallable { - val file = File("test.txt") - file.createNewFile() - file.bufferedWriter().use { - it.write("qweqwe") - } - file.readBytes() + fun download() = Mono.fromCallable { + val file = File("test.txt") + file.createNewFile() + file.bufferedWriter().use { + it.write("qweqwe") } + file.readBytes() } + /** + * @param file a file to be uploaded + * @return [Mono] with response + */ @PostMapping(value = ["/upload"], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE]) - fun upload(@RequestPart("file") file: Mono): Mono> { - return Mono.just(ResponseEntity.ok().body("test")) - } -} \ No newline at end of file + fun upload(@RequestPart("file") file: Mono) = Mono.just(ResponseEntity.ok().body("test")) +} diff --git a/save-backend/src/test/kotlin/org/cqfn/save/backend/DownloadFilesTest.kt b/save-backend/src/test/kotlin/org/cqfn/save/backend/DownloadFilesTest.kt index aba2454257..c280a8b71c 100644 --- a/save-backend/src/test/kotlin/org/cqfn/save/backend/DownloadFilesTest.kt +++ b/save-backend/src/test/kotlin/org/cqfn/save/backend/DownloadFilesTest.kt @@ -11,14 +11,15 @@ import kotlin.io.path.ExperimentalPathApi @WebFluxTest class DownloadFilesTest { - @Autowired lateinit var webClient: WebTestClient @Test fun checkDownload() { - webClient.get().uri("/download").exchange().expectStatus().isOk - webClient.get().uri("/download").exchange().expectBody(String::class.java).isEqualTo("qweqwe") + webClient.get().uri("/download").exchange() + .expectStatus().isOk + webClient.get().uri("/download").exchange() + .expectBody(String::class.java).isEqualTo("qweqwe") } @Test @@ -28,14 +29,14 @@ class DownloadFilesTest { val body = MultipartBodyBuilder().apply { part("file", object : ByteArrayResource("testString".toByteArray()) { - override fun getFilename(): String? { - return tmpFile.fileName.toString() - } + override fun getFilename() = tmpFile.fileName.toString() }) }.build() - webClient.post().uri("/upload").body(BodyInserters.fromMultipartData(body)).exchange().expectStatus().isOk + webClient.post().uri("/upload").body(BodyInserters.fromMultipartData(body)) + .exchange().expectStatus().isOk - webClient.post().uri("/upload").body(BodyInserters.fromMultipartData(body)).exchange().expectBody(String::class.java).isEqualTo("test") + webClient.post().uri("/upload").body(BodyInserters.fromMultipartData(body)) + .exchange().expectBody(String::class.java).isEqualTo("test") } -} \ No newline at end of file +} diff --git a/save-common/src/commonMain/kotlin/org.cqfn.save.domain/RunConfiguration.kt b/save-common/src/commonMain/kotlin/org/cqfn/save/domain/RunConfiguration.kt similarity index 100% rename from save-common/src/commonMain/kotlin/org.cqfn.save.domain/RunConfiguration.kt rename to save-common/src/commonMain/kotlin/org/cqfn/save/domain/RunConfiguration.kt diff --git a/save-orchestrator/src/main/kotlin/org/cqfn/save/orchestrator/SaveOrchestrator.kt b/save-orchestrator/src/main/kotlin/org/cqfn/save/orchestrator/SaveOrchestrator.kt index 503b8df470..2eaaf658c3 100644 --- a/save-orchestrator/src/main/kotlin/org/cqfn/save/orchestrator/SaveOrchestrator.kt +++ b/save-orchestrator/src/main/kotlin/org/cqfn/save/orchestrator/SaveOrchestrator.kt @@ -1,9 +1,12 @@ -package org.cqfn.save.backend +package org.cqfn.save.orchestrator import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.web.reactive.config.EnableWebFlux +/** + * An entrypoint for spring boot for save-orchestrator + */ @SpringBootApplication @EnableWebFlux open class SaveOrchestrator diff --git a/save-orchestrator/src/main/kotlin/org/cqfn/save/orchestrator/docker/ContainerManager.kt b/save-orchestrator/src/main/kotlin/org/cqfn/save/orchestrator/docker/ContainerManager.kt index f5b14cc259..6c97be77ba 100644 --- a/save-orchestrator/src/main/kotlin/org/cqfn/save/orchestrator/docker/ContainerManager.kt +++ b/save-orchestrator/src/main/kotlin/org/cqfn/save/orchestrator/docker/ContainerManager.kt @@ -1,16 +1,17 @@ -package org.cqfn.save.backend.docker +package org.cqfn.save.orchestrator.docker + +import org.cqfn.save.domain.RunConfiguration import com.github.dockerjava.api.DockerClient import com.github.dockerjava.api.command.BuildImageResultCallback +import com.github.dockerjava.api.model.HostConfig import com.github.dockerjava.core.DefaultDockerClientConfig import com.github.dockerjava.core.DockerClientConfig -import com.github.dockerjava.api.model.HostConfig import com.github.dockerjava.core.DockerClientImpl import com.github.dockerjava.httpclient5.ApacheDockerHttpClient import com.github.dockerjava.transport.DockerHttpClient import org.apache.commons.compress.archivers.tar.TarArchiveEntry import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream -import org.cqfn.save.domain.RunConfiguration import org.slf4j.LoggerFactory import java.io.BufferedOutputStream @@ -23,6 +24,11 @@ import kotlin.io.path.ExperimentalPathApi import kotlin.io.path.createTempDirectory import kotlin.io.path.createTempFile +/** + * A class that communicates with docker daemon + * + * @property dockerHost a URL of docker daemon, local unix socket by default + */ class ContainerManager(private val dockerHost: String = "unix:///var/run/docker.sock") { private val dockerClientConfig: DockerClientConfig = DefaultDockerClientConfig .createDefaultConfigBuilder() @@ -32,22 +38,27 @@ class ContainerManager(private val dockerHost: String = "unix:///var/run/docker. private val dockerHttpClient: DockerHttpClient = ApacheDockerHttpClient.Builder() .dockerHost(dockerClientConfig.dockerHost) .build() + + /** + * Main class from docker-java-api + */ internal val dockerClient: DockerClient = DockerClientImpl.getInstance(dockerClientConfig, dockerHttpClient) /** * Creates a docker container with [file], prepared to execute it * * @param runConfiguration a [RunConfiguration] for the supplied binary - * @param file an executable file - * @param resources additional files to be copied in the container too + * @param containerName a name for the created container + * @param file a file that will be included as an executable + * @param resources additional resources + * @return id of created container or null if it wasn't created * @throws DockerException if docker daemon has returned an error * @throws RuntimeException if an exception not specific to docker has occurred - * @return id of created container or null if it wasn't created */ internal fun createWithFile(runConfiguration: RunConfiguration, - containerName: String, - file: File, - resources: Collection = emptySet()): String { + containerName: String, + file: File, + resources: Collection = emptySet()): String { // ensure the image is present in the system dockerClient.pullImageCmd(DOCKER_REPO) .withTag("latest") @@ -72,13 +83,13 @@ class ContainerManager(private val dockerHost: String = "unix:///var/run/docker. } /** - * Creates a docker image with proided [resources] + * Creates a docker image with provided [resources] * * @param baseImage base docker image rom which this image will be built - * @param resources files to be included into the image - * @param resourcesPath absolute path to resources inside the image's FS - * @throws DockerException + * @param baseDir a context dir for Dockerfile + * @param resourcesPath path to additional resources * @return id of the created docker image + * @throws DockerException */ @OptIn(ExperimentalPathApi::class) internal fun buildImageWithResources(baseImage: String = "ubuntu:latest", @@ -87,11 +98,11 @@ class ContainerManager(private val dockerHost: String = "unix:///var/run/docker. val tmpDir = createTempDirectory().toFile() baseDir.copyRecursively(File(tmpDir, "resources")) val dockerFileAsText = - """ - FROM $baseImage - COPY resources $resourcesPath - RUN /bin/bash - """.trimIndent() // RUN command shouldn't matter because it will be replaced on container creation + """ + FROM $baseImage + COPY resources $resourcesPath + RUN /bin/bash + """.trimIndent() // RUN command shouldn't matter because it will be replaced on container creation val dockerFile = createTempFile(tmpDir.toPath()).toFile() dockerFile.writeText(dockerFileAsText) val buildImageResultCallback: BuildImageResultCallback = try { @@ -131,7 +142,7 @@ class ContainerManager(private val dockerHost: String = "unix:///var/run/docker. } companion object { - private const val DOCKER_REPO = "docker.io/library/ubuntu" private val log = LoggerFactory.getLogger(ContainerManager::class.java) + private const val DOCKER_REPO = "docker.io/library/ubuntu" } } diff --git a/save-orchestrator/src/test/kotlin/org/cqfn/save/orchestrator/docker/ContainerManagerTest.kt b/save-orchestrator/src/test/kotlin/org/cqfn/save/orchestrator/docker/ContainerManagerTest.kt index 90633b8b41..e325b58374 100644 --- a/save-orchestrator/src/test/kotlin/org/cqfn/save/orchestrator/docker/ContainerManagerTest.kt +++ b/save-orchestrator/src/test/kotlin/org/cqfn/save/orchestrator/docker/ContainerManagerTest.kt @@ -1,4 +1,4 @@ -package org.cqfn.save.backend.docker +package org.cqfn.save.orchestrator.docker import org.cqfn.save.domain.RunConfiguration import org.junit.jupiter.api.AfterEach @@ -51,7 +51,7 @@ class ContainerManagerTest { fun `should build an image with provided resources`() { val resourcesDir = createTempDirectory() repeat(5) { createTempFile(resourcesDir) } - val imageId = containerManager.buildImageWithResources(baseDir = resourcesDir.toFile(), resourcesPath = "/app/resources") + val imageId = containerManager.buildImageWithResources(baseDir = resourcesDir.toFile(), resourcesPath = "/app/resources") val inspectImageResponse = containerManager.dockerClient.inspectImageCmd(imageId).exec() Assertions.assertTrue(inspectImageResponse.size!! > 0) }