Automate your workflows with Kotlin Fosdem - 2020 1
Automate your workflows with Kotlin @martinbonnin @mgauzins 2
A daily work... 1. Assign a ticket 2. Create a branch 3. Code... π€ 4. Create a pull request But also... 5. Move ticket state 6. Merge pull request β Manage app translations 7. Move ticket state Keep the store app up to date β 8. Create an alpha (images, listings, archives) a. Increment a version Manage app rollout β b. Tag β Notify about the updates c. Push Publish to alternative stores β 9. Send a message to designers/product owners 10. Integrate feedbacks 11. Back to step 1 3
Environment PlayStore Github CI Appcenter Slack Jira Transifex 4
Why automating ? It takes times. β Reliability β β Reproducibility Documentation β β Fun β Kotlin to the rescue 5 https://xkcd.com/1319/
Why Kotlin? The language we use every day β No context change (bash syndrome) β β Every team member knows it Modern β β Great IDE Great Ecosystem β 6
What did we replace ? Ad-hoc scripts General purpose 3rd party tools Build system tools generate_docs.sh Fastlane Github hub build.gradle (Bash) (Ruby) (Go) (Groovy) after_success.sh Transifex cli (Bash) (Ruby) 7
Tools we used β Kotlin scripts β Based on Kscript β Kotlin command line app (cli) β Called Kinta β Based on Clikt 8
Kscript 9
Scripting - motivations β For short projects/single file projects No need for gradle β β Easy to setup/use 10
Scripting - simple example // hello.kts println( "Hello ${ args[0] }!" ) // running the script $ kotlinc -script hello.kts Fosdem Hello Fosdem! https://github.com/Kotlin/KEEP/blob/master/proposals/scripting-support.md 11
Kscript - scripting improvements β Compiled script caching β Shebang and interpreter usage β Dependencies Standalone binaries β β IDE support β https://github.com/holgerbrandl/kscript 12
Kscript - installation curl -s "https://get.sdkman.io" | bash # install sdkman source ~/.bash_profile # add sdkman to PATH sdk install kotlin # install Kotlin sdk install kscript # install Kscript touch hello.kts kscript --idea hello.kts # start the IDE 13
Kscript // weekend.kts $ chmod +x weekend.kts #!/usr/bin/env kscript @file:DependsOn( "com.squareup.okhttp3:okhttp $ ./weekend.kts :4.3.1" ) It is the weekend! import okhttp3.OkHttpClient import okhttp3.Request val weekend = Request.Builder().get().url( "http://isitweek endyet.com/" ).build(). let { OkHttpClient().newCall( it ) } .execute(). body !!.string(). toLowerCase (). co ntains ( "yes" ) if ( weekend ) { println ( "It is the weekend!" ) } else { println ( "Not yet :-|" ) } 14
Kscript - IDE $ kscript --idea weekend.kts 15
Kscript - Debugger 16
Kscript - Real life examples β Generating project website (mkdocs + github pages) Install scripts β Migration from build.gradle to build.gradle.kts β Finding duplicates in string.xml β β Categorizing my expenses ! etc... β 17
Scripting - limitations β JVM required β JVM startup time β Multiple files is hard to maintain β No Gradle => no plugins, kapt, etc... 18
Kinta: a Kotlin Cli 19
CLIKT : Presentation Open Source library β Command Line β Interface for Kotlin https://github.com/ajalt/clikt Help 04 03 Commands Argument/Option customisable, nested composable, type safe, commands prompt, default 20
CLIKT to Kinta β We need entry points for workflows then commands β Provide a simple way to launch theses commands by anyone. (Command line interface) β Reach even more platforms 21
Kinta CLI integration plugins { application } β apply plugin: 'application' tasks . withType <Jar> { archiveFileName .set( "kinta-cli.jar" ) Create a jar β manifest { attributes ( "Main-Class" to com.dailymotion.kinta.MainKt" ) } β Specify the βMainβ class from( configurations . runtimeClasspath .get(). map { if ( it . isDirectory ) it else zipTree( it ) Generate starting scripts } ) β } application { mainClassName = "com.dailymotion.kinta.MainKt" } 22 build.gradle.kts
PublishPlayStore workflow β What is a workflow? β Workflow detail β Upload archive β Create a release on a specific track β Find a local changelog for the version β Upload the changelog kinta publish beta --archiveFile=app-release.aab 23
PublishPlayStore workflow override fun run() { object PublishPlayStore : CliktCommand( PlayStoreIntegration.uploadDraft( name = "publish" , archiveFile = File(archiveFile), help = "Publish a version on the given track" ) { track = track ) private val track by argument( "--track" , help = "The Play Store track" ) PlayStoreIntegration.createRelease( track = track, private val archiveFile by argument( "--archiveFile" ) listVersionCodes = listOf(versionCode), percent = percentToApply private val percent by option( "--percent" , help = "The user fraction receiving the update" ).double() ) override fun run() { val changeLogs = LocalMetadataHelper.getChangelog(versionCode) // Beautiful code is coming... PlayStoreIntegration.uploadWhatsNew( } versionCode = versionCode, } whatsNewProvider = changeLogs ) } 24
A Swiss knife Builds β nightly β buildPR Translations β buildTag β txPull β txPush Git - tickets β txPR β startWork β PR Common tools β trigger branch β Play Store releases β hotfix Play Store metadatas β beta cleanLocal β β uploadWhatsNew β release β cleanRemote β uploadListing β uploadScreenshots β generateScreenshots 25
The daily work becomes simpler! 1. Assign a ticket kinta startWork {TICKET_ID} 2. Create a branch 3. Code (Sorry you definitely have to write code) 4. Create a pull request kinta pr 5. Move ticket state Keep the validation on GitHub interface 6. Merge pull request 7. Move ticket state 8. Create an alpha Increment version kinta nightly Tag Push 9. Send a message 26
Whatβs next 27
Kinta - customization β Make the kinta tool usable outside Dailymotion β 3rd party services have a well defined APIβ¦ β β¦ but every organization has their own processes and workflows. β Thereβs a fine line between customization and reuse 28
Kinta - Integration and Workflows An Integration is: A Workflow is: β A Kotlin class linked to a specific β A Clikt command for a specific domain: complex task: β Github β Publish a release Transifex Create a Translation PR β β β etc... β etc... Highly reusable Inside the host project β β β Redistributed Static Most of the times specific to the host β β β It doesnβt change often project Composed of atomic methods Uses integrations to accomplish β β β Documented using Kdoc complex tasks Inside the redistributed Documented using clikt β β kinta-integrations artifact 29
Kinta - Custom workflows Kinta cli custom-workflows.jar builtin-workflows.jar kinta-integrations.jar 30 β Custom workflows are built using gradle and loaded at runtime using a ServiceLocator Kinta also comes with default built in workflows: β β Publishing to the play store β Opening a pull request etc... β
Whatβs next β Figuring out a way to distribute the kinta binary β Also distribute the backend/webapp that hosts artifacts β https://github.com/dailymotion/kinta Feedbacks welcome β β Disclaimer: itβs still very early stage and things may break 31
Thanks. 32
Recommend
More recommend