From 004ab6c56a55cd066c46de59083ef35347f4fbf8 Mon Sep 17 00:00:00 2001 From: Cotes Chung <11371340+cotes2020@users.noreply.github.com> Date: Tue, 1 Mar 2022 23:23:20 +0800 Subject: [PATCH 1/4] build(deps): add `commitlint`, `husky`, and `standard-version` --- .gitignore | 1 + .husky/commit-msg | 4 ++++ package.json | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100755 .husky/commit-msg diff --git a/.gitignore b/.gitignore index 982a22d..ca4c7b4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ !.editorconfig !.nojekyll !.travis.yml +!.husky # bundler cache _site diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 0000000..7fed485 --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx --no -- commitlint --edit diff --git a/package.json b/package.json index 3a37427..a17cfe9 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,43 @@ "url": "https://github.com/cotes2020/jekyll-theme-chirpy/issues" }, "homepage": "https://github.com/cotes2020/jekyll-theme-chirpy#readme", - "dependencies": { + "scripts": { + "prepare": "husky install" + }, + "devDependencies": { + "@commitlint/cli": "^16.2.1", + "@commitlint/config-conventional": "^16.2.1", "gulp": "^4.0.2", "gulp-concat": "^2.6.1", "gulp-insert": "^0.5.0", "gulp-rename": "^2.0.0", "gulp-uglify": "^3.0.2", + "husky": "^7.0.4", + "standard-version": "^9.3.2", "uglify-js": "^3.14.3" + }, + "commitlint": { + "extends": [ + "@commitlint/config-conventional" + ] + }, + "standard-version": { + "skip": { + "commit": true, + "tag": true + }, + "types": [{ + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Improvements" + } + ] } } From dd264e793c7b9e8c005073e2bd8a94261c157de0 Mon Sep 17 00:00:00 2001 From: Cotes Chung <11371340+cotes2020@users.noreply.github.com> Date: Tue, 1 Mar 2022 23:23:50 +0800 Subject: [PATCH 2/4] ci(gh-actions): add `commitlint` for PR --- .github/workflows/commitlint.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/workflows/commitlint.yml diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 0000000..1e05511 --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,11 @@ +name: Lint Commit Messages +on: pull_request + +jobs: + commitlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: wagoid/commitlint-github-action@v4 From 42fe8f5d2129d1e1b43e95a1f4bdbbfeccfc561c Mon Sep 17 00:00:00 2001 From: Cotes Chung <11371340+cotes2020@users.noreply.github.com> Date: Tue, 1 Mar 2022 23:24:51 +0800 Subject: [PATCH 3/4] build(shell): update release tool to work with `standard-version` --- tools/bump.sh | 106 ---------------------- tools/release.sh | 222 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 183 insertions(+), 145 deletions(-) delete mode 100755 tools/bump.sh diff --git a/tools/bump.sh b/tools/bump.sh deleted file mode 100755 index 0824bc8..0000000 --- a/tools/bump.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env bash -# -# -# 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 -# - package.json -# -# 2. Then create a commit to automatically save the changes. -# -# Usage: -# -# Run on the default branch or hotfix branch -# -# Requires: Git, Gulp - -set -eu - -ASSETS=( - "_sass/jekyll-theme-chirpy.scss" - "_javascript/copyright" -) - -GEM_SPEC="jekyll-theme-chirpy.gemspec" - -NODE_META="package.json" - -_check_src() { - if [[ ! -f $1 && ! -d $1 ]]; then - echo -e "Error: Missing file \"$1\"!\n" - exit -1 - fi -} - -check() { - if [[ -n $(git status . -s) ]]; then - echo "Error: Commit unstaged files first, and then run this tool againt." - exit -1 - fi - - for i in "${!ASSETS[@]}"; do - _check_src "${ASSETS[$i]}" - done - - _check_src "$NODE_META" - _check_src "$GEM_SPEC" -} - -_bump_assets() { - for i in "${!ASSETS[@]}"; do - sed -i "s/v[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/v$1/" "${ASSETS[$i]}" - done - - gulp -} - -_bump_gemspec() { - sed -i "s/[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/$1/" "$GEM_SPEC" -} - -_bump_node() { - sed -i \ - "s,[\"]version[\"]: [\"][[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+[\"],\"version\": \"$1\"," \ - $NODE_META -} - -bump() { - _bump_assets "$1" - _bump_gemspec "$1" - _bump_node "$1" - - if [[ -n $(git status . -s) ]]; then - git add . - git commit -m "Bump version to $1" - fi -} - -main() { - check - - _latest_tag="$(git describe --tags $(git rev-list --tags --max-count=1))" - - echo "Input a version number (hint: latest version is ${_latest_tag:1})" - - read -p "> " _version - - [[ $_version =~ ^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]$ ]] || - ( - echo "Error: Illegal version number: '$_version'" - exit 1 - ) - - if git tag --list | egrep -q "^v$_version$"; then - echo "Error: version '$_version' already exists" - exit 1 - fi - - echo -e "Bump version to $_version\n" - bump "$_version" - -} - -main diff --git a/tools/release.sh b/tools/release.sh index a067141..99e462e 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -1,22 +1,44 @@ #!/usr/bin/env bash # -# According to the GitLab flow release branching model, -# cherry-pick the last commit on the main branch to the release branch, -# and then create a tag and gem package on the release branch (naming format: 'release/'). +# 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: +# Usage: run on main branch or the patch branch # -# It can be run on main branch, and it should be used after just finishing the last feature in the version plan, -# or just after merging the hotfix to the main branch. -# -# Requires: Git, Gulp +# Requires: Git, Node.js, NPX and RubyGems set -eu +opt_pre=false # preview mode option + +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" -opt_pre=false +NODE_CONFIG="package.json" + +FILES=( + "_sass/jekyll-theme-chirpy.scss" + "_javascript/copyright" + "$GEM_SPEC" + "$NODE_CONFIG" +) + +TOOLS=( + "git" + "npm" + "npx" + "gem" +) help() { echo "A tool to release new version Chirpy gem" @@ -26,19 +48,85 @@ help() { echo " bash ./tools/release.sh [options]" echo echo "Options:" - echo " -p, --preview Enable preview mode, only pakcage, and will not modify the branches" + echo " -p, --preview Enable preview mode, only package, and will not modify the branches" echo " -h, --help Print this information." } -check() { +_check_git() { + # ensure nothing is uncommitted if [[ -n $(git status . -s) ]]; then - echo "Error: Commit unstaged files first, and then run this tool againt." - exit -1 + echo "Abort: Commit the staged files first, and then run this tool again." + exit 1 fi - if [[ ! -f $GEM_SPEC ]]; then - echo -e "Error: Missing file \"$GEM_SPEC\"!\n" - exit -1 + # 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 + 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 } @@ -52,39 +140,95 @@ resume_config() { mv _config.yml.bak _config.yml } -release() { - _default_branch="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')" - _version="$(grep "spec.version" jekyll-theme-chirpy.gemspec | sed 's/.*= "//;s/".*//')" # X.Y.Z - _release_branch="release/${_version%.*}" - - if [[ $opt_pre = "false" ]]; then - # Modify the GitLab release branches - if [[ -z $(git branch -v | grep "$_release_branch") ]]; then - # create a new release branch - git checkout -b "$_release_branch" - else - # cherry-pick the latest commit from default branch to release branch - _last_commit="$(git rev-parse "$_default_branch")" - git checkout "$_release_branch" - git cherry-pick "$_last_commit" -m 1 - fi - - # Create a new tag - echo -e "Create tag v$_version\n" - git tag "v$_version" +# auto-generate a new version number to the file 'package.json' +standard_version() { + if $opt_pre; then + npx standard-version --prerelease rc + else + npx standard-version fi +} - # build a gem package - echo -e "Build the gem pakcage for v$_version\n" +# Prevent changelogs generated on master branch from having duplicate content +# (the another bug of `standard-version`) +standard_version_plus() { + temp_branch="prod-mirror" + temp_dir="$(mktemp -d)" + + git checkout -b "$temp_branch" "$PROD_BRANCH" + git merge --no-ff --no-edit "$STAGING_BRANCH" + + standard_version + + cp package.json CHANGELOG.md "$temp_dir" + + git checkout "$STAGING_BRANCH" + git reset --hard HEAD # undo the changes from $temp_branch + mv "$temp_dir"/* . # rewrite the changelog + + # clean up the temp stuff + rm -rf "$temp_dir" + git branch -D "$temp_branch" +} + +# 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 + + if $opt_pre; then + $opt_pre + exit 0 + fi + + git checkout "$PROD_BRANCH" + git merge --no-ff --no-edit "$working_branch" + + # Create a new tag on production branch + echo -e "Create tag v$_version\n" + git tag "v$_version" + + build_gem + + # 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() { check - release + + if [[ "$working_branch" == "$STAGING_BRANCH" ]]; then + standard_version_plus + else + standard_version + fi + + # Change heading of Patch version to level 2 (a bug from `standard-version`) + sed -i "s/^### \[/## \[/g" CHANGELOG.md + + _version="$(grep '"version":' package.json | sed 's/.*: "//;s/".*//')" + + echo -e "Bump version number to $_version\n" + bump "$_version" + + release "$_version" + + # Undo all changes on Git + $opt_pre && git reset --hard && git clean -fd + } while (($#)); do From 887859dd3238e530cc508d4134e3db2215d3885e Mon Sep 17 00:00:00 2001 From: Cotes Chung <11371340+cotes2020@users.noreply.github.com> Date: Tue, 1 Mar 2022 23:26:29 +0800 Subject: [PATCH 4/4] docs: update contributing guidelines --- .github/CONTRIBUTING.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 389502c..b35638a 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,6 +1,6 @@ # How to Contribute -We want to thank you for sparing time to improve this project! Here are some guidelines for contributingļ¼š +We'd like to thank you for sparing time to improve this project! Here are some guidelines for contributingļ¼š To ensure that the blog design is not confused, this project does not accept suggestions for design changes, such as color scheme, fonts, typography, etc. If your request is about an enhancement, it is recommended to first submit a [_Feature Request_](https://github.com/cotes2020/jekyll-theme-chirpy/issues/new?labels=enhancement&template=feature_request.md) issue to discuss whether your idea fits the project. @@ -9,34 +9,41 @@ To ensure that the blog design is not confused, this project does not accept sug Generally, contribute to the project by: 1. Fork this project on GitHub and clone it locally. -2. Create a new branch from the default branch and give it a descriptive name (e.g., `my-new-feature`, `fix-a-bug`). -3. After completing the development, submit a new _Pull Request_. +2. Create a new branch from the default branch and give it a descriptive name (format: `feature/` / `fix/`). +3. After completing the development, submit a new _Pull Request_. Note that the commit message must follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/), otherwise it will fail the PR check. ## Modifying JavaScript -If your contribution involves JS modification, please read the following sections. +If your contribution involves JavaScript modification, please read the following sections. ### Inline Scripts -If you need to add comments to the inline JS (the JS code between the tags ``), please use `/**/` instead of two slashes `//`. Because the HTML will be compressed by [jekyll-compress-html](https://github.com/penibelst/jekyll-compress-html) during deployment, but it cannot handle the `//` properly. And this will disrupt the structure of the compressed HTML. +If you need to add comments to the inline JavaScript (the code between the HTML tags ``), please use `/* */` instead of two slashes `//`. Because the HTML will be compressed by [jekyll-compress-html](https://github.com/penibelst/jekyll-compress-html) during deployment, but it cannot handle the `//` properly, which will disrupt the structure of the compressed HTML. ### External Scripts -If you need to add or modify JavaScripts in the directory `_javascript`, you need to install [Gulp.js](https://gulpjs.com/docs/en/getting-started/quick-start). +If you need to add/change/delete the JavaScript in the directory `_javascript/`, setting up [`Node.js`](https://nodejs.org/) and [`npx`](https://www.npmjs.com/package/npx) is a requirement. And then install the development dependencies: -During development, real-time debugging can be performed through the following commands: +```console +$ npm i +``` + +During JavaScript development, real-time debugging can be performed through the following commands: + +Firstly, start a Jekyll server: ```console $ bash tools/run.sh ``` -Open another terminal tab and run: +And then open a new terminal tab and run: ```console -$ gulp dev # Type 'Ctrl + C' to stop +# Type 'Ctrl + C' to stop +$ npx gulp dev ``` -After debugging, run the command `gulp` (without any argument) will automatically output the compressed files to the directory `assests/js/dist/`. +After debugging, run the command `npx gulp` (without any argument) will automatically output the compressed files to the directory `assets/js/dist/`. ---