#!/usr/bin/env bash # This script can be sourced as a library, or run with the function name as # the first argument and function arguments as its subsequent arguments. It # must be run with Bash specifically, not any other shell program. # I don't know for sure that tagging is necessary for the release, so I # have this function to allow us to decide whether or not to fail # if pushing the tag fails. function gitea_tag_push_fail() { return 0 } function gitea_tag() { # Examples: # git_repo_dir=/path/to/git; remote=origin; branch=master local git_repo_dir="$1" local remote="$2" local branch="$3" # Optional local commit="$4" local username="$5" local useremail="$6" local tagmsg="$7" if [ ! -d "$git_repo_dir" ]; then >&2 echo "Supplied directory does not exist." return 1 fi curr="$(pwd)" cd "$git_repo_dir" if [[ -z "$remote" ]]; then cd "$curr" >&2 echo "No remote specified." return 1 fi if [[ -z "$branch" ]]; then cd "$curr" >&2 echo "No branch specified." return 1 fi if [[ -z "$commit" ]]; then git rev-parse HEAD 2>&1 >/dev/null || (cd "$curr" && return 1) commit=$(git rev-parse HEAD) fi if [[ -z "$username" ]]; then username="BuildBot" fi if [[ -z "$useremail" ]]; then useremail="buildbot@bitmessage.io" fi if [[ -z "$tagmsg" ]]; then tagmsg="BuildBot: tag commit for release ${commit}" fi git config user.name "$username" git config user.email "$useremail" git tag -n | grep "${commit}" if [ $? -eq 0 ]; then cd "$curr" >&2 echo 'Tag for commit already exists, bailing out...' return 1 fi # Gitea doesn't appear to have a way to create tags via the HTTP API, which # is why we're doing things this way. However, it also appears that creating # a release also creates the tag if not present, which is why I optionally # allow a tag push to fail, because this whole process might not even be # necessary. git tag -a "g_${commit}" "${commit}" -m "${tagmsg}" || (cd "$curr" && return 2) git push --tags "${remote}" "${branch}" || (cd "$curr" && gitea_tag_push_fail) z="$?" cd "$curr" return $z } function gitea_create_release() { local git_repo_dir="$1" local repo_user="$2" local repo_name="$3" local api_token_file="$4" # Optional local commit="$5" local releasemsg="$6" local gitea_base_url="$7" if [ ! -d "$git_repo_dir" ]; then >&2 echo "Supplied directory does not exist." return 1 fi if [[ -z "$repo_user" ]]; then >&2 echo "No repo username specified." return 1 fi if [[ -z "$repo_name" ]]; then >&2 echo "No repo name specified." return 1 fi if [[ ! -f "$api_token_file" ]]; then >&2 echo "API token file does not exist." return 1 fi if [[ ! -f "$gitea_base_url" ]]; then gitea_base_url="git.bitmessage.org" fi curr="$(pwd)" cd "$git_repo_dir" if [[ -z "$commit" ]]; then git rev-parse HEAD 2>&1 >/dev/null || (cd "$curr" && return 1) commit=$(git rev-parse HEAD) fi if [[ -z "$releasemsg" ]]; then releasemsg="BuildBot automated release for commit ${commit}" fi # Note that the tag_name below must match the tag name in the gitea_tag step tee "release.json" > /dev/null < release_results.txt # We look for HTTP response code 201, which is only returned on success. # This is why the cURL command above is run with -i cat release_results.txt | grep ^HTTP/ | grep 201 >/dev/null if [ $? -ne 0 ]; then >&2 echo "There was an error creating the release. Manual intervention is needed." cd "$curr" return 2 fi # As a secondary check, we ensure that the release was assigned an ID tail -n 1 release_results.txt | jq .id | grep -P '^(\d)+$' >/dev/null if [ $? -ne 0 ]; then >&2 echo "There was an error creating the release. Manual intervention is needed." cd "$curr" return 2 fi cd "$curr" return 0 } function upload_release_artifact() { local git_repo_dir="$1" local repo_user="$2" local repo_name="$3" local api_token_file="$4" local artifact_file="$5" # Optional local commit="$6" local gitea_base_url="$7" local releaseidnum="$8" if [ ! -d "$git_repo_dir" ]; then >&2 echo "Supplied directory does not exist." return 1 fi if [[ -z "$repo_user" ]]; then >&2 echo "No repo username specified." return 1 fi if [[ -z "$repo_name" ]]; then >&2 echo "No repo name specified." return 1 fi if [[ ! -f "$api_token_file" ]]; then >&2 echo "API token file does not exist." return 1 fi if [[ ! -f "$artifact_file" ]]; then >&2 echo "Release artifact file does not exist." return 1 fi if [[ ! -f "$gitea_base_url" ]]; then gitea_base_url="git.bitmessage.org" fi artifact_file_name="$(basename $artifact_file)" curr="$(pwd)" cd "$git_repo_dir" if [[ -z "$commit" ]]; then git rev-parse HEAD 2>&1 >/dev/null || (cd "$curr" && return 1) commit=$(git rev-parse HEAD) fi # If a release ID number was not input, then check for the release_results.txt # file created in the previous function, and use the ID from that. if [[ -z "$releaseidnum" ]]; then cat release_results.txt | grep ^HTTP/ | grep 201 >/dev/null if [ $? -ne 0 ]; then >&2 echo "No release ID was provided, and release info from the release creation function is unavailable." cd "$curr" return 2 fi tail -n 1 release_results.txt | jq .id | grep -P '^(\d)+$' >/dev/null if [ $? -ne 0 ]; then >&2 echo "No release ID was provided, and release info from the release creation function is unavailable." cd "$curr" return 2 fi releaseid="$(tail -n 1 release_results.txt | jq .id)" else releaseid="${releaseidnum}" fi curl -X POST "https://${gitea_base_url}/api/v1/repos/${repo_user}/${repo_name}/releases/${releaseid}/assets?name=${artifact_file_name}" \ -H "accept: application/json" \ -H "Authorization: token $(cat $api_token_file)" \ -i \ -F "attachment=@${artifact_file}" > release_artifact.txt cat release_artifact.txt | grep ^HTTP/ | grep 201 >/dev/null if [ $? -ne 0 ]; then >&2 echo "The upload of the release attachment ${artifact_file_name} failed." rm -f release_artifact.txt cd "$curr" return 2 fi tail -n 1 release_artifact.txt | jq .id | grep -P '^(\d)+$' >/dev/null if [ $? -ne 0 ]; then >&2 echo "The upload of the release attachment ${artifact_file_name} failed." rm -f release_artifact.txt cd "$curr" return 2 fi rm -f release_artifact.txt cd "$curr" return 0 } if [[ ! "$(ps -o cmd -p $$ | tail -n 1 | tr -d '\n')" =~ "bash" ]]; then >&2 echo "Shell not bash, exiting." exit 1 fi # This is a bash-specific hack to determine if the file is being sourced or # run as a script. It will only work in bash, not other shells. (return 0 2>/dev/null) || "$@"