#!/usr/bin/env bash # # Release a new version to the GitLab flow production branch. # # For a new major/minor version, bump version on the main branch, and then merge into the production branch. # # For a patch version, bump the version number on the patch branch, then merge that branch into the main branch # and production branch. # # # Usage: run on the default, release or the patch branch # # Requires: Git, NPM and RubyGems set -eu opt_pre=false # preview mode option working_branch="$(git branch --show-current)" DEFAULT_BRANCH="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')" PROD_BRANCH="production" GEM_SPEC="jekyll-theme-chirpy.gemspec" NODE_CONFIG="package.json" CHANGE_LOG="docs/CHANGELOG.md" JS_DIST="assets/js/dist" BACKUP_PATH="$(mktemp -d)" FILES=( "$GEM_SPEC" "$NODE_CONFIG" ) TOOLS=( "git" "npm" "standard-version" "gem" ) help() { echo "A tool to release new version Chirpy gem" echo echo "Usage:" echo echo " bash ./tools/release [options]" echo echo "Options:" echo " -p, --preview Enable preview mode, only package, and will not modify the branches" echo " -h, --help Print this information." } _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() { # 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_pre || ( if [[ $working_branch != "$DEFAULT_BRANCH" && $working_branch != hotfix/* && $working_branch != "$PROD_BRANCH" ]]; then echo "> Abort: Please run on the default, release or patch 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 } _check_node_packages() { if [[ ! -d node_modules || "$(du node_modules | awk '{print $1}')" == "0" ]]; then npm i fi } check() { _check_cli _check_git _check_src _check_node_packages } # Auto-generate a new version number to the file 'package.json' bump_node() { bump="standard-version -i $CHANGE_LOG" if $opt_pre; then bump="$bump -p rc" fi eval "$bump" # Change heading of Patch version to heading level 2 (a bug from `standard-version`) sed -i "s/^### \[/## \[/g" "$CHANGE_LOG" # Replace multiple empty lines with a single empty line sed -i "/^$/N;/^\n$/D" "$CHANGE_LOG" } ## Bump new version to gem config file bump_gem() { _ver="$1" if $opt_pre; then _ver="${1/-/.}" fi sed -i "s/[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/$_ver/" "$GEM_SPEC" } # Creates a new tag on the production branch with the given version number. # Also commits the changes and merges the production branch into the default branch. branch() { _version="$1" # X.Y.Z git add . git commit -m "chore(release): $_version" # Create a new tag on production branch echo -e "> Create tag v$_version\n" git tag "v$_version" git checkout "$DEFAULT_BRANCH" git merge --no-ff --no-edit "$PROD_BRANCH" if [[ $working_branch == hotfix/* ]]; then # delete the patch branch git branch -D "$working_branch" fi } ## Build a Gem package build_gem() { git checkout "$PROD_BRANCH" # Remove unnecessary theme settings sed -i "s/^img_cdn:.*/img_cdn:/;s/^avatar:.*/avatar:/" _config.yml rm -f ./*.gem npm run build git add "$JS_DIST" -f # add JS distribution files to gem gem build "$GEM_SPEC" cp "$JS_DIST"/* "$BACKUP_PATH" # Resume the settings git reset git checkout . # restore the dist files for future development mkdir -p "$JS_DIST" && cp "$BACKUP_PATH"/* "$JS_DIST" # back to the default branch git checkout "$DEFAULT_BRANCH" } main() { check if [[ $opt_pre = false && $working_branch != "$PROD_BRANCH" ]]; then git checkout "$PROD_BRANCH" git merge --no-ff --no-edit "$working_branch" fi bump_node _version="$(grep '"version":' "$NODE_CONFIG" | sed 's/.*: "//;s/".*//')" bump_gem "$_version" if [[ $opt_pre = false ]]; then branch "$_version" fi echo -e "> Build the gem package for v$_version\n" build_gem } while (($#)); do opt="$1" case $opt in -p | --preview) opt_pre=true shift ;; -h | --help) help exit 0 ;; *) # unknown option help exit 1 ;; esac done main