98 lines
3.2 KiB
Bash
Executable file
98 lines
3.2 KiB
Bash
Executable file
#!/bin/bash
|
|
# Build jobbsok.plugin from an explicit include list.
|
|
#
|
|
# bash 3.2-clean and ASCII-only on purpose: the system bash on this Mac is 3.2.
|
|
#
|
|
# The include list is the whole point, and it is not a convenience. zip does
|
|
# not consult .gitignore, so archiving the repository root would ship .git,
|
|
# the virtualenv from Step 2, the local-only STATE.md and everything under
|
|
# .claude/ -- which holds the operator's decisions and absolute home paths.
|
|
# This archive is uploaded to Cowork once per milestone and its command is
|
|
# printed in a public README. An include list is the only form that is safe to
|
|
# publish.
|
|
#
|
|
# The virtualenv is excluded for a second reason on top of that one: a venv's
|
|
# absolute paths do not survive relocation, so an archived one would be broken
|
|
# wherever it landed. The supported route in an installed copy is to run
|
|
# scripts/bootstrap.sh once against it, which builds the environment under
|
|
# $CLAUDE_PLUGIN_DATA. README.md says so.
|
|
#
|
|
# Usage:
|
|
# bash scripts/package_plugin.sh # -> <repo root>/jobbsok.plugin
|
|
# bash scripts/package_plugin.sh --ut <sti> # -> somewhere else
|
|
|
|
set -eu
|
|
|
|
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
|
REPO_ROOT=$(cd "$SCRIPT_DIR/.." && pwd)
|
|
OUT="${REPO_ROOT}/jobbsok.plugin"
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--ut)
|
|
if [ $# -lt 2 ]; then
|
|
echo "package_plugin: --ut needs a path" >&2
|
|
exit 2
|
|
fi
|
|
OUT="$2"
|
|
shift 2 ;;
|
|
-h|--help)
|
|
sed -n '2,23p' "$0"
|
|
exit 0 ;;
|
|
*)
|
|
echo "package_plugin: unknown argument: $1" >&2
|
|
exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
case "$OUT" in
|
|
/*) ;;
|
|
*) OUT="$(pwd)/$OUT" ;;
|
|
esac
|
|
|
|
# Regenerate first: an archive carrying a stale stamp is the exact failure the
|
|
# stamp exists to catch, and building one would be worse than not stamping.
|
|
bash "${SCRIPT_DIR}/build_stamp.sh"
|
|
|
|
# The include list. Directories are archived whole, minus the exclusions below.
|
|
# Entries that do not exist yet are reported and skipped -- hooks/, templates/
|
|
# and SECURITY.md land in later steps -- but the two the archive is worthless
|
|
# without are required outright.
|
|
INCLUDE=".claude-plugin skills scripts hooks templates .mcp.json README.md SECURITY.md LICENSE BUILD_STAMP"
|
|
REQUIRED=".claude-plugin/plugin.json BUILD_STAMP"
|
|
|
|
for path in $REQUIRED; do
|
|
if [ ! -e "${REPO_ROOT}/${path}" ]; then
|
|
echo "package_plugin: required entry missing: $path" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
PRESENT=""
|
|
SKIPPED=""
|
|
for path in $INCLUDE; do
|
|
if [ -e "${REPO_ROOT}/${path}" ]; then
|
|
PRESENT="$PRESENT $path"
|
|
else
|
|
SKIPPED="$SKIPPED $path"
|
|
fi
|
|
done
|
|
|
|
if [ -n "$SKIPPED" ]; then
|
|
echo "package_plugin: not present yet, skipped:$SKIPPED"
|
|
fi
|
|
|
|
rm -f "$OUT"
|
|
|
|
# -X drops the extra file attributes, so the archive is reproducible enough
|
|
# that two builds of the same commit differ only in timestamps. The exclusions
|
|
# are belt to the include list's braces: nothing under scripts/ or skills/ that
|
|
# is a build artefact of a local test run may ride along.
|
|
cd "$REPO_ROOT"
|
|
# shellcheck disable=SC2086 -- PRESENT is a deliberate word-split list
|
|
zip -q -r -X "$OUT" $PRESENT \
|
|
-x '*/__pycache__/*' '*.pyc' '*/.pytest_cache/*' '*/.venv/*' '*.local.md' \
|
|
'*/.DS_Store'
|
|
|
|
echo "package_plugin: $(basename "$OUT") built from $(cat "${REPO_ROOT}/BUILD_STAMP")"
|
|
echo "package_plugin: $OUT"
|