-
Notifications
You must be signed in to change notification settings - Fork 1
288 lines (257 loc) · 11.4 KB
/
generate-blog-images.yml
File metadata and controls
288 lines (257 loc) · 11.4 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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
name: Generate Blog Images
on:
push:
branches:
- main
paths:
- 'content/**/*.md'
workflow_dispatch:
inputs:
image_service:
description: 'AI service to use'
required: false
default: 'modelscope'
type: choice
options:
- modelscope
- gemini
- both
target_type:
description: 'Generation target'
required: false
default: 'both'
type: choice
options:
- covers
- articles
- both
force_regenerate:
description: 'Force regenerate existing images'
required: false
default: false
type: boolean
auto_generate:
description: 'Auto-generate for new/updated articles only'
required: false
default: true
type: boolean
permissions:
contents: write
jobs:
generate-images:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.MY_GITHUB_TOKEN }}
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Install dependencies
run: |
cd scripts
pip install -r requirements.txt
pip install requests pillow python-dotenv
- name: Detect changed blog files
id: detect-changes
run: |
# 获取本次提交修改的.md文件
if [ "${{ github.event_name }}" = "push" ]; then
if [ -z "${{ github.event.before }}" ]; then
# First commit, process all content files
CHANGED_FILES=$(find content -name "*.md" -not -path "*/daily_ai/*" | tr '\n' ' ')
echo "First commit detected, processing all files"
else
# Get changed .md files, excluding daily_ai
CHANGED_FILES=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} | grep '\.md$' | grep '^content/' | grep -v 'daily_ai' | tr '\n' ' ' || true)
echo "Push detected, analyzing changed files"
fi
else
# 手动触发时处理所有没有图片的博客
CHANGED_FILES=""
echo "Manual workflow triggered"
fi
# Filter for files that need AI covers (have description but no ai_cover)
NEED_AI_COVER=""
if [ -n "$CHANGED_FILES" ]; then
for file in $CHANGED_FILES; do
if [ -f "$file" ]; then
# Check if file has description
if grep -q "^description:" "$file"; then
# Check if file doesn't have ai_cover or ai_generated: true
if ! grep -q "ai_cover:" "$file" || ! grep -q "ai_generated: true" "$file"; then
NEED_AI_COVER="$NEED_AI_COVER $file"
echo "Need AI cover: $file"
else
echo "Already has AI cover: $file"
fi
else
echo "No description, skipping: $file"
fi
fi
done
fi
echo "changed_files<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGED_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "need_ai_cover<<EOF" >> $GITHUB_OUTPUT
echo "$NEED_AI_COVER" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Generate images for new blogs
if: steps.detect-changes.outputs.changed_files != ''
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
run: |
cd scripts
# 确保文件路径存在
echo "Checking file paths..."
for file in ${{ steps.detect-changes.outputs.changed_files }}; do
if [ -f "$file" ]; then
echo "Found: $file"
else
echo "Missing: $file"
fi
done
python generate_image.py ${{ steps.detect-changes.outputs.changed_files }}
- name: Generate images for all blogs (manual trigger)
if: github.event_name == 'workflow_dispatch'
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
run: |
cd scripts
python generate_image.py --backfill
- name: Auto-generate ModelScope AI Covers for new blogs
if: github.event_name == 'push' && steps.detect-changes.outputs.need_ai_cover != ''
env:
MODELSCOPE_API_KEY: ${{ secrets.MODELSCOPE_API_KEY }}
TEXT2IMAGE_PROVIDER: modelscope
WORKFLOW_MODE: true
FORCE_REGENERATE: false
run: |
cd scripts
echo "🤖 Auto-generating ModelScope AI covers for new blogs..."
echo "Files needing AI covers: ${{ steps.detect-changes.outputs.need_ai_cover }}"
# Process files that need AI covers (limit to avoid API overload)
NEED_COVER_FILES="${{ steps.detect-changes.outputs.need_ai_cover }}"
file_count=0
max_files=5 # Limit per push to avoid API overload
for file in $NEED_COVER_FILES; do
if [ -f "$file" ] && [ $file_count -lt $max_files ]; then
echo "Processing: $file"
python ai_cover_generator.py --workflow-mode --target=covers --specific-file="$file"
file_count=$((file_count + 1))
elif [ $file_count -ge $max_files ]; then
echo "Reached limit of $max_files files, skipping remaining files"
break
fi
done
echo "✅ Auto-generation completed: processed $file_count files"
- name: Generate ModelScope AI Covers (manual trigger)
if: github.event_name == 'workflow_dispatch' && (contains(github.event.inputs.image_service, 'modelscope') || github.event.inputs.image_service == 'both')
env:
MODELSCOPE_API_KEY: ${{ secrets.MODELSCOPE_API_KEY }}
TEXT2IMAGE_PROVIDER: modelscope
WORKFLOW_MODE: true
FORCE_REGENERATE: ${{ github.event.inputs.force_regenerate }}
run: |
cd scripts
echo "🤖 Generating ModelScope AI covers..."
echo "Target: ${{ github.event.inputs.target_type }}"
echo "Force regenerate: $FORCE_REGENERATE"
# Generate covers if target includes covers
if [[ "${{ github.event.inputs.target_type }}" == "covers" || "${{ github.event.inputs.target_type }}" == "both" ]]; then
python ai_cover_generator.py --workflow-mode --target=covers --force=${FORCE_REGENERATE}
else
echo "Skipping cover generation (target: articles only)"
fi
- name: Create images directory
run: |
mkdir -p static/images/articles
mkdir -p static/images/generated-covers
echo "Created image directories"
- name: Commit generated images
if: always()
env:
GITHUB_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }}
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git
has_changes=false
# Check for article images
if [ -d "static/images/articles" ] && [ "$(ls -A static/images/articles 2>/dev/null)" ]; then
echo "Found new article images to commit"
git add static/images/articles/
has_changes=true
fi
# Check for generated covers
if [ -d "static/images/generated-covers" ] && [ "$(ls -A static/images/generated-covers 2>/dev/null)" ]; then
echo "Found new AI-generated covers to commit"
git add static/images/generated-covers/
has_changes=true
fi
# Commit if there are changes
if [ "$has_changes" = true ]; then
git commit -m "🤖 Auto-generate blog images and AI covers [skip ci]" || echo "No new changes to commit"
git push
echo "✅ Images committed successfully"
else
echo "ℹ️ No new images to commit"
fi
- name: Create summary
if: always()
run: |
echo "## Blog Image Generation Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📋 Configuration" >> $GITHUB_STEP_SUMMARY
echo "**Trigger:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
echo "**Image Service:** ${{ github.event.inputs.image_service || 'N/A' }}" >> $GITHUB_STEP_SUMMARY
echo "**Target Type:** ${{ github.event.inputs.target_type || 'N/A' }}" >> $GITHUB_STEP_SUMMARY
echo "**Force Regenerate:** ${{ github.event.inputs.force_regenerate || 'false' }}" >> $GITHUB_STEP_SUMMARY
echo "**Changed files:** ${{ steps.detect-changes.outputs.changed_files }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🖼️ Generated Article Images" >> $GITHUB_STEP_SUMMARY
if [ -d "static/images/articles" ] && [ "$(ls -A static/images/articles 2>/dev/null)" ]; then
echo "| Filename | Size | Type |" >> $GITHUB_STEP_SUMMARY
echo "|----------|------|------|" >> $GITHUB_STEP_SUMMARY
cd static/images/articles
ls -lh *.jpg *.png *.webp 2>/dev/null | while read -r line; do
filename=$(echo $line | awk '{print $9}')
size=$(echo $line | awk '{print $5}')
echo "| $filename | $size | Image |" >> $GITHUB_STEP_SUMMARY
done
else
echo "No article images generated" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🤖 Generated AI Covers" >> $GITHUB_STEP_SUMMARY
if [ -d "static/images/generated-covers" ] && [ "$(ls -A static/images/generated-covers 2>/dev/null)" ]; then
echo "| Filename | Size | AI Service |" >> $GITHUB_STEP_SUMMARY
echo "|----------|------|-----------|" >> $GITHUB_STEP_SUMMARY
cd static/images/generated-covers
ls -lh *.jpg *.png *.webp 2>/dev/null | while read -r line; do
filename=$(echo $line | awk '{print $9}')
size=$(echo $line | awk '{print $5}')
echo "| $filename | $size | ModelScope |" >> $GITHUB_STEP_SUMMARY
done
else
echo "No AI covers generated" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
# Add generation statistics
article_count=$(find static/images/articles -name "*.jpg" -o -name "*.png" -o -name "*.webp" 2>/dev/null | wc -l)
cover_count=$(find static/images/generated-covers -name "*.jpg" -o -name "*.png" -o -name "*.webp" 2>/dev/null | wc -l)
echo "### 📊 Statistics" >> $GITHUB_STEP_SUMMARY
echo "**Article Images:** $article_count files" >> $GITHUB_STEP_SUMMARY
echo "**AI Covers:** $cover_count files" >> $GITHUB_STEP_SUMMARY
echo "**Total Images:** $((article_count + cover_count)) files" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### ✅ Status" >> $GITHUB_STEP_SUMMARY
if [ $((article_count + cover_count)) -gt 0 ]; then
echo "🎉 **Generation Successful**: Images were generated and committed" >> $GITHUB_STEP_SUMMARY
else
echo "ℹ️ **No Generation**: No new images were generated" >> $GITHUB_STEP_SUMMARY
fi