initial commit
Some checks failed
Build and Deploy / build (push) Has been cancelled
Build and Deploy / deploy (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
2024-07-08 04:53:50 -05:00
parent 33ebd7d5c9
commit 2eeeb8b8c1
196 changed files with 12617 additions and 75 deletions

130
tools/init.sh Executable file
View File

@@ -0,0 +1,130 @@
#!/usr/bin/env bash
#
# Init the environment for new user.
set -eu
# CLI Dependencies
CLI=("git" "npm")
ACTIONS_WORKFLOW=pages-deploy.yml
RELEASE_HASH=$(git log --grep="chore(release):" -1 --pretty="%H")
# temporary file suffixes that make `sed -i` compatible with BSD and Linux
TEMP_SUFFIX="to-delete"
_no_gh=false
help() {
echo "Usage:"
echo
echo " bash /path/to/init [options]"
echo
echo "Options:"
echo " --no-gh Do not deploy to Github."
echo " -h, --help Print this help information."
}
# BSD and GNU compatible sed
_sedi() {
regex=$1
file=$2
sed -i.$TEMP_SUFFIX -E "$regex" "$file"
rm -f "$file".$TEMP_SUFFIX
}
_check_cli() {
for i in "${!CLI[@]}"; do
cli="${CLI[$i]}"
if ! command -v "$cli" &>/dev/null; then
echo "Command '$cli' not found! Hint: you should install it."
exit 1
fi
done
}
_check_status() {
if [[ -n $(git status . -s) ]]; then
echo "Error: Commit unstaged files first, and then run this tool again."
exit 1
fi
}
_check_init() {
if [[ $(git rev-parse HEAD^1) == "$RELEASE_HASH" ]]; then
echo "Already initialized."
exit 0
fi
}
check_env() {
_check_cli
_check_status
_check_init
}
reset_latest() {
git reset --hard "$RELEASE_HASH"
git clean -fd
git submodule update --init --recursive
}
init_files() {
if $_no_gh; then
rm -rf .github
else
## Change the files of `.github/`
temp="$(mktemp -d)"
find .github/workflows -type f -name "*$ACTIONS_WORKFLOW*" -exec mv {} "$temp/$ACTIONS_WORKFLOW" \;
rm -rf .github && mkdir -p .github/workflows
mv "$temp/$ACTIONS_WORKFLOW" .github/workflows/"$ACTIONS_WORKFLOW"
rm -rf "$temp"
## Cleanup image settings in site config
_sedi "s/(^timezone:).*/\1/;s/(^.*cdn:).*/\1/;s/(^avatar:).*/\1/" _config.yml
fi
# remove the other files
rm -rf _posts/*
# build assets
npm i && npm run build
# track the CSS/JS output
_sedi "/.*\/dist$/d;/^_app$/d" .gitignore
}
commit() {
git add -A
git commit -m "chore: initialize the environment" -q
echo -e "\n> Initialization successful!\n"
}
main() {
check_env
reset_latest
init_files
commit
}
while (($#)); do
opt="$1"
case $opt in
--no-gh)
_no_gh=true
shift
;;
-h | --help)
help
exit 0
;;
*)
# unknown option
help
exit 1
;;
esac
done
main

187
tools/release.sh Executable file
View File

@@ -0,0 +1,187 @@
#!/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"
PWA_DIST="_app"
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., '<hr>'
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" "$PWA_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

54
tools/run.sh Executable file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/env bash
#
# Run jekyll serve and then launch the site
prod=false
command="bundle exec jekyll s -l"
host="127.0.0.1"
help() {
echo "Usage:"
echo
echo " bash /path/to/run [options]"
echo
echo "Options:"
echo " -H, --host [HOST] Host to bind to."
echo " -p, --production Run Jekyll in 'production' mode."
echo " -h, --help Print this help information."
}
while (($#)); do
opt="$1"
case $opt in
-H | --host)
host="$2"
shift 2
;;
-p | --production)
prod=true
shift
;;
-h | --help)
help
exit 0
;;
*)
echo -e "> Unknown option: '$opt'\n"
help
exit 1
;;
esac
done
command="$command -H $host"
if $prod; then
command="JEKYLL_ENV=production $command"
fi
if [ -e /proc/1/cgroup ] && grep -q docker /proc/1/cgroup; then
command="$command --force_polling"
fi
echo -e "\n> $command\n"
eval "$command"

89
tools/test.sh Executable file
View File

@@ -0,0 +1,89 @@
#!/usr/bin/env bash
#
# Build and test the site content
#
# Requirement: html-proofer, jekyll
#
# Usage: See help information
set -eu
SITE_DIR="_site"
_config="_config.yml"
_baseurl=""
help() {
echo "Build and test the site content"
echo
echo "Usage:"
echo
echo " bash $0 [options]"
echo
echo "Options:"
echo ' -c, --config "<config_a[,config_b[...]]>" Specify config file(s)'
echo " -h, --help Print this information."
}
read_baseurl() {
if [[ $_config == *","* ]]; then
# multiple config
IFS=","
read -ra config_array <<<"$_config"
# reverse loop the config files
for ((i = ${#config_array[@]} - 1; i >= 0; i--)); do
_tmp_baseurl="$(grep '^baseurl:' "${config_array[i]}" | sed "s/.*: *//;s/['\"]//g;s/#.*//")"
if [[ -n $_tmp_baseurl ]]; then
_baseurl="$_tmp_baseurl"
break
fi
done
else
# single config
_baseurl="$(grep '^baseurl:' "$_config" | sed "s/.*: *//;s/['\"]//g;s/#.*//")"
fi
}
main() {
# clean up
if [[ -d $SITE_DIR ]]; then
rm -rf "$SITE_DIR"
fi
read_baseurl
# build
JEKYLL_ENV=production bundle exec jekyll b \
-d "$SITE_DIR$_baseurl" -c "$_config"
# test
bundle exec htmlproofer "$SITE_DIR" \
--disable-external \
--ignore-urls "/^http:\/\/127.0.0.1/,/^http:\/\/0.0.0.0/,/^http:\/\/localhost/"
}
while (($#)); do
opt="$1"
case $opt in
-c | --config)
_config="$2"
shift
shift
;;
-h | --help)
help
exit 0
;;
*)
# unknown option
help
exit 1
;;
esac
done
main