1. Configuration

To use delivery, you just have to apply the plugin in your project.

buildscript {
        repositories {
                jcenter()
        }

        dependencies {
                classpath 'com.leroymerlin.plugins:delivery-plugin:LAST_VERSION'
        }
}

apply plugin: 'com.leroymerlin.delivery'

2. Version.properties

Delivery use version.properties file define in project’s root path

#Version.properties sample
version=1.0.0
artifact=android-app
versionId=2

#You can override the project's group by adding group in this file
#group=com.leroymerlin.delivery.group
Warning
Delivery needs a version.properties file in your module. This file will contain your module version, versionId and artifact.

3. Delivery extension

Configure the delivery gradle extension in your build.gradle to fit your need.

delivery {
    // Enable the default git flow
    enableReleaseGitFlow = false

    // Link submodules's Install and Upload tasks with parent's tasks
    autoLinkSubModules = false

    // Define submodules path to link Install and Upload tasks with the project build tasks
    linkedSubModules = []

    // RepositoryHandler to archive your build artifact
    archiveRepositories = project.ext.archiveRepositories //default value

    // project flow container
    flows {
        ...
    }
    // artifact signing properties container
    signingProperties {
        ...
    }

    // docker registries configuration
    dockerRegistries {
        ...
    }
}
Note
You can find more documentation about archiveRepositories on the official groovy website.
Flows and signingProperties DSL are based on Gradle NamedDomainObjectContainer.

You can use system properties to inject scm credentials, set your project version and define your project group.

  • SCM_EMAIL // git email

  • SCM_USER // git username

  • SCM_PASSWORD // git password

  • VERSION // override actual version

  • GROUP_ID // override project’s group

4. Flows

Flow allows you to configure build steps.
Once a flow is configured, you can run it by calling the gradle task named "yourFlowName+Flow".

Methods provided by Delivery:
            //...
            flows {
                release { //will generate releaseFlow task
                    /**
                     * change and create scm branch
                     * @param name
                     * @param @optional create (default: false)
                     */
                    branch 'release', false
                    /**
                     * add files to be committed
                     * if files is not set, all files will be added
                     * @param files
                     */
                    add 'test.txt'
                    /**
                     * commit files
                     * if addAll is true, will add all files before commit
                     * @param message
                     * @param @optional addAll (default: false)
                     */
                    commit 'first commit', false
                    /**
                     * tag a commit
                     * @param @optional message
                     * @param @optional annotation
                     */
                    tag 'a message', 'an annotation'
                    /**
                     * merge a branch
                     * @param branch
                     */
                    merge 'develop'
                    /**
                     * pull changes from origin
                     */
                    pull
                    /**
                     * push changes to branch
                     * if branch is not set, push changes to actual branch
                     * if tags is true push all tags to remote
                     * @param @optional branch (default: current branch)
                     * @param @optional tags (default: true)
                     */
                    push
                    /**
                     * push tag
                     * if tagName is not set, push sane tags
                     * @param @optional tagName (default = all commit)
                     */
                    pushTag
                    /**
                     * delete a branch
                     * @param branchName
                     */
                    delete 'develop'
                    /**
                     * change the properties of the version.properties
                     * @param @optional version (default: null)
                     * @param @optional versionId (default: null)
                     * @param @optional artifact (default: null)
                     */
                    changeProperties '1.0.0', '3'
                    /**
                     * build the project
                     */
                    build
                    /**
                     * execute a command in the folder
                     * @param cmd
                     */
                    cmd 'a command'
                    /**
                     * cancel all changes not committed
                     */
                    discardChange
                    /**
                     * call a task by its name
                     * if newBuild is true, executes a Gradle build
                     * @param taskName
                     * @param @optional newBuild (default: false)
                     */
                    task 'customTask'
                    /**
                     * display a title in log
                     * @param stepName
                     * @param @optional title (default: stepName)
                     * @param @optional taskName (default: flowName+Step+stepName)
                     */
                    step 'name', 'hello world'
                }
            }
            //...
Note
To simplify your life, Delivery provides an implementation of git release flow.

5. Docker

Delivery allows you to build and push Docker images to registry.

You can configure docker registry in the delivery extension :

                //...
                dockerRegistries {
                    myEnterpriseRegistry {
                        url = "https://my-enterprise.registry.com"
                        password = "topsecret"
                        user = "panda"
                    }
                    homeRegistry {
                        propertiesFile = file("path/to/my/registry.properties")
                    }
                }
                //...

To build a docker image you have to create a DockerBuild task. Delivery will detect it and add it to the build tasks.

task('buildDockerImage', type: DockerBuild){
    buildPath '.' //default '.'
    imageName 'delivery-test' //default project.artifact
    registry 'myEnterpriseRegistry'
}

6. Signing config

SigningConfiguration allows you to configure artifacts signatures.
A configuration is a set of key/value pair. You can externalize critical data using a properties file

Example:
                //...
                signingProperties {
                    all {
                        // load file properties into all the signing property
                        propertiesFile = file("path/to/my/signing.properties")
                    }
                    specificBuildType {
                        // override singing properties for specific buildtype
                        propertiesFile = file("path/to/my/specific.properties")
                    }
                }
                //...
Warning
You should consider not to put keystore and credentials inside your repository.

6.1. Android

Note
Delivery now support Android projects using Android plugin 2.x.x and 3.x.x
                //...
                signingProperties {
                    // the name you set here has to match a buildtype
                    buildTypeName {
                        storeFile = 'path/to/my/store.jks'
                        storePassword = 'myStorePassword'
                        keyAlias = 'myAlias'
                        keyPassword = 'myPass'
                    }
                }
                //...

6.2. iOS

Note
iOS support is based on the open source project gradle-xcodePlugin
                //...
                signingProperties {
                    // you can set the name you want
                    // for each signingProperty, you'll archive an IPA
                    nameYouWant {
                        target = "delivery"
                        scheme = "delivery"
                        certificateURI = 'path/to/my/certificat.p12'
                        certificatePassword = 'myPass'
                        // you can specify multiple files separated by a comma
                        mobileProvisionURI = 'path/to/my/Provisioning_Profile.mobileprovision,path/to/my/Provisioning_Profile2.mobileprovision'
                    }
                }
                //...

6.3. Ionic

Important
Ionic support is only available with the last Ionic version
                //...
                signingProperties {
                    // you have to use android or ios name for ionic signing configs
                    android {
                        //See android needed properties
                    }
                    ios {
                        //See ios needed properties
                        //target and scheme are optionals for ionic
                    }
                }
                //...

6.4. React Native

A React Native project has to be configured as a Multi modules project. Apply the delivery plugin in the root project (in charge of Npm setup), :android:app module (to build android) and :ios (to build ios). One apply just link module with linkedSubModules in the delivery extension.

Caution
You may need to move the buildscript part in ":android" module to the root project in order to be used. Don’t forget to fix the react repository relative path (remove useless "../")

Example

delivery {
    archiveRepositories = {
        maven {
            url uri("./build/archive_react")
        }
    }
    linkedSubModules ":ios", ":android:app"

    //...

For more details check the reactNative project in test resources

6.5. Flutter

Apply the delivery plugin in the root flutter project, configure repositories and version. Then apply the plugin in the subproject in android/app folder and ios folder and configure signing configuration of each platform.

Caution
Don’t add android and ios as gradle submodule of your root project. Android flutter build does’t support no to be in root folder. Delivery FlutterConfigurator will run nested gradle build for you.

Example

apply plugin: 'com.leroymerlin.delivery'

delivery {
    archiveRepositories = {
        maven {
            url uri("${rootProject.buildDir}/archive_flutter")
        }
    }
    //...

For more details check the flutterproject project in test resources

7. Multi Modules

You can link Install task and Upload task from childs modules with parent module by using autoLinkSubModules = true or linkedSubModules = 'subModule1', …​

//...
//Here is a sample of a parent module's build.gradle
buildscript {
    repositories {
        mavenLocal()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        classpath "com.leroymerlin.plugins:delivery-plugin:${System.getProperty("DELIVERY_VERSION")}"
    }
}
allprojects {
    repositories {
        mavenLocal()
        mavenCentral()
    }
}

apply plugin: 'com.leroymerlin.delivery'

delivery {
    //autoLinkSubModules = true
    //linkedSubModules = ':lib'
}
//...
Note
Look at the sample for more informations
Caution
You need to apply Delivery on all modules you want to use with Delivery

8. Custom projects

If your project doesn’t answer the Delivery’s supported configurations (iOS, Android, Ionic, Java, Groovy), you can define your own configurator.

                //...
                configurator = [
                        /**
                         * Configure your project
                         */
                        configure           : {/*...*/ },
                        /**
                         * Apply some properties to your project
                         */
                        applyProperties     : {/*...*/ },
                        /**
                         * Apply the signing properties to your project
                         * @param property
                         */
                        applySigningProperty: { property -> /*...*/ }
                ]
                //...

To achieve your project’s build, you have to create one or more DeliveryBuild tasks, and define the variant names and output files.

                //...
                task('buildVariant', type: DeliveryBuild) {
                    variantName = 'variant'
                    outputFiles = ["release": file('build/variant.txt')]
                }.doFirst {
                    cmd('java -jar delivery-test.jar variant')
                }
                //...

9. Logs

By default Delivery provide beautiful and colorful logs. But if you prefer to watch classic logs you can set a system property or environment variable named ugly.

Tip
Sample to disable color logs
gradle myFlow -Dugly

10. Debug

listArtifacts task provides many informations about the artifacts that will be archived in the project

Example:
> Task :listArtifacts
File n°1
Name: android-app-dev-1.0.0-SNAPSHOT-debug.apk
Extension: apk
Type: apk
Classifier: debug
Group: com.leroymerlin.pandroid.plugin.testapp
Path: /Users/alexandre/Workspace/LM/delivery-gradle-plugin/delivery-plugin/build/tests/integration/android/build/outputs/apk/dev/debug/android-app-dev-1.0.0-SNAPSHOT-debug.apk
Url: file:/Users/alexandre/Workspace/LM/delivery-gradle-plugin/delivery-plugin/build/tests/integration/android/build/archive/


File n°2
Name: android-app-dev-1.0.0-SNAPSHOT-debug.apk
Extension: apk
Type: apk
Classifier: test-debug
Group: com.leroymerlin.pandroid.plugin.testapp
Path: /Users/alexandre/Workspace/LM/delivery-gradle-plugin/delivery-plugin/build/tests/integration/android/build/outputs/apk/dev/debug/android-app-dev-1.0.0-SNAPSHOT-debug.apk
Url: file:/Users/alexandre/Workspace/LM/delivery-gradle-plugin/delivery-plugin/build/tests/integration/android/build/archive/

listDockerImages task provides many informations about the docker image that will be archived in the project

11. Troubleshooting

11.1. Unknown error -1=ffffffffffffffff

If you’re using Delivery with automation server like Jenkins for iOS builds, you may see this error happens. To solve this, we made the plugin to be able to unlock the Apple Keychain which can solve this problem.

To use this feature, define a system property or environment variable named KEYCHAIN_PASSWORD.

Tip
Command executed to unlock the Apple Keychain
security unlock-keychain -p $KEYCHAIN_PASSWORD ~/Library/Keychains/login.keychain-db

11.2. attempt to unlock read lock, not locked by current thread

Known issue with Android plugin 3.1.+ https://issuetracker.google.com/issues/80464216

To fix it you should migrate to 3.2.+. For react project you may have to replace OutputFile.ABI by com.android.build.OutputFile.ABI in app/build.gradle