Skip to content

Commit

Permalink
Check zipalign before running zipalign again (#57)
Browse files Browse the repository at this point in the history
* Check zipalign before running zipalign

* Updating step version in test

* Update sample app to latest gradle, remove test failure ignores.

* Add tests for signed debug apk

* Handle error

* Seperate zipalign from main

* In case artifact is zipalign, still move it to a new destination
  • Loading branch information
lpusok authored Oct 6, 2020
1 parent e6f8b89 commit 5124b4a
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 115 deletions.
189 changes: 121 additions & 68 deletions bitrise.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,27 @@ default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git

app:
envs:
- BITRISE_STEP_GIT_CLONE_URL: https://github.com/bitrise-steplib/steps-sign-apk.git

- SAMPLE_APP_REPOSITORY_URL: https://github.com/bitrise-samples/sample-apps-android-abi-split.git
- SAMPLE_APP_REPOSITORY_URL: https://github.com/bitrise-io/sample-apps-android-abi-split.git
- BRANCH: master
- GRADLEW_PATH: "./gradlew"

# define these in your .bitrise.secrets.yml
- BITRISEIO_ANDROID_KEYSTORE_URL: $BITRISEIO_ANDROID_KEYSTORE_URL
- BITRISEIO_ANDROID_KEYSTORE_PASSWORD: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD
- BITRISEIO_ANDROID_KEYSTORE_ALIAS: $BITRISEIO_ANDROID_KEYSTORE_ALIAS
- BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD
- BITRISEIO_ANDROID_KEYSTORE_1_URL: $BITRISEIO_ANDROID_KEYSTORE_1_URL
- BITRISEIO_ANDROID_KEYSTORE_PASSWORD_1: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_1
- BITRISEIO_ANDROID_KEYSTORE_ALIAS_1: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_1
- BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_1: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_1
- BITRISEIO_ANDROID_KEYSTORE_2_URL: $BITRISEIO_ANDROID_KEYSTORE_2_URL
- BITRISEIO_ANDROID_KEYSTORE_PASSWORD_2: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_2
- BITRISEIO_ANDROID_KEYSTORE_ALIAS_2: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_2
- BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_2: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_2
- BITRISEIO_ANDROID_KEYSTORE_3_URL: $BITRISEIO_ANDROID_KEYSTORE_3_URL
- BITRISEIO_ANDROID_KEYSTORE_PASSWORD_3: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_3
- BITRISEIO_ANDROID_KEYSTORE_ALIAS_3: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_3
- BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_3: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_3
- BITRISEIO_ANDROID_KEYSTORE_4_URL: $BITRISEIO_ANDROID_KEYSTORE_4_URL
- BITRISEIO_ANDROID_KEYSTORE_PASSWORD_4: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_4
- BITRISEIO_ANDROID_KEYSTORE_ALIAS_4: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_4
- BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_4: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_4

workflows:
# ----------------------------------------------------------------
Expand All @@ -28,6 +38,7 @@ workflows:
- go-test:
after_run:
- test_apk
- test_apk_debug
- test_bundle

test_apk:
Expand All @@ -36,22 +47,34 @@ workflows:
- APK_FILE_INCLUDE_FILTER: "*.apk"
after_run:
- create_build_artifact
- test
- _jarsigner
- _apksigner

# Using apksigner zipalign fails to zipalign already zipaligned artifact
test_apk_debug:
envs:
- GRADLE_TASK: assembleDebug
- APK_FILE_INCLUDE_FILTER: "*.apk"
after_run:
- create_build_artifact
- _jarsigner
- _apksigner

test_bundle:
envs:
- GRADLE_TASK: bundleRelease
- APK_FILE_INCLUDE_FILTER: "*.aab"
after_run:
- create_build_artifact
- test
- _jarsigner
- _apksigner

create_build_artifact:
steps:
- script:
inputs:
- content: |-
#!/bin/bash
#!/usr/bin/env bash
set -ex
rm -rf ./_tmp
- change-workdir:
Expand All @@ -78,114 +101,144 @@ workflows:
git remote add origin "${SAMPLE_APP_REPOSITORY_URL}"
git fetch || exit 1
[[ -n "${COMMIT}" ]] && git checkout "${COMMIT}" || git checkout "${BRANCH}"
- install-missing-android-tools@2.3.3:
- install-missing-android-tools:
inputs:
- ndk_revision: '16'
run_if: ".IsCI"
- script:
inputs:
- content: |-
#!/usr/bin/env bash
set -ex
envman unset --key BITRISE_APK_PATH
envman unset --key BITRISE_AAB_PATH
- gradle-runner:
inputs:
- gradle_task: "$GRADLE_TASK"
- gradlew_path: "$GRADLEW_PATH"
- apk_file_include_filter: $APK_FILE_INCLUDE_FILTER
- app_file_include_filter: $APK_FILE_INCLUDE_FILTER
- script:
inputs:
- content: |-
#!/usr/bin/env bash
set -ex
if [ -n "$BITRISE_APK_PATH" ]; then
envman add --key ORIG_BITRISE_APK_PATH --value ${BITRISE_APK_PATH}
fi
test:
reset_apk_path:
steps:
- path::./:
is_skippable: true
title: Step Test - keystore pass == key pass with Jar signer
- script:
inputs:
- keystore_url: $BITRISEIO_ANDROID_KEYSTORE_1_URL
- keystore_password: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_1
- keystore_alias: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_1
- private_key_password: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_1
- content: |-
#!/usr/bin/env bash
set -ex
if [ -n "$ORIG_BITRISE_APK_PATH" ]; then
envman add --key BITRISE_APK_PATH --value ${ORIG_BITRISE_APK_PATH}
fi
_jarsigner:
steps:
- script:
inputs:
- content: |-
echo "jarsigner"
envman add --key APK_SIGNER --value "false"
after_run:
- _tests

_apksigner:
steps:
- script:
inputs:
- content: |-
echo "apksigner"
envman add --key APK_SIGNER --value "true"
after_run:
- _tests

_tests:
after_run:
- reset_apk_path
- test1
- reset_apk_path
- test2
- reset_apk_path
- test3
- reset_apk_path
- test4
- reset_apk_path
- test5
- reset_apk_path
- test6

test1:
steps:
- path::./:
is_skippable: true
title: Step Test - keystore pass == key pass with APK signer
title: Step Test - keystore pass == key pass
inputs:
- keystore_url: $BITRISEIO_ANDROID_KEYSTORE_1_URL
- keystore_password: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_1
- keystore_alias: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_1
- private_key_password: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_1
- use_apk_signer: true
- path::./:
is_skippable: true
title: Step Test - keystore pass != key pass with Jar signer
inputs:
- keystore_url: $BITRISEIO_ANDROID_KEYSTORE_2_URL
- keystore_password: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_2
- keystore_alias: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_2
- private_key_password: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_2
- use_apk_signer: $APK_SIGNER

test2:
steps:
- path::./:
is_skippable: true
title: Step Test - keystore pass != key pass with APK signer
title: Step Test - keystore pass != key pass
inputs:
- keystore_url: $BITRISEIO_ANDROID_KEYSTORE_2_URL
- keystore_password: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_2
- keystore_alias: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_2
- private_key_password: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_2
- use_apk_signer: true
- use_apk_signer: $APK_SIGNER

test3:
steps:
- path::./:
is_skippable: true
title: Step Test - default alias
inputs:
- keystore_url: $BITRISEIO_ANDROID_KEYSTORE_3_URL
- keystore_password: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_3
- keystore_alias: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_3
- private_key_password: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_3
- use_apk_signer: $APK_SIGNER

test4:
steps:
- path::./:
is_skippable: true
title: Step Test - default alias with APK signer
inputs:
- keystore_url: $BITRISEIO_ANDROID_KEYSTORE_3_URL
- keystore_password: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_3
- keystore_alias: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_3
- private_key_password: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_3
- use_apk_signer: true
- path::./:
is_skippable: true
title: Step Test - android studio generated keystore (jks)
inputs:
- keystore_url: $BITRISEIO_ANDROID_KEYSTORE_4_URL
- keystore_password: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_4
- keystore_alias: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_4
- private_key_password: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_4
- use_apk_signer: $APK_SIGNER

test5:
steps:
- path::./:
is_skippable: true
title: Step Test - android studio generated keystore (jks) with APK signer
inputs:
- keystore_url: $BITRISEIO_ANDROID_KEYSTORE_4_URL
- keystore_password: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_4
- keystore_alias: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_4
- private_key_password: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_4
- use_apk_signer: true
- path::./:
is_skippable: true
title: Step Test - android studio generated keystore (jks) + custom artifact name
inputs:
- keystore_url: $BITRISEIO_ANDROID_KEYSTORE_4_URL
- keystore_password: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_4
- keystore_alias: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_4
- private_key_password: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_4
- output_name: "test-artifact-name"
- use_apk_signer: $APK_SIGNER

test6:
steps:
- path::./:
is_skippable: true
title: Step Test - android studio generated keystore (jks) + custom artifact name with APK signer
inputs:
- keystore_url: $BITRISEIO_ANDROID_KEYSTORE_4_URL
- keystore_password: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_4
- keystore_alias: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_4
- private_key_password: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_4
- output_name: "test-artifact-name"
- use_apk_signer: true
- path::./:
is_skippable: true
title: Step Test - android studio generated keystore (jks) + custom artifact name second time to see collisions if any
inputs:
- keystore_url: $BITRISEIO_ANDROID_KEYSTORE_4_URL
- keystore_password: $BITRISEIO_ANDROID_KEYSTORE_PASSWORD_4
- keystore_alias: $BITRISEIO_ANDROID_KEYSTORE_ALIAS_4
- private_key_password: $BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD_4
- output_name: "test-artifact-name"
- use_apk_signer: $APK_SIGNER

_go_tests:
steps:
Expand All @@ -206,7 +259,7 @@ workflows:
title: Dependency update
inputs:
- content: |-
#!/bin/bash
#!/usr/bin/env bash
set -ex
go get -u -v github.com/golang/dep/cmd/dep
dep ensure -v
Expand All @@ -219,6 +272,6 @@ workflows:
- script:
inputs:
- content: |-
#!/bin/bash
#!/usr/bin/env bash
set -ex
stepman audit --step-yml ./step.yml
49 changes: 2 additions & 47 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,21 +202,6 @@ func unsignBuildArtifact(aapt, pth string) error {
return removeFilesFromBuildArtifact(aapt, pth, signingFiles)
}

func zipalignBuildArtifact(zipalign, pth, dstPth string, pageAlign bool) error {
cmdSlice := []string{zipalign}

if pageAlign {
cmdSlice = append(cmdSlice, "-p")
}

cmdSlice = append(cmdSlice, "-f", "4", pth, dstPth)
prinatableCmd := command.PrintableCommandArgs(false, cmdSlice)
log.Printf("=> %s", prinatableCmd)

_, err := keystore.ExecuteForOutput(cmdSlice)
return err
}

func prettyBuildArtifactBasename(buildArtifactPth string) string {
buildArtifactBasenameWithExt := path.Base(buildArtifactPth)
buildArtifactExt := filepath.Ext(buildArtifactBasenameWithExt)
Expand Down Expand Up @@ -422,19 +407,17 @@ func signJarSigner(zipalign, tmpDir string, unsignedBuildArtifactPth string, bui
fmt.Println()

fullPath, err := zipAlignArtifact(zipalign, unalignedBuildArtifactPth, buildArtifactDir, buildArtifactBasename, artifactExt, "signed", outputName, pageAlignConfig)

if err != nil {
failf("Failed to zip align artifact, error: %s", err)
failf("Failed to zipalign Build Artifact: %s", err)
}

return fullPath
}

func signAPK(zipalign, tmpDir string, unsignedBuildArtifactPth string, buildArtifactDir string, buildArtifactBasename string, artifactExt string, outputName string, apkSigner SignatureConfiguration, pageAlignConfig pageAlignStatus) string {
alignedPath, err := zipAlignArtifact(zipalign, unsignedBuildArtifactPth, buildArtifactDir, buildArtifactBasename, artifactExt, "aligned", "", pageAlignConfig)

if err != nil {
failf("Failed to zip align artifact, error: %s", err)
failf("Failed to zipalign Build Artifact, error: %s", err)
}

signedArtifactName := fmt.Sprintf("%s-bitrise-signed%s", buildArtifactBasename, artifactExt)
Expand All @@ -461,34 +444,6 @@ func signAPK(zipalign, tmpDir string, unsignedBuildArtifactPth string, buildArti
return fullPath
}

func zipAlignArtifact(zipalign, unalignedBuildArtifactPth string, buildArtifactDir string, buildArtifactBasename string, artifactExt string, fullPathExt string, outputName string, pageAlignConfig pageAlignStatus) (string, error) {
log.Infof("Zipalign Build Artifact")
signedArtifactName := fmt.Sprintf("%s-bitrise-%s%s", buildArtifactBasename, fullPathExt, artifactExt)
if artifactName := fmt.Sprintf("%s%s", outputName, artifactExt); outputName != "" {
log.Printf("- Exporting (%s) as: %s", signedArtifactName, artifactName)
signedArtifactName = artifactName
}
fullPath := filepath.Join(buildArtifactDir, signedArtifactName)

pageAlign := pageAlignConfig == pageAlignYes
// Only care about .so memory page alignment for APKs
if !strings.EqualFold(artifactExt, ".aab") && pageAlignConfig == pageAlignAuto {
extractNativeLibs, err := parseAPKextractNativeLibs(unalignedBuildArtifactPth)
if err != nil {
log.Warnf("Failed to parse APK manifest to read extractNativeLibs attribute: %s", err)
pageAlign = true
} else {
pageAlign = !extractNativeLibs
}
}

if err := zipalignBuildArtifact(zipalign, unalignedBuildArtifactPth, fullPath, pageAlign); err != nil {
failf("Failed to zipalign Build Artifact, error: %s", err)
}

return fullPath, nil
}

func exportAPK(signedAPKPaths []string, joinedAPKOutputPaths string) {
if err := tools.ExportEnvironmentWithEnvman("BITRISE_SIGNED_APK_PATH", signedAPKPaths[len(signedAPKPaths)-1]); err != nil {
log.Warnf("Failed to export APK (%s) error: %s", signedAPKPaths[len(signedAPKPaths)-1], err)
Expand Down
Loading

0 comments on commit 5124b4a

Please sign in to comment.