Giter Club home page Giter Club logo

android-signing-plugin's Introduction

Jenkins Android Signing Plugin

Summary and Purpose

The Android Signing plugin provides a simple build step for signing Android APK build artifacts. The advantage of this plugin is that you can use Jenkins to centrally manage, protect, and provide all of your Android release signing certificates without the need to distribute private keys and passwords to every developer. This is especially useful in multi-node/cloud environments so you do not need to copy the signing keystore to every Jenkins node. Furthermore, using this plugin externalizes your keystore and private key passwords from your build script, and keeps them encrypted rather than storing them in a plain-text properties file. This plugin also does not use a shell command to perform the signing, eliminating the potential that private key passwords appear on a command-line invocation.

Background

This version is a fork from Big Nerd Ranch's now deprecated original repository which is the basis of a nice blog post, Continuous Delivery for Android. Thanks to Big Nerd Ranch for the original work.

This plugin depends on the Jenkins Credentials Plugin for retrieving private key credentials for signing APKs. Thanks to CloudBees and Stephen Connolly for the Credentials Plugin.

This plugin also depends on Android's apksig library to sign APKs programmatically. apksig backs the apksigner utility in the Android SDK Developer Tools package. Using apksig ensures the signed APKs this plugin produces comply with the newer APK Signature Scheme v2 and APK Signature Scheme v3. Thanks to Google/Android for making that library available as a Maven dependency.

Building

Run mvn package to build a deployable HPI bundle for Jenkins. Note this plugin REQUIRES JDK 1.8 to build and run because of the dependency on the Android apksig library.

Installation

First, make sure your Jenkins instance has the Credentials Plugin (linked above). Check the POM for version requirements. Copy the target/android-signing.hpi plugin bundle to $JENKINS_HOME/plugins/ directory, and restart Jenkins.

As of this writing, this plugin is not yet hosted in the Jenkins Update Centre, so you cannot install using the Jenkins UI.

Usage

Before adding a Sign Android APKs build step to a job, you must configure a certificate credential using the Credentials Plugin's UI. As of this writing, this plugin requires a password-protected PKCS12 keystore containing a private key entry protected by the same password. Because of how the Credentials Plugin loads key stores, you must protect your key store with a non-empty password. You were doing that anyway, right?

This plugin requires access to the Android SDK's zipalign command. This implies that whatever Jenkins node is performing your build has access to an installed Android SDK, which is likely the case if you built your APK in a Jenkins job as well.

Once the prerequisites are setup, you can now add the Sign Android APKs build step to a job. The configuration UI is fairly straight forward. Select the certificate credential you created previously, supply the alias of the private key/certificate chain (optional if you have only one key entry), and finally supply the name or Ant-style glob pattern specifying the APK files relative to the job workspace you want to sign. You can specify multiple glob patterns separated by commas if you wish. For most projects **/*-unsigned.apk should suffice.

Sign Android APKs form

You can tell a Sign Android APKs build step the location of zipalign in the following ways, in order of precedence:

  1. Zipalign Path form input (expands environment variable references, e.g., ${CUSTOM_ANDROID_ZIPALIGN})
  2. ANDROID_HOME Override form input (expands environment variable references, e.g., ${CUSTOM_ANDROID_HOME})
  3. ANDROID_ZIPALIGNbuild variable
  4. ANDROID_ZIPALIGN environment variable
  5. ANDROID_HOME build variable
  6. ANDROID_HOME environment variable
  7. PATH environment variable
    1. A directory in PATH containing a file called zipalign
    2. A directory in PATH that appears to be an Android SDK home, i.e., contains the android or sdkmanager utilities

To access the first two override form parameters above, click the Advanced button on the Sign Android APKs build step form group.

Sign Android APKs form

Environment variables can come from various plugins, such as Environment Injetor Plugin or Custom Tools Plugin. The plugin searches an Android SDK home directory by finding the latest version under the build-tools directory installed in your SDK, and attempting to use the zipalign file that should be there, such as ${ANDROID_HOME}/build-tools/25.0.2/zipalign. Hence. be sure your Android SDK has the Build Tools package installed. I recommend setting up the SDK using the Custom Tools Plugin. To cover the Windows case, the plugin will search for zipalign.exe as well.

Note that this plugin assumes your Android build has produced an unsigned, unaligned APK. If you are using the Gradle Android plugin to build your APK, that means a previous Jenkins build step probably invoked the assembleRelease task on your build script and there were no signingConfig blocks that applied to your APK. In that case Gradle will have produced the necessary unsigned, unaligned APK, ready for the Android Signing Plugin to sign.

Output Signed APKs

As of version 2.2.0, there are two choices for the location where a Sign Android APKs build step will write signed APKs. You can change this behavior by clicking the Advanced button in the Sign Android APKs step form group of a Freestyle job, and checking the desired radio button in the Signed APK Destination group.

  • Output to unsigned APK sibling - The new and default choice writes the signed APK to the same directory where the input unsigned APK resides, the same as the standard Android Gradle build would do. This option is useful when you want to use your Gradle build script to do something like publish the signed APK in a Gradle build step after your Sign Android APKs build step runs. The standard Gradle Android plugin build should produce an unsigned APK named with the -unsigned.apk suffix. In that case, the Android Signing Plugin plugin will simply remove the -unsigned component to create the signed APK file name. Otherwise, the plugin will insert -signed before .apk in the unsigned APK name. For example, myApp-release-unsigned.apk becomes myApp-release.apk, whereas myApp-forElmo.apk becomes myApp-forElmo-signed.apk.
  • Output to separate directory - The original behavior writes signed APKs to a directory named like SignApksBuilder-out/my-app-unsigned.apk/my-app-signed.apk, where my-app-unsigned.apk is a directory named after the unsigned input APK. This is to avoid multiple signing steps in a single job overwriting each other's output APKs, and multiple APKs matched within a signing step colliding. It's clearly not fool-proof, however, so be mindful if you are signing multple APKs in a single job and/or signing step.

Regardless of the output option you choose, if you use the plugin's Archive Signed APKs and/or Archive Unsigned APKs option, the plugin archives the artifacts under the SignApksBuilder-out/<KEY_STORE_ID>/<KEY_ALIAS>/my-app-unsigned.apk/ directory in the build's archive.

Pipeline

Here is an example of signing APKs from a Pipeline script:

node {
    // ... steps to build unsigned APK ...
    signAndroidApks (
        keyStoreId: "myApp.signerKeyStore",
        keyAlias: "myTeam",
        apksToSign: "**/*-unsigned.apk"
        // uncomment the following line to output the signed APK to a separate directory as described above
        // signedApkMapping: [ $class: UnsignedApkBuilderDirMapping ]
        // uncomment the following line to output the signed APK as a sibling of the unsigned APK, as described above, or just omit signedApkMapping
        // you can override these within the script if necessary
        // androidHome: env.ANDROID_HOME
        // zipalignPath: env.ANDROID_ZIPALIGN
    )
}

Like the Free Style Job build step described above, the Pipeline step will attempt to use ANDROID_ZIPALIGN and ANDROID_HOME, in that priority order, from the Jenkins environment variables. Note the wrapping node context; this plugin assumes the Pipeline step will have a workspace available.

Job DSL

This plugin offers a Job DSL extension. You can include a Sign Android APKs build step in the steps context of a Job DSL script:

freeStyleJob('myApp.seed') {
    scm {
        git 'git://github.com/mygithub/myApp.git', 'master', {
            extensions {
                relativeTragetDirectory 'myApp'
            }
        }
    }
    steps {
        gradle {
            rootBuildScriptDir 'myApp'
            useWrapper true
            tasks 'clean assembleRelease'
        }
        signAndroidApks '**/myApp-unsigned.apk', {
            keyStoreId 'myApp.keyStore'
            keyAlias 'myAppKey'
            // uncomment the following line to output the signed APK to a separate directory as described above
            // signedApkMapping unsignedApkNameDir()
            // uncomment the following line to output the signed APK as a sibling of the unsigned APK, as described above, or just omit signedApkMapping
            // signedApkMapping unsignedApkSibling()
            archiveSignedApks true
            archiveUnsignedApks true
            androidHome '/opt/android-sdk'
        }
    }
}

The availble options are analogous to those in the build step configuration web UI.

Support

Please submit all issues to Jenkins Jira. Do not use GitHub issues.

Release Notes

See the change log.

License and Copyright

See the included LICENSE and NOTICE text files for original Work and Derivative Work copyright and license information.

android-signing-plugin's People

Contributors

daniel-beck-bot avatar jlleitschuh avatar kurtisnelson avatar maks avatar matthew-compton avatar restjohn avatar sandyiscool avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.