chore: consolidate new foundation and archive v1 (#1495)
This commit is contained in:
+148
@@ -0,0 +1,148 @@
|
||||
#!/bin/bash
|
||||
# milestone-create.sh - Create milestones on Gitea or GitHub
|
||||
# Usage: milestone-create.sh -t "Title" [-d "Description"] [--due "YYYY-MM-DD"]
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/detect-platform.sh"
|
||||
|
||||
# Default values
|
||||
TITLE=""
|
||||
DESCRIPTION=""
|
||||
DUE_DATE=""
|
||||
LIST_ONLY=false
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [OPTIONS]
|
||||
|
||||
Create or list milestones on the current repository (Gitea or GitHub).
|
||||
|
||||
Versioning Convention:
|
||||
- Features get dedicated milestones
|
||||
- Pre-MVP milestones MUST use 0.0.x and MUST start at 0.0.1
|
||||
- 0.1.0 is reserved for MVP release
|
||||
- After MVP, continue semantic progression (0.1.x, 0.2.x, ...)
|
||||
|
||||
Options:
|
||||
-t, --title TITLE Milestone title/version (e.g., "0.0.1")
|
||||
-d, --desc DESCRIPTION Milestone description
|
||||
--due DATE Due date (YYYY-MM-DD format)
|
||||
--list List existing milestones
|
||||
-h, --help Show this help message
|
||||
|
||||
Examples:
|
||||
$(basename "$0") --list
|
||||
$(basename "$0") -t "0.0.1" -d "Pre-MVP Foundation Sprint"
|
||||
$(basename "$0") -t "0.1.0" -d "MVP Release" --due "2025-03-01"
|
||||
EOF
|
||||
exit "${1:-2}"
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
# Usage-error contract (R4, 2026-08-28): usage errors print to STDERR and exit 2,
|
||||
# distinct from provider, credential, and verification failures (exit 1).
|
||||
usage_error() {
|
||||
echo "Error: $*" >&2
|
||||
usage >&2
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-t|--title)
|
||||
[[ $# -ge 2 && "$2" != - && "$2" != --* && ! "$2" =~ ^-[[:alnum:]] ]] || usage_error "option $1 requires a value (option-like values are rejected; bare - is reserved)"
|
||||
TITLE="$2"
|
||||
shift 2
|
||||
;;
|
||||
-d|--desc)
|
||||
[[ $# -ge 2 && "$2" != - && "$2" != --* && ! "$2" =~ ^-[[:alnum:]] ]] || usage_error "option $1 requires a value (option-like values are rejected; bare - is reserved)"
|
||||
DESCRIPTION="$2"
|
||||
shift 2
|
||||
;;
|
||||
--due)
|
||||
[[ $# -ge 2 && "$2" != - && "$2" != --* && ! "$2" =~ ^-[[:alnum:]] ]] || usage_error "option $1 requires a value (option-like values are rejected; bare - is reserved)"
|
||||
DUE_DATE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--list)
|
||||
LIST_ONLY=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1" >&2
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
PLATFORM=$(detect_platform)
|
||||
|
||||
if [[ "$LIST_ONLY" == true ]]; then
|
||||
case "$PLATFORM" in
|
||||
github)
|
||||
prov_rc=0
|
||||
gh api repos/:owner/:repo/milestones --jq '.[] | "\(.number)\t\(.title)\t\(.state)\t\(.open_issues)/\(.closed_issues) issues"' || prov_rc=$?
|
||||
[[ "$prov_rc" -eq 0 ]] || { echo "Error: provider command failed (exit ${prov_rc}; provider failure, not a usage error)" >&2; exit 1; }
|
||||
;;
|
||||
gitea)
|
||||
REPO_ARGS=$(get_gitea_repo_args) || {
|
||||
echo "Error: Could not resolve Gitea repo/login for remote host" >&2
|
||||
exit 1
|
||||
}
|
||||
prov_rc=0
|
||||
tea milestones list $REPO_ARGS || prov_rc=$?
|
||||
[[ "$prov_rc" -eq 0 ]] || { echo "Error: provider command failed (exit ${prov_rc}; provider failure, not a usage error)" >&2; exit 1; }
|
||||
;;
|
||||
*)
|
||||
echo "Error: Could not detect git platform" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -z "$TITLE" ]]; then
|
||||
usage_error "Title is required (-t) for creating milestones"
|
||||
fi
|
||||
|
||||
case "$PLATFORM" in
|
||||
github)
|
||||
# GitHub uses the API for milestone creation
|
||||
# Use jq to safely construct JSON so titles/descriptions containing
|
||||
# quotes or special characters do not corrupt the payload (F-07).
|
||||
JSON_PAYLOAD=$(jq -n \
|
||||
--arg t "$TITLE" \
|
||||
--arg d "$DESCRIPTION" \
|
||||
--arg due "${DUE_DATE}" \
|
||||
'{"title": $t}
|
||||
+ (if $d != "" then {"description": $d} else {} end)
|
||||
+ (if $due != "" then {"due_on": ($due + "T00:00:00Z")} else {} end)')
|
||||
|
||||
prov_rc=0
|
||||
gh api repos/:owner/:repo/milestones --method POST --input - <<< "$JSON_PAYLOAD" || prov_rc=$?
|
||||
[[ "$prov_rc" -eq 0 ]] || { echo "Error: provider command failed (exit ${prov_rc}; provider failure, not a usage error)" >&2; exit 1; }
|
||||
echo "Milestone '$TITLE' created successfully"
|
||||
;;
|
||||
gitea)
|
||||
REPO_ARGS=$(get_gitea_repo_args) || {
|
||||
echo "Error: Could not resolve Gitea repo/login for remote host" >&2
|
||||
exit 1
|
||||
}
|
||||
CMD=(tea milestones create --title "$TITLE")
|
||||
[[ -n "$DESCRIPTION" ]] && CMD+=(--description "$DESCRIPTION")
|
||||
[[ -n "$DUE_DATE" ]] && CMD+=(--deadline "$DUE_DATE")
|
||||
prov_rc=0
|
||||
"${CMD[@]}" $REPO_ARGS || prov_rc=$?
|
||||
[[ "$prov_rc" -eq 0 ]] || { echo "Error: provider command failed (exit ${prov_rc}; provider failure, not a usage error)" >&2; exit 1; }
|
||||
echo "Milestone '$TITLE' created successfully"
|
||||
;;
|
||||
*)
|
||||
echo "Error: Could not detect git platform" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user