#!/usr/bin/env bash # # Requires: Git, NPM and RubyGems set -eu opt_pre=false # option for bump gem version opt_pkg=false # option for building gem package MAIN_BRANCH="master" RELEASE_BRANCH="production" GEM_SPEC="jekyll-theme-chirpy.gemspec" NODE_SPEC="package.json" CHANGELOG="docs/CHANGELOG.md" CONFIG="_config.yml" CSS_DIST="_sass/dist" JS_DIST="assets/js/dist" FILES=( "$GEM_SPEC" "$NODE_SPEC" "$CHANGELOG" "$CONFIG" ) TOOLS=( "git" "npm" "gem" ) help() { echo -e "A tool to release new version Chirpy gem.\nThis tool will:" echo " 1. Build a new gem and publish it to RubyGems.org" echo " 2. Merge the release branch into the default branch" echo echo "Usage:" echo " bash $0 [options]" echo echo "Options:" echo " --prepare Preparation for release" echo " -p, --package Build a gem package only, for local packaging in case of auto-publishing failure" echo " -h, --help Display this help message" } _check_cli() { for i in "${!TOOLS[@]}"; do cli="${TOOLS[$i]}" if ! command -v "$cli" &>/dev/null; then echo "> Command '$cli' not found!" exit 1 fi done } _check_git() { $opt_pre || ( # ensure that changes have been committed if [[ -n $(git status . -s) ]]; then echo "> Abort: Commit the staged files first, and then run this tool again." exit 1 fi ) $opt_pkg || ( if [[ "$(git branch --show-current)" != "$RELEASE_BRANCH" ]]; then echo "> Abort: Please run the tool in the '$RELEASE_BRANCH' branch." exit 1 fi ) } _check_src() { for i in "${!FILES[@]}"; do _src="${FILES[$i]}" if [[ ! -f $_src && ! -d $_src ]]; then echo -e "> Error: Missing file \"$_src\"!\n" exit 1 fi done } init() { _check_cli _check_git _check_src echo -e "> npm install\n" npm i } ## Bump new version to gem-spec file _bump_version() { _version="$(grep '"version":' "$NODE_SPEC" | sed 's/.*: "//;s/".*//')" sed -i "s/[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/$_version/" "$GEM_SPEC" echo "> Bump gem version to $_version" } _improve_changelog() { # Replace multiple empty lines with a single empty line sed -i '/^$/N;/^\n$/D' "$CHANGELOG" # Escape left angle brackets of HTML tag in the changelog as they break the markdown structure. e.g., '
' sed -i -E 's/\s(<[a-z])/ \\\1/g' "$CHANGELOG" } prepare() { _bump_version _improve_changelog } ## Build a Gem package build_gem() { # Remove unnecessary theme settings sed -i -E "s/(^timezone:).*/\1/;s/(^cdn:).*/\1/;s/(^avatar:).*/\1/" $CONFIG rm -f ./*.gem npm run build # add CSS/JS distribution files to gem package git add "$CSS_DIST" "$JS_DIST" -f echo -e "\n> gem build $GEM_SPEC\n" gem build "$GEM_SPEC" echo -e "\n> Resume file changes ...\n" git reset git checkout . } # Push the gem to RubyGems.org (using $GEM_HOST_API_KEY) push_gem() { gem push ./*.gem } ## Merge the release branch into the default branch merge() { git fetch origin "$MAIN_BRANCH" git checkout -b "$MAIN_BRANCH" origin/"$MAIN_BRANCH" git merge --no-ff --no-edit "$RELEASE_BRANCH" || ( git merge --abort echo -e "\n> Conflict detected. Aborting merge.\n" exit 0 ) git push origin "$MAIN_BRANCH" } main() { init if $opt_pre; then prepare exit 0 fi build_gem $opt_pkg && exit 0 push_gem merge } while (($#)); do opt="$1" case $opt in --prepare) opt_pre=true shift ;; -p | --package) opt_pkg=true shift ;; -h | --help) help exit 0 ;; *) # unknown option help exit 1 ;; esac done main