Shipkit is a framework that helps automate continuous delivery of open source software projects. It allows developers to easily manage releases by automatically bumping versions, generating release notes, creating tags, and publishing releases when code is merged to master. Shipkit integrates with Travis CI to run release tasks like tests and publication. It aims to reduce the manual work of releases so developers can focus on coding.
3. About you!
● Who is developer of Open Source Software?
● How do you release new version?
● Do you plan to contribute to Open Source?
4. Do you like manage releases?
● To include a feature in a release or not?
● Am I ready to release or should I test more?
● Oh no… release notes…
● Build, sign, release, tag, etc.
● Documentation?
6. Shipkit - main principles
● Almost every merged pull request lands new version in JCenter / Maven Central
● Easy to use, smart defaults
● Configure once and use all the time
● Automate as much as possible
● Don’t need to manage CI server
8. Why JCenter?
● Maven Central requirements:
○ Supply Javadoc and Sources
○ Sign Files with GPG/PGP
○ Sufficient Metadata in pom: groupId, artifactId, version, project(name,
description, url), information about(license, developer, SCM)
● Stability of Maven Central (in the past)
JCenter:
● Less restrictive
● Sign files
● Better stability
● Automatically sync with JCenter and Maven Central (retry when Maven Central is
down)
9. What can Shipkit?
● Bump version
● Generate release notes
● Upload release notes to repo and GitHub Release page
● Create a git tag
● Check if new release is needed
● Test dependers (downstreams projects)
● Release to JCenter and Maven Central
● Release unpacked Javadoc in HTML format
● Release plugins to Gradle Portal
10. Task 1 - init project & add Shipkit
● Fork https://github.com/mstachniuk/shipkit-workshop on GitHub
● Change name
● Add me as collaborator
● Enable issues: Settings -> Issues
● Send the link to the repo to me!
● Clone your repo to local machine
● Change project name in settings.gradle
● Import to IntelliJ Idea
● Add in build.gradle in plugins section:
id 'org.shipkit.java' version '2.2.2'
● Run:
./gradlew initShipkit
● Check a diff in your IDE
11. What add Shipkit to the project
#Version of the produced binaries. This file is intended to be checked-in.
#It will be automatically bumped by release automation.
version=1.0-SNAPSHOT
version.properties
> Task :initVersioning
Configured '1.0-SNAPSHOT' version in 'version.properties' file.
Please remove 'version=1.0-SNAPSHOT' setting from *.gradle file.
Please review and check in generated file: version.properties
Version number is now stored in 'version.properties' file. Don't set
'version' in *.gradle file.
./gradlew initShipkit
12. What add Shipkit to the project
Please change version to:
1.0.0
or similar
13. What add Shipkit to the project
language: java
jdk:
- oraclejdk8
install:
- true
branches:
except:
- /^vd/
script:
- ./gradlew build -s && ./gradlew ciPerformRelease
.travis.yml
14. What add Shipkit to the project
//This default Shipkit configuration file was created automatically and is intended to be
checked-in.
//To leverage Shipkit fully, please fix the TODO items, refer to our Getting Started
Guide for help:
//
// https://github.com/mockito/shipkit/blob/master/docs/getting-started.md
//
shipkit { … }
allprojects {
plugins.withId("org.shipkit.bintray") {
bintray { … }}}
gradle/shipkit.gradle
15. What add Shipkit to the project
shipkit {
//TODO is the repository correct?
gitHub.repository = "mstachniuk/shipkit-workshop-XX"
//TODO generate and use your own read-only GitHub personal access token
gitHub.readOnlyAuthToken = "76826c9ec886612f504d12fd4268b16721c4f85d"
//TODO generate GitHub write token, and ensure your Travis CI has this env
variable exported
gitHub.writeAuthToken = System.getenv("GH_WRITE_TOKEN")
}
gradle/shipkit.gradle
18. Task 2 - Generate GitHub tokens
● Copy and store your tokens for the moment (e.g. in text editor)
● Set gitHub.readOnlyAuthToken in shipkit.gradle
● Write GitHub token is mandatory to make commit by Travis CI
● Never commit your write GitHub token!
19. Task 3 - Setup Travis CI
● Go to https://travis-ci.org or https://travis-ci.com
● Log in and Sync repositories
● Add new repository
20. Task 3 - Setup Travis CI
● Enable integration
● Go to settings
21. Task 3 - Setup Travis CI
● Add Environment Variable:
Name: GH_WRITE_TOKEN
Value: your write token copied from GitHub
29. Files commited by Shipkit
<sup><sup>*Release notes were automatically generated by [Shipkit](http://shipkit.org/)*</sup></sup>
#### 1.0.0
- 2019-01-06 - 4 commits by [Marcin Stachniuk](https://github.com/mstachniuk) - published to
[![Bintray](https://img.shields.io/badge/Bintray-1.0.0-green.svg)](https://bintray.com/shipkit-bootstrap/bootstrap/maven/1.0.0)
- Add Shipkit to project [(#2)](https://github.com/mstachniuk/shipkit-workshop/pull/2)
docs/release-notes.md
31. Files commited by Shipkit
#Version of the produced binaries. This file is intended to be checked-in.
#It will be automatically bumped by release automation.
version=1.0.0
version.properties
#Version of the produced binaries. This file
#It will be automatically bumped by releas
version=1.0.1
previousVersion=1.0.0
32. Versioning by Shipkit
● Shipkit use property version in version.properties as current version
● The previous version is useful for:
○ Compare current and previous version (check if something was changed)
● Those properties are updated during release
● No SNAPSHOTS, -beta, RC1 versions!
● Shipkit prefers semantic versioning (simplified)
34. Semantic Versioning Specification
MAJOR.MINOR.PATCH
1. Software using Semantic Versioning MUST declare a public API.
2. MAJOR, MINOR & PATCH are non-negative integers, and MUST NOT contain
leading zeroes. Each element MUST increase numerically. E.g:
1.9.0 -> 1.10.0 -> 1.11.0.
3. The content of released version MUST NOT be modified. Any modification -> new
release.
4. Major version zero (0.y.z) is for initial development. Anything may change at any
time. The public API should not be considered stable.
5. Version 1.0.0 defines the public API.
35. Semantic Versioning Specification
MAJOR.MINOR.PATCH
6. Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible
bug fixes are introduced. A bug fix is defined as an internal change that fixes
incorrect behavior.
7. Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards
compatible functionality is introduced to the public API or if any public API
functionality is marked as deprecated. It MAY be incremented if substantial new
functionality or improvements are introduced within the private code. It MAY
include patch level changes. Patch version MUST be reset to 0 when minor
version is incremented.
36. Semantic Versioning Specification
MAJOR.MINOR.PATCH
8. Major version X (X.y.z | X > 0) MUST be incremented if any backwards
incompatible changes are introduced to the public API. It MAY include minor and
patch level changes. Patch and minor version MUST be reset to 0 when major
version is incremented.
More 9-11: https://semver.org/
39. Task 6: Configure Release Notes
● Merge PR and add to message: [ci skip-release]
40. Task 6: Configure Release Notes
[ci skip-release] at the end of commit message prevent:
● publish release
● create tag
● update release notes
[ci skip] at the end of commit message prevent:
● execute a build
● add PR to release notes
It’s useful for commits made automatically by Shipkit
You can configure that by:
git.commitMessagePostfix = "[ci skip]"
releaseNotes.ignoreCommitsContaining = ["[ci skip]"]
41. Task 7: Release Notes
● See issues
● Create PR for: “Floating point support”
● Add enhancement label to PR
43. Task 7: Release Notes
● Merge adding [ci skip-release]
● Remember about good PR name i.e.: Fix #NUMBER long support
● See issues
● Create PR for: “Long support”
● Add enhancement label to PR
● Repeat for: float, BigInteger and BigDecimal (the last one - no [ci skip-release])
49. How to skip release?
● Add to commit message suffix: [ci skip-release]
● When Pull Request is build
● Building on NOT release branch, default: master|release/.+
○ Can be changed by: git.releasableBranchRegex = "branch_regex"
● No changes in binaries
○ Source jars
○ dependency-info.json (file generated by Shipkit and store in source jar)
● Commit contains suffix: [ci skip-compare-publications]
● Set property 'skipComparePublications' on task releaseNeeded to true (see
Mockito release model)
● Set SKIP_RELEASE environment variable
53. Task 10: Ship Javadoc
● Create on your Github account project: shipkit-workshop-X-javadoc
● Add in your project:
apply plugin: "org.shipkit.java"
// enable Shipkit Javadoc plugin.
apply plugin: "org.shipkit.javadoc"
● Make some change in the code
● Commit, create PR, merge
● Check shipkit-workshop-X-javadoc on the GitHub
54. Shipping Javadoc configuration options
// OPTIONAL GitHub repository (owner/repo) where Javadocs are shipped.
// The default value is gitHub.repository + "-javadoc"
javadoc.repository = "mstachniuk/shipkit-example-javadoc"
// OPTIONAL GitHub Javadoc repository branch name. The branch needs to exist.
// By default it's using the branch set as main in GitHub repo, usually master.
javadoc.repositoryBranch = "gh-pages"
// OPTIONAL GitHub Javadoc repository directory where put javadoc files. By default it's project root directory.
javadoc.repositoryDirectory = "dir1/dir2"
// OPTIONAL Commit message used to commit Javadocs. Default: "Update current and ${version} Javadocs.
[ci skip]"
// You can override this message and ${version} will be replaced by currently build version.
// You don't need to specify "[ci skip]" in your message - it will be added automatically.
javadoc.commitMessage = "Update Javadoc by awesome Shipkit"
56. Configuration possibilities - GitHub Enterprise
// OPTIONAL GitHub url, default: https://github.com
// It's useful when you're using on-premises GitHub Enterprise.
gitHub.url = "https://github.com"
// OPTIONAL GitHub API url, default: https://api.github.com
// It's useful when you're using on-premises GitHub Enterprise.
gitHub.apiUrl = "https://api.github.com"
57. Configuration possibilities - Release Notes location
// OPTIONAL Path to file where release notes will be generated by Shipkit, default:
docs/release-notes.md
releaseNotes.file = "docs/release-notes.md"
58. Configuration possibilities - Publication repository
// OPTIONAL Publication Repository where we look for your published binary, default:
empty
// It is currently used to configure repository Badge URL when generating release
notes.
releaseNotes.publicationRepository = ""
59. Configuration possibilities - Git settings for commits made by Shipkit
// OPTIONAL Git user for creating commit, tag and Pull Request with release notes,
default: shipkit-org
git.user = "shipkit-org"
// OPTIONAL Git user email for creating commit, tag and Pull Request with release
notes, default: <shipkit.org@gmail.com>
git.email = "<shipkit.org@gmail.com>"
60. Configuration possibilities - Tag prefix
// OPTIONAL Prefix added to the version to create VCS-addressable tag, default: v
// Empty string is ok and it means that there is not prefix.
git.tagPrefix = "v"
62. Publish to Maven Central
How to create account on Maven Central?
63. Publish to Maven Central
● Create account: https://issues.sonatype.org/
● Create new issue
● Generate tokens:
https://solidsoft.wordpress.com/2015/09/08/deploy-to-maven-central-using-api-key-
aka-auth-token/
● Set tokens in TravisCI
64. Publish to Maven Central
bintray {
key = '7ea297848ca948adb7d3ee92a83292112d7ae989'
pkg {
//TODO configure Bintray settings per your project (https://github.com/bintray/gradle-bintray-plugin)
repo = 'bootstrap'
user = 'shipkit-bootstrap-bot'
userOrg = 'shipkit-bootstrap'
name = 'maven'
licenses = ['MIT']
labels = ['continuous delivery', 'release automation', 'shipkit']
}
}
gradle/shipkit.gradle
bintray {
key = System.getenv("BINTRAY_API_KEY")
pkg {
repo = 'mstachniuk-maven-repo'
user = 'mstachniuk'
name = 'maven'
licenses = ['MIT']
labels = ['graphql', 'kotlin', 'java', 'schema']
version {
mavenCentralSync {
sync = true
user = System.env.NEXUS_TOKEN_USER
password = System.env.NEXUS_TOKEN_PWD
}
}
}
}
65. How to deliver Gradle plugin?
● The best example is Shipkit project itself
● In your build.gradle:
apply plugin: 'com.gradle.plugin-publish'
66. Incubating Features - upgrade downstream
● Check if new version works with dependers (child / downstream projects)
apply plugin: 'org.shipkit.ci-upgrade-downstream'
upgradeDownstream {
repositories = ['mockito/shipkit-example', 'mockito/shipkit']
}
67. Incubating Features - upgrade dependency
Child depends on parent project.
In child project you can execute:
./gradlew performVersionUpgrade
-Pdependency=parentGroup:parentArtifactName:parentVersion
It will create PR for you. When all check are green you can merge it.
More info:
https://github.com/mockito/shipkit/blob/master/docs/gradle-plugins/upgrade-dependen
cy-plugin.md
68. Tips and hacks - do not release everything
● Do not release each module
In module/build.gradle file:
bintrayUpload.enabled = false
69. Tips and hacks - license
● Another (not MIT) licence in POM (See #755)
In shipkit.gradle file:
plugins.withId("org.shipkit.java-publish") {
publishing.publications.javaLibrary.pom.withXml {
//refer to Groovy xml Node reference for more info how to
manipulate xml
asNode().licenses.replaceNode {
licenses {
license {
name "Eclipse Public License v2.0"
url "http://www.eclipse.org/legal/epl-v20.html"
}
}
}}}
70. Tips and hacks - Mockito release model
Mockito release model (#911):
● all versions are released in JCenter
● some of them are released in Maven Central
74. Our plans
● Work on getting the community adopt Shipkit
● Continue work on incubating and new features
● Support OSS and enterprise in transition into CI/CD model
● Solve issues