Skip to content

Production crons

Production crons #612

# Hobby Vercel only allows once-per-day native crons. Hourly report fan-out is
# triggered here. Secrets live on the agent-production environment (not repo secrets):
# CRON_SECRET — same value as Vercel Production
# CONTROL_PLANE_URL — e.g. https://usejunction.dev (already used by agent releases)
name: Production crons
on:
schedule:
# Daily report fan-out; app gates on local 19:00
- cron: "5 * * * *"
workflow_dispatch:
permissions:
contents: read
concurrency:
group: production-crons-daily-report-send
cancel-in-progress: false
jobs:
daily-report-send:
name: Daily report send
runs-on: ubuntu-latest
environment: agent-production
# PDF generation can approach the route maxDuration (300s)
timeout-minutes: 8
steps:
- name: Require environment secrets
env:
CRON_SECRET: ${{ secrets.CRON_SECRET }}
CONTROL_PLANE_URL: ${{ secrets.CONTROL_PLANE_URL }}
run: |
if [ -z "$CRON_SECRET" ] || [ -z "$CONTROL_PLANE_URL" ]; then
echo "::error::Set agent-production environment secrets CRON_SECRET and CONTROL_PLANE_URL (Settings → Environments → agent-production)"
exit 1
fi
- name: POST /api/cron/daily-report-send
env:
CRON_SECRET: ${{ secrets.CRON_SECRET }}
CONTROL_PLANE_URL: ${{ secrets.CONTROL_PLANE_URL }}
run: |
set -euo pipefail
base="${CONTROL_PLANE_URL%/}"
code=$(curl -sS -o /tmp/cron-body.json -w "%{http_code}" \
-X POST "$base/api/cron/daily-report-send" \
-H "Authorization: Bearer $CRON_SECRET" \
-H "Content-Type: application/json" \
--max-time 300)
echo "HTTP $code"
cat /tmp/cron-body.json || true
echo
test "$code" = "200"