Automatic WordPress security: local firewall, malware and file-integrity scanning, vulnerability protection, quarantine, scheduled backups, an optional page cache, and automatic global threat intelligence. See README.md for installation, update, and uninstall instructions.
98 lines
3.6 KiB
Bash
Executable File
98 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Production release packaging -- docs/design/production-distribution-and-updates.md
|
|
# sections 1-3, 16, 18. Builds the public download ZIP from a clean git
|
|
# checkout (git archive -- never the working tree, so uncommitted local
|
|
# files can never leak into a release), strips comments/whitespace
|
|
# (not obfuscation -- see strip-comments.php's own header), and audits
|
|
# the result against an explicit allowlist before packaging, failing
|
|
# closed on anything unexpected rather than silently shipping it.
|
|
#
|
|
# Usage: bin/build-release.sh [git-ref] (defaults to HEAD)
|
|
#
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
REF="${1:-HEAD}"
|
|
BUILD_DIR="$(mktemp -d)"
|
|
STAGE_DIR="${BUILD_DIR}/argus-wordpress-defence"
|
|
OUT_DIR="${REPO_ROOT}/dist"
|
|
|
|
cleanup() { rm -rf "${BUILD_DIR}"; }
|
|
trap cleanup EXIT
|
|
|
|
echo "==> Packaging ${REF} from a clean checkout (git archive, not the working tree)"
|
|
mkdir -p "${STAGE_DIR}"
|
|
git -C "${REPO_ROOT}" archive "${REF}" | tar -x -C "${STAGE_DIR}"
|
|
|
|
echo "==> Removing dev-only paths not meant for the production artifact"
|
|
rm -rf \
|
|
"${STAGE_DIR}/docs" \
|
|
"${STAGE_DIR}/tests" \
|
|
"${STAGE_DIR}/README.md" \
|
|
"${STAGE_DIR}/ARGUS_WORDPRESS_SECURITY_ARCHITECTURE.md" \
|
|
"${STAGE_DIR}/.gitignore" \
|
|
"${STAGE_DIR}/bin"
|
|
|
|
echo "==> Allowlist audit -- fail closed on anything unexpected"
|
|
UNEXPECTED=0
|
|
while IFS= read -r -d '' item; do
|
|
rel="${item#"${STAGE_DIR}"/}"
|
|
case "$rel" in
|
|
argus-wordpress-defence.php|uninstall.php|readme.txt) ;;
|
|
admin|admin/*|includes|includes/*|mu-loader|mu-loader/*|assets|assets/*|languages|languages/*) ;;
|
|
*)
|
|
if [ -f "$item" ]; then
|
|
echo " UNEXPECTED FILE: ${rel}"
|
|
UNEXPECTED=1
|
|
fi
|
|
;;
|
|
esac
|
|
done < <(find "${STAGE_DIR}" -print0)
|
|
|
|
# Reject known-forbidden patterns explicitly, even inside allowlisted dirs.
|
|
if find "${STAGE_DIR}" \( -name "*.key" -o -name "*.pem" -o -name ".env*" -o -name "*.map" \) | grep -q .; then
|
|
echo " FORBIDDEN FILE TYPE found (key/pem/.env/source map)"
|
|
UNEXPECTED=1
|
|
fi
|
|
|
|
if [ "${UNEXPECTED}" -ne 0 ]; then
|
|
echo "==> BUILD FAILED: allowlist audit found unexpected content. Nothing was packaged."
|
|
exit 1
|
|
fi
|
|
echo " clean -- only allowlisted paths present"
|
|
|
|
# Read the version BEFORE stripping -- it lives inside the plugin
|
|
# header's own DocBlock comment, which php_strip_whitespace() below
|
|
# would otherwise remove before this ever got a chance to read it.
|
|
VERSION="$(grep -oP '(?<=Version:)\s*\K\S+' "${STAGE_DIR}/argus-wordpress-defence.php" | head -1)"
|
|
if [ -z "${VERSION}" ]; then
|
|
echo "==> BUILD FAILED: could not read plugin version from argus-wordpress-defence.php"
|
|
exit 1
|
|
fi
|
|
echo "==> Packaging version ${VERSION}"
|
|
|
|
echo "==> Stripping comments/whitespace (not obfuscation -- see bin/strip-comments.php)"
|
|
php "${REPO_ROOT}/bin/strip-comments.php" "${STAGE_DIR}"
|
|
|
|
mkdir -p "${OUT_DIR}"
|
|
ZIP_PATH="${OUT_DIR}/argus-wordpress-defence-${VERSION}.zip"
|
|
rm -f "${ZIP_PATH}"
|
|
# Prefer the `zip` CLI when present (most CI runners have it); fall
|
|
# back to PHP's ZipArchive (bin/zip-directory.php) for a host that
|
|
# only has the PHP extension -- either is a real, complete archive, no
|
|
# feature difference between the two paths.
|
|
if command -v zip >/dev/null 2>&1; then
|
|
( cd "${BUILD_DIR}" && zip -rq "${ZIP_PATH}" "argus-wordpress-defence" )
|
|
else
|
|
php "${REPO_ROOT}/bin/zip-directory.php" "${STAGE_DIR}" "${ZIP_PATH}" "argus-wordpress-defence"
|
|
fi
|
|
|
|
SHA256="$(sha256sum "${ZIP_PATH}" | cut -d' ' -f1)"
|
|
echo "${SHA256} $(basename "${ZIP_PATH}")" > "${ZIP_PATH}.sha256"
|
|
|
|
echo "==> Done"
|
|
echo " ${ZIP_PATH}"
|
|
echo " SHA-256: ${SHA256}"
|
|
echo " Size: $(du -h "${ZIP_PATH}" | cut -f1)"
|