-
Notifications
You must be signed in to change notification settings - Fork 3.6k
172 lines (152 loc) · 6.51 KB
/
Copy pathsync-newsletter.yml
File metadata and controls
172 lines (152 loc) · 6.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
name: '📬 Newsletter · 🔄 Sync from Buttondown'
# =============================================================================
# Newsletter — Sync Buttondown content into dev + main
# =============================================================================
#
# Daily content-only sync. Pulls published emails from Buttondown, commits
# them to dev (so site-preview-dev picks them up), cherry-picks the same
# commit onto main (the stable release branch), and dispatches
# site-publish-live so the post lands on mlsysbook.ai.
#
# Why both branches:
# - dev is the integration trunk; pushing there auto-triggers
# site-preview-dev.yml so the dev preview gets the new post.
# - main is the stable release branch from which gh-pages is published.
# Newsletter content auto-promotes to main because it's contained to
# site/newsletter/posts/ and can't conflict with anything else.
#
# Why we dispatch site-publish-live instead of building here:
# - Single deploy path. Only site-publish-live writes to gh-pages, so the
# hashed bootstrap CSS in site_libs/ stays in sync with the unified
# site's about/community HTML by construction.
# - Past bug: this workflow used to do its own partial deploy of
# newsletter + site_libs and corrupted /site_libs/ for the about and
# community pages, because their HTML still referenced the previously
# deployed bootstrap-{HASH}.css.
#
# Triggers:
# - Schedule: Daily at 6 AM UTC (1 AM ET)
# - Manual: workflow_dispatch
#
# Secrets: BUTTONDOWN_API_KEY, GITHUB_TOKEN
#
# Related:
# - site/newsletter/cli/ — news CLI (pull subcommand powers this)
# - site-publish-live.yml — full unified-site deploy from main
# - site-preview-dev.yml — auto-triggered by our push to dev
# =============================================================================
on:
schedule:
- cron: '0 6 * * *' # Daily at 6am UTC (1am ET)
workflow_dispatch: {}
permissions:
contents: write
actions: write # required to dispatch site-publish-live via `gh workflow run`
concurrency:
group: newsletter-sync
cancel-in-progress: true
jobs:
sync:
name: '📬 Sync Buttondown → dev + main'
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout dev (full history for cherry-pick)
uses: actions/checkout@v6
with:
ref: dev
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: 🐍 Setup Python
uses: actions/setup-python@v6
with:
python-version: ${{ vars.PYTHON_VERSION || '3.12' }}
- name: 📦 Install news CLI
run: pip install -r site/newsletter/requirements.txt
- name: 📬 Pull from Buttondown
env:
BUTTONDOWN_API_KEY: ${{ secrets.BUTTONDOWN_API_KEY }}
run: python3 site/newsletter/bin/news pull
- name: 📦 Commit new posts to dev
id: commit_dev
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# _stats.yml is gitignored — regenerated fresh on every render by
# publish-live's `news pull`. We only commit post markdown here.
git add site/newsletter/posts/
if git diff --staged --quiet; then
echo "ℹ️ No new newsletter posts"
echo "has_new_posts=false" >> "$GITHUB_OUTPUT"
exit 0
fi
COUNT=$(git diff --staged --name-only | wc -l | tr -d ' ')
git commit -m "chore: sync $COUNT newsletter post(s) from Buttondown [automated]"
# Push with retry. Capture SHA *after* successful push because
# `git pull --rebase` during retry rewrites the local commit's SHA.
NEWSLETTER_SHA=""
for i in 1 2 3; do
if git push origin dev; then
NEWSLETTER_SHA=$(git rev-parse HEAD)
echo "✅ Pushed $COUNT post(s) to dev (SHA: $NEWSLETTER_SHA)"
break
fi
echo "⚠️ Push to dev failed (attempt $i/3), rebasing..."
git pull --rebase origin dev
done
if [ -z "$NEWSLETTER_SHA" ]; then
echo "❌ Push to dev failed after 3 attempts"
exit 1
fi
echo "newsletter_sha=$NEWSLETTER_SHA" >> "$GITHUB_OUTPUT"
echo "has_new_posts=true" >> "$GITHUB_OUTPUT"
- name: 🍒 Cherry-pick newsletter commit onto main
if: steps.commit_dev.outputs.has_new_posts == 'true'
env:
NEWSLETTER_SHA: ${{ steps.commit_dev.outputs.newsletter_sha }}
run: |
git fetch origin main
git checkout main
git reset --hard origin/main
if ! git cherry-pick "$NEWSLETTER_SHA"; then
echo "❌ Cherry-pick failed — main and dev have diverged in"
echo " site/newsletter/posts/. The newsletter post is safely on"
echo " dev (SHA: $NEWSLETTER_SHA). Resolve the divergence and"
echo " re-run the workflow."
git cherry-pick --abort || true
exit 1
fi
for i in 1 2 3; do
if git push origin main; then
echo "✅ Cherry-picked newsletter commit onto main"
break
fi
echo "⚠️ Push to main failed (attempt $i/3), rebasing..."
if ! git pull --rebase origin main; then
echo "❌ Rebase failed during cherry-pick promotion"
exit 1
fi
done
- name: 🚀 Dispatch site-publish-live on main
if: steps.commit_dev.outputs.has_new_posts == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh workflow run site-publish-live.yml --ref main
echo "✅ Dispatched site-publish-live on main"
echo ""
echo "Watch: https://github.com/${{ github.repository }}/actions/workflows/site-publish-live.yml"
- name: 📊 Summary
if: always()
run: |
{
echo "## 📬 Newsletter Sync"
echo ""
if [ "${{ steps.commit_dev.outputs.has_new_posts }}" = "true" ]; then
echo "- ✅ Pulled new post(s) from Buttondown"
echo "- ✅ Committed to \`dev\` (\`${{ steps.commit_dev.outputs.newsletter_sha }}\`)"
echo "- ✅ Cherry-picked onto \`main\`"
echo "- 🚀 Dispatched \`site-publish-live\` on \`main\` — newsletter live in ~5 min"
else
echo "No new posts from Buttondown. Nothing to do."
fi
} >> "$GITHUB_STEP_SUMMARY"