From 3c793f158c6e81e7cce2f3669db4eeb269cb7de2 Mon Sep 17 00:00:00 2001 From: Max Weiss Date: Fri, 14 May 2021 13:52:22 -0700 Subject: [PATCH] Initial commit --- gitea_release.sh | 272 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100755 gitea_release.sh diff --git a/gitea_release.sh b/gitea_release.sh new file mode 100755 index 0000000..d4a0a55 --- /dev/null +++ b/gitea_release.sh @@ -0,0 +1,272 @@ +#!/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) || "$@" +