Skip to content

Instantly share code, notes, and snippets.

@mark-software
Created March 13, 2022 02:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mark-software/d9ab3c427669b3e8d49b5439cb71ce6f to your computer and use it in GitHub Desktop.
Save mark-software/d9ab3c427669b3e8d49b5439cb71ce6f to your computer and use it in GitHub Desktop.
App Center Android deploy script
#!/bin/sh
# Description:
# This script releases a build to App Center using the last commit message for release notes.
# Each new line in the commit will be a separate bullet in the release notes.
# If the release notes contain the word "skip_appcenter_release" then no release will be generated.
# Example script usage:
# deploy.sh [dev|release] {API key}
# Environment variables defined in CircleCi:
# $APP_CENTER_API_TOKEN_STAGING
# $APP_CENTER_API_TOKEN_PROD
# $APP_CENTER_DISTRIBUTION_GROUP
# $APP_CENTER_OWNER_NAME
cd ProjectRoot
APPCENTER_OUTPUT_DIRECTORY="."
VERSION=$(./gradlew -q ":app:printVersion" | tail -n 1)
APP_NAME=ParentAppStaging
CONTENT_TYPE='application/vnd.android.package-archive'
ENV_NAME=staging
APK_NAME="AppName-staging-$VERSION.apk"
if [ "$1" == "release" ]; then
APK_NAME="AppName-production-$VERSION.apk"
ENV_NAME=release
APP_NAME=ParentAppProd
fi
echo "Preparing to build $APK_NAME"
RELEASE_FILE_LOCATION=$(pwd)"/app/build/outputs/apk/$ENV_NAME/$APK_NAME"
FILE_SIZE_BYTES=$(wc -c $RELEASE_FILE_LOCATION | awk '{print $1}')
# -------------- Handle release notes --------------
# Get the last commit message and use it as release notes
RELEASE_NOTES=$(git log -1 --pretty=%B | grep -v -e '^$' | grep -v "^Merge pull request" | sed -e 's/^/\* /' | awk '{printf "%s\\n", $0}')
echo -e "Formatted release notes are below:\n$RELEASE_NOTES\n\n"
if [[ $RELEASE_NOTES == *"skip_appcenter_release"* ]]; then
echo "**** Skipping App Center release. ****"
exit 0
fi
# -------------- Begin upload process --------------
UPLOAD_DOMAIN="https://file.appcenter.ms/upload"
API_URL="https://api.appcenter.ms/v0.1/apps/$APP_CENTER_OWNER_NAME/$APP_NAME"
AUTH="X-API-Token: $2"
ACCEPT_JSON="Accept: application/json"
# Create upload resource - step 1/7 **************************
echo "Creating upload resource (1/7)"
upload_json=$(curl -s -X POST -H "Content-Type: application/json" -H "$ACCEPT_JSON" -H "$AUTH" "$API_URL/uploads/releases")
releases_id=$(echo $upload_json | jq -r '.id')
package_asset_id=$(echo $upload_json | jq -r '.package_asset_id')
url_encoded_token=$(echo $upload_json | jq -r '.url_encoded_token')
# Upload metadata - step 2/7 **************************
echo "Creating metadata (2/7)"
metadata_url="$UPLOAD_DOMAIN/set_metadata/$package_asset_id?file_name=$APK_NAME&file_size=$FILE_SIZE_BYTES&token=$url_encoded_token&content_type=$CONTENT_TYPE"
meta_response=$(curl -s -d POST -H "Content-Type: application/json" -H "$ACCEPT_JSON" -H "$AUTH" "$metadata_url")
chunk_size=$(echo $meta_response | jq -r '.chunk_size')
split_dir=$APPCENTER_OUTPUT_DIRECTORY/split-dir
mkdir -p $split_dir
eval split -b $chunk_size $RELEASE_FILE_LOCATION $split_dir/split
# Upload APK chunks - step 3/7 **************************
echo "Uploading chunked binary (3/7)"
binary_upload_url="$UPLOAD_DOMAIN/upload_chunk/$package_asset_id?token=$url_encoded_token"
block_number=1
for i in $split_dir/*
do
echo "start uploading chunk $i"
url="$binary_upload_url&block_number=$block_number"
size=$(wc -c $i | awk '{print $1}')
curl -X POST $url --data-binary "@$i" -H "Content-Length: $size" -H "Content-Type: $CONTENT_TYPE"
block_number=$(($block_number + 1))
printf "\n"
done
# Finalize upload - step 4/7 **************************
echo "Finalising upload (4/7)"
finish_url="$UPLOAD_DOMAIN/finished/$package_asset_id?token=$url_encoded_token"
curl -d POST -H "Content-Type: application/json" -H "$ACCEPT_JSON" -H "$AUTH" "$finish_url"
# Commit release - step 5/7 **************************
echo "Committing release (5/7)"
commit_url="$API_URL/uploads/releases/$releases_id"
curl -H "Content-Type: application/json" -H "$ACCEPT_JSON" -H "$AUTH" \
--data '{"upload_status": "uploadFinished","id": "$releases_id"}' \
-X PATCH \
$commit_url
# Poll for release ID - step 6/7 **************************
echo "\nPolling for release ID (6/7)"
release_id=null
counter=0
max_poll_attempts=15
while [[ $release_id == null && ($counter -lt $max_poll_attempts)]]
do
poll_result=$(curl -s -H "Content-Type: application/json" -H "$ACCEPT_JSON" -H "$AUTH" $commit_url)
release_id=$(echo $poll_result | jq -r '.release_distinct_id')
echo $counter $release_id
counter=$((counter + 1))
sleep 3
done
if [[ $release_id == null ]];
then
echo "Failed to find release from App Center"
exit 1
fi
# Distribute build - step 7/7 **************************
echo "Distributing build (7/7)"
distribute_url="$API_URL/releases/$release_id"
distribute_response=$(curl -H "Content-Type: application/json" -H "$ACCEPT_JSON" -H "$AUTH" \
--data '{"destinations": [{ "name": "'"$APP_CENTER_DISTRIBUTION_GROUP"'"}], "notify_testers": true, "release_notes": "'"$RELEASE_NOTES"'" }' \
-X PATCH \
$distribute_url)
status_code=$(echo $distribute_response | jq -r '.status')
if [[ $status_code == 500 ]];
then
echo "Failed to distribute app. Response = $distribute_response"
exit 1
fi
# -------------- End upload process --------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment