feat: Phase 1 添加 GHA 定时、run-daily.sh 与 Docker 部署
让早报可在无本地服务器环境下定时生成并推送企微,补齐 Linux/CI 入口。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
106
run-daily.sh
Normal file
106
run-daily.sh
Normal file
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env bash
|
||||
# Daily report: generate + push to WeCom webhook
|
||||
# Usage:
|
||||
# ./run-daily.sh
|
||||
# ./run-daily.sh --skip-push
|
||||
# ./run-daily.sh --skip-generate
|
||||
# ./run-daily.sh --force
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$ROOT"
|
||||
|
||||
LOCK_FILE="$ROOT/.cache/run-daily.lock"
|
||||
LOCK_MAX_MINUTES=30
|
||||
SKIP_PUSH=0
|
||||
SKIP_GENERATE=0
|
||||
FORCE=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--skip-push) SKIP_PUSH=1 ;;
|
||||
--skip-generate) SKIP_GENERATE=1 ;;
|
||||
--force) FORCE=1 ;;
|
||||
-h|--help)
|
||||
echo "Usage: $0 [--skip-push] [--skip-generate] [--force]"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
load_dotenv() {
|
||||
local file="$1"
|
||||
[[ -f "$file" ]] || return 0
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
||||
[[ "$line" != *"="* ]] && continue
|
||||
local name="${line%%=*}"
|
||||
local value="${line#*=}"
|
||||
name="${name#"${name%%[![:space:]]*}"}"
|
||||
name="${name%"${name##*[![:space:]]}"}"
|
||||
value="${value#"${value%%[![:space:]]*}"}"
|
||||
value="${value%"${value##*[![:space:]]}"}"
|
||||
value="${value%\"}"
|
||||
value="${value#\"}"
|
||||
value="${value%\'}"
|
||||
value="${value#\'}"
|
||||
if [[ -n "$name" && -n "$value" ]]; then
|
||||
export "$name=$value"
|
||||
fi
|
||||
done < "$file"
|
||||
}
|
||||
|
||||
lock_active() {
|
||||
[[ -f "$LOCK_FILE" ]] || return 1
|
||||
local now lock_ts age_minutes
|
||||
now="$(date +%s)"
|
||||
lock_ts="$(date -r "$LOCK_FILE" +%s 2>/dev/null || stat -c %Y "$LOCK_FILE" 2>/dev/null || echo 0)"
|
||||
age_minutes=$(( (now - lock_ts) / 60 ))
|
||||
[[ "$age_minutes" -lt "$LOCK_MAX_MINUTES" ]]
|
||||
}
|
||||
|
||||
set_lock() {
|
||||
mkdir -p "$(dirname "$LOCK_FILE")"
|
||||
date -Iseconds > "$LOCK_FILE"
|
||||
}
|
||||
|
||||
clear_lock() {
|
||||
rm -f "$LOCK_FILE"
|
||||
}
|
||||
|
||||
if [[ "$FORCE" -eq 0 ]] && lock_active; then
|
||||
echo "Skip: run-daily already ran within ${LOCK_MAX_MINUTES} minutes (lock: $LOCK_FILE). Use --force to override."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
set_lock
|
||||
trap clear_lock EXIT
|
||||
|
||||
load_dotenv "$ROOT/.env"
|
||||
load_dotenv "$ROOT/.env.local"
|
||||
|
||||
PYTHON="${PYTHON:-python}"
|
||||
DATE="$(TZ=Asia/Shanghai date +%Y-%m-%d)"
|
||||
REPORT_WECOM="$ROOT/output/${DATE}.wecom.md"
|
||||
|
||||
if [[ "$SKIP_GENERATE" -eq 0 ]]; then
|
||||
echo "Generating daily report: $DATE"
|
||||
"$PYTHON" -m daily generate
|
||||
fi
|
||||
|
||||
if [[ "$SKIP_PUSH" -eq 0 ]]; then
|
||||
if [[ ! -f "$REPORT_WECOM" ]]; then
|
||||
echo "Report not found: $REPORT_WECOM" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Pushing to WeCom webhook..."
|
||||
"$PYTHON" -m daily push "$REPORT_WECOM"
|
||||
fi
|
||||
|
||||
echo "Done: $DATE"
|
||||
Reference in New Issue
Block a user