From bb9c5762ff424a9ae8df77d5dcebafa262fbe264 Mon Sep 17 00:00:00 2001 From: Alex Gonzalez Date: Fri, 27 Oct 2023 16:36:26 +0200 Subject: [PATCH 1/4] balena-api: add release assets helper functions Change-type: patch Signed-off-by: Alex Gonzalez --- automation/include/balena-api.inc | 230 +++++++++++++++++++++++++++++- 1 file changed, 229 insertions(+), 1 deletion(-) 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}" +} From 2c55cdc09d5fb38a225b1b11c413de1d5206fb44 Mon Sep 17 00:00:00 2001 From: Alex Gonzalez Date: Tue, 31 Oct 2023 12:48:45 +0100 Subject: [PATCH 2/4] balena-deploy: Add changelog to deployed artifacts Deploying the changelog will allow to deploy it as a release asset. Change-type: patch Signed-off-by: Alex Gonzalez --- automation/include/balena-deploy.inc | 3 +++ 1 file changed, 3 insertions(+) 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 From 173ab9a844e9c77f46bd5f022a62fc9100b83002 Mon Sep 17 00:00:00 2001 From: Alex Gonzalez Date: Tue, 31 Oct 2023 12:49:38 +0100 Subject: [PATCH 3/4] balena-deploy-block.sh: deploy licenses and changelog as release assets This will make it possible to surface these build artifacts to users. Change-type: patch Signed-off-by: Alex Gonzalez --- automation/entry_scripts/balena-deploy-block.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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}" From 635816960ec1f836433a397a420292462bafd2c5 Mon Sep 17 00:00:00 2001 From: Alex Gonzalez Date: Tue, 31 Oct 2023 13:44:06 +0100 Subject: [PATCH 4/4] Dockerfiles: update balenaCLI version to 17.2.2 Update balenaCLI from 14.5.15 to 17.2.2 (current latest) Change-type: patch Signed-off-by: Alex Gonzalez --- automation/Dockerfile_balena-push-env | 2 +- automation/Dockerfile_yocto-build-env | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 && \