#!/usr/bin/env bash set -euo pipefail WF_DIR="${HOME}/.gemini/config/global_workflows" SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" usage() { cat <<'EOF' Usage: ./workflow list ./workflow run [args...] Workflows: load-ids daily-work-log hotfix-prod demo-day-pptx start-task [--stash] promote-env [--force-main] monthly-report now-push "" ["detail 1" "detail 2"...] EOF } require_repo() { git -C "${SELF_DIR}" rev-parse --is-inside-work-tree >/dev/null } ensure_dev_window_for_main() { local now_dow now_hm now_dow="$(date +%u)" # 1..7 = Mon..Sun now_hm="$(date +%H%M)" if [[ "${now_dow}" -gt 4 || "${now_hm}" -gt 1200 ]]; then echo "WARNING: 現在不在標準上線時段(週一至週四 12:00 前)。" if [[ "${1:-}" != "--force-main" ]]; then echo "中止。若確認要繼續,請加上 --force-main。" exit 1 fi fi } cmd_list() { ls -1 "${WF_DIR}" 2>/dev/null | sed 's/\.md$//' } cmd_load_ids() { sed -n '1,120p' "${HOME}/.gemini/AGENTS.md" echo sed -n '1,120p' "${HOME}/.gemini/GEMINI.md" echo echo "身份與全域規範已加載完成。" } cmd_daily_work_log() { require_repo git -C "${SELF_DIR}" log --since="midnight" --pretty=format:"%h - %s (%an)" } cmd_hotfix_prod() { require_repo local name="${1:-}" if [[ -z "${name}" ]]; then echo "hotfix-prod 需要 hotfix 名稱。" exit 1 fi git -C "${SELF_DIR}" checkout main git -C "${SELF_DIR}" pull origin main git -C "${SELF_DIR}" checkout -b "hotfix/${name}" echo "已建立分支 hotfix/${name}。完成修復後請自行合併到 main,再回補 demo/dev。" } cmd_demo_day_pptx() { cat <<'EOF' demo-day-pptx 已觸發: 1) 先產出 implementation_plan.md(7-9頁)給你確認 2) 確認後再執行 PPTX 產製 EOF } cmd_start_task() { require_repo local kind="${1:-}" name="${2:-}" stash_opt="${3:-}" if [[ ! "${kind}" =~ ^(feat|fix|refactor|docs)$ ]] || [[ -z "${name}" ]]; then echo "用法:./workflow run start-task [--stash]" exit 1 fi if [[ -n "$(git -C "${SELF_DIR}" status --porcelain)" && "${stash_opt}" == "--stash" ]]; then git -C "${SELF_DIR}" stash push -u -m "workflow:start-task" fi git -C "${SELF_DIR}" checkout dev git -C "${SELF_DIR}" pull origin dev git -C "${SELF_DIR}" checkout -b "${kind}/${name}" if git -C "${SELF_DIR}" stash list | rg -q "workflow:start-task"; then git -C "${SELF_DIR}" stash pop || true fi echo "已切到分支 ${kind}/${name}" } cmd_promote_env() { require_repo local src="${1:-}" dst="${2:-}" force_main="${3:-}" if [[ -z "${src}" || -z "${dst}" ]]; then echo "用法:./workflow run promote-env [--force-main]" exit 1 fi if [[ "${src}" == "dev" && "${dst}" != "demo" ]]; then echo "僅允許 dev -> demo。" exit 1 fi if [[ "${src}" == "demo" && "${dst}" != "main" ]]; then echo "僅允許 demo -> main。" exit 1 fi if [[ "${dst}" == "main" ]]; then ensure_dev_window_for_main "${force_main:-}" fi echo "=== 待晉升提交 ===" git -C "${SELF_DIR}" log "${dst}..${src}" --oneline || true echo echo "=== 敏感檔案檢查 ===" git -C "${SELF_DIR}" diff --name-only "${dst}...${src}" | rg "^(database/migrations/|\.env\.example|rbac-rules\.md)" || true git -C "${SELF_DIR}" checkout "${dst}" git -C "${SELF_DIR}" pull origin "${dst}" git -C "${SELF_DIR}" merge "${src}" --no-ff -m "[PROMOTE] ${src} -> ${dst}" git -C "${SELF_DIR}" push origin "${dst}" git -C "${SELF_DIR}" checkout dev } cmd_monthly_report() { local year="${1:-}" month="${2:-}" if [[ ! "${year}" =~ ^[0-9]{4}$ ]] || [[ ! "${month}" =~ ^[0-9]{1,2}$ ]]; then echo "用法:./workflow run monthly-report " exit 1 fi local out="${SELF_DIR}/docs/monthly-report-${year}-$(printf "%02d" "${month}").md" mkdir -p "${SELF_DIR}/docs" cat > "${out}" < "" ["detail 1" ...]' exit 1 fi local p="[${prefix}]" if [[ ! "${p}" =~ ^\[(FIX|FEAT|DOCS|STYLE|REFACTOR)\]$ ]]; then echo "prefix 僅能為 FIX/FEAT/DOCS/STYLE/REFACTOR" exit 1 fi if [[ "${target}" == "main" ]]; then ensure_dev_window_for_main "${4:-}" fi local msg="${p} ${summary}" if [[ "$#" -gt 0 ]]; then msg+=$'\n\n' local i=1 for item in "$@"; do msg+="${i}. ${item}"$'\n' i=$((i+1)) done fi git -C "${SELF_DIR}" add -A git -C "${SELF_DIR}" commit -m "${msg}" local cur cur="$(git -C "${SELF_DIR}" branch --show-current)" git -C "${SELF_DIR}" push origin "${cur}:${target}" } main() { local action="${1:-}" case "${action}" in list) cmd_list ;; run) local name="${2:-}" shift 2 || true case "${name}" in load-ids) cmd_load_ids "$@" ;; daily-work-log) cmd_daily_work_log "$@" ;; hotfix-prod) cmd_hotfix_prod "$@" ;; demo-day-pptx) cmd_demo_day_pptx "$@" ;; start-task) cmd_start_task "$@" ;; promote-env) cmd_promote_env "$@" ;; monthly-report) cmd_monthly_report "$@" ;; now-push) cmd_now_push "$@" ;; *) usage; exit 1 ;; esac ;; *) usage; exit 1 ;; esac } main "$@"