Skip to content

Daily LinkedIn Post #18

Daily LinkedIn Post

Daily LinkedIn Post #18

Workflow file for this run

name: Daily LinkedIn Post
on:
schedule:
# GitHub `schedule` uses UTC only (no Europe/Madrid in cron).
# 06:00 UTC = 07:00 in Europe/Madrid when offset is CET (UTC+1, roughly late Oct–late Mar).
# For 07:00 during CEST (UTC+2, roughly late Mar–late Oct), use: cron: '0 5 * * *'
# Post goes live when this job finishes — the LinkedIn UGC API does not support “publish at midnight”
# from an earlier run; for ~midnight local posts, run the job near midnight instead (e.g. 23:00 UTC ≈ 00:00 CET).
- cron: '0 6 * * *'
workflow_dispatch:
inputs:
day_number:
description: 'Specific day number to post (1-500, leave empty for auto)'
required: false
default: ''
dry_run:
description: 'Dry run - generate but do not publish'
required: false
default: 'false'
type: choice
options:
- 'false'
- 'true'
jobs:
post:
name: Generate and Publish Post
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: pip install -r requirements.txt
# LINKEDIN_MEMBER_SUB = OpenID id_token "sub" (same as local .env). Required if userinfo/me fail in CI.
- name: Create .env file from GitHub Secrets
run: |
cat > .env << EOF
GEMINI_API_KEY=${{ secrets.GEMINI_API_KEY }}
LINKEDIN_EMAIL=${{ secrets.LINKEDIN_EMAIL }}
LINKEDIN_PASSWORD=${{ secrets.LINKEDIN_PASSWORD }}
LINKEDIN_ACCESS_TOKEN=${{ secrets.LINKEDIN_ACCESS_TOKEN }}
LINKEDIN_MEMBER_SUB=${{ secrets.LINKEDIN_MEMBER_SUB }}
CHROMA_PERSIST_DIR=./data/chroma
POST_CALENDAR_PATH=./data/post_calendar.csv
SCHEDULE_HOUR=12
SCHEDULE_MINUTE=15
TIMEZONE=Europe/Madrid
CALENDAR_SEQUENCE_START=${{ vars.CALENDAR_SEQUENCE_START }}
DRY_RUN=${{ github.event.inputs.dry_run || secrets.DRY_RUN || 'false' }}
EOF
- name: Run post pipeline
run: |
if [ -n "${{ github.event.inputs.day_number }}" ]; then
python main.py --run-now --day ${{ github.event.inputs.day_number }}
else
python main.py --run-now
fi
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
LINKEDIN_EMAIL: ${{ secrets.LINKEDIN_EMAIL }}
LINKEDIN_PASSWORD: ${{ secrets.LINKEDIN_PASSWORD }}
LINKEDIN_ACCESS_TOKEN: ${{ secrets.LINKEDIN_ACCESS_TOKEN }}
LINKEDIN_MEMBER_SUB: ${{ secrets.LINKEDIN_MEMBER_SUB }}
# Must match .env above: scheduled runs use secrets.DRY_RUN (omit or set false for real posts).
DRY_RUN: ${{ github.event.inputs.dry_run || secrets.DRY_RUN || 'false' }}
- name: Clean up .env
if: always()
run: rm -f .env