diff --git a/tools/includes/send_tracks_event.sh b/tools/includes/send_tracks_event.sh new file mode 100644 index 0000000000000..b63064644ab45 --- /dev/null +++ b/tools/includes/send_tracks_event.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# Sends a tracks event. +# - 1: Event name +# - 2: An optional JSON-formatted payload of extra tracks params, e.g. `{"a":1, "b":2}` +function send_tracks_event { + # Bail if no event name is provided. + if [[ -z "$1" ]]; then + return + fi + + local TRACKS_URL TRACKS_RESPONSE USER_AGENT PAYLOAD + TRACKS_URL='https://public-api.wordpress.com/rest/v1.1/tracks/record?http_envelope=1' + USER_AGENT='jetpack-monorepo-cli' + PAYLOAD=$(jq -nr --arg email "$(git config --get user.email)" '.commonProps._ul = $email') + + # Add event name to payload. + PAYLOAD=$(jq -r --arg eventName "$1" '.events = [{_en: $eventName}]' <<< "$PAYLOAD") + + # Add extra params to payload if provided. + if [[ -n "$2" ]]; then + PAYLOAD=$(jq --argjson extraParams "$2" '.events[0] += $extraParams' <<< "$PAYLOAD") + fi + + # True on fail to bypass pipefail. + TRACKS_RESPONSE=$(curl --fail -sS "$TRACKS_URL" \ + -H "User-Agent: $USER_AGENT" \ + -H 'Accept-Encoding: gzip, deflate' \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + --data "$PAYLOAD" \ + --compressed 2>&1 || true) + + if ! jq -e . <<< "$TRACKS_RESPONSE" &> /dev/null; then + # Likely a cURL error response. + echo "Invalid response: $TRACKS_RESPONSE" + elif ! jq -e '.code == 202' <<< "$TRACKS_RESPONSE" &> /dev/null; then + # Likely a Tracks error response. + echo "Failed Tracks call: $TRACKS_RESPONSE" + fi +} diff --git a/tools/includes/version-compare.sh b/tools/includes/version-compare.sh index 2bb5dc7218cab..10bfdd10c5b0c 100644 --- a/tools/includes/version-compare.sh +++ b/tools/includes/version-compare.sh @@ -88,3 +88,89 @@ function version_compare { [[ ${#A[@]} -gt ${#B[@]} ]] fi } + +# Compute the difference between two version numbers, semver style. +# +# Note this is a bit looser than `pnpm semver`, as it accepts 4-part versions. +# +# @param $1 First version. +# @param $2 Second version. +# Outputs: equal, suffix, patch, minor, or major. +function version_diff { + # Variable for the version_difference call + local INCREMENT + + # Returning 0 if neither $1 > $2, nor $2 > $1 + if ! version_compare "$1" "$2" 1 && ! version_compare "$2" "$1" 1; then + echo "equal" + return + fi + + if version_compare "$1" "$2"; then + + # $1 is greater than $2 + version_get_increment "$2" "$1" + else + + # $2 is greater than $1 + version_get_increment "$1" "$2" + fi + + case "$INCREMENT" in + "1") + echo "prerelease" + ;; + "2") + echo "patch" + ;; + "3") + echo "minor" + ;; + "4") + echo "major" + ;; + esac +} + +# Compute the increment needed to get from $1 to $2, semver style. +# +# Note this is a bit looser than `pnpm semver`, as it accepts 4-part versions. +# +# @param $1 First version. +# @param $2 Second version. +function version_get_increment { + + local V1="${1%%+*}" V2="${2%%+*}" + + local A=() B=() i DIFF + + # First, compare the version parts. + IFS='.' read -r -a A <<<"${V1%%-*}" + IFS='.' read -r -a B <<<"${V2%%-*}" + + while [[ ${#A[@]} -lt ${#B[@]} ]]; do + A+=( 0 ) + done + while [[ ${#B[@]} -lt ${#A[@]} ]]; do + B+=( 0 ) + done + + i=0 + + # If AA is ahead of BB, we have found our difference. + while [[ $i -lt ${#A[@]} && $i -lt ${#B[@]} ]]; do + local AA=${A[$i]} + local BB=${B[$i]} + + if [[ $AA -lt $BB ]]; then + let DIFF="4 - $i" + + INCREMENT=$DIFF + return + fi + i=$((i + 1)) + done + + # Version parts were equal, this means that the difference is the suffix. + INCREMENT=1 +} diff --git a/tools/release-plugin.sh b/tools/release-plugin.sh index fd40355eb2cd7..f801fff87e1a3 100755 --- a/tools/release-plugin.sh +++ b/tools/release-plugin.sh @@ -10,7 +10,7 @@ BASE=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) . "$BASE/tools/includes/version-compare.sh" . "$BASE/tools/includes/normalize-version.sh" . "$BASE/tools/includes/changelogger.sh" - +. "$BASE/tools/includes/send_tracks_event.sh" # Instructions function usage { @@ -143,6 +143,50 @@ done proceed_p "" "Proceed releasing above projects?" Y +# Sending tracking event +TRACKING_DATA="{}" +RELEASED_PLUGINS="{}" +for PLUGIN in "${!PROJECTS[@]}"; do + + CUR_VERSION=$("$BASE/tools/plugin-version.sh" "$PLUGIN") + VERSION_DIFF=$( version_diff "$CUR_VERSION" "${PROJECTS[$PLUGIN]}" ) + + if [[ "${PROJECTS[$PLUGIN]}" == *-* ]]; then + + # The version is a prerelease. + if proceed_p "" "Is this $PLUGIN release fixing a known problem caused by a previous release?" N; then + VERSION_DIFF="bugfix" + fi + + elif [[ "${PROJECTS[$PLUGIN]}" =~ ^[0-9]+\.[0-9]+\.[0.]*[1-9] ]]; then + + # The version in patch-level. + VERSION_DIFF="bugfix" + + # If a project follows semver versioning, we prompt. + if jq -e '.extra.changelogger["versioning"] == "semver"' "$BASE/projects/$PLUGIN/composer.json" &>/dev/null; then + if ! proceed_p "" "Is this $PLUGIN release fixing a known problem caused by a previous release?" N; then + VERSION_DIFF="patch" + fi + fi + fi + + RELEASED_PLUGINS=$( + jq \ + --arg property "$( echo "$PLUGIN" | sed 's/\//_/' )_release_type" \ + --arg value "$VERSION_DIFF" \ + '.[ $property ] = $value' <<< "$RELEASED_PLUGINS" + ) + RELEASED_PLUGINS=$( + jq \ + --arg property "$( echo "$PLUGIN" | sed 's/\//_/' )_version" \ + --arg value "${PROJECTS[$PLUGIN]}" \ + '.[ $property ] = $value' <<< "$RELEASED_PLUGINS" + ) +done + +send_tracks_event "jetpack_release_start" "$RELEASED_PLUGINS" + # Figure out which release branch prefixes to use. PREFIXDATA=$(jq -n 'reduce inputs as $in ({}; .[ $in.extra["release-branch-prefix"] | if . == null then empty elif type == "array" then .[] else . end ] += [ input_filename | capture( "projects/plugins/(?

[^/]+)/composer\\.json$" ).p ] ) | to_entries | sort_by( ( .value | -length ), .key ) | from_entries' "$BASE"/projects/plugins/*/composer.json) TMP=$(jq -rn --argjson d "$PREFIXDATA" '$d | reduce to_entries[] as $p ({ s: ( $ARGS.positional | map( sub( "^plugins/"; "" ) ) ), o: []}; if $p.value - .s == [] then .o += [ $p.key ] | .s -= $p.value else . end) | .o[]' --args "${!PROJECTS[@]}") @@ -173,9 +217,11 @@ fi git checkout -b prerelease if ! git push -u origin HEAD; then + send_tracks_event "jetpack_release_prerelease_push" '{"result": "failure"}' die "Branch push failed. Check #jetpack-releases and make sure no one is doing a release already, then delete the branch at https://github.com/Automattic/jetpack/branches" fi GITBASE=$( git rev-parse --verify HEAD ) +send_tracks_event "jetpack_release_prerelease_push" '{"result": "success"}' # Loop through the projects and update the changelogs after building the arguments. for PLUGIN in "${!PROJECTS[@]}"; do @@ -246,14 +292,17 @@ while [[ $SECONDS -lt $TIMEOUT && -z "$BUILDID" ]]; do done if [[ -z "$BUILDID" ]]; then + send_tracks_event "jetpack_release_github_build" '{"result": "not_found"}' die "Build ID not found. Check GitHub actions to see if build on prerelease branch is running, then continue with manual steps." fi yellow "Build ID found, waiting for build to complete and push to mirror repos." if ! gh run watch "${BUILDID[0]}" --exit-status; then + send_tracks_event "jetpack_release_github_build" '{"result": "failure"}' echo "Build failed! Check for build errors on GitHub for more information." && die fi +send_tracks_event "jetpack_release_github_build" '{"result": "success"}' yellow "Build is complete." # Wait for new versions of any composer packages to be up. @@ -409,3 +458,5 @@ if [[ ${#MANUALBOTH[@]} -gt 0 ]]; then the stable tag with \`./tools/stable-tag.sh \` and you're all set. EOM fi + +send_tracks_event "jetpack_release_done"