WP Plugin Starter 1.0.0: a fresh start
The parts every wpallstars plugin needs: settings screen with search and an empty General tab, Read Me tab, features as classes, replaced plugins, the shared GitHub updater, release and check scripts, CI and the shared rules. scripts/rename-plugin.sh starts a new plugin; scripts/sync-core.sh keeps plugins' core files in step with this starter. Built with aidevops (https://aidevops.sh).
This commit is contained in:
commit
2f91c3e6af
62 files changed
+10929
No files matched your search
Executable
+195
@@ -0,0 +1,195 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build the release zips of the plugin from a Git ref.
|
||||
#
|
||||
# Two builds of the same version, both with one {slug}/ folder inside (the
|
||||
# slug is the main file's name, scripts/lib/plugin.sh):
|
||||
# {slug}-X.Y.Z.zip
|
||||
# GitHub release asset: the files in Git, less .distignore.
|
||||
# wordpress-org-{slug}-X.Y.Z.zip
|
||||
# WordPress.org build: the same, less the files in .distignore-wporg and
|
||||
# the GitHub updater header lines. Its name does not start with the
|
||||
# slug, so no updater picks it even if it is attached to a GitHub
|
||||
# release by mistake (it takes the first asset whose name starts with
|
||||
# the plugin slug). Never attach it to a GitHub release.
|
||||
# SHA256SUMS
|
||||
#
|
||||
# Files come from the Git ref (git archive), never from the working tree, so
|
||||
# uncommitted changes and untracked files are never included.
|
||||
#
|
||||
# Usage: scripts/build-release.sh [--ref REF] [--out DIR] [--quiet]
|
||||
# --ref REF Commit, branch or tag to build (default: HEAD).
|
||||
# --out DIR Output folder (default: dist/ in the repository, gitignored).
|
||||
# --quiet Print only the paths of the zips.
|
||||
#
|
||||
# Needs git, rsync, zip, unzip and shasum or sha256sum.
|
||||
|
||||
set -euo pipefail
|
||||
umask 022
|
||||
export TZ=UTC
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
readonly SCRIPT_DIR
|
||||
# shellcheck source=scripts/lib/plugin.sh disable=SC1091 # followed only with -x
|
||||
. "$SCRIPT_DIR/lib/plugin.sh"
|
||||
readonly WPORG_IGNORE=".distignore-wporg"
|
||||
# Header lines read only by GitHub updaters (ours and Git Updater); left out of the WordPress.org build.
|
||||
readonly WPORG_STRIP_HEADERS='GitHub Plugin URI|Primary Branch|Release Asset'
|
||||
|
||||
TMP_DIR=""
|
||||
SLUG=""
|
||||
MAIN_FILE=""
|
||||
|
||||
die() {
|
||||
local message="$1"
|
||||
printf 'build-release: %s\n' "$message" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
usage() {
|
||||
sed -n '2,24p' "$0" | sed 's/^# \{0,1\}//'
|
||||
return 0
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
if [ -n "$TMP_DIR" ] && [ -d "$TMP_DIR" ]; then
|
||||
rm -rf "$TMP_DIR"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
need() {
|
||||
local tool="$1"
|
||||
command -v "$tool" >/dev/null 2>&1 || die "needs $tool"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Version: header of the main file at a commit.
|
||||
version_at() {
|
||||
local sha="$1"
|
||||
git show "$sha:$MAIN_FILE" | sed -n 's/^[[:space:]*]*Version:[[:space:]]*\([^[:space:]]*\).*/\1/p' | head -n 1
|
||||
return 0
|
||||
}
|
||||
|
||||
sha256_of() {
|
||||
local file="$1"
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
shasum -a 256 "$file" | cut -d' ' -f1
|
||||
else
|
||||
sha256sum "$file" | cut -d' ' -f1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Zip <folder>/<SLUG> as <zip>, with the slug folder at the top. Fixed times,
|
||||
# modes (umask) and entry order make the same ref give the same zip anywhere.
|
||||
make_zip() {
|
||||
local folder="$1"
|
||||
local zip_path="$2"
|
||||
local partial="$zip_path.partial"
|
||||
rm -f "$zip_path" "$partial"
|
||||
(cd "$folder" && find "$SLUG" -exec touch -h -t 202001010000 {} + && find "$SLUG" | LC_ALL=C sort | zip -qX "$partial" -@)
|
||||
mv "$partial" "$zip_path"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Remove the GitHub updater header lines from the main file of a build.
|
||||
strip_updater_headers() {
|
||||
local main="$1"
|
||||
local stripped="$main.tmp"
|
||||
grep -Ev "^[[:space:]*]*($WPORG_STRIP_HEADERS):" "$main" >"$stripped"
|
||||
mv "$stripped" "$main"
|
||||
return 0
|
||||
}
|
||||
|
||||
main() {
|
||||
local ref="HEAD"
|
||||
local out=""
|
||||
local quiet=0
|
||||
local arg
|
||||
while [ $# -gt 0 ]; do
|
||||
arg="$1"
|
||||
case "$arg" in
|
||||
--ref)
|
||||
[ $# -ge 2 ] || die "--ref needs a value"
|
||||
ref="$2"
|
||||
shift
|
||||
;;
|
||||
--out)
|
||||
[ $# -ge 2 ] || die "--out needs a value"
|
||||
out="$2"
|
||||
shift
|
||||
;;
|
||||
--quiet) quiet=1 ;;
|
||||
-h | --help)
|
||||
usage
|
||||
return 0
|
||||
;;
|
||||
*) die "unknown argument: $arg" ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
local tool
|
||||
for tool in git rsync zip unzip; do
|
||||
need "$tool"
|
||||
done
|
||||
|
||||
local root sha version
|
||||
root="$(git rev-parse --show-toplevel)" || die "run this inside a checkout of the plugin"
|
||||
cd "$root"
|
||||
sha="$(git rev-parse --verify --quiet "$ref^{commit}")" || die "not a commit: $ref"
|
||||
plugin_identity "$sha" || die "cannot tell which plugin this is at $ref"
|
||||
SLUG="$PLUGIN_SLUG"
|
||||
MAIN_FILE="$PLUGIN_MAIN_FILE"
|
||||
version="$(version_at "$sha")"
|
||||
[ -n "$version" ] || die "no Version: header in $MAIN_FILE at $ref"
|
||||
|
||||
if [ "$ref" = "HEAD" ] && [ -n "$(git status --porcelain --untracked-files=no)" ] && [ "$quiet" -eq 0 ]; then
|
||||
printf 'Note: uncommitted changes are not in the build (it is made from HEAD).\n'
|
||||
fi
|
||||
|
||||
[ -n "$out" ] || out="$root/dist"
|
||||
mkdir -p "$out"
|
||||
out="$(cd "$out" && pwd)"
|
||||
|
||||
trap cleanup EXIT
|
||||
TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/$SLUG-build.XXXXXX")"
|
||||
mkdir -p "$TMP_DIR/src" "$TMP_DIR/github/$SLUG" "$TMP_DIR/wporg/$SLUG"
|
||||
|
||||
git archive --format=tar "$sha" | tar -x -C "$TMP_DIR/src"
|
||||
# .distignore lists itself and is export-ignored, so read it from Git.
|
||||
git show "$sha:.distignore" >"$TMP_DIR/distignore" || die ".distignore missing at $ref"
|
||||
rsync -a --exclude-from="$TMP_DIR/distignore" "$TMP_DIR/src/" "$TMP_DIR/github/$SLUG/"
|
||||
[ -f "$TMP_DIR/github/$SLUG/$MAIN_FILE" ] || die "$MAIN_FILE is not in the build; check .distignore"
|
||||
|
||||
if git cat-file -e "$sha:$WPORG_IGNORE" 2>/dev/null; then
|
||||
git show "$sha:$WPORG_IGNORE" >"$TMP_DIR/wporg-ignore"
|
||||
else
|
||||
: >"$TMP_DIR/wporg-ignore"
|
||||
fi
|
||||
rsync -a --exclude-from="$TMP_DIR/wporg-ignore" "$TMP_DIR/github/$SLUG/" "$TMP_DIR/wporg/$SLUG/"
|
||||
strip_updater_headers "$TMP_DIR/wporg/$SLUG/$MAIN_FILE"
|
||||
|
||||
local github_zip="$out/$SLUG-$version.zip"
|
||||
local wporg_zip="$out/wordpress-org-$SLUG-$version.zip"
|
||||
make_zip "$TMP_DIR/github" "$github_zip"
|
||||
make_zip "$TMP_DIR/wporg" "$wporg_zip"
|
||||
|
||||
{
|
||||
printf '%s %s\n' "$(sha256_of "$github_zip")" "$(basename "$github_zip")"
|
||||
printf '%s %s\n' "$(sha256_of "$wporg_zip")" "$(basename "$wporg_zip")"
|
||||
} >"$out/SHA256SUMS"
|
||||
|
||||
if [ "$quiet" -eq 1 ]; then
|
||||
printf '%s\n%s\n' "$github_zip" "$wporg_zip"
|
||||
return 0
|
||||
fi
|
||||
printf '%s %s from %s (%s)\n' "$PLUGIN_NAME" "$version" "$ref" "${sha:0:12}"
|
||||
printf ' GitHub release: %s (%s files)\n' "$github_zip" "$(unzip -Z1 "$github_zip" | grep -cv '/$')"
|
||||
printf ' WordPress.org: %s (%s files)\n' "$wporg_zip" "$(unzip -Z1 "$wporg_zip" | grep -cv '/$')"
|
||||
printf ' Checksums: %s\n' "$out/SHA256SUMS"
|
||||
printf 'Check them with: scripts/preflight-release.sh --ref %s\n' "$ref"
|
||||
return 0
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in new issue
Block a user