@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
@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
@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
@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
@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...
@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.