Changeset View
Changeset View
Standalone View
Standalone View
contrib/devtools/github-release.sh
- This file was added.
Property | Old Value | New Value |
---|---|---|
File Mode | null | 100755 |
#!/usr/bin/env bash | |||||
export LC_ALL=C | |||||
set -u | |||||
SCRIPT_PATH="$(cd "$(dirname "$0")"; pwd)" | |||||
Fabien: What about `"$(dirname "$0")"` ? The chance that the directory doesn't exist is null, and if… | |||||
ORIGINAL_PWD=$(pwd) | |||||
TOPLEVEL="$(cd "${SCRIPT_PATH}"; echo $(git rev-parse --show-toplevel))" | |||||
Lint: ShellCheck found an issue: Useless echo? Instead of 'echo $(cmd)', just use 'cmd'. Lint: ShellCheck found an issue:: Useless echo? Instead of 'echo $(cmd)', just use 'cmd'. | |||||
OAUTH_TOKEN_PATH="${PWD}/.github-oauth-token" | |||||
TAG="" | |||||
help_message() { | |||||
echo "Create a draft Github release and upload binaries." | |||||
echo "Usage: $0 <options>" | |||||
echo "-a, --asset-dir (required) Path to the top-level directory outputted by a Gitian build." | |||||
echo " This directory must contain linux, osx, and win binaries in those respective sub-directories." | |||||
echo "-d, --dry-run Run through the script, but do not touch existing tags, push to Github, or upload release files." | |||||
echo "-h, --help Display this help message." | |||||
echo "-o, --oauth-token Path to a file containing your OAuth token (defaults to: '${OAUTH_TOKEN_PATH}')." | |||||
echo "-t, --tag (required) The git tag create a release for. This tag must already exist." | |||||
} | |||||
ASSET_DIR="" | |||||
DRY_RUN="false" | |||||
# Parse command line arguments | |||||
while [[ $# -gt 0 ]]; do | |||||
case $1 in | |||||
-a|--assets-dir) | |||||
ASSET_DIR=$(cd $2; pwd) | |||||
shift # shift past argument | |||||
shift # shift past value | |||||
;; | |||||
-d|--dry-run) | |||||
DRY_RUN="true" | |||||
shift # shift past argument | |||||
;; | |||||
-h|--help) | |||||
help_message | |||||
exit 0 | |||||
;; | |||||
-o|--oauth-token) | |||||
OAUTH_TOKEN_PATH="$2" | |||||
shift # shift past argument | |||||
shift # shift past value | |||||
;; | |||||
-t|--tag) | |||||
TAG="$2" | |||||
shift # shift past argument | |||||
shift # shift past value | |||||
;; | |||||
*) | |||||
echo "Unknown argument: $1" | |||||
help_message | |||||
exit 1 | |||||
;; | |||||
esac | |||||
done | |||||
# Sanity checks on the release tag | |||||
if [ -z "${TAG}" ]; then | |||||
echo "Error: The release tag was not set. Try setting it with [ -t | --tag ]" | |||||
exit 10 | |||||
fi | |||||
TAG_PATTERN="^v[0-9]*\.[0-9]*\.[0-9]*" | |||||
if [[ ! ${TAG} =~ ${TAG_PATTERN} ]]; then | |||||
echo "Error: Tag '${TAG}' does not match the expected versioning pattern '${TAG_PATTERN}'" | |||||
exit 11 | |||||
fi | |||||
# Fetch OAuth token | |||||
if [ ! -f "${OAUTH_TOKEN_PATH}" ]; then | |||||
echo "Error: OAuth token file '${OAUTH_TOKEN_PATH}' does not exist" | |||||
exit 12 | |||||
fi | |||||
OAUTH_TOKEN=$(cat "${OAUTH_TOKEN_PATH}") | |||||
if [ -z "${OAUTH_TOKEN}" ]; then | |||||
echo "Error: OAuth token is empty" | |||||
exit 13 | |||||
fi | |||||
# Fetch remote tags and make sure the tag exists | |||||
cd "${SCRIPT_PATH}" | |||||
GIT_REPO="https://${OAUTH_TOKEN}@github.com/bitcoin-abc/bitcoin-abc.git" | |||||
git fetch "${GIT_REPO}" tag "${TAG}" | |||||
if [ "$?" -ne 0 ]; then | |||||
FabienUnsubmitted Not Done Inline ActionsYou can make it simpler with: This is repeated several times in the script. Fabien: You can make it simpler with:
`if ! git fetch "${GIT_REPO}" tag "${TAG}"; then`
or:
`git fetch… | |||||
echo "Error: Remote does not have tag '${TAG}'." | |||||
exit 20 | |||||
fi | |||||
cd "${ORIGINAL_PWD}" | |||||
VERSION=$(echo "${TAG}" | cut -c 2-) | |||||
# Collect list of assets (binaries) to upload | |||||
if [ -z "${ASSET_DIR}" ]; then | |||||
echo "Error: Asset directory was not set. Try setting it with [ -a | --asset-dir ]" | |||||
exit 30 | |||||
fi | |||||
ASSET_LIST=() | |||||
if [ -d "${ASSET_DIR}" ]; then | |||||
LINUX_BINARIES="${ASSET_DIR}/linux/bitcoin-abc-${VERSION}-*" | |||||
for ASSET_FILE in ${LINUX_BINARIES}; do | |||||
if [[ ! ${ASSET_FILE} =~ debug ]]; then | |||||
if [ -f "${ASSET_FILE}" ]; then | |||||
ASSET_LIST+=("${ASSET_FILE}") | |||||
fi | |||||
fi | |||||
done | |||||
OSX_BINARY="${ASSET_DIR}/osx/bitcoin-abc-${VERSION}-osx-unsigned.dmg" | |||||
if [ -f "${OSX_BINARY}" ]; then | |||||
ASSET_LIST+=("${OSX_BINARY}") | |||||
fi | |||||
WIN_BINARIES="${ASSET_DIR}/win/bitcoin-abc-${VERSION}-*-setup-unsigned.exe" | |||||
for ASSET_FILE in ${WIN_BINARIES}; do | |||||
if [ -f "${ASSET_FILE}" ]; then | |||||
ASSET_LIST+=("${ASSET_FILE}") | |||||
fi | |||||
done | |||||
else | |||||
echo "Error: Asset directory '${ASSET_DIR}' does not exist" | |||||
exit 31 | |||||
fi | |||||
# Fetch release notes | |||||
RELEASE_NOTES=$(cat "${TOPLEVEL}/doc/release-notes/release-notes-${VERSION}.md" | jq -Rs '.') | |||||
Lint: ShellCheck found an issue: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead. Lint: ShellCheck found an issue:: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead. | |||||
if [ "${RELEASE_NOTES}" == '""' ]; then | |||||
echo "Error: Could not fetch release notes for version '${VERSION}'" | |||||
exit 40 | |||||
fi | |||||
# Format request data | |||||
POST_DATA="{\"tag_name\": \"${TAG}\", \"name\": \"${VERSION}\", \"body\": ${RELEASE_NOTES}, \"draft\": true}" | |||||
URL="https://api.github.com/repos/bitcoin-abc/bitcoin-abc/releases" | |||||
if [ "${DRY_RUN}" == "true" ]; then | |||||
echo "POST request data that would be sent to '${URL}':" | |||||
printf '%s\n' "${POST_DATA}" | |||||
echo | |||||
if [ ${#ASSET_LIST[@]} -gt 0 ]; then | |||||
echo "Would attempt to upload these files:" | |||||
for FILENAME in "${ASSET_LIST[@]}"; do | |||||
echo "${FILENAME}" | |||||
done | |||||
else | |||||
echo "Warning: Would attempt to upload no files" | |||||
fi | |||||
else | |||||
echo "Creating draft release..." | |||||
RESPONSE=$(curl -X POST -H "Content-Type: application/json" -H "Authorization: token ${OAUTH_TOKEN}" -d "${POST_DATA}" "${URL}") | |||||
CURL_EXIT_CODE=$? | |||||
echo "Curl response:" | |||||
echo "${RESPONSE}" | |||||
if [ "${CURL_EXIT_CODE}" -ne 0 ]; then | |||||
echo "On requesting '${URL}'" | |||||
echo "Curl exited with code: ${CURL_EXIT_CODE}" | |||||
exit 60 | |||||
fi | |||||
RELEASE_ID=$(echo "${RESPONSE}" | jq '.id') | |||||
JQ_EXIT_CODE=$? | |||||
if [ "${JQ_EXIT_CODE}" -ne 0 ]; then | |||||
echo "Error: jq failed with exit code: ${JQ_EXIT_CODE}" | |||||
exit 61 | |||||
fi | |||||
UPLOAD_URL="https://uploads.github.com/repos/bitcoin-abc/bitcoin-abc/releases/${RELEASE_ID}/assets" | |||||
echo "Uploading assets..." | |||||
ASSET_COUNTER=0 | |||||
if [ ${#ASSET_LIST[@]} -gt 0 ]; then | |||||
for FILEPATH in "${ASSET_LIST[@]}"; do | |||||
echo "Uploading '${FILEPATH}'..." | |||||
FILENAME=$(basename "${FILEPATH}") | |||||
UPLOAD_RESPONSE=$(curl -X POST -H "Content-Type:application/octet-stream" -H "Authorization: token ${OAUTH_TOKEN}" --data-binary "@${FILEPATH}" "${UPLOAD_URL}?name=${FILENAME}") | |||||
if [ "$?" == 0 ]; then | |||||
ASSET_COUNTER=$((ASSET_COUNTER + 1)) | |||||
else | |||||
echo "Upload of '${FILEPATH}' failed." | |||||
echo "Curl response:" | |||||
echo "${UPLOAD_RESPONSE}" | |||||
fi | |||||
done | |||||
fi | |||||
echo "Uploaded ${ASSET_COUNTER} assets." | |||||
fi | |||||
echo "Done." |
What about "$(dirname "$0")" ? The chance that the directory doesn't exist is null, and if cd fails for any reason you get the wrong path (you can use set -e for this).
The same applies in various places in the script.