Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .distignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/config
/node_modules
/tests
/scripts
/bin

.distignore
.editorconfig
Expand Down
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/node_modules export-ignore -diff
/tests export-ignore
/vendor export-ignore -diff
/scripts export-ignore
/bin export-ignore
/.distignore export-ignore
/.editorconfig export-ignore
/.gitattributes export-ignore
Expand Down
262 changes: 262 additions & 0 deletions bin/bump.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
#!/usr/bin/env bash
#
# Bump the plugin version across package, block metadata, PHP, and docs.
#
# Usage (no chmod required):
# bash bin/bump.sh patch
# bash bin/bump.sh minor
# bash bin/bump.sh major
# bash bin/bump.sh 2.2.0
# npm run bump -- patch
# npm run bump -- 2.2.0
#
# macOS sed (-i '') is assumed.
#

set -euo pipefail

# ---------------------------------------------------------------------------
# Assets — add or remove paths here
# ---------------------------------------------------------------------------

ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"

# JSON files that expose a top-level "version" field
JSON_VERSION_FILES=(
".plugin-data"
"package.json"
"src/faq/block.json"
"src/faq-answer/block.json"
"src/faq-item/block.json"
"src/faq-question/block.json"
)

PACKAGE_LOCK_FILE="package-lock.json"
PHP_FILE="blockparty-faq.php"
README_TXT="readme.txt"
CHANGELOG="CHANGELOG.md"

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

UPDATED_FILES=()

log_updated() {
UPDATED_FILES+=( "$1" )
}

require_file() {
local file="$1"
if [[ ! -f "${ROOT_DIR}/${file}" ]]; then
echo "Error: Missing file ${file}" >&2
exit 1
fi
}

replace_json_version() {
local file="$1"
local path="${ROOT_DIR}/${file}"
require_file "${file}"
sed -i '' "s/\"version\": \"[0-9]*\.[0-9]*\.[0-9]*\"/\"version\": \"${VERSION}\"/" "${path}"
log_updated "${file}"
}

usage() {
local code="${1:-0}"
echo "Usage: bash bin/bump.sh <patch|minor|major|x.y.z>"
echo ""
echo "Examples:"
echo " bash bin/bump.sh patch"
echo " bash bin/bump.sh minor"
echo " bash bin/bump.sh 2.2.0"
echo " npm run bump -- patch"
exit "${code}"
}

resolve_version() {
local current="$1"
local input="$2"

if [[ "${input}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "${input}"
return
fi

local major minor patch
IFS='.' read -r major minor patch <<< "${current}"

case "${input}" in
major)
echo "$((major + 1)).0.0"
;;
minor)
echo "${major}.$((minor + 1)).0"
;;
patch)
echo "${major}.${minor}.$((patch + 1))"
;;
*)
echo "Error: Unknown bump argument \"${input}\". Use patch, minor, major, or an explicit x.y.z version." >&2
exit 1
;;
esac
}

escape_sed() {
printf '%s\n' "$1" | sed -e 's/[.[\*^$\/]/\\&/g'
}

# ---------------------------------------------------------------------------
# Args
# ---------------------------------------------------------------------------

if [[ -z "${1:-}" || "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage "$([[ -n "${1:-}" ]] && echo 0 || echo 1)"
fi

INPUT="$1"

require_file ".plugin-data"
CURRENT="$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([0-9]*\.[0-9]*\.[0-9]*\)".*/\1/p' "${ROOT_DIR}/.plugin-data" | head -n 1)"

if [[ -z "${CURRENT}" ]]; then
echo "Error: Could not read current version from .plugin-data" >&2
exit 1
fi

if ! [[ "${CURRENT}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Invalid current version \"${CURRENT}\" in .plugin-data" >&2
exit 1
fi

VERSION="$(resolve_version "${CURRENT}" "${INPUT}")"

if [[ "${VERSION}" == "${CURRENT}" ]]; then
echo "Error: Version is already ${CURRENT}" >&2
exit 1
fi

echo "Bumping version: ${CURRENT} → ${VERSION}"
TODAY="$(date +%Y-%m-%d)"

# ---------------------------------------------------------------------------
# JSON version fields
# ---------------------------------------------------------------------------

for file in "${JSON_VERSION_FILES[@]}"; do
replace_json_version "${file}"
done

# ---------------------------------------------------------------------------
# package-lock.json (root + packages[""] only)
# ---------------------------------------------------------------------------

if [[ -f "${ROOT_DIR}/${PACKAGE_LOCK_FILE}" ]]; then
# Root "version" (near top of file)
sed -i '' '1,5s/"version": "[0-9]*\.[0-9]*\.[0-9]*"/"version": "'"${VERSION}"'"/' "${ROOT_DIR}/${PACKAGE_LOCK_FILE}"
# packages[""].version
sed -i '' '6,12s/"version": "[0-9]*\.[0-9]*\.[0-9]*"/"version": "'"${VERSION}"'"/' "${ROOT_DIR}/${PACKAGE_LOCK_FILE}"
log_updated "${PACKAGE_LOCK_FILE}"
fi

# ---------------------------------------------------------------------------
# Main plugin PHP
# ---------------------------------------------------------------------------

require_file "${PHP_FILE}"
sed -i '' "s/^\( \* Version:[[:space:]]*\)$(escape_sed "${CURRENT}")/\1${VERSION}/" "${ROOT_DIR}/${PHP_FILE}"
sed -i '' "s/define( 'BLOCKPARTY_FAQ_VERSION', '$(escape_sed "${CURRENT}")' )/define( 'BLOCKPARTY_FAQ_VERSION', '${VERSION}' )/" "${ROOT_DIR}/${PHP_FILE}"
log_updated "${PHP_FILE}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silent success on missed replacements

Medium Severity

sed and awk updates no longer verify that a match was found. If the PHP header, define, Stable tag, or changelog markers differ slightly from what the patterns expect, those fields stay unchanged while the script still reports a successful bump and lists the files as updated. The previous Node script failed loudly via replaceOnce in these cases.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 10a4188. Configure here.


# ---------------------------------------------------------------------------
# readme.txt — Stable tag + changelog + Upgrade Notice stubs
# ---------------------------------------------------------------------------

require_file "${README_TXT}"
sed -i '' "s/^\(Stable tag:[[:space:]]*\)$(escape_sed "${CURRENT}")/\1${VERSION}/" "${ROOT_DIR}/${README_TXT}"

if grep -q "^= ${VERSION} - " "${ROOT_DIR}/${README_TXT}"; then
echo "Error: readme.txt already contains a changelog entry for ${VERSION}" >&2
exit 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guards run after partial writes

Medium Severity

Duplicate changelog and Upgrade Notice checks run only after JSON, lockfile, PHP, and Stable tag have already been rewritten. An explicit bump to a version that already appears in readme.txt history exits with an error but leaves those version fields updated, so the working tree ends up half-bumped.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 10a4188. Configure here.

fi

awk -v ver="${VERSION}" -v today="${TODAY}" -v current="${CURRENT}" '
{
if ( $0 ~ ("^= " current " - ") ) {
print "= " ver " - " today " ="
print "* TBD"
print ""
}
print
}
' "${ROOT_DIR}/${README_TXT}" > "${ROOT_DIR}/${README_TXT}.tmp"
mv "${ROOT_DIR}/${README_TXT}.tmp" "${ROOT_DIR}/${README_TXT}"

if grep -q "^= ${VERSION} =$" "${ROOT_DIR}/${README_TXT}"; then
echo "Error: readme.txt already contains an Upgrade Notice for ${VERSION}" >&2
exit 1
fi

awk -v ver="${VERSION}" '
{
print
if ( $0 == "== Upgrade Notice ==" ) {
getline
print ""
print "= " ver " ="
print "TBD"
print ""
if ( $0 != "" ) {
print
}
}
}
' "${ROOT_DIR}/${README_TXT}" > "${ROOT_DIR}/${README_TXT}.tmp"
mv "${ROOT_DIR}/${README_TXT}.tmp" "${ROOT_DIR}/${README_TXT}"
log_updated "${README_TXT}"

# ---------------------------------------------------------------------------
# CHANGELOG.md — Keep a Changelog entry
# ---------------------------------------------------------------------------

require_file "${CHANGELOG}"

if grep -q "^## \[${VERSION}\]" "${ROOT_DIR}/${CHANGELOG}"; then
echo "Error: CHANGELOG.md already contains an entry for ${VERSION}" >&2
exit 1
fi

awk -v ver="${VERSION}" -v today="${TODAY}" '
{
print
if ( !inserted && index( $0, "Semantic Versioning" ) ) {
getline
print ""
print "## [" ver "] - " today
print ""
print "### Changed"
print ""
print "- TBD"
print ""
inserted = 1
# Marker is followed by a blank line; skip the consumed blank.
next
}
}
' "${ROOT_DIR}/${CHANGELOG}" > "${ROOT_DIR}/${CHANGELOG}.tmp"
mv "${ROOT_DIR}/${CHANGELOG}.tmp" "${ROOT_DIR}/${CHANGELOG}"
log_updated "${CHANGELOG}"

# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------

echo ""
echo "Bumped version ${CURRENT} → ${VERSION}"
echo "Updated files:"
for file in "${UPDATED_FILES[@]}"; do
echo " - ${file}"
done
echo ""
echo "Fill in the TBD changelog entries before releasing."
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"make-json": "wp i18n make-json languages/blockparty-faq-fr_FR.po languages/ --no-purge",
"env:start": "wp-env start",
"env:stop": "wp-env stop",
"bump": "node scripts/bump-version.js"
"bump": "bash bin/bump.sh"
},
"dependencies": {
"@beapi/be-a11y": "^1.7.2",
Expand Down
Loading