0

我正在使用 Jenkins 为 Android 应用程序设置 CI。我正在尝试使用Custom Tools Plugin将 Android SDK 配置为 Jenkins 全局工具。这是我在 中配置的安装 shell 脚本Jenkins>Global Tool Configuration

printf "\nInstalling Android SDK as a Jenkins Custom Tool\n"

pwd
ls -la

if [ ! -d build-tools ];
    then
        printf "There's no dir by the name 'build-tools' on this agent yet. Will proceed to install the Android SDK.\n"

        printf "Downloading the Android SDK tools for Linux\n"
        curl -o android.zip https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
        printf "Download successful\n"

        printf "Unzipping downloaded Android SDK tools\n"
        unzip -o -z android.zip
        printf "Done unzipping\n"

        printf "Removing downloaded zip file\n"
        rm android.zip
        printf "Done removing\n"

        printf "Installing Android Build Tools 23.0.1\n"
        echo "y" | tools/bin/sdkmanager "build-tools;23.0.1"
        printf "Done installing Android Build Tools 23.0.1\n"
    else
        printf "There's already a dir by the name 'build-tools' on this agent. Aborting installation of the Android SDK.\n"
fi
printf "Done installing Android SDK as a Jenkins Custom Tool\n\n"

我目前正在尝试设置的作业从另一个位置下载未签名的 apk 并尝试对其进行签名。

这是詹金斯文件:

properties([
    parameters([
        [
            $class: 'CredentialsParameterDefinition',
            name: 'ANDROID_KEYSTORE_FILE',
            credentialType: 'com.cloudbees.plugins.credentials.impl.CertificateCredentialsImpl',
            defaultValue: params.ANDROID_KEYSTORE_FILE?:'',
            description: 'The Android keystore file in p12 format.',
            required: false
        ],
        string(
            name: 'ANDROID_SIGN_KEY_ALIAS',
            defaultValue: params.ANDROID_SIGN_KEY_ALIAS?:'',
            description: 'The alias of the signing key inside your keystore. If your keystore only has one key, you can leave this blank.',
        ),
    ])
])

stage('Binary sign'){
    node('standard'){
        def pwd = pwd()
        echo(pwd)
        sh('curl -o foo-unsigned.apk https://some/place/in/my/intranet/FooApp_12.apk')
        sh('ls -la')

        def androidHome = tool('android-sdk')

        //Let's sign and archive the unsigned and signed apk files
        withEnv([
            "ANDROID_HOME=${androidHome}"]) {

            signAndroidApks (
                keyStoreId: params.ANDROID_KEYSTORE_FILE,
                keyAlias: params.ANDROID_SIGN_KEY_ALIAS,
                apksToSign: "**/*-unsigned.apk",
                androidHome: env.ANDROID_HOME,
                archiveSignedApks: true,
                archiveUnsignedApks: true
            )   
        }
    }
}

您可以看到我正在使用signAndroidApks步骤。问题是当它执行时我得到这个错误:

[android-sign-test] $ echo "resolving effective environment"
[SignApksBuilder] zipalign ANDROID_HOME explicitly set to /Jenkins/tools/com.cloudbees.jenkins.plugins.customtools.CustomTool/android
[SignApksBuilder] found zipalign in Android SDK's latest build tools: /Jenkins/tools/com.cloudbees.jenkins.plugins.customtools.CustomTool/android/build-tools/23.0.1/zipalign
[SignApksBuilder] /Jenkins/tools/com.cloudbees.jenkins.plugins.customtools.CustomTool/android/build-tools/23.0.1/zipalign -f -p 4 /Jenkins/workspace/AFS-2.0/android-sign-test/foo-unsigned.apk /Jenkins/workspace/AFS-2.0/android-sign-test/SignApksBuilder-out/zipalign/aligned-foo-unsigned-6084722845076851930.apk
[android-sign-test] $ /Jenkins/tools/com.cloudbees.jenkins.plugins.customtools.CustomTool/android/build-tools/23.0.1/zipalign -f -p 4 /Jenkins/workspace/AFS-2.0/android-sign-test/foo-unsigned.apk /Jenkins/workspace/AFS-2.0/android-sign-test/SignApksBuilder-out/zipalign/aligned-foo-unsigned-6084722845076851930.apk
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] }
[Pipeline] // stage
[Pipeline] End of Pipeline
java.io.IOException: error=2, No such file or directory
    at java.lang.UNIXProcess.forkAndExec(Native Method)
    at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
    at java.lang.ProcessImpl.start(ProcessImpl.java:134)
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
    at hudson.Proc$LocalProc.<init>(Proc.java:249)
    at hudson.Proc$LocalProc.<init>(Proc.java:218)
    at hudson.Launcher$LocalLauncher.launch(Launcher.java:930)
    at hudson.Launcher$ProcStarter.start(Launcher.java:450)
    at hudson.Launcher$RemoteLaunchCallable.call(Launcher.java:1299)
    at hudson.Launcher$RemoteLaunchCallable.call(Launcher.java:1260)
    at hudson.remoting.UserRequest.perform(UserRequest.java:153)
    at hudson.remoting.UserRequest.perform(UserRequest.java:50)
    at hudson.remoting.Request$2.run(Request.java:336)
    at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:68)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at hudson.remoting.Engine$1$1.run(Engine.java:94)
    at java.lang.Thread.run(Thread.java:748)
Caused: java.io.IOException: Cannot run program "/Jenkins/tools/com.cloudbees.jenkins.plugins.customtools.CustomTool/android/build-tools/23.0.1/zipalign" (in directory "/Jenkins/workspace/AFS-2.0/android-sign-test"): error=2, No such file or directory
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
    at hudson.Proc$LocalProc.<init>(Proc.java:249)
    at hudson.Proc$LocalProc.<init>(Proc.java:218)
    at hudson.Launcher$LocalLauncher.launch(Launcher.java:930)
    at hudson.Launcher$ProcStarter.start(Launcher.java:450)
    at hudson.Launcher$RemoteLaunchCallable.call(Launcher.java:1299)
    at hudson.Launcher$RemoteLaunchCallable.call(Launcher.java:1260)
    at hudson.remoting.UserRequest.perform(UserRequest.java:153)
    at hudson.remoting.UserRequest.perform(UserRequest.java:50)
    at hudson.remoting.Request$2.run(Request.java:336)
    at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:68)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at hudson.remoting.Engine$1$1.run(Engine.java:94)
    at java.lang.Thread.run(Thread.java:748)
    at ......remote call to JNLP4-connect connection from ip-172-16-2-29.eu-west-1.compute.internal/172.16.2.29:44916(Native Method)
    at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1545)
    at hudson.remoting.UserResponse.retrieve(UserRequest.java:253)
    at hudson.remoting.Channel.call(Channel.java:830)
    at hudson.Launcher$RemoteLauncher.launch(Launcher.java:1053)
    at hudson.Launcher$ProcStarter.start(Launcher.java:450)
    at hudson.Launcher$ProcStarter.join(Launcher.java:461)
    at org.jenkinsci.plugins.androidsigning.SignApksBuilder.perform(SignApksBuilder.java:332)
    at org.jenkinsci.plugins.androidsigning.SignApksStep$SignApksStepExecution.run(SignApksStep.java:174)
    at org.jenkinsci.plugins.androidsigning.SignApksStep$SignApksStepExecution.run(SignApksStep.java:126)
    at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1$1.call(AbstractSynchronousNonBlockingStepExecution.java:47)
    at hudson.security.ACL.impersonate(ACL.java:260)
    at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1.run(AbstractSynchronousNonBlockingStepExecution.java:44)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Finished: FAILURE

你可以看到堆栈说No such file or directory,但我已经检查过,zipalign 可执行文件和未签名的 apk 都在它们应该在的位置。有没有人遇到过这个问题?有任何想法吗?

4

1 回答 1

0

我找到了解决问题的方法。首先,我尝试了一个更简单的脚本,看看我是否可以真正调用该zipalign程序:

stage('Binary sign'){
    node('standard'){

        sh("/Jenkins/tools/com.cloudbees.jenkins.plugins.customtools.CustomTool/android-sdk/build-tools/23.0.1/zipalign")
    }
}

这导致了以下错误:

zipalign: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory

经过一番研究,我发现这与某些 Linux 发行版上缺乏对 32 位可执行文件的支持有关。我的构建代理运行的是AWS Linux,它显然没有对 32 位二进制文​​件提供开箱即用的支持。Android SDK 构建工具都是 32 位可执行文件。因此,经过一些研究,我尝试安装库以支持 32 位二进制文​​件:

yum install glibc.i686

执行上面相同的脚本然后产生了这个错误:

zipalign: error while loading shared libraries: libz.so.1: cannot open shared object file: No such file or directory

然后我也尝试了:

yum install libzip.i686

这终于解决了这个问题。zipalign上面的脚本现在在不带参数调用时呈现正常的响应。

Zip alignment utility
Copyright (C) 2009 The Android Open Source Project

Usage: zipalign [-f] [-p] [-v] [-z] <align> infile.zip outfile.zip
       zipalign -c [-v] <align> infile.zip

  <align>: alignment in bytes, e.g. '4' provides 32-bit alignment
  -c: check alignment only (does not modify file)
  -f: overwrite existing outfile.zip
  -p: page align stored shared object files
  -v: verbose output
  -z: recompress using Zopfli

我的原始脚本现在执行良好。

于 2017-07-27T13:10:58.370 回答