Skip to content

Commit 4a22818

Browse files
committed
feat: implemented missing parts for blog automation
1 parent 6aea9cb commit 4a22818

8 files changed

Lines changed: 341 additions & 526 deletions

File tree

Lines changed: 43 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
name: Import Meetup Events
1+
name: Publish reviewed blogs
22

33
on:
44
workflow_dispatch:
55
schedule:
6-
- cron: '0 7 * * *' # check for new blogs at 7:00am
6+
- cron: '0 7 * * *' # daily at 07:00 UTC: publish any newly reviewed blogs
7+
78
jobs:
8-
check-for-changes:
9+
publish-blogs:
910
if: github.repository == 'Women-Coding-Community/WomenCodingCommunity.github.io'
1011
runs-on: ubuntu-latest
11-
outputs:
12-
has_new_rows: ${{ steps.check-blog.outputs.has_new_rows }}
13-
new_row_indices: ${{ steps.check-blog.outputs.new_row_indices }}
1412

1513
steps:
1614
- name: Checkout repository
@@ -24,69 +22,51 @@ jobs:
2422
- name: Cache pip
2523
uses: actions/cache@v4
2624
with:
27-
path: ~/.cache/pip
28-
key: ${{ runner.os }}-pip-${{ hashFiles('tools/requirements.txt') }}
29-
restore-keys: |
30-
${{ runner.os }}-pip-
25+
path: ~/.cache/pip
26+
key: ${{ runner.os }}-pip-blog-${{ hashFiles('tools/blog_automation/requirements.txt') }}
27+
restore-keys: |
28+
${{ runner.os }}-pip-blog-
3129
3230
- name: Install dependencies
3331
run: |
34-
python -m pip install --upgrade pip
35-
pip install -r tools/requirements.txt
36-
37-
- name: Check for new blog entries
38-
id: check-blog
39-
run: |
40-
cd tools/blog_automation
41-
python check_for_new_blogs.py
32+
python -m pip install --upgrade pip
33+
pip install -r tools/blog_automation/requirements.txt
4234
43-
# If there are new rows, run the blog_exporter script
44-
run-blog-automation:
45-
needs: check-for-changes
46-
if: needs.check-for-changes.outputs.has_new_rows == 'true'
47-
runs-on: ubuntu-latest
35+
- name: Write service account key
36+
run: echo "$SERVICE_ACCOUNT_KEY" > tools/blog_automation/service_account_key.json
37+
env:
38+
SERVICE_ACCOUNT_KEY: ${{ secrets.BLOG_AUTOMATION_SERVICE_ACCOUNT }}
4839

49-
steps:
50-
- name: Checkout repository
51-
uses: actions/checkout@v5
40+
- name: Export reviewed blogs
41+
run: |
42+
cd tools/blog_automation
43+
python publish_reviewed_blogs.py
5244
53-
- name: Set up Python
54-
uses: actions/setup-python@v5
55-
with:
56-
python-version: '3.12'
45+
- name: Remove service account key
46+
if: always()
47+
run: rm -f tools/blog_automation/service_account_key.json
5748

58-
- name: Cache pip
59-
uses: actions/cache@v4
60-
with:
61-
path: ~/.cache/pip
62-
key: ${{ runner.os }}-pip-${{ hashFiles('tools/requirements.txt') }}
63-
restore-keys: |
64-
${{ runner.os }}-pip-
49+
- name: Create or Update Pull Request
50+
id: create-pr
51+
uses: peter-evans/create-pull-request@v7
52+
with:
53+
token: ${{ secrets.GHA_ACTIONS_ALLOW_TOKEN }}
54+
commit-message: "Automated import of reviewed blog posts"
55+
branch: "automation/import-blog"
56+
team-reviewers: "Women-Coding-Community/leaders"
57+
title: "Automated import of reviewed blog posts"
58+
body: |
59+
This PR was created automatically by a GitHub Action.
6560
66-
- name: Install dependencies
67-
run: |
68-
python -m pip install --upgrade pip
69-
pip install -r tools/requirements.txt
61+
It contains every blog marked `isReviewedandApproved` (and not yet
62+
`isPublished`) in the submissions spreadsheet:
63+
- new posts under `_posts/`
64+
- cover images under `assets/images/blog/`
7065
71-
- name: Export new blogs
72-
run: |
73-
cd tools/blog_automation
74-
for row_index in ${{ needs.check-for-changes.outputs.new_row_indices }}; do
75-
python blog_exporter.py --row_index "$row_index"
76-
done
77-
78-
- name: Create or Update Pull Request
79-
id: create-pr
80-
uses: peter-evans/create-pull-request@v7
81-
with:
82-
token: ${{ secrets.GHA_ACTIONS_ALLOW_TOKEN }}
83-
commit-message: "Automated blog import from Google Docs"
84-
branch: "automation/import-blog"
85-
team-reviewers: "Women-Coding-Community/leaders"
86-
title: "Automated import of blog posts"
87-
body: |
88-
This PR was created automatically by a GitHub Action to import new blog posts.
89-
The new blog posts have been added to `_posts/` directory.
90-
The `blog_info_snapshot.csv` has been updated to track processed entries.
91-
labels: |
92-
automation
66+
The spreadsheet's `isPublished` column has already been set to TRUE for
67+
these rows. Please review the rendered posts before merging.
68+
labels: |
69+
automation
70+
add-paths: |
71+
_posts/**
72+
assets/images/blog/**

tools/blog_automation/README.md

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ To allow our scripts to access Google Drive and export documents, you need to cr
1717
👉 **Note:** You need the **Project Editor** or **Owner** role on this project to create service accounts and keys.
1818
If you’re the one who created the project, you already have these permissions.
1919

20-
### 1. Enable the Drive API
20+
### 1. Enable the Drive and Sheets APIs
2121
1. In the left menu, go to **APIs & Services → Library**.
22-
2. Search for **Google Drive API**.
23-
3. Click **Enable**.
22+
2. Search for **Google Drive API** and click **Enable**.
23+
3. Search for **Google Sheets API** and click **Enable** (needed to read the submissions spreadsheet).
2424

2525
### 2. Create a Service Account
2626
1. In the left menu, go to **IAM & Admin → Service Accounts**.
@@ -47,6 +47,7 @@ If you’re the one who created the project, you already have these permissions.
4747
4. Give it at least **Viewer** access.
4848
5. Save changes.
4949
- Now the service account can read/export files in that folder or doc.
50+
6. Repeat the **Share** step for the **blog submissions spreadsheet** (the Google Form responses sheet), giving the service account **Editor** access. Editor (not just Viewer) is required because the pipeline writes `isPublished = TRUE` back to a row after exporting it.
5051

5152
---
5253

@@ -75,19 +76,53 @@ Then the **Document ID** is:
7576

7677
Use this ID in your scripts when exporting the document.
7778

78-
## Run Automation
79+
## Export a single blog manually (for testing)
7980
1. Activate virtual environment: `source venv/bin/activate`
80-
2. Run the script: `python blog_exporter [--row_index <ROW_INDEX>]`, where the row_index refers to the row of the CSV. This defaults to -1, or the last row in the CSV.
81+
2. Export one Google Doc into a post:
82+
`python blog_exporter.py --doc_id <DOC_ID> --author_name "Jane Doe" --image_link "<DRIVE_IMAGE_LINK>"`
8183

82-
**Notes and Options**
83-
- The blog csv defaults to blog_info_snapshot.csv
84+
This is handy to check a Doc renders correctly. The full pipeline below reads all
85+
of this metadata from the spreadsheet automatically.
8486

8587
## Tests
8688

8789
Run `pytest test_blog_exporter.py`
8890

89-
## GitHub Actions automation
90-
There is a GitHub Action .github/workflows/run_blog_exporter.yml which checks for any new rows in the blog_info_snapshot.csv, and runs the blog_exporter.py script for each new row.
91+
## CI/CD pipeline: publish a blog when you mark it reviewed
92+
93+
The Google Sheet is the **single source of truth** — there is no local CSV. The
94+
GitHub Action [`.github/workflows/run_blog_exporter.yml`](../../.github/workflows/run_blog_exporter.yml)
95+
turns a reviewed blog into a draft pull request automatically.
96+
97+
### How to publish a blog (the editor's workflow)
98+
1. In the submissions spreadsheet (the **Form Responses 1** sheet), set the row's
99+
**`isReviewedandApproved`** cell to **`TRUE`** once the draft is reviewed.
100+
Leave **`isPublished`** blank/`FALSE`.
101+
2. Within a day (or immediately via **Actions → Publish reviewed blogs → Run
102+
workflow**) the action exports the blog, sets that row's **`isPublished`** to
103+
`TRUE` in the sheet, and opens/updates a PR
104+
(`Automated import of reviewed blog posts`) with the new post and cover image.
105+
3. **Review the rendered post and merge.**
106+
107+
### What runs
108+
`publish_reviewed_blogs.py` reads the sheet and exports every row where
109+
`isReviewedandApproved` is `TRUE` and `isPublished` is not `TRUE`. Because the
110+
`isPublished` flag is written straight back to the sheet, a blog is never exported
111+
twice — and the existing backlog (already `isPublished = TRUE`) is left alone.
112+
113+
> The draft must be a **native Google Doc** (Drive can only export those to
114+
> Markdown). If a submitter uploaded a `.docx`/`.pdf`, open it and do
115+
> **File → Save as Google Docs** first, otherwise that row is skipped with an error.
116+
117+
### One-time repo setup
118+
- **Service account needs Editor access to the spreadsheet** (see setup step 4) so
119+
the pipeline can write back `isPublished`.
120+
- **Secret `BLOG_AUTOMATION_SERVICE_ACCOUNT`** — paste the full contents of
121+
`service_account_key.json` into a repository secret with this name
122+
(Settings → Secrets and variables → Actions). The workflow writes it to disk at
123+
runtime and deletes it afterwards; the key is never committed.
124+
- **Secret `GHA_ACTIONS_ALLOW_TOKEN`** — already used by the other automations; it
125+
lets the action open the pull request.
91126

92127

93128

0 commit comments

Comments
 (0)