Skip to content

Commit

Permalink
initial OpenSource commit!
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdubiel committed Sep 23, 2014
1 parent bf352ac commit ddf0dc3
Show file tree
Hide file tree
Showing 43 changed files with 2,134 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/build/

.gradle/

.nb-gradle/
.nb-gradle-properties

.idea
*.iml

sonar-project.properties
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
axion-release-plugin changelog
====

* **0.9.0** (23.09.2014)
* refactored API to be more verbose
* refactored all configuration options
* added per-branch version settings
* **0.3.0** (24.08.2014)
* removed tags fetching option as it was inefficient in CI anyway
* **0.2.8** (22.08.2014)
* added option to pass custom SSH key
* added option to fetch tags before resolving version
* **0.2.6** (19.08.2014)
* possibility to attach remote repository, useful in Bamboo CI builds
* **0.2.5** (18.08.2014)
* documented, final version of dry-run
* more verbose logging
* options to disable checks (verification) before release
* **0.2.4** (?)
* added dry-run capability
196 changes: 196 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
axion-release-plugin
====

*gradle release and version management plugin*


Releasing versions in Gradle is very different from releasing in Maven. Maven came with
[maven-release-plugin](maven.apache.org/maven-release/maven-release-plugin/) which
did all the dirty work. Gradle has no such tool and probably doesn't need it anyway. Evolution of software craft came
to the point, when we start thinking about SCM as ultimate source of truth about project version. No longer version
hardcoded in **pom.xml** or **build.gradle**.

**axion-release-plugin** embraces this philosophy. Instead of reading project version from buildfile, it is derived
from nearest tag in SCM (or set to default if nothing was tagged). If current commit is tagged commit, project has
a release version. If there were any commits after last tag, project is in SNAPSHOT version. This very simple and
intuitive philosophy makes it a lot easier to manage project versions along SCM tag versions.

## Why write new plugin?

There are a few plugins that try to do the same - question is do we need another one?

* [build-version-plugin](https://github.com/GeoNet/gradle-build-version-plugin/) - plugin that was main source of inspiration, reads build version but lacks release options
* [ari gradle-release-plugin](https://github.com/ari/gradle-release-plugin) - takes only branch/tag name for version
* [townsfolk gradle-release-plugin](https://github.com/townsfolk/gradle-release) - more oldschhol, maven-release-plugin-like approach

What I needed was plugin that exposes version taken from nearest tag (like **build-version-plugin**) which at the same time
will be easily integrated with maven-publish and signing. It also needs to be Continuous Integration-aware.

## Usage

In order for release plugin to work, you need to access you repository using ssh keys, not http authorization! Support for
other means of authorization is on our TODO list.

```groovy
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath group: 'pl.allegro.tech.build', name: 'axion-release-plugin', version: '0.9.0'
}
}
apply plugin: 'axion-release'
// configure version
scmVersion {
tag {
prefix = 'tag-prefix'
}
}
// make our version is available to all
project.version = scmVersion.version
```

## Tasks

* `currentVersion` - prints current version as seen by plugin.
* `verifyRelease` - check some basic stuff before release, i.e. if there are no uncommited files and if branch is not ahead of origin
* `release` - create tag with current version and push it to remote

## Example

```
# git tag
project-0.1.0
# ./gradlew currentVersion
0.1.0
# git commit -m "Some commit."
# ./gradlew currentVersion
0.1.1-SNAPSHOT
# ./gradlew release
# git tag
project-0.1.0 project-0.1.1
# ./gradlew currentVersion
0.1.1
# ./graldew publish
published project-0.1.1 release version
```

## Options

### Command line

#### Force version

To force version, set `release.forceVersion` project property, for example to start with new 2.0.0 version:

```
./gradlew release -Prelease.forceVersion=2.0.0
```

Plugin recognizes if you are on tag or not and adds additional "-SNAPSHOT" suffix when necessary.
This property is ignored if it has empty value.

#### Dry run

To check how release would behave without actually releasing anything, use `release.dryRun` option:

```
./gradlew release -Prelease.dryRun
```

This will output actions it would take during release, but won't persist changes.

#### Disabling checks

By default plugin checks if there are no uncommited changes and if local branch is ahead of remote before release. These
checks can be disabled from command line using:

* `release.disableChecks` - disable all checks
* `release.disableUncommitedCheck` - disable uncommited changes check
* `release.disableRemoteCheck` - disable ahead of remote check

```
./gradlew release -Prelease.disableChecks // disable all checks
```

#### Attaching to remote

When running release in CI environment (as it should be always done!) it might be necessary to attach remote before pushing
the tag - this is the case of Atlassian Bamboo CI, which does very shallow fetch of repo, not clone. To do this, pass
`release.attachRemote` property, which value should be url to remote. Remote name will be taken from configuration.

```
./gradlew release -Prelease.attachRemote="ssh://git@hello.com/repo.git"
```

#### Using custom SSH key

Use `release.customKeyFile` and `release.customKeyPassword` properties to force Git to use custom SSH keys to authorize in
remote repository.

```
./gradlew release -Prelease.customKeyFile="./keys/secret_key_rsa" -Prelease.customKeyPassword=password
```

### Plugin

```groovy
scmVersion {
remote = 'myRemote' // 'origin' by default
tag {
prefix = 'tag-prefix' // prefix to be used, 'release' by default
versionSeparator = '-' // separator between prefix and version number, '-' by default
serialize = { tag, version -> rules.prefix + rules.versionSeparator + version } // creates tag name fro mraw version
deserialize = { tag, position -> /* ... */ } // reads raw version from tag
initialVersion = { tag, position -> /* ... */ } // returns initial version if none found, 0.1.0 by default
}
versionCreator = { version, position -> /* ... */ } // creates version visible for Gradle from raw version and current position in scm
branchVersionCreators = [
'feature/.*': { version, position -> /* ... */ },
'bugfix/.*': { version, position -> /* ... */ }
] // map [regexp: closure] of version creators per branch, first match wins but no order is guaranteed (depends on created map instance)
checks {
uncommitedChanges = false // permanently disable uncommited changes check
aheadOfRemote = false // permanently disable ahead of remote check
}
}
```

In `versionCreator` and `branchVersionCreators` closure arguments, `position` contains the following attributes:

* `latestTag` - the name of the latest tag.
* `branch` - the name of the current branch.
* `onTag` - true, if current commit is tagged.

## Publishing released version

Publishing release version is simple with **axion-release-plugin**. Since release does not increase version unless
you commit something, you can publish release version any time by calling gradle once again:

```
./gradlew release
./gradlew publish
```

Why not make it work in single Gradle run? **maven-publish** plugin reads **project.version** in configuration phase.
Any change made by tasks running prior to publishing won't be recognized.

## License

**axion-release-plugin** is published under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).

100 changes: 100 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
apply plugin: 'groovy'
apply plugin: 'signing'
apply plugin: 'maven'
apply plugin: 'jacoco'

group = 'pl.allegro.tech.build'
version = '0.9.0'

repositories {
mavenCentral()
}

dependencies {
compile gradleApi()
compile localGroovy()

compile group: 'org.ajoberstar', name: 'grgit', version: '0.2.3'
compile group: 'com.github.zafarkhaja', name: 'java-semver', version: '0.7.2'

testCompile(group: 'org.spockframework', name: 'spock-core', version: '0.7-groovy-2.0') {
exclude group: 'org.codehaus.groovy', module: 'groovy-all'
}
testCompile(group: 'cglib', name: 'cglib-nodep', version: '3.1')
}

test {
testLogging {
exceptionFormat = 'full'
}
}

task wrapper(type: Wrapper) {
gradleVersion = '2.1'
}

task groovydocJar(type: Jar) {
classifier = 'groovydoc'
from groovydoc
}

task sourceJar(type: Jar) {
classifier = 'sources'
from sourceSets.main.allSource
}

artifacts {
archives groovydocJar, sourceJar
}

signing {
sign configurations.archives
}

uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }

def username = project.ext.has('nexusUser') ? project.ext.nexusUser : ''
def password = project.ext.has('nexusPassword') ? project.ext.nexusPassword : ''

repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2/') {
authentication(userName: username, password: password)
}

snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots/') {
authentication(userName: username, password: password)
}

pom.project {
name 'axion-release-plugin'

packaging 'jar'

description 'Gradle release and version management plugin.'
url 'https://github.com/allegro/axion-release-plugin'
inceptionYear '2014'

scm {
connection 'scm:git:git@github.com:allegro/axion-release-plugin.git'
developerConnection 'scm:git:git@github.com:allegro/axion-release-plugin.git'
url 'https://github.com/allegro/axion-release-plugin'
}

licenses {
license {
name 'The Apache License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}

developers {
developer {
name 'Adam Dubiel'
}
}
}
}
}
}
Binary file added gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
6 changes: 6 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#Tue Sep 23 21:14:11 CEST 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-bin.zip
Loading

0 comments on commit ddf0dc3

Please sign in to comment.