Browse Source

initial drone

code formatting
add spotbug
add ktlint, detekt

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
tags/0.5.0-rc1
tobiasKaminsky 5 months ago
parent
commit
e1b75c8b31
No account linked to committer's email address
15 changed files with 1230 additions and 16 deletions
  1. +48
    -0
      .drone.yml
  2. +85
    -2
      build.gradle
  3. +523
    -0
      detekt.yml
  4. +2
    -2
      gradle/wrapper/gradle-wrapper.properties
  5. +163
    -0
      scripts/analysis/analysis-wrapper.sh
  6. +1
    -0
      scripts/analysis/findbugs-results.txt
  7. +130
    -0
      scripts/analysis/findbugs-up.rb
  8. +9
    -0
      scripts/analysis/getBranchBase.sh
  9. +9
    -0
      scripts/analysis/getBranchName.sh
  10. +2
    -0
      scripts/analysis/lint-results.txt
  11. +199
    -0
      scripts/analysis/lint-up.rb
  12. +13
    -0
      scripts/checkGplayLimitation.sh
  13. +10
    -0
      scripts/checkIfRunDrone.sh
  14. +35
    -0
      spotbugs-filter.xml
  15. +1
    -12
      src/test/java/com/nextcloud/android/sso/api/API.java

+ 48
- 0
.drone.yml View File

@@ -0,0 +1,48 @@
kind: pipeline
name: analysis

steps:
- name: analysis
image: nextcloudci/android:android-50
environment:
GIT_USERNAME:
from_secret: GIT_USERNAME
GIT_TOKEN:
from_secret: GIT_TOKEN
LOG_USERNAME:
from_secret: LOG_USERNAME
LOG_PASSWORD:
from_secret: LOG_PASSWORD
commands:
- scripts/checkIfRunDrone.sh $GIT_USERNAME $GIT_TOKEN $DRONE_PULL_REQUEST || exit 0
- export BRANCH=$(scripts/analysis/getBranchName.sh $GIT_USERNAME $GIT_TOKEN $DRONE_PULL_REQUEST)
- scripts/analysis/analysis-wrapper.sh $GIT_USERNAME $GIT_TOKEN $BRANCH $LOG_USERNAME $LOG_PASSWORD $DRONE_BUILD_NUMBER $DRONE_PULL_REQUEST

- name: notify
image: drillster/drone-email
settings:
port: 587
from: nextcloud-drone@kaminsky.me
recipients_only: true
username:
from_secret: EMAIL_USERNAME
password:
from_secret: EMAIL_PASSWORD
recipients:
from_secret: EMAIL_RECIPIENTS
host:
from_secret: EMAIL_HOST
when:
event:
- push
status:
- failure
branch:
- master

trigger:
branch:
- master
event:
- push
- pull_request

+ 85
- 2
build.gradle View File

@@ -1,11 +1,26 @@
import com.github.spotbugs.SpotBugsTask

buildscript {
ext {
kotlin_version = '1.3.41'
}
repositories {
google()
jcenter()
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots/'
}
maven {
url 'https://plugins.gradle.org/m2/'
}
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
classpath 'gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:1.6.6'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.0.0-RC14"
}
}

@@ -16,7 +31,18 @@ repositories {

apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
group='com.github.nextcloud'
apply plugin: "com.github.spotbugs"
apply plugin: "io.gitlab.arturbosch.detekt"

group = 'com.github.nextcloud'

spotbugs {
toolVersion = '3.1.12'
}

configurations {
ktlint
}

android {
compileSdkVersion 28
@@ -38,16 +64,68 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions{
lintOptions {
// translations are imported from transifex, so no need to check here
disable 'MissingTranslation'
disable 'ExtraTranslation'
disable 'MissingQuantity'
disable 'InconsistentArrays'
disable 'TypographyEllipsis'
disable 'GradleDependency'
disable 'VectorPath'
disable 'IconMissingDensityFolder'
disable 'IconDensities'
abortOnError false
htmlReport true
htmlOutput file("$project.buildDir/reports/lint/lint.html")
}
productFlavors {
}

tasks.register("spotbugsDebug", SpotBugsTask) {
ignoreFailures = false
effort = "max"
reportLevel = "medium"
classes = fileTree("$project.buildDir/intermediates/javac/debug/compileDebugJavaWithJavac/classes/")
excludeFilter = file("${project.rootDir}/spotbugs-filter.xml")
pluginClasspath = project.configurations.spotbugsPlugins
source = fileTree('src/main/java')
classpath = files()
include '**/*.java'
exclude '**/gen/**'

reports {
xml.enabled = false
html.enabled = true
html {
destination = file("$project.buildDir/reports/spotbugs/spotbugs.html")
}
}
}
}

task ktlint(type: JavaExec, group: "verification") {
description = "Check Kotlin code style."
main = "com.pinterest.ktlint.Main"
classpath = configurations.ktlint
args "--reporter=plain", "--reporter=plain,output=${buildDir}/ktlint.txt,src/**/*.kt"
}

task ktlintFormat(type: JavaExec, group: "formatting") {
description = "Fix Kotlin code style deviations."
main = "com.pinterest.ktlint.Main"
classpath = configurations.ktlint
args "-F", "src/**/*.kt"
}

detekt {
reports {
xml {
enabled = false
}
}
config = files("detekt.yml")
input = files("src/")
}

dependencies {
@@ -66,6 +144,11 @@ dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.3'

spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.9.0'
spotbugsPlugins 'com.mebigfatguy.fb-contrib:fb-contrib:7.4.6'

ktlint "com.pinterest:ktlint:0.34.1"

// Required for local unit tests (JUnit 4 framework)
testImplementation 'junit:junit:4.12'
// required if you want to use Mockito for unit tests

+ 523
- 0
detekt.yml View File

@@ -0,0 +1,523 @@
autoCorrect: true

test-pattern: # Configure exclusions for test sources
active: true
patterns: # Test file regexes
- '.*/test/.*'
- '.*/androidTest/.*'
- '.*Test.kt'
- '.*Spec.kt'
- '.*Spek.kt'
exclude-rule-sets:
- 'comments'
exclude-rules:
- 'NamingRules'
- 'WildcardImport'
- 'MagicNumber'
- 'MaxLineLength'
- 'LateinitUsage'
- 'StringLiteralDuplication'
- 'SpreadOperator'
- 'TooManyFunctions'
- 'ForEachOnRange'
- 'FunctionMaxLength'
- 'TooGenericExceptionCaught'
- 'InstanceOfCheckForException'

build:
maxIssues: 10
weights:
# complexity: 2
# LongParameterList: 1
# style: 1
# comments: 1

processors:
active: true
exclude:
# - 'FunctionCountProcessor'
# - 'PropertyCountProcessor'
# - 'ClassCountProcessor'
# - 'PackageCountProcessor'
# - 'KtFileCountProcessor'

console-reports:
active: true
exclude:
# - 'ProjectStatisticsReport'
# - 'ComplexityReport'
# - 'NotificationReport'
# - 'FindingsReport'
# - 'BuildFailureReport'

comments:
active: true
CommentOverPrivateFunction:
active: false
CommentOverPrivateProperty:
active: false
EndOfSentenceFormat:
active: false
endOfSentenceFormat: ([.?!][ \t\n\r\f<])|([.?!]$)
UndocumentedPublicClass:
active: false
searchInNestedClass: true
searchInInnerClass: true
searchInInnerObject: true
searchInInnerInterface: true
UndocumentedPublicFunction:
active: false

complexity:
active: true
ComplexCondition:
active: true
threshold: 4
ComplexInterface:
active: false
threshold: 10
includeStaticDeclarations: false
ComplexMethod:
active: true
threshold: 10
ignoreSingleWhenExpression: false
ignoreSimpleWhenEntries: false
LabeledExpression:
active: false
ignoredLabels: ""
LargeClass:
active: true
threshold: 600
LongMethod:
active: true
threshold: 60
LongParameterList:
active: true
threshold: 6
ignoreDefaultParameters: false
MethodOverloading:
active: false
threshold: 6
NestedBlockDepth:
active: true
threshold: 4
StringLiteralDuplication:
active: false
threshold: 3
ignoreAnnotation: true
excludeStringsWithLessThan5Characters: true
ignoreStringsRegex: '$^'
TooManyFunctions:
active: true
thresholdInFiles: 11
thresholdInClasses: 11
thresholdInInterfaces: 11
thresholdInObjects: 11
thresholdInEnums: 11
ignoreDeprecated: false
ignorePrivate: false
ignoreOverridden: false

empty-blocks:
active: true
EmptyCatchBlock:
active: true
allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
EmptyClassBlock:
active: true
EmptyDefaultConstructor:
active: true
EmptyDoWhileBlock:
active: true
EmptyElseBlock:
active: true
EmptyFinallyBlock:
active: true
EmptyForBlock:
active: true
EmptyFunctionBlock:
active: true
ignoreOverriddenFunctions: false
EmptyIfBlock:
active: true
EmptyInitBlock:
active: true
EmptyKtFile:
active: true
EmptySecondaryConstructor:
active: true
EmptyWhenBlock:
active: true
EmptyWhileBlock:
active: true

exceptions:
active: true
ExceptionRaisedInUnexpectedLocation:
active: false
methodNames: 'toString,hashCode,equals,finalize'
InstanceOfCheckForException:
active: false
NotImplementedDeclaration:
active: false
PrintStackTrace:
active: false
RethrowCaughtException:
active: false
ReturnFromFinally:
active: false
SwallowedException:
active: false
ignoredExceptionTypes: 'InterruptedException,NumberFormatException,ParseException,MalformedURLException'
ThrowingExceptionFromFinally:
active: false
ThrowingExceptionInMain:
active: false
ThrowingExceptionsWithoutMessageOrCause:
active: false
exceptions: 'IllegalArgumentException,IllegalStateException,IOException'
ThrowingNewInstanceOfSameException:
active: false
TooGenericExceptionCaught:
active: true
exceptionNames:
- ArrayIndexOutOfBoundsException
- Error
- Exception
- IllegalMonitorStateException
- NullPointerException
- IndexOutOfBoundsException
- RuntimeException
- Throwable
allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
TooGenericExceptionThrown:
active: true
exceptionNames:
- Error
- Exception
- Throwable
- RuntimeException

formatting:
active: true
android: false
autoCorrect: true
ChainWrapping:
active: true
autoCorrect: true
CommentSpacing:
active: true
autoCorrect: true
Filename:
active: true
FinalNewline:
active: true
autoCorrect: true
ImportOrdering:
active: false
Indentation:
active: true
autoCorrect: true
indentSize: 4
continuationIndentSize: 4
MaximumLineLength:
active: true
maxLineLength: 120
ModifierOrdering:
active: true
autoCorrect: true
NoBlankLineBeforeRbrace:
active: true
autoCorrect: true
NoConsecutiveBlankLines:
active: true
autoCorrect: true
NoEmptyClassBody:
active: true
autoCorrect: true
NoItParamInMultilineLambda:
active: false
NoLineBreakAfterElse:
active: true
autoCorrect: true
NoLineBreakBeforeAssignment:
active: true
autoCorrect: true
NoMultipleSpaces:
active: true
autoCorrect: true
NoSemicolons:
active: true
autoCorrect: true
NoTrailingSpaces:
active: true
autoCorrect: true
NoUnitReturn:
active: true
autoCorrect: true
NoUnusedImports:
active: true
autoCorrect: true
NoWildcardImports:
active: true
autoCorrect: true
PackageName:
active: true
autoCorrect: true
ParameterListWrapping:
active: true
autoCorrect: true
indentSize: 4
SpacingAroundColon:
active: true
autoCorrect: true
SpacingAroundComma:
active: true
autoCorrect: true
SpacingAroundCurly:
active: true
autoCorrect: true
SpacingAroundKeyword:
active: true
autoCorrect: true
SpacingAroundOperators:
active: true
autoCorrect: true
SpacingAroundParens:
active: true
autoCorrect: true
SpacingAroundRangeOperator:
active: true
autoCorrect: true
StringTemplate:
active: true
autoCorrect: true

naming:
active: true
ClassNaming:
active: true
classPattern: '[A-Z$][a-zA-Z0-9$]*'
ConstructorParameterNaming:
active: true
parameterPattern: '[a-z][A-Za-z0-9]*'
privateParameterPattern: '[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
EnumNaming:
active: true
enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*'
ForbiddenClassName:
active: false
forbiddenName: ''
FunctionMaxLength:
active: false
maximumFunctionNameLength: 30
FunctionMinLength:
active: false
minimumFunctionNameLength: 3
FunctionNaming:
active: true
functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$'
excludeClassPattern: '$^'
ignoreOverridden: true
FunctionParameterNaming:
active: true
parameterPattern: '[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverriddenFunctions: true
MatchingDeclarationName:
active: true
MemberNameEqualsClassName:
active: false
ignoreOverriddenFunction: true
ObjectPropertyNaming:
active: true
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
packagePattern: '^[a-z]+(\.[a-z][A-Za-z0-9]*)*$'
TopLevelPropertyNaming:
active: true
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
maximumVariableNameLength: 64
VariableMinLength:
active: false
minimumVariableNameLength: 1
VariableNaming:
active: true
variablePattern: '[a-z][A-Za-z0-9]*'
privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true

performance:
active: true
ArrayPrimitive:
active: false
ForEachOnRange:
active: true
SpreadOperator:
active: true
UnnecessaryTemporaryInstantiation:
active: true

potential-bugs:
active: true
DuplicateCaseInWhenExpression:
active: true
EqualsAlwaysReturnsTrueOrFalse:
active: false
EqualsWithHashCodeExist:
active: true
ExplicitGarbageCollectionCall:
active: true
InvalidRange:
active: false
IteratorHasNextCallsNextMethod:
active: false
IteratorNotThrowingNoSuchElementException:
active: false
LateinitUsage:
active: false
excludeAnnotatedProperties: ""
ignoreOnClassesPattern: ""
UnconditionalJumpStatementInLoop:
active: false
UnreachableCode:
active: true
UnsafeCallOnNullableType:
active: false
UnsafeCast:
active: false
UselessPostfixExpression:
active: false
WrongEqualsTypeParameter:
active: false

style:
active: true
CollapsibleIfStatements:
active: false
DataClassContainsFunctions:
active: false
conversionFunctionPrefix: 'to'
EqualsNullCall:
active: false
EqualsOnSignatureLine:
active: false
ExplicitItLambdaParameter:
active: false
ExpressionBodySyntax:
active: false
includeLineWrapping: false
ForbiddenComment:
active: true
values: 'TODO:,FIXME:,STOPSHIP:'
ForbiddenImport:
active: false
imports: ''
ForbiddenVoid:
active: false
FunctionOnlyReturningConstant:
active: false
ignoreOverridableFunction: true
excludedFunctions: 'describeContents'
LoopWithTooManyJumpStatements:
active: false
maxJumpCount: 1
MagicNumber:
active: true
ignoreNumbers: '-1,0,1,2'
ignoreHashCodeFunction: true
ignorePropertyDeclaration: false
ignoreConstantDeclaration: true
ignoreCompanionObjectPropertyDeclaration: true
ignoreAnnotation: false
ignoreNamedArgument: true
ignoreEnums: false
MandatoryBracesIfStatements:
active: false
MaxLineLength:
active: true
maxLineLength: 120
excludePackageStatements: true
excludeImportStatements: true
excludeCommentStatements: false
MayBeConst:
active: false
ModifierOrder:
active: true
NestedClassesVisibility:
active: false
NewLineAtEndOfFile:
active: true
NoTabs:
active: false
OptionalAbstractKeyword:
active: true
OptionalUnit:
active: false
OptionalWhenBraces:
active: false
PreferToOverPairSyntax:
active: false
ProtectedMemberInFinalClass:
active: false
RedundantVisibilityModifierRule:
active: false
ReturnCount:
active: true
max: 2
excludedFunctions: "equals"
excludeLabeled: false
excludeReturnFromLambda: true
SafeCast:
active: true
SerialVersionUIDInSerializableClass:
active: false
SpacingBetweenPackageAndImports:
active: false
ThrowsCount:
active: true
max: 2
TrailingWhitespace:
active: false
UnderscoresInNumericLiterals:
active: false
acceptableDecimalLength: 5
UnnecessaryAbstractClass:
active: false
excludeAnnotatedClasses: "dagger.Module"
UnnecessaryApply:
active: false
UnnecessaryInheritance:
active: false
UnnecessaryLet:
active: false
UnnecessaryParentheses:
active: false
UntilInsteadOfRangeTo:
active: false
UnusedImports:
active: false
UnusedPrivateClass:
active: false
UnusedPrivateMember:
active: false
allowedNames: "(_|ignored|expected|serialVersionUID)"
UseDataClass:
active: false
excludeAnnotatedClasses: ""
UtilityClassWithPublicConstructor:
active: false
VarCouldBeVal:
active: false
WildcardImport:
active: true
excludeImports: 'java.util.*,kotlinx.android.synthetic.*'

+ 2
- 2
gradle/wrapper/gradle-wrapper.properties View File

@@ -3,5 +3,5 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
distributionSha256Sum=336b6898b491f6334502d8074a6b8c2d73ed83b92123106bd4bf837f04111043
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
distributionSha256Sum=53b71812f18cdb2777e9f1b2a0f2038683907c90bdc406bc64d8b400e1fb2c3b

+ 163
- 0
scripts/analysis/analysis-wrapper.sh View File

@@ -0,0 +1,163 @@
#!/usr/bin/env bash

#1: GIT_USERNAME
#2: GIT_TOKEN
#3: BRANCH
#4: LOG_USERNAME
#5: LOG_PASSWORD
#6: DRONE_BUILD_NUMBER
#7: PULL_REQUEST_NUMBER

stableBranch="master"
repository="android-singleSignOn"
codacyProject=160903

ruby scripts/analysis/lint-up.rb $1 $2 $3
lintValue=$?

ruby scripts/analysis/findbugs-up.rb $1 $2 $3
findbugsValue=$?


./gradlew ktlint
ktlintValue=$?

./gradlew detekt
detektValue=$?

# exit codes:
# 0: count was reduced
# 1: count was increased
# 2: count stayed the same

echo "Branch: $3"

if [ $3 = $stableBranch ]; then
echo "New findbugs result for $stableBranch at: https://www.kaminsky.me/nc-dev/$repository-findbugs/$stableBranch.html"
curl -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-findbugs/$stableBranch.html --upload-file build/reports/spotbugs/spotbugs.html

summary=$(sed -n "/<h1>Summary<\/h1>/,/<h1>Warnings<\/h1>/p" build/reports/spotbugs/spotbugs.html | head -n-1 | sed s'/<\/a>//'g | sed s'/<a.*>//'g | sed s"/Summary/SpotBugs ($stableBranch)/" | tr "\"" "\'" | tr -d "\r\n")
curl -u $4:$5 -X PUT -d "$summary" https://nextcloud.kaminsky.me/remote.php/webdav/$repository-findbugs/findbugs-summary-$stableBranch.html

if [ $lintValue -ne 1 ]; then
echo "New lint result for $stableBranch at: https://www.kaminsky.me/nc-dev/$repository-lint/$stableBranch.html"
curl -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-lint/$stableBranch.html --upload-file build/reports/lint/lint.html
exit 0
fi
else
if [ -e $6 ]; then
name=$stableBranch"-"$(date +%F)
else
name=$6;
fi
echo "New lint results at https://www.kaminsky.me/nc-dev/$repository-lint/$name.html"
curl 2>/dev/null -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-lint/$name.html --upload-file build/reports/lint/lint.html

echo "New findbugs results at https://www.kaminsky.me/nc-dev/$repository-findbugs/$name.html"
curl 2>/dev/null -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-findbugs/$name.html --upload-file build/reports/spotbugs/spotbugs.html

# delete all old comments, starting with Codacy
oldComments=$(curl 2>/dev/null -u $1:$2 -X GET https://api.github.com/repos/nextcloud/$repository/issues/$7/comments | jq '.[] | (.id |tostring) + "|" + (.user.login | test("nextcloud-android-bot") | tostring) + "|" + (.body | test("<h1>Codacy.*") | tostring)' | grep "true|true" | tr -d "\"" | cut -f1 -d"|")

echo $oldComments | while read comment ; do
curl 2>/dev/null -u $1:$2 -X DELETE https://api.github.com/repos/nextcloud/$repository/issues/comments/$comment
done

# lint and findbugs file must exist
if [ ! -s build/reports/lint/lint.html ] ; then
echo "lint.html file is missing!"
exit 1
fi

if [ ! -s build/reports/spotbugs/spotbugs.html ] ; then
echo "spotbugs.html file is missing!"
exit 1
fi

# add comment with results
lintResultNew=$(grep "Lint Report.* [0-9]* warning" build/reports/lint/lint.html | cut -f2 -d':' |cut -f1 -d'<')

lintErrorNew=$(echo $lintResultNew | grep "[0-9]* error" -o | cut -f1 -d" ")
if ( [ -z $lintErrorNew ] ); then
lintErrorNew=0
fi

lintWarningNew=$(echo $lintResultNew | grep "[0-9]* warning" -o | cut -f1 -d" ")
if ( [ -z $lintWarningNew ] ); then
lintWarningNew=0
fi

lintResultOld=$(curl 2>/dev/null https://raw.githubusercontent.com/nextcloud/$repository/$stableBranch/scripts/analysis/lint-results.txt)
lintErrorOld=$(echo $lintResultOld | grep "[0-9]* error" -o | cut -f1 -d" ")
if ( [ -z $lintErrorOld ] ); then
lintErrorOld=0
fi

lintWarningOld=$(echo $lintResultOld | grep "[0-9]* warning" -o | cut -f1 -d" ")
if ( [ -z $lintWarningOld ] ); then
lintWarningOld=0
fi

if [ $stableBranch = "master" ] ; then
codacyValue=$(curl 2>/dev/null https://app.codacy.com/dashboards/breakdown\?projectId\=$codacyProject | grep "total issues" | cut -d">" -f3 | cut -d"<" -f1)
codacyResult="<h1>Codacy</h1>$codacyValue"
else
codacyResult=""
fi

lintResult="<h1>Lint</h1><table width='500' cellpadding='5' cellspacing='2'><tr class='tablerow0'><td>Type</td><td><a href='https://www.kaminsky.me/nc-dev/"$repository"-lint/"$stableBranch".html'>$stableBranch</a></td><td><a href='https://www.kaminsky.me/nc-dev/"$repository"-lint/"$name".html'>PR</a></td></tr><tr class='tablerow1'><td>Warnings</td><td>"$lintWarningOld"</td><td>"$lintWarningNew"</td></tr><tr class='tablerow0'><td>Errors</td><td>"$lintErrorOld"</td><td>"$lintErrorNew"</td></tr></table>"
findbugsResultNew=$(sed -n "/<h1>Summary<\/h1>/,/<h1>Warnings<\/h1>/p" build/reports/spotbugs/spotbugs.html |head -n-1 | sed s'/<\/a>//'g | sed s'/<a.*>//'g | sed s"#Summary#<a href=\"https://www.kaminsky.me/nc-dev/$repository-findbugs/$name.html\">SpotBugs</a> (new)#" | tr "\"" "\'" | tr -d "\n")
findbugsResultOld=$(curl 2>/dev/null https://www.kaminsky.me/nc-dev/$repository-findbugs/findbugs-summary-$stableBranch.html | tr "\"" "\'" | tr -d "\r\n" | sed s"#SpotBugs#<a href=\"https://www.kaminsky.me/nc-dev/$repository-findbugs/$stableBranch.html\">SpotBugs</a>#" | tr "\"" "\'" | tr -d "\n")


if ( [ $lintValue -eq 1 ] ) ; then
lintMessage="<h1>Lint increased!</h1>"
fi

if ( [ $findbugsValue -eq 1 ] ) ; then
findbugsMessage="<h1>SpotBugs increased!</h1>"
fi

if ( [ $ktlintValue -eq 1 ] ) ; then
sed -i ':a;N;$!ba;s#\n#<br />#g;s#^<br />##g' build/ktlint.txt
curl -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-ktlint/$name.html --upload-file build/ktlint.txt
ktlintMessage="<h1>Kotlin lint found errors</h1><a href='https://www.kaminsky.me/nc-dev/$repository-ktlint/$name.html'>Lint</a>"
fi

if ( [ $detektValue -eq 1 ] ) ; then
curl -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-detekt/$name.html --upload-file build/reports/detekt/detekt.html
detektMessage="<h1>Detekt errors found</h1><a href='https://www.kaminsky.me/nc-dev/$repository-detekt/$name.html'>Lint</a>"
fi

# check gplay limitation: all changelog files must only have 500 chars
gplayLimitation=$(scripts/checkGplayLimitation.sh)

if [ ! -z "$gplayLimitation" ]; then
gplayLimitation="<h1>Following files are beyond 500 char limit:</h1><br><br>"$gplayLimitation
fi

curl -u $1:$2 -X POST https://api.github.com/repos/nextcloud/$repository/issues/$7/comments -d "{ \"body\" : \"$codacyResult $lintResult $findbugsResultNew $findbugsResultOld $lintMessage $findbugsMessage $ktlintMessage $detektMessage $gplayLimitation \" }"

if [ ! -z "$gplayLimitation" ]; then
exit 1
fi

if [ ! $lintValue -eq 2 ]; then
exit $lintValue
fi


if [ $ktlintValue -eq 1 ]; then
exit 1
fi

if [ $detektValue -eq 1 ]; then
exit 1
fi

if [ $findbugsValue -eq 2 ]; then
exit 0
else
exit $findbugsValue
fi
fi

+ 1
- 0
scripts/analysis/findbugs-results.txt View File

@@ -0,0 +1 @@
999

+ 130
- 0
scripts/analysis/findbugs-up.rb View File

@@ -0,0 +1,130 @@
## Script from https://github.com/tir38/android-lint-entropy-reducer at 07.05.2017
# adapts to drone, use git username / token as parameter

Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8

puts "=================== starting Android FindBugs Entropy Reducer ===================="

# get args
git_user, git_token, git_branch = ARGV

# ======================== SETUP ============================

# User name for git commits made by this script.
TRAVIS_GIT_USERNAME = String.new("Drone CI server")

# File name and relative path of generated FindBugs report. Must match build.gradle file:
# lintOptions {
# htmlOutput file("[FILE_NAME].html")
# }
FINDBUGS_REPORT_FILE = String.new("build/reports/spotbugs/spotbugs.html")

# File name and relative path of previous results of this script.
PREVIOUS_FINDBUGS_RESULTS_FILE=String.new("scripts/analysis/findbugs-results.txt")

# Flag to evaluate warnings. true = check warnings; false = ignore warnings
CHECK_WARNINGS = true

# File name and relative path to custom FindBugs rules; Can be null or "".
CUSTOM_FINDBUGS_FILE = String.new("")

# ================ SETUP DONE; DON'T TOUCH ANYTHING BELOW ================

require 'fileutils'
require 'pathname'
require 'open3'

# since we need the xml-simple gem, and we want this script self-contained, let's grab it just when we need it
begin
gem "xml-simple"
rescue LoadError
system("gem install xml-simple")
Gem.clear_paths
end

require 'xmlsimple'

# run FindBugs
puts "running FindBugs..."
system './gradlew spotbugsDebug'

# find FindBugs report file
findbugs_reports = Dir.glob(FINDBUGS_REPORT_FILE)
if findbugs_reports.length == 0
puts "Findbugs HTML report not found."
exit 1
end
findbugs_report = String.new(findbugs_reports[0])

# find number of warnings
current_warning_count = `grep -A 3 "<b>Total</b>" build/reports/spotbugs/spotbugs.html | tail -n1 | cut -f2 -d">" | cut -f1 -d"<"`.to_i
puts "found warnings: " + current_warning_count.to_s

# get warning counts from last successful build

previous_results = false

previous_findbugs_reports = Dir.glob(PREVIOUS_FINDBUGS_RESULTS_FILE)
if previous_findbugs_reports.nil? || previous_findbugs_reports.length == 0
previous_findbugs_report = File.new(PREVIOUS_FINDBUGS_RESULTS_FILE, "w") # create for writing to later
else
previous_findbugs_report = String.new(previous_findbugs_reports[0])

previous_warning_count = File.open(previous_findbugs_report, &:readline).match(/[0-9]*/)[0].to_i

if previous_warning_count.nil?
previous_results = false
else
previous_results = true

puts "previous warnings: " + previous_warning_count.to_s
end
end

# compare previous warning count with current warning count
if previous_results == true && current_warning_count > previous_warning_count
puts "FAIL: warning count increased"
exit 1
end

# check if warning and error count stayed the same
if previous_results == true && current_warning_count == previous_warning_count
puts "SUCCESS: count stayed the same"
exit 2
end

# warning count DECREASED
puts "SUCCESS: count decreased from " + previous_warning_count.to_s + " to " + current_warning_count.to_s

# write new results to file (will overwrite existing, or create new)
File.write(previous_findbugs_report, current_warning_count)

# push changes to github (if this script is run locally, we don't want to overwrite git username and email, so save temporarily)
previous_git_username, _ = Open3.capture2('git config user.name')
previous_git_username = previous_git_username.strip

previous_git_email, _ = Open3.capture3('git config user.email')
previous_git_email = previous_git_email.strip

# update git user name and email for this script
system ("git config --local user.name '" + git_user + "'")
system ("git config --local user.email 'android@nextcloud.com'")
system ("git remote rm origin")
system ("git remote add origin https://" + git_user + ":" + git_token + "@github.com/nextcloud/android-single-signon")

# add previous FindBugs result file to git
system ('git add ' + PREVIOUS_FINDBUGS_RESULTS_FILE)

# commit changes; Add "skip ci" so that we don't accidentally trigger another Drone build
system ('git commit -sm "Drone: update FindBugs results to reflect reduced error/warning count [skip ci]" ')

# push to origin
system ('git push origin HEAD:' + git_branch)

# restore previous git user name and email
system("git config --local user.name '#{previous_git_username}'")
system("git config --local user.email '#{previous_git_email}'")

puts "SUCCESS: count was reduced"
exit 0 # success

+ 9
- 0
scripts/analysis/getBranchBase.sh View File

@@ -0,0 +1,9 @@
#!/bin/bash

# $1: username, $2: password/token, $3: pull request number

if [ -z $3 ] ; then
echo "master";
else
curl 2>/dev/null -u $1:$2 https://api.github.com/repos/nextcloud/android-singlesignon/pulls/$3 | jq .base.ref
fi

+ 9
- 0
scripts/analysis/getBranchName.sh View File

@@ -0,0 +1,9 @@
#!/bin/bash

# $1: username, $2: password/token, $3: pull request number

if [ -z $3 ] ; then
echo "master";
else
curl 2>/dev/null -u $1:$2 https://api.github.com/repos/nextcloud/android-singlesignon/pulls/$3 | grep \"ref\": | grep -v '"master"' | cut -d"\"" -f4
fi

+ 2
- 0
scripts/analysis/lint-results.txt View File

@@ -0,0 +1,2 @@
DO NOT TOUCH; GENERATED BY DRONE
<span class="mdl-layout-title">Lint Report: 2 warnings</span>

+ 199
- 0
scripts/analysis/lint-up.rb View File

@@ -0,0 +1,199 @@
## Script from https://github.com/tir38/android-lint-entropy-reducer at 07.05.2017
# adapts to drone, use git username / token as parameter

Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8

puts "=================== starting Android Lint Entropy Reducer ===================="

# get args
git_user, git_token, git_branch = ARGV

# ======================== SETUP ============================

# User name for git commits made by this script.
TRAVIS_GIT_USERNAME = String.new("Drone CI server")

# File name and relative path of generated Lint report. Must match build.gradle file:
# lintOptions {
# htmlOutput file("[FILE_NAME].html")
# }
LINT_REPORT_FILE = String.new("build/reports/lint/lint.html")

# File name and relative path of previous results of this script.
PREVIOUS_LINT_RESULTS_FILE=String.new("scripts/analysis/lint-results.txt")

# Flag to evaluate warnings. true = check warnings; false = ignore warnings
CHECK_WARNINGS = true

# File name and relative path to custom lint rules; Can be null or "".
CUSTOM_LINT_FILE = String.new("")

# ================ SETUP DONE; DON'T TOUCH ANYTHING BELOW ================

require 'fileutils'
require 'pathname'
require 'open3'

# since we need the xml-simple gem, and we want this script self-contained, let's grab it just when we need it
begin
gem "xml-simple"
rescue LoadError
system("gem install xml-simple")
Gem.clear_paths
end

require 'xmlsimple'

# add custom Lint jar
if !CUSTOM_LINT_FILE.nil? &&
CUSTOM_LINT_FILE.length > 0

ENV["ANDROID_LINT_JARS"] = Dir.pwd + "/" + CUSTOM_LINT_FILE
puts "adding custom lint rules to default set: "
puts ENV["ANDROID_LINT_JARS"]
end

# run Lint
puts "running Lint..."
system './gradlew clean lint'

# confirm that Lint ran w/out error
result = $?.to_i
if result != 0
puts "FAIL: failed to run ./gradlew clean lint"
exit 1
end

# find Lint report file
lint_reports = Dir.glob(LINT_REPORT_FILE)
if lint_reports.length == 0
puts "Lint HTML report not found."
exit 1
end
lint_report = String.new(lint_reports[0])

# find error/warning count string in HTML report
error_warning_string = ""
File.open lint_report do |file|
error_warning_string = file.find { |line| line =~ /([0-9]* error[s]? and )?[0-9]* warning[s]?/ }
end

# find number of errors
error_string = error_warning_string.match(/[0-9]* error[s]?/)

if (error_string.nil?)
current_error_count = 0
else
current_error_count = error_string[0].match(/[0-9]*/)[0].to_i
end

puts "found errors: " + current_error_count.to_s

# find number of warnings
if CHECK_WARNINGS == true
warning_string = error_warning_string.match(/[0-9]* warning[s]?/)[0]
current_warning_count = warning_string.match(/[0-9]*/)[0].to_i
puts "found warnings: " + current_warning_count.to_s
end

# get previous error and warning counts from last successful build

previous_results = false

previous_lint_reports = Dir.glob(PREVIOUS_LINT_RESULTS_FILE)
if previous_lint_reports.nil? ||
previous_lint_reports.length == 0

previous_lint_report = File.new(PREVIOUS_LINT_RESULTS_FILE, "w") # create for writing to later
else
previous_lint_report = String.new(previous_lint_reports[0])

previous_error_warning_string = ""
File.open previous_lint_report do |file|
previous_error_warning_string = file.find { |line| line =~ /([0-9]* error[s]? and )?[0-9]* warning[s]?/ }
end

unless previous_error_warning_string.nil?
previous_results = true

previous_error_string = previous_error_warning_string.match(/[0-9]* error[s]?/)
if previous_error_string.nil?
previous_error_string = "0 errors"
else
previous_error_string = previous_error_string[0]
end
previous_error_count = previous_error_string.match(/[0-9]*/)[0].to_i
puts "previous errors: " + previous_error_count.to_s

if CHECK_WARNINGS == true
previous_warning_string = previous_error_warning_string.match(/[0-9]* warning[s]?/)
if previous_warning_string.nil?
previous_warning_string = "0 warnings"
else
previous_warning_string = previous_warning_string[0]
end
previous_warning_count = previous_warning_string.match(/[0-9]*/)[0].to_i
puts "previous warnings: " + previous_warning_count.to_s
end
end
end

# compare previous error count with current error count
if previous_results == true &&
current_error_count > previous_error_count
puts "FAIL: error count increased"
exit 1
end

# compare previous warning count with current warning count
if CHECK_WARNINGS == true &&
previous_results == true &&
current_warning_count > previous_warning_count

puts "FAIL: warning count increased"
exit 1
end

# check if warning and error count stayed the same
if previous_results == true &&
current_error_count == previous_error_count &&
current_warning_count == previous_warning_count

puts "SUCCESS: count stayed the same"
exit 2
end

# either error count or warning count DECREASED

# write new results to file (will overwrite existing, or create new)
File.write(previous_lint_report, "DO NOT TOUCH; GENERATED BY DRONE\n" + error_warning_string)

# push changes to github (if this script is run locally, we don't want to overwrite git username and email, so save temporarily)
previous_git_username, _ = Open3.capture2('git config user.name')
previous_git_username = previous_git_username.strip

previous_git_email, _ = Open3.capture3('git config user.email')
previous_git_email = previous_git_email.strip

# update git user name and email for this script
system ("git config --local user.name '" + git_user + "'")
system ("git config --local user.email 'android@nextcloud.com'")
system ("git remote rm origin")
system ("git remote add origin https://" + git_user + ":" + git_token + "@github.com/nextcloud/android-singlesignon")

# add previous Lint result file to git
system ('git add ' + PREVIOUS_LINT_RESULTS_FILE)

# commit changes; Add "skip ci" so that we don't accidentally trigger another Drone build
system ('git commit -sm "Drone: update Lint results to reflect reduced error/warning count [skip ci]" ')

# push to origin
system ('git push origin HEAD:' + git_branch)

# restore previous git user name and email
system("git config --local user.name '#{previous_git_username}'")
system("git config --local user.email '#{previous_git_email}'")

puts "SUCCESS: count was reduced"
exit 0 # success

+ 13
- 0
scripts/checkGplayLimitation.sh View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash

result=""

for log in fastlane/metadata/android/*/changelogs/*
do
if [[ -e $log && $(wc -m $log | cut -d" " -f1) -gt 500 ]]
then
result=$log"<br>"$result
fi
done

echo -e "$result";

+ 10
- 0
scripts/checkIfRunDrone.sh View File

@@ -0,0 +1,10 @@
#!/bin/sh -e

export BRANCH=$(scripts/analysis/getBranchBase.sh $1 $2 $3 | sed s'/"//'g)
if [ $(git diff --name-only origin/$BRANCH | grep -c "^src") -eq 0 ] ; then
echo "No source files changed"
exit 1
else
echo "Source files changed -> continue with CI"
exit 0
fi

+ 35
- 0
spotbugs-filter.xml View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
<Match>
<Class name="~.*\.Manifest\$.*" />
</Match>
<Match>
<Class name="~.*\.R\$.*" />
</Match>
<Match>
<Class name="~.*\.R\$.*" />
</Match>
<Match>
<Class name="~.*\$\$Parcelable.*" />
</Match>

<!-- Dagger code is autogenerated. Exclude it from Check. -->
<Match>
<Or>
<Class name="~.*\.Dagger.*" />
<Class name="~com.nextcloud.client.di\..*_.*" />
</Or>
</Match>
<!-- Dagger generated code uses internal APIs -->
<Match>
<Class name="~.*\..*.*Factory" />
<Bug pattern="IICU_INCORRECT_INTERNAL_CLASS_USE" />
</Match>

<Bug pattern="PATH_TRAVERSAL_IN" />
<Bug pattern="ANDROID_EXTERNAL_FILE_ACCESS" />
<Bug pattern="BAS_BLOATED_ASSIGNMENT_SCOPE" />

<!-- This is unmanageable for now due to large amount of interconnected static state -->
<Bug pattern="FCCD_FIND_CLASS_CIRCULAR_DEPENDENCY" />
</FindBugsFilter>

+ 1
- 12
src/test/java/com/nextcloud/android/sso/api/API.java View File

@@ -2,6 +2,7 @@ package com.nextcloud.android.sso.api;

import java.util.List;
import java.util.Map;

import io.reactivex.Completable;
import io.reactivex.Observable;
import okhttp3.ResponseBody;
@@ -27,26 +28,21 @@ import retrofit2.http.Streaming;


public interface API {

@GET("version")
Observable<String> getRequest();

@GET("folders")
Observable<List<String>> getFolders();


@POST("folders")
Call<List<String>> postFolder(@Body Map<String, Object> folderMap);


@PUT("feeds/{feedId}/rename")
Completable putFeed(@Path("feedId") long feedId, @Body Map<String, String> paramMap);


@DELETE("feeds/{feedId}")
Completable deleteFeed(@Path("feedId") long feedId);


/** ITEMS **/
@GET("items")
Call<List<String>> getItems(
@@ -66,13 +62,9 @@ public interface API {
@Query("id") long id
);


@PUT("items/read/multiple")
Call<Void> putMarkItemsRead(@Body String items);




@PATCH("test")
Call<Void> invalidPATCH();

@@ -83,11 +75,9 @@ public interface API {
@GET("test")
Call<Void> getWithHeader();


@GET("/test")
Call<Void> getDynamicHeader(@Header("Content-Range") String contentRange);


@NextcloudAPI.FollowRedirects
@GET("/test")
Call<Void> getFollowRedirects();
@@ -102,5 +92,4 @@ public interface API {

@GET("cloud/capabilities?format=json")
Call<ResponseBody> getCapabilities(@Query("test") long test);

}

Loading…
Cancel
Save