aboutsummaryrefslogtreecommitdiffhomepage
path: root/bin/github/github-release.sh
blob: 70ba6723ca336ed2e77a80aed23a610a37d954d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env sh
#
# Author: Hsieh Chin Fan (typebrook) <typebrook@gmail.com>
# License: MIT
# https://gist.github.com/typebrook/4947769e266173303d8848f496e272c9
#
# Originally created by stefanbuck
# fork from: https://gist.github.com/stefanbuck/ce788fee19ab6eb0b4447a85fc99f447
#
# --
# This script manages a release note or its asset with GitHub API v3.
# It accepts the following parameters:
#
# * repo
# * tag
# * type (asset or edit)
# * filename
# * github_api_token
# * action (optional, could be upload, overwrite, rename, delete, default to be upload)
# * extra  (optional, new filename for action 'rename')
# * create (optional, create a new release if it doesn't exist)
#
# Example:
#
# # Upload a file as asset. If there is a asset with the same filename, then overwrite it.
# github-release.sh github_api_token=TOKEN repo=stefanbuck/playground tag=v0.1.0 type=asset filename=./build.zip overwrite=true
#
# # Edit a release note with file content
# github-release.sh github_api_token=TOKEN repo=stefanbuck/playground tag=v0.1.0 type=edit filename=note

# Check dependencies.
set -e

# Validate settings.
[ "$TRACE" ] && set -x
# Keep tty
exec 3>&1

CONFIG=$@

for line in $CONFIG; do
  eval "$line"
done

# Define variables.
GH_API="https://api.github.com"
GH_REPO="$GH_API/repos/$repo"
GH_TAGS="$GH_REPO/releases/tags/$tag"
AUTH="Authorization: token $github_api_token"

if [ "$tag" = 'LATEST' ]; then
  GH_TAGS="$GH_REPO/releases/latest"
fi
if [ "$type" = '' ]; then
  sed -E -n -e ' /^$/ q; /# --/,$ s/^# *//p' "$0"
  exit 0
fi

# Validate token.
curl -o /dev/null -sH "$AUTH" $GH_REPO || { echo "Error: Invalid repo, token or network issue!";  exit 1; }

# Read asset tags.
response=$(curl -sH "$AUTH" $GH_TAGS)

# Get ID of the release.
release_id=$(echo "$response" | grep -m1 -w \"id\": | sed -E -e 's/[^0-9]//g')
if [ -z "$release_id" ]; then
  if [ "$create" = 'true' ]; then
    body=$(cat <<EOF
{
  "tag_name": "$tag",
  "target_commitish": "master",
  "name": "$tag",
  "body": "",
  "draft": false,
  "prerelease": false
}
EOF
    )
    response=$(curl -H "$AUTH" -H "Content-Type: application/json" -d "$body" "$GH_REPO/releases")
    release_id=$(echo "$response" | grep -m1 -w \"id\": | sed -E -e 's/[^0-9]//g')
  else
    echo "Error: Failed to get release id for tag: $tag"; echo "$response" | awk 'length($0)<100' >&2
    exit 1
  fi
fi

post_asset() {
  # Upload asset
  echo "Uploading asset... " >&3
  # Construct url
  GH_ASSET="https://uploads.github.com/repos/$repo/releases/$release_id/assets?name=$1"

  curl --data-binary @"$filename" -H "$AUTH" -H "Content-Type: application/octet-stream" $GH_ASSET
}

rename_asset() {
  echo "Renaming asset($1) from $2 to $3" >&3
  curl -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
    --data "{\"name\":\"$3\", \"label\":\"$3\"}" "$GH_REPO/releases/assets/$1"
}

delete_asset() {
  echo "Deleting asset($1)... " >&3
  curl -X "DELETE" -H "$AUTH" "$GH_REPO/releases/assets/$1"
}

upload_asset() {
  # Get ID of the asset based on given filename.
  # If exists, delete it.
  eval $(echo "$response" | grep -C2 "\"name\": \"$(basename $filename)\"" | grep -m 1 "id.:" | grep -w id | tr : = | tr -cd '[[:alnum:]]=' | sed 's/id/asset_id/')
  if [ "$asset_id" = ""  ]; then
    echo "No need to overwrite asset"
    post_asset $(basename $filename)
  else
    if [ "$action" = "overwrite" ]; then
      new_asset_id=$(post_asset "bak_$(basename $filename)" | sed -E 's/^\{[^{]+"id":([0-9]+).+$/\1/')
      [ "$new_asset_id" = "" ] && exit 1 || delete_asset "$asset_id"

      rename_asset "$new_asset_id" "bak_$(basename $filename)" "$(basename $filename)"
    elif [ "$action" = "rename" ]; then
      rename_asset "$asset_id" "$filename" "$extra"
    elif [ "$action" = "delete" ]; then
      delete_asset "$asset_id"
      exit 0
    else
      echo "File already exists on tag $tag"
      echo "If you want to overwrite it, set action=overwrite"
      exit 1
    fi
  fi
}

edit_release() {
  GH_RELEASE="$GH_REPO/releases/$release_id"
  body=$(cat <<EOF
{
  "tag_name": "$tag",
  "target_commitish": "master",
  "name": "$tag",
  "body": "$(cat $filename | sed 's/"/\\"/g; $! s/$/\\n/' | tr -d '\n')",
  "draft": false,
  "prerelease": false
}
EOF
  )
  curl -X PATCH -H "$AUTH" -H "Content-Type: application/json" -d "$body" $GH_RELEASE
}

case $type in
  asset) upload_asset;;
  edit) edit_release;;
  *) echo "type should be 'asset' or 'edit'";;
esac