ci(release): replace standard-version
with semantic-release
(#1666)
[`standard-version`](https://github.com/conventional-changelog/standard-version/) has been deprecated since May 2022, so it is necessary to stop using it for this project. [**`semantic-release`**](https://github.com/semantic-release/semantic-release) is available as a more capable alternative to help automate the release process: 1. Updating Node/Gem version numbers 2. Generating changelogs 3. Automating GitHub Releases 4. Building Chirpy-gem and pushing it to RubyGems.org 5. Create commits and tags on the `production` branch 6. Merge the `production` branch into the `master` branch > ⚠️ Note: Step _6_ may be canceled in CD environments due to merge conflicts, so we need to do this step manually in such cases. Whenever a commit is pushed to the release branch (`production`), all of the above release processes will be triggered.
This commit is contained in:
parent
8c1be9f2f3
commit
bf16d6039a
5 changed files with 194 additions and 126 deletions
38
.github/workflows/cd.yml
vendored
38
.github/workflows/cd.yml
vendored
|
@ -1,17 +1,37 @@
|
||||||
name: CD
|
name: CD
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
|
||||||
- "v[0-9]+.[0-9]+.[0-9]+"
|
|
||||||
branches:
|
branches:
|
||||||
- docs
|
- production
|
||||||
|
tags-ignore:
|
||||||
|
- "**"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
launch:
|
release:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- run: |
|
- uses: actions/checkout@v4
|
||||||
curl -X POST -H "Accept: application/vnd.github+json" \
|
|
||||||
-H "Authorization: Bearer ${{ secrets.GH_PAT }}" \
|
- uses: ruby/setup-ruby@v1
|
||||||
https://api.github.com/repos/${{ secrets.BUILDER }}/dispatches \
|
with:
|
||||||
-d '{"event_type":"deploy", "client_payload":{"branch": "${{ github.ref_name }}"}}'
|
ruby-version: 3.2
|
||||||
|
bundler-cache: true
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: latest
|
||||||
|
|
||||||
|
- run: npm install
|
||||||
|
- run: npx semantic-release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }}
|
||||||
|
|
||||||
|
publish:
|
||||||
|
needs: release
|
||||||
|
uses: ./.github/workflows/publish.yml
|
||||||
|
|
17
.github/workflows/publish.yml
vendored
Normal file
17
.github/workflows/publish.yml
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
name: Publish
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- docs
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
launch:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- run: |
|
||||||
|
curl -X POST -H "Accept: application/vnd.github+json" \
|
||||||
|
-H "Authorization: Bearer ${{ secrets.GH_PAT }}" \
|
||||||
|
https://api.github.com/repos/${{ secrets.BUILDER }}/dispatches \
|
||||||
|
-d '{"event_type":"deploy", "client_payload":{"branch": "${{ github.ref_name }}"}}'
|
|
@ -1,7 +1,5 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
||||||
|
|
||||||
## [6.5.5](https://github.com/cotes2020/jekyll-theme-chirpy/compare/v6.5.4...v6.5.5) (2024-03-23)
|
## [6.5.5](https://github.com/cotes2020/jekyll-theme-chirpy/compare/v6.5.4...v6.5.5) (2024-03-23)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
93
package.json
93
package.json
|
@ -28,10 +28,15 @@
|
||||||
"@commitlint/config-conventional": "^19.1.0",
|
"@commitlint/config-conventional": "^19.1.0",
|
||||||
"@rollup/plugin-babel": "^6.0.4",
|
"@rollup/plugin-babel": "^6.0.4",
|
||||||
"@rollup/plugin-terser": "^0.4.4",
|
"@rollup/plugin-terser": "^0.4.4",
|
||||||
|
"@semantic-release/changelog": "^6.0.3",
|
||||||
|
"@semantic-release/exec": "^6.0.3",
|
||||||
|
"@semantic-release/git": "^10.0.1",
|
||||||
|
"conventional-changelog-conventionalcommits": "^7.0.2",
|
||||||
"husky": "^9.0.11",
|
"husky": "^9.0.11",
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
"rollup": "^4.13.2",
|
"rollup": "^4.13.2",
|
||||||
"rollup-plugin-license": "^3.3.1",
|
"rollup-plugin-license": "^3.3.1",
|
||||||
|
"semantic-release": "^23.0.8",
|
||||||
"stylelint": "^16.3.1",
|
"stylelint": "^16.3.1",
|
||||||
"stylelint-config-standard-scss": "^13.0.0"
|
"stylelint-config-standard-scss": "^13.0.0"
|
||||||
},
|
},
|
||||||
|
@ -89,24 +94,76 @@
|
||||||
"media-feature-range-notation": "prefix"
|
"media-feature-range-notation": "prefix"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"standard-version": {
|
"release": {
|
||||||
"skip": {
|
"branches": [
|
||||||
"commit": true,
|
"production"
|
||||||
"tag": true
|
],
|
||||||
},
|
"plugins": [
|
||||||
"types": [
|
[
|
||||||
{
|
"@semantic-release/commit-analyzer",
|
||||||
"type": "feat",
|
{
|
||||||
"section": "Features"
|
"preset": "conventionalcommits"
|
||||||
},
|
}
|
||||||
{
|
],
|
||||||
"type": "fix",
|
[
|
||||||
"section": "Bug Fixes"
|
"@semantic-release/release-notes-generator",
|
||||||
},
|
{
|
||||||
{
|
"preset": "conventionalcommits",
|
||||||
"type": "perf",
|
"presetConfig": {
|
||||||
"section": "Improvements"
|
"types": [
|
||||||
}
|
{
|
||||||
|
"type": "feat",
|
||||||
|
"section": "Features"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fix",
|
||||||
|
"section": "Bug Fixes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "perf",
|
||||||
|
"section": "Improvements"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "refactor",
|
||||||
|
"section": "Changes",
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"@semantic-release/changelog",
|
||||||
|
{
|
||||||
|
"changelogFile": "docs/CHANGELOG.md",
|
||||||
|
"changelogTitle": "# Changelog"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"@semantic-release/npm",
|
||||||
|
{
|
||||||
|
"npmPublish": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"@semantic-release/exec",
|
||||||
|
{
|
||||||
|
"prepareCmd": "bash tools/release --prepare",
|
||||||
|
"publishCmd": "bash tools/release"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"@semantic-release/git",
|
||||||
|
{
|
||||||
|
"assets": [
|
||||||
|
"docs",
|
||||||
|
"package.json",
|
||||||
|
"*.gemspec"
|
||||||
|
],
|
||||||
|
"message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@semantic-release/github"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
170
tools/release
170
tools/release
|
@ -1,56 +1,47 @@
|
||||||
#!/usr/bin/env bash
|
#!/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
|
# Requires: Git, NPM and RubyGems
|
||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
opt_pre=false # preview mode option
|
opt_pre=false # option for bump gem version
|
||||||
|
opt_pkg=false # option for building gem package
|
||||||
|
|
||||||
working_branch="$(git branch --show-current)"
|
MAIN_BRANCH="master"
|
||||||
|
RELEASE_BRANCH="production"
|
||||||
DEFAULT_BRANCH="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')"
|
|
||||||
|
|
||||||
PROD_BRANCH="production"
|
|
||||||
|
|
||||||
GEM_SPEC="jekyll-theme-chirpy.gemspec"
|
GEM_SPEC="jekyll-theme-chirpy.gemspec"
|
||||||
NODE_CONFIG="package.json"
|
NODE_SPEC="package.json"
|
||||||
CHANGE_LOG="docs/CHANGELOG.md"
|
CHANGELOG="docs/CHANGELOG.md"
|
||||||
|
CONFIG="_config.yml"
|
||||||
|
|
||||||
JS_DIST="assets/js/dist"
|
JS_DIST="assets/js/dist"
|
||||||
BACKUP_PATH="$(mktemp -d)"
|
|
||||||
|
|
||||||
FILES=(
|
FILES=(
|
||||||
"$GEM_SPEC"
|
"$GEM_SPEC"
|
||||||
"$NODE_CONFIG"
|
"$NODE_SPEC"
|
||||||
|
"$CHANGELOG"
|
||||||
|
"$CONFIG"
|
||||||
)
|
)
|
||||||
|
|
||||||
TOOLS=(
|
TOOLS=(
|
||||||
"git"
|
"git"
|
||||||
"npm"
|
"npm"
|
||||||
"standard-version"
|
|
||||||
"gem"
|
"gem"
|
||||||
)
|
)
|
||||||
|
|
||||||
help() {
|
help() {
|
||||||
echo "A tool to release new version Chirpy gem"
|
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
|
||||||
echo "Usage:"
|
echo "Usage:"
|
||||||
echo
|
echo " bash ./tools/release [options]"
|
||||||
echo " bash ./tools/release [options]"
|
|
||||||
echo
|
echo
|
||||||
echo "Options:"
|
echo "Options:"
|
||||||
echo " -p, --preview Enable preview mode, only package, and will not modify the branches"
|
echo " --prepare Preparation for release"
|
||||||
echo " -h, --help Print this information."
|
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() {
|
_check_cli() {
|
||||||
|
@ -70,11 +61,9 @@ _check_git() {
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$opt_pre || (
|
$opt_pkg || (
|
||||||
if [[ $working_branch != "$DEFAULT_BRANCH" &&
|
if [[ "$(git branch --show-current)" != "$RELEASE_BRANCH" ]]; then
|
||||||
$working_branch != hotfix/* &&
|
echo "> Abort: Please run the tool in the '$RELEASE_BRANCH' branch."
|
||||||
$working_branch != "$PROD_BRANCH" ]]; then
|
|
||||||
echo "> Abort: Please run on the default, release or patch branch."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
)
|
)
|
||||||
|
@ -103,108 +92,95 @@ check() {
|
||||||
_check_node_packages
|
_check_node_packages
|
||||||
}
|
}
|
||||||
|
|
||||||
# Auto-generate a new version number to the file 'package.json'
|
## Bump new version to gem-spec file
|
||||||
bump_node() {
|
_bump_version() {
|
||||||
bump="standard-version -i $CHANGE_LOG"
|
_version="$(grep '"version":' "$NODE_SPEC" | sed 's/.*: "//;s/".*//')"
|
||||||
|
sed -i "s/[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/$_version/" "$GEM_SPEC"
|
||||||
|
echo "> Bump gem version to $_version"
|
||||||
|
}
|
||||||
|
|
||||||
if $opt_pre; then
|
_improve_changelog() {
|
||||||
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
|
# Replace multiple empty lines with a single empty line
|
||||||
sed -i "/^$/N;/^\n$/D" "$CHANGE_LOG"
|
sed -i '/^$/N;/^\n$/D' "$CHANGELOG"
|
||||||
|
# Escape left angle brackets of HTML tag in the changelog as they break the markdown structure. e.g., '<hr>'
|
||||||
|
sed -i -E 's/\s(<[a-z])/ \\\1/g' "$CHANGELOG"
|
||||||
}
|
}
|
||||||
|
|
||||||
## Bump new version to gem config file
|
prepare() {
|
||||||
bump_gem() {
|
_bump_version
|
||||||
_ver="$1"
|
_improve_changelog
|
||||||
|
|
||||||
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 a Gem package
|
||||||
build_gem() {
|
build_gem() {
|
||||||
git checkout "$PROD_BRANCH"
|
if $opt_pkg; then
|
||||||
|
BACKUP_PATH="$(mktemp -d)"
|
||||||
|
cp "$JS_DIST"/* "$BACKUP_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
# Remove unnecessary theme settings
|
# Remove unnecessary theme settings
|
||||||
sed -i "s/^cdn:.*/cdn:/;s/^avatar:.*/avatar:/" _config.yml
|
sed -i "s/^cdn:.*/cdn:/;s/^avatar:.*/avatar:/" $CONFIG
|
||||||
rm -f ./*.gem
|
rm -f ./*.gem
|
||||||
|
|
||||||
npm run build
|
npm run build
|
||||||
git add "$JS_DIST" -f # add JS distribution files to gem
|
git add "$JS_DIST" -f # add JS distribution files to gem
|
||||||
gem build "$GEM_SPEC"
|
gem build "$GEM_SPEC"
|
||||||
cp "$JS_DIST"/* "$BACKUP_PATH"
|
|
||||||
|
|
||||||
# Resume the settings
|
# resume the settings
|
||||||
git reset
|
git reset
|
||||||
git checkout .
|
git checkout .
|
||||||
|
|
||||||
# restore the dist files for future development
|
if $opt_pkg; then
|
||||||
mkdir -p "$JS_DIST" && cp "$BACKUP_PATH"/* "$JS_DIST"
|
# restore the dist files for future development
|
||||||
|
mkdir -p "$JS_DIST" && cp "$BACKUP_PATH"/* "$JS_DIST"
|
||||||
|
rm -rf "$BACKUP_PATH"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# back to the default branch
|
# Push the gem to RubyGems.org (using $GEM_HOST_API_KEY)
|
||||||
git checkout "$DEFAULT_BRANCH"
|
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() {
|
main() {
|
||||||
check
|
check
|
||||||
|
|
||||||
if [[ $opt_pre = false && $working_branch != "$PROD_BRANCH" ]]; then
|
if $opt_pre; then
|
||||||
git checkout "$PROD_BRANCH"
|
prepare
|
||||||
git merge --no-ff --no-edit "$working_branch"
|
exit 0
|
||||||
fi
|
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
|
build_gem
|
||||||
|
$opt_pkg && exit 0
|
||||||
|
push_gem
|
||||||
|
merge
|
||||||
}
|
}
|
||||||
|
|
||||||
while (($#)); do
|
while (($#)); do
|
||||||
opt="$1"
|
opt="$1"
|
||||||
case $opt in
|
case $opt in
|
||||||
-p | --preview)
|
--prepare)
|
||||||
opt_pre=true
|
opt_pre=true
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
-p | --package)
|
||||||
|
opt_pkg=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
-h | --help)
|
-h | --help)
|
||||||
help
|
help
|
||||||
exit 0
|
exit 0
|
||||||
|
|
Loading…
Reference in a new issue