Slide 1

Slide 1 text

Automate All The Things Nate Ebel

Slide 2

Slide 2 text

@n8ebel #oredev Why Automate?

Slide 3

Slide 3 text

@n8ebel #oredev Consistently build the right thing at the right time

Slide 4

Slide 4 text

@n8ebel #oredev Save time and energy for the real challenges

Slide 5

Slide 5 text

@n8ebel #oredev Make projects more approachable

Slide 6

Slide 6 text

@n8ebel #oredev Slides & Repo ● https://github.com/n8ebel/AutomationSandbox ● https://github.com/n8ebel/GitHubActionsAutomationSandbox ● Speakerdeck - @n8ebel

Slide 7

Slide 7 text

@n8ebel #oredev What to Automate?

Slide 8

Slide 8 text

@n8ebel #oredev Automate All The Things!

Slide 9

Slide 9 text

@n8ebel #oredev What To Automate? QUALITY REVIEW DEPLOY BUILD Where are you losing time, energy, or joy?

Slide 10

Slide 10 text

@n8ebel #oredev Automating Your Build

Slide 11

Slide 11 text

@n8ebel #oredev Automating Your Build BUILD BUILD Assemble Test Quality Deploy Educate

Slide 12

Slide 12 text

@n8ebel #oredev Automating Your Build CONFIG BUILD ASSEMBLE TEST DEPLOY

Slide 13

Slide 13 text

@n8ebel #oredev Automating Your Build CircleCI Bitrise GitHub Actions Codemagic

Slide 14

Slide 14 text

@n8ebel #oredev Building With GitHub Actions ● Add “workflow” .yml file(s) ● Define when to run ● Define build/script steps ● Push to default branch ● Start building

Slide 15

Slide 15 text

@n8ebel #oredev Building With GitHub Actions ... on: [pull_request, issues] jobs: greeting: runs-on: ubuntu-latest steps: - uses: actions/first-interaction@v1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} issue-message: 'Thank you for helping us make this project better ' pr-message: 'Thank you for submitting your first PR ' .github/workflows/greet_contributor.yml

Slide 16

Slide 16 text

@n8ebel #oredev Building With GitHub Actions

Slide 17

Slide 17 text

@n8ebel #oredev Building With GitHub Actions ... steps: - uses: actions/checkout@v1 - name: set up JDK 1.8 uses: actions/setup-java@v1 with: java-version: 1.8 - name: Build & Test Project run: ./gradlew assemble .github/workflows/build_project.yml

Slide 18

Slide 18 text

@n8ebel #oredev Building With CircleCI Workows run in response to triggers ● Push, Pull_request, New Issue, Schedule, etc...

Slide 19

Slide 19 text

@n8ebel #oredev Enforcing Build Status Checks

Slide 20

Slide 20 text

@n8ebel #oredev Building With CircleCI

Slide 21

Slide 21 text

@n8ebel #oredev Enforcing Build Status Checks - Settings -> Branches - Click ‘Add Rule’ - Require Status Checks To Pass Before Merging

Slide 22

Slide 22 text

@n8ebel #oredev Enforcing Build Status Checks

Slide 23

Slide 23 text

@n8ebel #oredev Enforcing Build Status Checks

Slide 24

Slide 24 text

@n8ebel #oredev Now we have an automated build process

Slide 25

Slide 25 text

@n8ebel #oredev Validating Code Quality

Slide 26

Slide 26 text

@n8ebel #oredev Validating Code Quality ANDROID LINT CODE FORMATTING CODE SMELLS TESTS

Slide 27

Slide 27 text

@n8ebel #oredev Validating code quality with your automated build

Slide 28

Slide 28 text

@n8ebel #oredev Validating Code Quality - Add/Configure formatting/quality tool within project - Integrate with build script - Report issues

Slide 29

Slide 29 text

@n8ebel #oredev Validating Code Formatting With ktlint ... - name: Check Kotlin Formatting run: ./gradlew ktlintCheck --continue Update build workflow to incorporate new build task .github/workflows/build_project.yml

Slide 30

Slide 30 text

@n8ebel #oredev Validating Code Formatting With ktlint

Slide 31

Slide 31 text

@n8ebel #oredev What’s the problem here?

Slide 32

Slide 32 text

@n8ebel #oredev Failing builds require time and context switching

Slide 33

Slide 33 text

@n8ebel #oredev Locally validating code quality

Slide 34

Slide 34 text

@n8ebel #oredev Locally Validating Code Quality ● Reformat/Lint code using IDE ● Run ktlint, Android Lint, etc locally ● Avoid pushing code which fails the build

Slide 35

Slide 35 text

@n8ebel #oredev Reformatting Code Using IDE ● Set project code style from pre-defined style ● Customize as desired ● Update .gitignore ● Ensure code styles included in repo ● Optimize imports on the fly

Slide 36

Slide 36 text

@n8ebel #oredev Reformatting Code Using IDE # IDEA/Android Studio ignores *.iml /.idea/* # IDEA/Android Studio Ignore exceptions !/.idea/codeStyles/ !/.idea/fileTemplates/ !/.idea/inspectionProfiles/ !/.idea/scopes/ !/.idea/copyright/ ... .gitignore

Slide 37

Slide 37 text

@n8ebel #oredev Reformatting Code Using IDE - Add project code styles to git - Configure as desired to pass formatting checks

Slide 38

Slide 38 text

@n8ebel #oredev Reformatting Code Using IDE Bonus tip for enforcing ktlint rules within Android Studio & IntelliJ

Slide 39

Slide 39 text

@n8ebel #oredev Running ktlint Locally ● Have to remember to run local checks before pushing code ● Can use git-hooks to automatically run these checks

Slide 40

Slide 40 text

@n8ebel #oredev Git hooks are scripts that Git executes before or after events such as: commit, push, and receive.

Slide 41

Slide 41 text

@n8ebel #oredev Enforcing Code Quality With Git Hooks PRE-PUSH CHECK FORMATTING PRE-COMMIT DO SOMETHING

Slide 42

Slide 42 text

@n8ebel #oredev Enforcing Code Quality With Git Hooks #!/bin/sh # Adapted from https://proandroiddev.com/ooga-chaka-git-hooks-to-enforce-code-quality-11ce8d0d23cb echo "Checking code formatting" ./gradlew app:ktlintCheck --daemon status=$? if [ "$status" = 0 ] ; then echo "No formatting issues were found" exit 0 else echo 1>&2 "* There are code formatting issues that must be addressed" exit 1 fi .git/hooks/pre-push

Slide 43

Slide 43 text

@n8ebel #oredev Automating Git Hook Installation #!/bin/sh # Adapted from https://proandroiddev.com/ooga-chaka-git-hooks-to-enforce-code-quality-11ce8d0d23cb echo "Checking code formatting" ./gradlew app:ktlintCheck --daemon status=$? if [ "$status" = 0 ] ; then echo "No formatting issues were found" exit 0 else echo 1>&2 "* There are code formatting issues that must be addressed" exit 1 fi /scripts/git-hooks/pre-push.sh

Slide 44

Slide 44 text

@n8ebel #oredev Enforcing Code Quality With Git Hooks task copyGitHooks(type: Copy) { description 'Copies the git hooks from scripts/git-hooks to the .git folder.' ... } task installGitHooks(type: Exec) { description 'Installs the git hooks from scripts/git-hooks.' ... } afterEvaluate { tasks['clean'].dependsOn installGitHooks // We install the hook at the first occasion } git-hooks.gradle

Slide 45

Slide 45 text

@n8ebel #oredev Enforcing Code Quality With Git Hooks ... apply from: 'git-hooks.gradle' build.gradle

Slide 46

Slide 46 text

@n8ebel #oredev Now We Can Prevent Pushes That Will Fail, And Share With The Team

Slide 47

Slide 47 text

@n8ebel #oredev Reviewing Code

Slide 48

Slide 48 text

@n8ebel #oredev Reviewing Code Validate Changes Discuss Approaches Learn

Slide 49

Slide 49 text

@n8ebel #oredev Creating PR templates

Slide 50

Slide 50 text

@n8ebel #oredev Creating PR Templates Want to Avoid This Lack Of Detail

Slide 51

Slide 51 text

@n8ebel #oredev Creating PR Templates Favor and Encourage More Detail

Slide 52

Slide 52 text

@n8ebel #oredev Creating PR Templates ### Related To-Do ** link ** ### Proposed Changes * change 1 * change 2 ### Additional Info ** any additional useful context or info ** ### Checklist - [ ] Tests - [ ] Translations ### Screenshots Original | Updated :-------------------------:|:-------------------------: ** original screenshot ** | ** updated screenshot ** .github/pull_request_template.md ● Link to issue ● Describe changes ● Additional context ● Checklists ● Screenshots

Slide 53

Slide 53 text

@n8ebel #oredev Creating PR Templates ● PR Sections Pre-Populated Based On Template ● Encourage Contributors To Provide Ample Detail

Slide 54

Slide 54 text

@n8ebel #oredev Creating issue templates

Slide 55

Slide 55 text

@n8ebel #oredev Creating Issue Templates --- name: Bug report about: Create a report to help us improve title: '' labels: bug assignees: '' --- **Description** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. See error **Expected behavior** ... .github/ISSUE_TEMPLATE/bug_report.md

Slide 56

Slide 56 text

@n8ebel #oredev Creating Issue Templates --- name: Feature request about: Suggest an idea for this project title: '' labels: enhancement assignees: '' --- **What problem are you trying to solve?** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. .github/ISSUE_TEMPLATE/feature_request.md

Slide 57

Slide 57 text

@n8ebel #oredev Using Issue Templates Choose a Template When Creating an Issue

Slide 58

Slide 58 text

@n8ebel #oredev Using Issue Templates ● Issue Will Pre-Populate Based On Template ● Encourage Contributors To Provide Enough Information

Slide 59

Slide 59 text

@n8ebel #oredev Referencing GitHub Issues Close issues via keyword in PR descriptions or commits ● ‘Closes’ ● ‘Fixes’ ● ‘Resolves’ ● etc...

Slide 60

Slide 60 text

@n8ebel #oredev Supercharging PRs with Danger

Slide 61

Slide 61 text

@n8ebel #oredev Danger runs during your CI process, and gives teams the chance to automate common code review chores.

Slide 62

Slide 62 text

@n8ebel #oredev What Is Danger? DANGER CHECK APK SIZE DEPENDENCY UPDATES INLINE LINT COMMENTS INFORMATIONAL MESSAGES ETC...

Slide 63

Slide 63 text

@n8ebel #oredev What Is Danger? Add Useful Messages, Statistics, Warnings, etc to Your Pull Requests

Slide 64

Slide 64 text

@n8ebel #oredev Adding Danger To Your Project source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } gem 'danger' Gemfile ● Add/update project Gemfile ● Run `bundle install` ● Run `bundle exec danger init` ● Follow the CLI setup process

Slide 65

Slide 65 text

@n8ebel #oredev Adding Danger To Your Project ... - name: Install Ruby uses: actions/setup-ruby@v1 with: ruby-version: '2.6' - name: Install Bundler run: | gem install bundler bundle install --jobs 4 --retry 3 - name: Run Danger run: bundle exec danger env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} .github/workflows/build_project.yml

Slide 66

Slide 66 text

@n8ebel #oredev Adding PR Comments With Danger # thank PR author message "Thanks @#{github.pr_author} " Dangerfile

Slide 67

Slide 67 text

@n8ebel #oredev Warning For WIP PRs With Danger # Make it more obvious that a PR is a work in progress and shouldn't be merged yet warn("PR is a Work in Progress and not ready to merge") if github.pr_title.include? "[WIP]" Dangerfile

Slide 68

Slide 68 text

@n8ebel #oredev Reporting APK Size With Danger # Notify of the release APK size. apk_size = (File.size('app/build/outputs/apk/release/app-release-unsigned.apk').to_f / 2**20).round(2) message "Release APK size: #{apk_size} MB" Dangerfile

Slide 69

Slide 69 text

@n8ebel #oredev Enforcing Useful PR Descriptions With Danger # Encourage contributors to write useful descriptions warn("Please provide a Pull Request description ...") if github.pr_body.length < 20 Dangerfile

Slide 70

Slide 70 text

@n8ebel #oredev Reporting Dependency Updates With Danger

Slide 71

Slide 71 text

@n8ebel #oredev Reporting Dependency Updates With Danger ... - name: Check Dependency Versions run: ./gradlew dependencyUpdates .github/workflows/build_project.yml plugins { id "org.jlleitschuh.gradle.ktlint" version "7.1.0" id "com.github.ben-manes.versions" version "0.20.0" } build.gradle Gradle Versions Plugin

Slide 72

Slide 72 text

@n8ebel #oredev Reporting Dependency Updates With Danger # Notify of outdated dependencies update_count = File.readlines("build/dependencyUpdates/report.txt").select { |line| line =~ /->/ }.count if update_count > 10 # More than 10 libraries to update is cumbersome in a comment, so summarize warn "There are #{update_count} dependencies with new milestone versions." elsif update_count > 0 file = File.open("build/dependencyUpdates/report.txt", "rb").read heading = "The following dependencies have later milestone versions:" warn file.slice(file.index(heading)..-1) end Dangerfile

Slide 73

Slide 73 text

@n8ebel #oredev Reporting Dependency Updates With Danger

Slide 74

Slide 74 text

@n8ebel #oredev Reporting Dependency Updates With Danger name: Check Dependency Versions on: schedule: - cron: '0 8 * * *' ... steps: - name: Checkout uses: actions/checkout@v1 - name: Check Dependency Versions run: ./gradlew dependencyUpdates .github/workflows/check_dependencies.yml

Slide 75

Slide 75 text

@n8ebel #oredev Reporting ktlint Errors With Danger

Slide 76

Slide 76 text

@n8ebel #oredev Reporting ktlint Errors With Danger gem 'danger' gem 'danger-checkstyle_format' Gemfile # Report inline ktlint issues checkstyle_format.base_path = Dir.pwd checkstyle_format.report 'app/build/reports/ktlint/ktlintMainSourceSetCheck.xml' Dangerfile

Slide 77

Slide 77 text

@n8ebel #oredev Reporting ktlint Errors With Danger # ignore inline messages that are outside of the current diff github.dismiss_out_of_range_messages Dangerfile

Slide 78

Slide 78 text

@n8ebel #oredev Reporting With Danger And More… ● Android Lint ● Test Coverage ● String Translations ● Change In APK Size ● etc...

Slide 79

Slide 79 text

@n8ebel #oredev Deploying Your App

Slide 80

Slide 80 text

@n8ebel #oredev Deploying Your App ● Daily build ● Scheduled build ● Triggered build ● YOLO

Slide 81

Slide 81 text

@n8ebel #oredev Customizing app deployment

Slide 82

Slide 82 text

@n8ebel #oredev Customizing App Deployment Merge to Develop Distribute Test Build Merge to Master Upload to Google Play

Slide 83

Slide 83 text

@n8ebel #oredev Deploying Test Builds On Merge name: Deploy to Crashlytics on: push: branches: develop - name: Build project run: ./gradlew :app:assembleDebug --build-cache --stacktrace ... - name: Deploy to Crashlytics run: ./gradlew :app:crashlyticsUploadDistributionDebug --build-cache --stacktrace if: success() .github/workflows/deploy_debug.yml

Slide 84

Slide 84 text

@n8ebel #oredev Deploying Test Builds On Merge Automating Release Notes For Test Builds Generate internal release notes from git history

Slide 85

Slide 85 text

@n8ebel #oredev Deploying Release Builds On Merge name: Deploy to Play on: push: branches: master - name: Build project run: ./gradlew :app:assembleRelease --build-cache --stacktrace ... - name: Deploy to Play run: ./gradlew :app:publishReleaseApk --build-cache --stacktrace if: success() .github/workflows/deploy_release.yml

Slide 86

Slide 86 text

@n8ebel #oredev Deploying Release Builds On Merge ● Deploy Release Builds With Gradle Play Publisher ● Store Release Info In Repo ● Track Changes Over Time ● Full Internal Release By Merging To Master

Slide 87

Slide 87 text

@n8ebel #oredev Automate All The Things

Slide 88

Slide 88 text

@n8ebel #oredev What To Automate? QUALITY REVIEW DEPLOY BUILD

Slide 89

Slide 89 text

@n8ebel #oredev Losing time, energy, or joy to some task? … try automating it.

Slide 90

Slide 90 text

@n8ebel #oredev Resources ● https://github.com/n8ebel/AutomationSandbox ● https://github.com/n8ebel/GitHubActionsAutomationSandbox

Slide 91

Slide 91 text

@n8ebel #oredev Resources ● https://proandroiddev.com/ooga-chaka-git-hooks-to-enforce-code-quality-11ce8d0d23cb ● https://help.github.com/en/articles/creating-a-pull-request-template-for-your-repository ● https://help.github.com/en/articles/closing-issues-using-keywords ● https://danger.systems/ruby/ ● https://danger.systems/guides/getting_started.html#including-danger ● https://blog.bitrise.io/automating-code-review-tasks-for-multi-module-android-projects ● https://github.com/Triple-T/gradle-play-publisher ● https://try.crashlytics.com/beta/ ● https://github.com/noboru-i/danger-checkstyle_format

Slide 92

Slide 92 text

@n8ebel #oredev Special Thanks ● Ryan Harter ● Joe Birch ● Sebastiano Poggi

Slide 93

Slide 93 text

@n8ebel #oredev Thank You "n8ebel".apply { Twitter YouTube LinkedIn Instagram } Stay In Touch