cloudfoundry-incubator/stratos

View on GitHub
build/tools/changelog.sh

Summary

Maintainability
Test Coverage
#!/bin/bash

# Colours
CYAN="\033[96m"
YELLOW="\033[93m"
RED="\033[91m"
RESET="\033[0m"
BOLD="\033[1m"

# Program Paths:
PROG=$(basename ${BASH_SOURCE[0]})
PROG_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
STRATOS_DIR="$( cd "${PROG_DIR}/../.." && pwd )"
CHANGELOG="${STRATOS_DIR}/CHANGELOG.md"

echo -e "${CYAN}${BOLD}===================================${RESET}"
echo -e "${CYAN}${BOLD}Generating Changelog from Milestone${RESET}"
echo -e "${CYAN}${BOLD}===================================${RESET}"

echo -e "${YELLOW}Stratos Directory: ${STRATOS_DIR}${RESET}"
echo ""

STATE="+state:closed"
while getopts ":a" opt; do
  case $opt in
    a)
    STATE=""
      ;;
  esac
done

shift $((OPTIND-1))

# Get the version number from the package.json file

# This is the base repository
REPO=${1:-cloudfoundry/stratos}
FORK=""

# Check if this is a fork
REPO_URL=$(git config --get remote.origin.url)
REGEX="(https:\/\/|git@)github.com[\/:]([a-z0-9A-Z]*)\/([a-z0-9A-Z\-]*)"
if [[ $REPO_URL =~ $REGEX ]]; then
  FORK=${BASH_REMATCH[2]}/${BASH_REMATCH[3]}
  if [ "$FORK" == "$REPO" ]; then
    FORK=""
  else
    echo -e "GitHub repository: ${CYAN}${BOLD}$FORK${RESET}"
  fi
fi

MILESTONE=$(cat "${STRATOS_DIR}/package.json" | jq -r .version)
echo -e "${YELLOW}Current version  : ${BOLD}${MILESTONE}${RESET}"

# Find the last release from the Changelog
CURRENT=$(cat "${STRATOS_DIR}/CHANGELOG.md" | grep -m1  '## [0-9]*.[0-9]*.[0-9]*')
CURRENT="${CURRENT:3}"
if [ "$CURRENT" == "$MILESTONE" ]; then
  CURRENT=$(cat "${STRATOS_DIR}/CHANGELOG.md" | grep -m2  '## [0-9]*.[0-9]*.[0-9]*' | tail -n1)
  CURRENT="${CURRENT:3}"

  # There is already a section for this release - so remove it
  echo "Removing old changelog for release ${MILESTONE}"
  sed -i.bak '/^# Change Log/,/^\## '"${CURRENT}"'/{//!d;};' ${CHANGELOG}
fi

echo -e "${YELLOW}Previous version : ${BOLD}$CURRENT${RESET}"

function search() {
  FILTER=$1
  if [ -n "${FORK_QUERY}" ]; then
    curl -s "https://api.github.com/search/issues?q=${FORK_QUERY}+-label:release-notes${FILTER}" | jq -r '.items | .[] | "- \(.title) [\\#\(.number)](\(.html_url))"' | tee -a ${CHANGELOG}
  fi
  curl -s "https://api.github.com/search/issues?q=${QUERY}+-label:release-notes${FILTER}" | jq -r '.items | .[] | "- \(.title) [\\#\(.number)](\(.html_url))"' | tee -a ${CHANGELOG}
}

function breaking_changes() {
  FILTER=$1
  if [ -n "${FORK_QUERY}" ]; then
    curl -s "https://api.github.com/search/issues?q=${FORK_QUERY}+-label:release-notes${FILTER}" | jq -r '.items | .[] | "- **\(.title)**\n\n  \(.body)"' > ${CHANGELOG}.breaking
  fi
  curl -s "https://api.github.com/search/issues?q=${QUERY}+-label:release-notes${FILTER}" | jq -r '.items | .[] | "- **\(.title)**\n\n  \(.body)"' > ${CHANGELOG}.breaking
}


function get_banner() {
  BANNER="label:release-notes"
  banner=""
  if [ -n "${FORK_QUERY}" ]; then
    banner=$(curl -s "https://api.github.com/search/issues?q=${BANNER}+${FORK_QUERY}" | jq -r '.items | .[] | .body')
  fi
  if [ -z "${banner}" ]; then
    banner=$(curl -s "https://api.github.com/search/issues?q=${BANNER}+${QUERY}" | jq -r '.items | .[] | .body')
  fi

  if [ -z "${banner}" ]; then
    banner="This release contains a number of fixes and improvements:"
  fi
}

function log() {
  echo "$1" | tee -a ${CHANGELOG}
}

COMPARE_REPO=${REPO}
QUERY="repo:${REPO}+milestone:${MILESTONE}${STATE}"
if [ -n "${FORK}" ]; then
  FORK_QUERY="repo:${FORK}+milestone:${MILESTONE}${STATE}"
  COMPARE_REPO=${FORK}
fi

BUGS="+label:bug"
NON_BUGS="+-label:bug+-label:breaking-change"
BREAKING_CHANGES="+label:breaking-change"

mv ${CHANGELOG} CHANGELOG.old

get_banner

echo ""
echo -e "${CYAN}${BOLD}Generating Change log - content for version ${MILESTONE} will be shown below"
echo -e "---------------------------------------------------------------------${RESET}"

echo  "# Change Log" > ${CHANGELOG}
log ""
log "## ${MILESTONE}"
log ""
log "[Full Changelog](https://github.com/${COMPARE_REPO}/compare/${CURRENT}...${MILESTONE})"
log ""
log "$banner"
log ""
log "**Improvements:**"
log ""
search $NON_BUGS

log ""

log "**Fixes:**"
log ""
search $BUGS

log ""

rm -f ${CHANGELOG}.breaking

breaking_changes $BREAKING_CHANGES

SIZE=$(wc -c ${CHANGELOG}.breaking | awk '{print $1}')
if [ "$SIZE" -ne 0 ]; then
  log "**Breaking Changes:**"
  log ""
  cat ${CHANGELOG}.breaking | tee -a ${CHANGELOG}
fi

rm -f ${CHANGELOG}.breaking

log ""

tail -n +2 CHANGELOG.old >> ${CHANGELOG}
rm CHANGELOG.old

sed -i.bak 's/\# Change Log.*\#\# ${CURRENT}//' ${CHANGELOG}