#!/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 main branch or the patch branch # # Requires: Git, NPM and RubyGems set -eu opt_pre=false # preview mode option opt_skip_ver=false # option for skip versioning working_branch="$(git branch --show-current)" STAGING_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" FILES=( "_sass/jekyll-theme-chirpy.scss" "_javascript/copyright" "$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.sh [options]" echo echo "Options:" echo " -k, --skip-versioning Skip the step of generating the version number." echo " -p, --preview Enable preview mode, only package, and will not modify the branches" echo " -h, --help Print this information." } _check_git() { # ensure nothing is uncommitted if [[ -n $(git status . -s) ]]; then echo "Abort: Commit the staged files first, and then run this tool again." exit 1 fi # ensure the working branch is the main/patch branch if [[ $working_branch != "$STAGING_BRANCH" && $working_branch != hotfix/* ]]; then echo "Abort: Please run on the main branch or patch branches." exit 1 fi } _check_src() { if [[ ! -f $1 && ! -d $1 ]]; then echo -e "Error: Missing file \"$1\"!\n" exit 1 fi } _check_command() { if ! command -v "$1" &>/dev/null; then echo "Command '$1' not found" exit 1 fi } _check_node_packages() { if [[ ! -d node_modules || "$(du node_modules | awk '{print $1}')" == "0" ]]; then npm i fi } check() { _check_git for i in "${!FILES[@]}"; do _check_src "${FILES[$i]}" done for i in "${!TOOLS[@]}"; do _check_command "${TOOLS[$i]}" done _check_node_packages } _bump_file() { for i in "${!FILES[@]}"; do if [[ ${FILES[$i]} == $NODE_CONFIG ]]; then continue fi sed -i "s/v[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/v$1/" "${FILES[$i]}" done npx gulp } _bump_gemspec() { sed -i "s/[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/$1/" "$GEM_SPEC" } # 1. Bump latest version number to the following files: # # - _sass/jekyll-theme-chirpy.scss # - _javascript/copyright # - assets/js/dist/*.js (will be built by gulp later) # - jekyll-theme-chirpy.gemspec # # 2. Create a commit to save the changes. bump() { _bump_file "$1" _bump_gemspec "$1" if [[ $opt_pre = false && -n $(git status . -s) ]]; then git add . git commit -m "chore(release): $1" fi } ## Remove unnecessary theme settings cleanup_config() { cp _config.yml _config.yml.bak sed -i "s/^img_cdn:.*/img_cdn:/;s/^avatar:.*/avatar:/" _config.yml } resume_config() { mv _config.yml.bak _config.yml } # build a gem package build_gem() { echo -e "Build the gem package for v$_version\n" cleanup_config rm -f ./*.gem gem build "$GEM_SPEC" resume_config } # Update the git branch graph, tag, and then build the gem package. release() { _version="$1" # X.Y.Z # Create a new tag on working branch echo -e "Create tag v$_version\n" git tag "v$_version" git checkout "$PROD_BRANCH" git merge --no-ff --no-edit "$working_branch" # merge from patch branch to the staging branch # NOTE: This may break due to merge conflicts, so it may need to be resolved manually. if [[ $working_branch == hotfix/* ]]; then git checkout "$STAGING_BRANCH" git merge --no-ff --no-edit "$working_branch" git branch -D "$working_branch" fi } main() { if [[ $opt_skip_ver = false ]]; then check # auto-generate a new version number to the file 'package.json' if $opt_pre; then standard-version --prerelease rc else standard-version fi fi _version="$(grep '"version":' "$NODE_CONFIG" | sed 's/.*: "//;s/".*//')" echo -e "Bump version number to $_version\n" bump "$_version" build_gem if [[ $opt_pre = true ]]; then # Undo all changes on Git git reset --hard && git clean -fd else release "$_version" fi } while (($#)); do opt="$1" case $opt in -p | --preview) opt_pre=true shift ;; -k | --skip-versioning) opt_skip_ver=true shift ;; -h | --help) help exit 0 ;; *) # unknown option help exit 1 ;; esac done main