diff --git a/automation/Dockerfile_balena-push-env b/automation/Dockerfile_balena-push-env index 14174da0d..d58219482 100644 --- a/automation/Dockerfile_balena-push-env +++ b/automation/Dockerfile_balena-push-env @@ -24,7 +24,7 @@ RUN curl -sSL https://download.docker.com/linux/static/edge/x86_64/docker-${DOCK && mv /docker/* /usr/local/bin/ # Install balena-cli -ENV BALENA_CLI_VERSION 14.5.15 +ENV BALENA_CLI_VERSION 17.2.2 RUN curl -sSL https://github.com/balena-io/balena-cli/releases/download/v$BALENA_CLI_VERSION/balena-cli-v$BALENA_CLI_VERSION-linux-x64-standalone.zip > balena-cli.zip && \ unzip balena-cli.zip && \ mv balena-cli/* /usr/bin && \ diff --git a/automation/Dockerfile_yocto-build-env b/automation/Dockerfile_yocto-build-env index caf6f0bc1..426cbdbd1 100644 --- a/automation/Dockerfile_yocto-build-env +++ b/automation/Dockerfile_yocto-build-env @@ -36,7 +36,7 @@ RUN apt-get update && apt-get install -y docker-ce=${DOCKER_VERSION} docker-ce-c VOLUME /var/lib/docker # Install balena-cli -ENV BALENA_CLI_VERSION 14.5.15 +ENV BALENA_CLI_VERSION 17.2.2 RUN curl -sSL https://github.com/balena-io/balena-cli/releases/download/v$BALENA_CLI_VERSION/balena-cli-v$BALENA_CLI_VERSION-linux-x64-standalone.zip > balena-cli.zip && \ unzip balena-cli.zip && \ mv balena-cli/* /usr/bin && \ diff --git a/automation/entry_scripts/balena-deploy-block.sh b/automation/entry_scripts/balena-deploy-block.sh index 224f832a1..2135b22e0 100755 --- a/automation/entry_scripts/balena-deploy-block.sh +++ b/automation/entry_scripts/balena-deploy-block.sh @@ -40,6 +40,20 @@ if [ -z "${_releaseID}" ]; then exit 1 fi +_assets="$(find /deploy/deploy-jenkins -name licenses.tar.gz) /deploy/CHANGELOG.md" +_rid=$(balena_api_releaseID_from_commitID "${_releaseID}" "${API_ENV}" "${BALENAOS_TOKEN}") +for _asset in ${_assets}; do + if [ -f "${_asset}" ]; then + _aid=$(balena_api_add_release_asset "${_rid}" "${API_ENV}" "${BALENAOS_TOKEN}" "${_asset}") + if [ -n "${_aid}" ]; then + echo "[INFO] Added ${_asset} with ID ${_aid} to release ${_releaseID}" + else + echo "[ERROR] Failed to add ${_asset} to release ${_releaseID}" + exit 1 + fi + fi +done + # Legacy hostapp tagging if [ "${DEPLOY}" = "yes" ] && [ "${FINAL}" = "yes" ]; then balena_lib_release_finalize "${_releaseID}" "${BALENAOS_ACCOUNT}/${APPNAME}" "${API_ENV}" "${BALENAOS_TOKEN}" "${ESR}" diff --git a/automation/include/balena-api.inc b/automation/include/balena-api.inc index 5ccb64eb8..c90fea5c3 100755 --- a/automation/include/balena-api.inc +++ b/automation/include/balena-api.inc @@ -1,6 +1,6 @@ #!/bin/bash -CURL="curl -s" +CURL="curl --silent --retry 10 --location --compressed" VERBOSE=${VERBOSE:-0} [ "${VERBOSE}" = "verbose" ] && set -x @@ -1065,3 +1065,231 @@ balena_api_is_release_final() { _final=$(echo "${_json}" | jq -r '.d[0].is_final') echo "${_final}" } + +# Returns release ID from release commit ID +# Arguments: +# +# $1: Release commit ID +# $2: Balena target environment +# $3: Balena API token +# +# Return: +# Release ID if success, nothing otherwise +# Result: +# Success or failure +balena_api_releaseID_from_commitID() { + local _release_id="${1}" + local _apiEnv="${2}" + local _token="${3}" + local _json + local _id + + _apiEnv=${_apiEnv:-$(balena_lib_environment)} + _token=${_token:-$(balena_lib_token)} + if [ -n "${_token}" ]; then + _json=$(${CURL} -XGET -H "Content-type: application/json" "https://api.${_apiEnv}/${TRANSLATION}/release?\$filter=commit%20eq%20%27${_release_id}%27" -H "Authorization: Bearer ${_token}") + else + _json=$(${CURL} -XGET -H "Content-type: application/json" "https://api.${_apiEnv}/${TRANSLATION}/release?\$filter=commit%20eq%20%27${_release_id}%27") + fi + __pp_json "${_json}" + _id=$(echo "${_json}" | jq -r '.d[0].id') + echo "${_id}" +} + +do_http_request() { + local _request="${1:-"GET"}" + local _errfile + local _outfile + local _status_code + + _errfile=$(mktemp) + _outfile=$(mktemp) + if _status_code=$(${CURL} -X"${_request}" -w "%{http_code}" -o "${_outfile}" "${@:2}" 2>"${_errfile}"); then + rm -f "${_errfile}" + case "${_status_code}" in + 2*) + cat "${_outfile}" + rm -f "${_outfile}" + return 0 + ;; + 4*) + echo "FAIL $(cat "${_outfile}")" >&2 + rm -f "${_outfile}" + return 1 + ;; + 5*) + echo "ERROR $(cat "${_outfile}")" >&2 + rm -f "${_outfile}" + return 1 + ;; + *) + echo "WARN $(cat "${_outfile}")" >&2 + rm -f "${_outfile}" + return 1 + ;; + esac + else + echo "WARN $(cat "${_errfile}")" >&2 + rm -f "${_errfile}" "${_outfile}" + return 1 + fi +} + +do_post() { + do_http_request "POST" "$@" +} + +do_delete() { + do_http_request "DELETE" "$@" +} + +do_get() { + do_http_request "GET" "$@" +} + +# Attaches a file to a release +# Arguments: +# +# $1: Release commit ID +# $2: Balena target environment +# $3: Balena API token +# $4: Local path to asset file +# $5: Asset key - defaults to file name +# +# Return: +# New asset ID +# Result: +# Success or failure +balena_api_add_release_asset() { + local _release_id="${1}" + local _apiEnv="${2}" + local _token="${3}" + local _asset_path="${4}" + local _asset_key="${5:-$(basename "${_asset_path}")}" + local _json + local _id + + local TRANSLATION="resin" + + _apiEnv=${_apiEnv:-$(balena_lib_environment)} + _token=${_token:-$(balena_lib_token)} + + [ -z "${_token}" ] && >&2 echo "[balena_api_add_release_asset]: Authentication token is required" && return 1 + + _json=$(do_post "https://api.${_apiEnv}/${TRANSLATION}/release_asset" -H "Authorization: Bearer ${_token}" --form "release=${_release_id}" --form "asset_key=${_asset_key}" --form "asset=@${_asset_path}") + __pp_json "${_json}" + _id=$(echo "${_json}" | jq -r '.id') + echo "${_id}" +} + +# Outputs a release asset in JSON format +# Arguments: +# +# $1: Release ID +# $2: Balena target environment +# $3: Balena API token +# $4: Asset key +# +# Return: +# Release asset in JSON format +# Result: +# Success or failure +balena_api_get_release_asset() { + local _release_id="${1}" + local _apiEnv="${2}" + local _token="${3}" + local _asset_key="${4}" + local _json + + _apiEnv=${_apiEnv:-$(balena_lib_environment)} + _token=${_token:-$(balena_lib_token)} + + [ -z "${_token}" ] && >&2 echo "[balena_api_get_release_asset]: Authentication token is required" && return 1 + _json=$(balena_api_get_release_assets "${_release_id}" "${_apiEnv}" "${_token}") + __pp_json "${_json}" + echo "${_json}" | jq -r '.d[0].release_asset[] | select(.asset_key == '\"${_asset_key}\"')' +} + +# Outputs a release asset URL +# Arguments: +# +# $1: Release ID +# $2: Balena target environment +# $3: Balena API token +# $4: Asset key +# +# Return: +# Release asset in JSON format +# Result: +# Success or failure +balena_api_get_release_asset_url() { + local _release_id="${1}" + local _apiEnv="${2}" + local _token="${3}" + local _asset_key="${4}" + local _json + local _href + + _apiEnv=${_apiEnv:-$(balena_lib_environment)} + _token=${_token:-$(balena_lib_token)} + + [ -z "${_token}" ] && >&2 echo "[balena_api_get_release_asset_url]: Authentication token is required" && return 1 + _json=$(balena_api_get_release_asset "${_release_id}" "${_apiEnv}" "${_token}" "${_asset_key}") + __pp_json "${_json}" + _href=$(echo "${_json}" | jq -r '.asset.href') + echo "${_href}" +} + + +# Outputs all release assets in JSON format +# Arguments: +# +# $1: Release ID +# $2: Balena target environment +# $3: Balena API token +# +# Return: +# Release assets in JSON format +# Result: +# Success or failure +balena_api_get_release_assets() { + local _release_id="${1}" + local _apiEnv="${2}" + local _token="${3}" + local _json + + local TRANSLATION="resin" + + _apiEnv=${_apiEnv:-$(balena_lib_environment)} + _token=${_token:-$(balena_lib_token)} + + [ -z "${_token}" ] && >&2 echo "[balena_api_get_release_assets]: Authentication token is required" && return 1 + _json=$(do_get "https://api.${_apiEnv}/${TRANSLATION}/release(${_release_id})?\$select=id&\$expand=release_asset" -H "Authorization: Bearer ${_token}") + __pp_json "${_json}" + echo "${_json}" +} + + +# Removes a release asset +# Arguments: +# +# $1: Aset ID +# $2: Balena target environment +# $3: Balena API token +# +# Result: +# Success or failure +balena_api_delete_release_asset() { + local _asset_id="${1}" + local _apiEnv="${2}" + local _token="${3}" + local _json + + local TRANSLATION="resin" + + _apiEnv=${_apiEnv:-$(balena_lib_environment)} + _token=${_token:-$(balena_lib_token)} + + [ -z "${_token}" ] && >&2 echo "[balena_api_delete_release_asset]: Authentication token is required" && return 1 + do_delete "https://api.${_apiEnv}/${TRANSLATION}/release_asset(${_asset_id})" -H "Authorization: Bearer ${_token}" +} diff --git a/automation/include/balena-deploy.inc b/automation/include/balena-deploy.inc index bf5473e0d..f464b4520 100644 --- a/automation/include/balena-deploy.inc +++ b/automation/include/balena-deploy.inc @@ -62,6 +62,9 @@ balena_deploy_artifacts () { if [ -d "${_yocto_licenses_deploy}" ]; then tar -czf "${_deploy_dir}/licenses.tar.gz" -C $(dirname "${_yocto_licenses_deploy}") $(basename "${_yocto_licenses_deploy}") fi + if [ -f "${device_dir}/CHANGELOG.md" ]; then + cp -v "${device_dir}/CHANGELOG.md" "${_deploy_dir}" + fi test "${_slug}" = "edge" && return