Commit 2fa5cd82 authored by Ivaria's avatar Ivaria

Merge release.sh from upstream

parent 857219f1
......@@ -56,6 +56,8 @@ game_type=
file_type=
file_name="{package-name}-{project-version}{nolib}{classic}"
wowi_markup="bbcode"
## END USER OPTIONS
if [[ ${BASH_VERSINFO[0]} -lt 4 ]] || [[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 3 ]]; then
......@@ -64,6 +66,7 @@ if [[ ${BASH_VERSINFO[0]} -lt 4 ]] || [[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VER
fi
# Game versions for uploading
declare -A game_flavors=( ["retail"]="mainline" ["classic"]="classic" ["bc"]="bcc" )
declare -A game_versions
toc_version=
......@@ -81,7 +84,8 @@ escape_substr() {
# File name templating
filename_filter() {
local classic alpha beta
local classic alpha beta invalid
[ -n "$skip_invalid" ] && invalid="&" || invalid="_"
if [[ "$game_type" != "retail" ]] && [[ "$game_type" != "classic" || "${si_project_version,,}" != *"-classic"* ]] && [[ "$game_type" != "bc" || "${si_project_version,,}" != *"-bc"* ]]; then
# only append the game type if the tag doesn't include it
classic="-$game_type"
......@@ -104,7 +108,7 @@ filename_filter() {
-e "s/{beta}/${beta}/g" \
-e "s/{nolib}/${nolib:+-nolib}/g" \
-e "s/{classic}/${classic}/g" \
-e "s/[^A-Za-z0-9._-]/_/g" \
-e "s/\([^A-Za-z0-9._-]\)/${invalid}/g" \
<<< "$1"
}
......@@ -129,7 +133,7 @@ toc_filter() {
# Process command-line options
usage() {
cat <<-'EOF' >&2
Usage: release.sh [-cdelLosuz] [-t topdir] [-r releasedir] [-p curse-id] [-w wowi-id] [-g game-version] [-m pkgmeta.yml] [-n filename]
Usage: release.sh [options]
-c Skip copying files into the package directory.
-d Skip uploading.
-e Skip checkout of external repositories.
......@@ -146,152 +150,119 @@ usage() {
-a wago-id Set the project id used on Wago Addons for uploading. (Use 0 to unset the TOC value)
-g game-version Set the game version to use for uploading.
-m pkgmeta.yaml Set the pkgmeta file to use.
-n archive-name Set the archive name template. Use "-n help" for more info.
-n package-name Set the package zip file name. Use "-n help" for more info.
EOF
}
OPTIND=1
while getopts ":celLzusop:dw:a:r:t:g:m:n:" opt; do
case $opt in
c)
# Skip copying files into the package directory.
skip_copying="true"
;;
e)
# Skip checkout of external repositories.
skip_externals="true"
;;
l)
# Skip @localization@ keyword replacement.
skip_localization="true"
;;
L)
# Skip uploading to CurseForge.
skip_cf_upload="true"
;;
d)
# Skip uploading.
skip_upload="true"
;;
o)
# Skip deleting any previous package directory.
overwrite="true"
;;
p)
slug="$OPTARG"
;;
w)
addonid="$OPTARG"
;;
a)
wagoid="$OPTARG"
;;
r)
# Set the release directory to a non-default value.
releasedir="$OPTARG"
;;
s)
# Create a nolib package.
nolib="true"
skip_externals="true"
;;
t)
# Set the top-level directory of the checkout to a non-default value.
if [ ! -d "$OPTARG" ]; then
echo "Invalid argument for option \"-t\" - Directory \"$OPTARG\" does not exist." >&2
usage
exit 1
fi
topdir="$OPTARG"
;;
u)
# Skip Unix-to-DOS line-ending translation.
line_ending="unix"
;;
z)
# Skip generating the zipfile.
skip_zipfile="true"
;;
g)
OPTARG="${OPTARG,,}"
# shortcut for classic
case "$OPTARG" in
retail|classic|bc)
game_type="$OPTARG"
# game_version from toc
;;
*)
# Set version (x.y.z)
# Build game version/type is set from the last version if a list
IFS=',' read -ra V <<< "$OPTARG"
for i in "${V[@]}"; do
if [[ ! "$i" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)[a-z]?$ ]]; then
echo "Invalid argument for option \"-g\" ($i)" >&2
usage
exit 1
fi
if [[ ${BASH_REMATCH[1]} == "1" && ${BASH_REMATCH[2]} == "13" ]]; then
game_type="classic"
elif [[ ${BASH_REMATCH[1]} == "2" && ${BASH_REMATCH[2]} == "5" ]]; then
game_type="bc"
else
game_type="retail"
fi
if [ -n "${game_versions[$game_type]}" ]; then
echo "Invalid argument for option \"-g\" ($i) - Only one version per game type is supported." >&2
usage
exit 1
fi
game_versions[$game_type]="$i"
done
game_version="$OPTARG"
esac
;;
m)
# Set the pkgmeta file.
if [ ! -f "$OPTARG" ]; then
echo "Invalid argument for option \"-m\" - File \"$OPTARG\" does not exist." >&2
usage
exit 1
fi
pkgmeta_file="$OPTARG"
;;
n)
if [ "$OPTARG" = "help" ]; then
cat <<-'EOF' >&2
Set the archive name template. There are several string substitutions you can use to
include version control or build type infomation in the file name.
c) skip_copying="true" ;; # Skip copying files into the package directory
z) skip_zipfile="true" ;; # Skip creating a zip file
e) skip_externals="true" ;; # Skip checkout of external repositories
l) skip_localization="true" ;; # Skip @localization@ keyword replacement
L) skip_cf_upload="true" ;; # Skip uploading to CurseForge
d) skip_upload="true" ;; # Skip uploading
u) line_ending="unix" ;; # Use LF instead of CRLF as the line ending for all text files
o) overwrite="true" ;; # Don't delete existing directories in the release directory
p) slug="$OPTARG" ;; # Set CurseForge project id
w) addonid="$OPTARG" ;; # Set WoWInterface addon id
a) wagoid="$OPTARG" ;; # Set Wago Addons project id
r) releasedir="$OPTARG" ;; # Set the release directory
t) # Set the top-level directory of the checkout
if [ ! -d "$OPTARG" ]; then
echo "Invalid argument for option \"-t\" - Directory \"$OPTARG\" does not exist." >&2
usage
exit 1
fi
topdir="$OPTARG"
;;
s) # Create a nolib package without externals
nolib="true"
skip_externals="true"
;;
g) # Set the game type or version
OPTARG="${OPTARG,,}"
case "$OPTARG" in
retail|classic|bc) game_type="$OPTARG" ;; # game_version from toc
mainline) game_type="retail" ;;
bcc) game_type="bc" ;;
*)
# Set game version (x.y.z)
# Build game type set from the last value if a list
IFS=',' read -ra V <<< "$OPTARG"
for i in "${V[@]}"; do
if [[ ! "$i" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)[a-z]?$ ]]; then
echo "Invalid argument for option \"-g\" ($i)" >&2
usage
exit 1
fi
if [[ ${BASH_REMATCH[1]} == "1" && ${BASH_REMATCH[2]} == "13" ]]; then
game_type="classic"
elif [[ ${BASH_REMATCH[1]} == "2" && ${BASH_REMATCH[2]} == "5" ]]; then
game_type="bc"
else
game_type="retail"
fi
# Only one version per game type is allowed
if [ -n "${game_versions[$game_type]}" ]; then
echo "Invalid argument for option \"-g\" ($i) - Only one version per game type is supported." >&2
usage
exit 1
fi
game_versions[$game_type]="$i"
done
game_version="$OPTARG"
esac
;;
m) # Set the pkgmeta file
if [ ! -f "$OPTARG" ]; then
echo "Invalid argument for option \"-m\" - File \"$OPTARG\" does not exist." >&2
usage
exit 1
fi
pkgmeta_file="$OPTARG"
;;
n) # Set the package file name
if [ "$OPTARG" = "help" ]; then
cat <<-'EOF' >&2
Set the package zip file name. There are several string substitutions you can
use to include version control and build type infomation in the file name.
The default file name is "{package-name}-{project-version}{nolib}{classic}".
The default file name is "{package-name}-{project-version}{nolib}{classic}".
Tokens: {package-name}{project-revision}{project-hash}{project-abbreviated-hash}
{project-author}{project-date-iso}{project-date-integer}{project-timestamp}
{project-version}{game-type}{release-type}
Tokens: {package-name}{project-revision}{project-hash}{project-abbreviated-hash}
{project-author}{project-date-iso}{project-date-integer}{project-timestamp}
{project-version}{game-type}{release-type}
Flags: {alpha}{beta}{nolib}{classic}
Flags: {alpha}{beta}{nolib}{classic}
Tokens are always replaced with their value. Flags are shown prefixed with a dash
depending on the build type.
EOF
exit 0
fi
# TODO some sort of validation?
file_name="$OPTARG"
;;
:)
echo "Option \"-$OPTARG\" requires an argument." >&2
usage
exit 1
;;
\?)
if [ "$OPTARG" = "?" ] || [ "$OPTARG" = "h" ]; then
Tokens are always replaced with their value. Flags are shown prefixed with a dash
depending on the build type.
EOF
exit 0
fi
file_name="$OPTARG"
if skip_invalid=true filename_filter "$file_name" | grep -q '[{}]'; then
tokens=$( skip_invalid=true filename_filter "$file_name" | sed -e '/^[^{]*{\|}[^{]*{\|}[^{]*/s//}{/g' -e 's/^}\({.*}\){$/\1/' )
echo "Invalid argument for option \"-n\" - Invalid substitutions: $tokens" >&2
exit 1
fi
;;
:)
echo "Option \"-$OPTARG\" requires an argument." >&2
usage
exit 0
fi
echo "Unknown option \"-$OPTARG\"" >&2
usage
exit 1
;;
exit 1
;;
\?)
if [ "$OPTARG" = "?" ] || [ "$OPTARG" = "h" ]; then
usage
exit 0
fi
echo "Unknown option \"-$OPTARG\"" >&2
usage
exit 1
;;
esac
done
shift $((OPTIND - 1))
......@@ -960,37 +931,40 @@ elif [ "$repository_type" = "hg" ]; then
fi
fi
# TOC file processing.
tocfile=$(
cd "$topdir" || exit
filename=$( ls ./*.toc -1 2>/dev/null | head -n1 )
if [[ -z "$filename" && -n "$package" ]]; then
# Handle having the core addon in a sub dir, which people have starting doing
# for some reason. Tons of caveats, just make the base dir your base addon people!
filename=$( ls "$package"/*.toc -1 2>/dev/null | head -n1 )
###
### Process TOC file
###
# Set the package name from a TOC file name
if [[ -z "$package" ]]; then
package=$( cd "$topdir" && find *.toc -maxdepth 0 2>/dev/null | head -n1 )
if [[ -z "$package" ]]; then
echo "Could not find an addon TOC file. In another directory? Set 'package-as' in .pkgmeta" >&2
exit 1
fi
package=${package%.toc}
if [[ $package =~ ^(.*)-(Mainline|Classic|BCC)$ ]]; then
package="${BASH_REMATCH[1]}"
fi
echo "$filename"
)
if [[ -z "$tocfile" || ! -f "$topdir/$tocfile" ]]; then
echo "Could not find an addon TOC file. In another directory? Make sure it matches the 'package-as' in .pkgmeta" >&2
exit 1
fi
# Set the package name from the TOC filename.
toc_name=$( basename "$tocfile" | sed 's/\.toc$//' )
if [[ -n "$package" && "$package" != "$toc_name" ]]; then
echo "Addon package name does not match TOC file name." >&2
exit 1
toc_path="$package.toc"
# Handle having the main addon in a sub dir
if [[ ! -f "$topdir/$toc_path" && -f "$topdir/$package/$toc_path" ]]; then
toc_path="$package/$toc_path"
fi
if [ -z "$package" ]; then
package="$toc_name"
if [[ ! -f "$topdir/$toc_path" ]]; then
echo "Could not find an addon TOC file. In another directory? Make sure it matches the 'package-as' in .pkgmeta" >&2
exit 1
fi
# Get the interface version for setting the upload version.
toc_file=$(
# remove bom and cr and apply some non-version toc filters
[ "$file_type" != "alpha" ] && _tf_alpha="true"
sed -e $'1s/^\xEF\xBB\xBF//' -e $'s/\r//g' "$topdir/$tocfile" | toc_filter alpha ${_tf_alpha} | toc_filter debug true
sed -e $'1s/^\xEF\xBB\xBF//' -e $'s/\r//g' "$topdir/$toc_path" | toc_filter alpha ${_tf_alpha} | toc_filter debug true
)
root_toc_version=$( awk '/^## Interface:/ { print $NF; exit }' <<< "$toc_file" )
toc_version="$root_toc_version"
......@@ -1934,6 +1908,10 @@ else
changelog="CHANGELOG.md"
changelog_markup="markdown"
if [ -n "$wowi_gen_changelog" ] && [ -z "$wowi_convert_changelog" ]; then
wowi_markup="markdown"
fi
start_group "Generating changelog of commits into $changelog" "changelog"
_changelog_range=
......@@ -2005,7 +1983,7 @@ else
# WoWI uses BBCode, generate something usable to post to the site
# the file is deleted on successful upload
if [ -n "$addonid" ] && [ -n "$tag" ] && [ -n "$wowi_gen_changelog" ]; then
if [ -n "$addonid" ] && [ -n "$tag" ] && [ -n "$wowi_gen_changelog" ] && [ "$wowi_markup" = "bbcode" ]; then
wowi_changelog="$releasedir/WOWI-$project_version-CHANGELOG.txt"
cat <<- EOF | line_ending_filter > "$wowi_changelog"
[size=5]${project}[/size]
......@@ -2047,7 +2025,7 @@ else
# WoWI uses BBCode, generate something usable to post to the site
# the file is deleted on successful upload
if [ -n "$addonid" ] && [ -n "$tag" ] && [ -n "$wowi_gen_changelog" ]; then
if [ -n "$addonid" ] && [ -n "$tag" ] && [ -n "$wowi_gen_changelog" ] && [ "$wowi_markup" = "bbcode" ]; then
wowi_changelog="$releasedir/WOWI-$project_version-CHANGELOG.txt"
cat <<- EOF | line_ending_filter > "$wowi_changelog"
[size=5]${project}[/size]
......@@ -2083,7 +2061,7 @@ else
# WoWI uses BBCode, generate something usable to post to the site
# the file is deleted on successful upload
if [ -n "$addonid" ] && [ -n "$tag" ] && [ -n "$wowi_gen_changelog" ]; then
if [ -n "$addonid" ] && [ -n "$tag" ] && [ -n "$wowi_gen_changelog" ] && [ "$wowi_markup" = "bbcode" ]; then
wowi_changelog="$releasedir/WOWI-$project_version-CHANGELOG.txt"
cat <<- EOF | line_ending_filter > "$wowi_changelog"
[size=5]${project}[/size]
......@@ -2321,8 +2299,8 @@ if [ -z "$skip_zipfile" ]; then
-H "x-api-token: $cf_token" \
-F "metadata=<-" \
-F "file=@$archive" \
"$project_site/api/projects/$slug/upload-file" ) &&
{
"$project_site/api/projects/$slug/upload-file"
) && {
case $result in
200) echo "Success!" ;;
302)
......@@ -2388,7 +2366,7 @@ if [ -z "$skip_zipfile" ]; then
_wowi_args=()
if [ -f "$wowi_changelog" ]; then
_wowi_args+=("-F changelog=<$wowi_changelog")
elif [ -n "$manual_changelog" ]; then
elif [ -n "$manual_changelog" ] || [ "$wowi_markup" = "markdown" ]; then
_wowi_args+=("-F changelog=<$pkgdir/$changelog")
fi
if [ -z "$wowi_archive" ]; then
......@@ -2398,19 +2376,21 @@ if [ -z "$skip_zipfile" ]; then
echo "Uploading $archive_name ($_wowi_game_version) to https://www.wowinterface.com/downloads/info$addonid"
resultfile="$releasedir/wi_result.json"
result=$( curl -sS --retry 3 --retry-delay 10 \
-w "%{http_code}" -o "$resultfile" \
-H "x-api-token: $wowi_token" \
-F "id=$addonid" \
-F "version=$archive_version" \
-F "compatible=$_wowi_game_version" \
"${_wowi_args[@]}" \
-F "updatefile=@$archive" \
"https://api.wowinterface.com/addons/update" ) &&
{
-w "%{http_code}" -o "$resultfile" \
-H "x-api-token: $wowi_token" \
-F "id=$addonid" \
-F "version=$archive_version" \
-F "compatible=$_wowi_game_version" \
"${_wowi_args[@]}" \
-F "updatefile=@$archive" \
"https://api.wowinterface.com/addons/update"
) && {
case $result in
202)
echo "Success!"
rm -f "$wowi_changelog" 2>/dev/null
if [ -f "$wowi_changelog" ]; then
rm -f "$wowi_changelog" 2>/dev/null
fi
;;
401)
echo "Error! No addon for id \"$addonid\" found or you do not have permission to upload files."
......@@ -2466,8 +2446,8 @@ if [ -z "$skip_zipfile" ]; then
-H "accept: application/json" \
-F "metadata=<-" \
-F "file=@$archive" \
"https://addons.wago.io/api/projects/$wagoid/version" ) &&
{
"https://addons.wago.io/api/projects/$wagoid/version"
) && {
case $result in
200|201) echo "Success!" ;;
302)
......@@ -2502,21 +2482,32 @@ if [ -z "$skip_zipfile" ]; then
_ghf_file_name=$2
_ghf_file_path=$3
_ghf_resultfile="$releasedir/gh_asset_result.json"
_ghf_content_type="application/${_ghf_file_name##*.}" # zip or json
# check if an asset exists and delete it (editing a release)
asset_id=$( curl -sS -H "Authorization: token $github_token" "https://api.github.com/repos/$project_github_slug/releases/$_ghf_release_id/assets" | jq --arg file "$_ghf_file_name" '.[] | select(.name? == $file) | .id' )
asset_id=$( curl -sS \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $github_token" \
"https://api.github.com/repos/$project_github_slug/releases/$_ghf_release_id/assets" \
| jq --arg file "$_ghf_file_name" '.[] | select(.name? == $file) | .id'
)
if [ -n "$asset_id" ]; then
curl -s -H "Authorization: token $github_token" -X DELETE "https://api.github.com/repos/$project_github_slug/releases/assets/$asset_id" &>/dev/null
curl -s \
-X DELETE \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $github_token" \
"https://api.github.com/repos/$project_github_slug/releases/assets/$asset_id" &>/dev/null
fi
echo -n "Uploading $_ghf_file_name... "
result=$( curl -sS --retry 3 --retry-delay 10 \
-w "%{http_code}" -o "$_ghf_resultfile" \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $github_token" \
-H "Content-Type: application/zip" \
-H "Content-Type: $_ghf_content_type" \
--data-binary "@$_ghf_file_path" \
"https://uploads.github.com/repos/$project_github_slug/releases/$_ghf_release_id/assets?name=$_ghf_file_name" ) &&
{
"https://uploads.github.com/repos/$project_github_slug/releases/$_ghf_release_id/assets?name=$_ghf_file_name"
) && {
if [ "$result" = "201" ]; then
echo "Success!"
else
......@@ -2534,32 +2525,73 @@ if [ -z "$skip_zipfile" ]; then
return 0
}
_gh_metadata='{ "filename": "'"$archive_name"'", "nolib": false, "metadata": ['
for type in "${!game_versions[@]}"; do
_gh_metadata+='{ "flavor": "'"${game_flavors[$type]}"'", "interface": '"$toc_version"' },'
done
_gh_metadata=${_gh_metadata%,}
_gh_metadata+='] }'
if [ -f "$nolib_archive" ]; then
_gh_metadata+=',{ "filename": "'"$nolib_archive_name"'", "nolib": true, "metadata": ['
for type in "${!game_versions[@]}"; do
_gh_metadata+='{ "flavor": "'"${game_flavors[$type]}"'", "interface": '"$toc_version"' },'
done
_gh_metadata=${_gh_metadata%,}
_gh_metadata+='] }'
fi
_gh_metadata='{ "releases": ['"$_gh_metadata"'] }'
_gh_payload=$( cat <<-EOF
{
"tag_name": "$tag",
"name": "$tag",
"body": $( jq --slurp --raw-input '.' < "$pkgdir/$changelog" ),
"draft": false,
"prerelease": $( [[ "${tag,,}" == *"beta"* || "${tag,,}" == *"alpha"* ]] && echo true || echo false )
"prerelease": $( [[ "$file_type" != "release" ]] && echo true || echo false )
}
EOF
)
resultfile="$releasedir/gh_result.json"
release_id=$( curl -sS -H "Authorization: token $github_token" "https://api.github.com/repos/$project_github_slug/releases/tags/$tag" | jq '.id // empty' )
release_id=$( curl -sS \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $github_token" \
"https://api.github.com/repos/$project_github_slug/releases/tags/$tag" \
| jq '.id // empty'
)
if [ -n "$release_id" ]; then
echo "Updating GitHub release: https://github.com/$project_github_slug/releases/tag/$tag"
_gh_release_url="-X PATCH https://api.github.com/repos/$project_github_slug/releases/$release_id"
# combine version info
_gh_metadata_url=$( curl -sS \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $github_token" \
"https://api.github.com/repos/$project_github_slug/releases/$release_id/assets" \
| jq -r '.[] | select(.name? == "release.json") | .url // empty'
)
if [ -n "$_gh_metadata_url" ]; then
_gh_previous_metadata=$( curl -sSL --fail \
-H "Accept: application/octet-stream" \
-H "Authorization: token $github_token" \
"$_gh_metadata_url"
) && {
_gh_metadata=$( jq -s '.[0].releases + .[1].releases | unique_by(.filename) | { releases: [.[]] }' <<< "${_gh_previous_metadata} ${_gh_metadata}" )
} || {
echo "Warning: Unable to update release.json ($?)"
}
fi
else
echo "Creating GitHub release: https://github.com/$project_github_slug/releases/tag/$tag"
_gh_release_url="https://api.github.com/repos/$project_github_slug/releases"
fi
result=$( echo "$_gh_payload" | curl -sS --retry 3 --retry-delay 10 \
-w "%{http_code}" -o "$resultfile" \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $github_token" \
-d @- \
$_gh_release_url ) &&
{
$_gh_release_url
) && {
if [ "$result" = "200" ] || [ "$result" = "201" ]; then # edited || created
if [ -z "$release_id" ]; then
release_id=$( jq '.id' < "$resultfile" )
......@@ -2568,6 +2600,7 @@ if [ -z "$skip_zipfile" ]; then
if [ -f "$nolib_archive" ]; then
upload_github_asset "$release_id" "$nolib_archive_name" "$nolib_archive"
fi
jq -c <<< "$_gh_metadata" > "$releasedir/release.json" && upload_github_asset "$release_id" "release.json" "$releasedir/release.json"
else
echo "Error! ($result)"
if [ -s "$resultfile" ]; then
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment