Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-46437

Android Signing plugin cannot find zipalign on Linux

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Major
    • Resolution: Not A Defect
    • Component/s: android-signing-plugin
    • Labels:
    • Environment:
      Jenkins 2.69/Android Signing Plugin 2.2.5 running on Kubernetes 1.6. The actual build machine is Debian Jesse within a Docker container running as a Jenkins slave.
    • Similar Issues:

      Description

      Signing APKs in a Jenkins Pipeline fails with following message:

       

      [Test_Sign_APK] Running shell script
      + ls -l /opt/android-sdk/build-tools/26.0.1/zipalign
      -rwxr-xr-x. 1 android android 131217 Aug  9 15:53 /opt/android-sdk/build-tools/26.0.1/zipalign
      [Pipeline] signAndroidApks
      Executing shell script inside container [imeet-android-sdk] of pod [jenkins-slave-jdq6t-l2nht]
      Executing command: "echo" ""resolving effective environment"" 
      printf "EXITCODE %3d" $?; exit
      # cd "/home/jenkins/workspace/Test_Sign_APK"
      "echo" ""resolving effective environment"" 
      printf "EXITCODE %3d" $?; exit
      # resolving effective environment
      # EXITCODE   0[SignApksBuilder] zipalign path explicitly set to /opt/android-sdk/build-tools/26.0.1/zipalign
      [SignApksBuilder] no zipalign or zipalign.exe found in path /opt/android-sdk/build-tools/26.0.1
      [Pipeline] }
      [Pipeline] // stage
      [Pipeline] }
      [Pipeline] // container
      [Pipeline] }
      [Pipeline] // node
      [Pipeline] }
      [Pipeline] // podTemplate
      [Pipeline] End of Pipeline
      ERROR: failed to find zipalign path in parameters or environment
      Finished: FAILURE

       

      Note in the second line that I the pipeline (code below) runs 'ls -l' on the full path of zipalign and it returns successfully with the correct file and permissions.

      The relevant Pipeline code snipped for brevity:

       

      env.ANDROID_HOME = '/opt/android-sdk'
      env.ANDROID_ZIPALIGN = '/opt/android-sdk/build-tools/26.0.1/zipalign'
      
      <snip>
      
      stage ('Sign APK') {
        sh "ls -l ${ANDROID_ZIPALIGN}"
          signAndroidApks (
          keyStoreId: "AndroidSigningKeystore",
          keyAlias: "AndroidSigningKeystore",
          apksToSign: "**/*.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
        )
      }

       

       

       

        Attachments

          Activity

          Hide
          restjohn Robert St. John added a comment - - edited

          I'm not familiar with running Jenkins in your configuration with Kubernates and Docker, but I just took a quick look at the Kubernates plugin pipeline step reference and source on GitHub.  The pipeline step reference's first line is "Selects a container of the slave pod so that all shell steps are executed in that container."  Further, all of the examples on GitHub only demonstrate running shell steps within the container blocks.  These hints lead me to believe that the Kubernates plugin does not support running any Jenkins build steps other than shell scripts or other processes started using the Launcher passed to a build step.  If you know different, please tell me and I will investigate the issue further.

          As a potential workaround, you could try using the skipZipalign flag inside your signAndroidApks block:

          signAndroidApks {
            ...
            apksToSign: zipalignedByPreviousBuildStep.apk
            skipZipalign: true
          }

          Before signing the APK in your pipeline, run a shell command to zipalign the APK:

          sh "${ANDROID_ZIPALIGN} -f -p 4 build/outputs/apk/myApp-unsigned.apk zipalignedByPreviousBuildStep.apk"

          Be aware, however, that I am not sure what will happen when the Android Signing plugin attempts to sign that APK inside a container block.  I am guessing that will still fail, if my above assumptions about the Kubernates plugin are correct.  In that case, and if you are tied to using the Kubernates plugin, you can try signing the APK with a shell step as well by using the Android SDK's apksigner tool.  I believe you can use withCredentials {...} and its CertificateMultiBinding class to retrieve the key store file to your the Jenkins slave and pass the resulting key store path to the apksigner command.

          Show
          restjohn Robert St. John added a comment - - edited I'm not familiar with running Jenkins in your configuration with Kubernates and Docker, but I just took a quick look at the Kubernates plugin pipeline step reference and source on GitHub.  The pipeline step reference's first line is "Selects a container of the slave pod so that all shell steps are executed in that container."  Further, all of the examples  on GitHub only demonstrate running shell steps within the container blocks.  These hints lead me to believe that the Kubernates plugin does not support running any Jenkins build steps other than shell scripts or other processes started using the Launcher  passed to a build step.  If you know different, please tell me and I will investigate the issue further. As a potential workaround, you could try using the  skipZipalign flag inside your signAndroidApks block: signAndroidApks { ... apksToSign: zipalignedByPreviousBuildStep.apk skipZipalign: true } Before signing the APK in your pipeline, run a shell command to zipalign the APK: sh "${ANDROID_ZIPALIGN} -f -p 4 build/outputs/apk/myApp-unsigned.apk zipalignedByPreviousBuildStep.apk" Be aware, however, that I am not sure what will happen when the Android Signing plugin attempts to sign that APK inside a container block.  I am guessing that will still fail, if my above assumptions about the Kubernates plugin are correct.  In that case, and if you are tied to using the Kubernates plugin, you can try signing the APK with a shell step as well by using the Android SDK's apksigner  tool.  I believe you can use  withCredentials {... }  and its CertificateMultiBinding class to retrieve the key store file to your the Jenkins slave and pass the resulting key store path to the apksigner command.
          Hide
          gteshome Gashaw Teshome added a comment -

          Thank you for the pointer - setting 'skipZipalign: true' got me past the error so I can safely say that signing does work within the container block. Everything from accessing the keystore to signing the APK worked as expected on Kubernetes once I got past the zipalign issue.

          It turns out the APK is already zipaligned as part of the build process so there's no need to run the zipalign command via a shell. Thanks for your help.

          Show
          gteshome Gashaw Teshome added a comment - Thank you for the pointer - setting ' skipZipalign: true ' got me past the error so I can safely say that signing does work within the container block. Everything from accessing the keystore to signing the APK worked as expected on Kubernetes once I got past the zipalign issue. It turns out the APK is already zipaligned as part of the build process so there's no need to run the zipalign command via a shell. Thanks for your help.

            People

            • Assignee:
              restjohn Robert St. John
              Reporter:
              gteshome Gashaw Teshome
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: