Morning Brief #5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Morning Brief | |
| on: | |
| schedule: | |
| # Daily morning: 10pm UTC = 8am AEST (next day) | |
| - cron: "0 22 * * *" | |
| # Intraday checks: weekdays only (Mon-Fri) | |
| - cron: "0 0 * * 1-5" # 10am AEST | |
| - cron: "0 2 * * 1-5" # 12pm AEST | |
| - cron: "0 4 * * 1-5" # 2pm AEST | |
| - cron: "0 6 * * 1-5" # 4pm AEST | |
| workflow_dispatch: | |
| inputs: | |
| mode: | |
| description: "Run mode" | |
| required: false | |
| default: "daily" | |
| type: choice | |
| options: | |
| - daily | |
| - weekly | |
| - intraday | |
| jobs: | |
| send-brief: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| # Write config.json from secret (gitignored, contains private portfolio data) | |
| - run: printenv CONFIG_JSON > config.json | |
| env: | |
| CONFIG_JSON: ${{ secrets.CONFIG_JSON }} | |
| # Restore intraday state cache (morning baseline for comparison) | |
| - uses: actions/cache@v4 | |
| with: | |
| path: state/ | |
| key: intraday-state-${{ github.run_id }} | |
| restore-keys: | | |
| intraday-state- | |
| # Determine run mode from schedule or manual input | |
| - name: Determine mode | |
| id: mode | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "mode=${{ github.event.inputs.mode }}" >> $GITHUB_OUTPUT | |
| elif [ "${{ github.event.schedule }}" = "0 22 * * *" ]; then | |
| echo "mode=daily" >> $GITHUB_OUTPUT | |
| else | |
| echo "mode=intraday" >> $GITHUB_OUTPUT | |
| fi | |
| echo "Resolved mode: $(grep mode= $GITHUB_OUTPUT | cut -d= -f2)" | |
| # Daily morning brief | |
| - run: npm run start | |
| if: steps.mode.outputs.mode == 'daily' | |
| env: | |
| RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }} | |
| NEWS_API_KEY: ${{ secrets.NEWS_API_KEY }} | |
| GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} | |
| RECIPIENT_EMAIL: ${{ secrets.RECIPIENT_EMAIL }} | |
| TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} | |
| TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} | |
| # Weekly rebalancing report | |
| - run: npm run weekly | |
| if: steps.mode.outputs.mode == 'weekly' | |
| env: | |
| RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }} | |
| RECIPIENT_EMAIL: ${{ secrets.RECIPIENT_EMAIL }} | |
| TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} | |
| TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} | |
| # Intraday check — no NEWS_API_KEY (saves quota) | |
| - run: npm run intraday | |
| if: steps.mode.outputs.mode == 'intraday' | |
| env: | |
| RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }} | |
| GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} | |
| RECIPIENT_EMAIL: ${{ secrets.RECIPIENT_EMAIL }} | |
| TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} | |
| TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} | |
| # Weekly rebalancing report — Sunday 10pm UTC = Monday 8am AEST | |
| send-weekly: | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'schedule' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - run: npm ci | |
| - run: printenv CONFIG_JSON > config.json | |
| env: | |
| CONFIG_JSON: ${{ secrets.CONFIG_JSON }} | |
| - run: | | |
| DAY_OF_WEEK=$(date -u +%u) | |
| if [ "$DAY_OF_WEEK" = "7" ]; then | |
| npm run weekly | |
| else | |
| echo "Not Sunday (day=$DAY_OF_WEEK), skipping weekly report" | |
| fi | |
| env: | |
| RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }} | |
| RECIPIENT_EMAIL: ${{ secrets.RECIPIENT_EMAIL }} | |
| TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} | |
| TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} |