Skip to main content

Automating Daily Blog Posts with GitHub Actions and Blogger API

Blogger · GitHub Actions · Automation

Automating Daily Blog Posts with GitHub Actions and the Blogger API

What it solves

Write posts ahead of time, queue them once, and let the workflow publish them on schedule.

What runs it

A GitHub Actions workflow calls a Python script that reads a JSON queue and publishes due posts through the Blogger API.

What to remember

GitHub Actions schedules use UTC and run from the default branch, so your publish times need to be planned around that.

Introduction

Writing blog posts ahead of time is easy. Remembering to publish them on the right day is harder.

Paperboy solves that by letting you keep scheduled posts in a JSON file and having GitHub Actions publish them to Blogger automatically every day. No always-on server. No cron job on your laptop. No manual publishing step when the day arrives.

This guide walks through how the system works, how to configure it, and how to queue your own posts for automatic publication.

Prerequisites

What You Need Before You Start

  • a Blogger blog and its numeric Blog ID
  • a Google Cloud project with the Blogger API enabled
  • Google OAuth2 credentials JSON for Blogger access
  • a GitHub account and repository to store the workflow and secrets
  • Python 3.9 or newer if you want to test the script locally
Practical note The most important setup items are the Blogger API credentials and the GitHub Actions secrets. If those are wrong, the rest of the workflow will not matter.
Architecture

How the System Works

The automation is made of three pieces:

  1. blog_posts.json — the queue of posts you want published later
  2. run.py — the Python script that reads the queue, talks to Blogger, and publishes due posts
  3. .github/workflows/daily-run.yml — the GitHub Actions workflow that runs the script on a schedule

Each workflow run downloads the JSON queue, compares each post’s post_date to the current time, skips anything incomplete or already published, and creates any post whose scheduled time has arrived.

The key idea is simple: the repository stores the queue, GitHub Actions provides the clock, and the Blogger API handles publication.

Repository setup

Step 1 — Fork the Repository

Fork the Paperboy repository to your own GitHub account, then clone your fork locally:

git clone https://github.com/YOUR_USERNAME/paperboy
cd paperboy

From that point forward, your fork becomes the control panel for the entire publishing workflow.

Dependencies

Step 2 — Install the Python Requirements

Install the required libraries with:

pip install -r requirements.txt

The main dependencies are the Google authentication libraries, the Google API client, and requests.

Secrets

Step 3 — Configure GitHub Actions Secrets

In your repository, go to Settings → Secrets and variables → Actions and add the values the workflow needs.

client-secret

The JSON client secret downloaded from Google Cloud when you create OAuth credentials.

credentials-json

The token JSON used for non-interactive authentication. This should already contain a valid access token and refresh token if you want the scheduled workflow to run unattended.

blog-id

Your Blogger blog’s numeric ID, which you can find in the Blogger dashboard URL.

github-repo

Your repository in owner/repo format, such as YOUR_USERNAME/paperboy.

Important If credentials-json does not contain a valid token, the unattended GitHub Actions run cannot complete the interactive OAuth flow for you.
Post queue

Step 4 — Write Posts in blog_posts.json

Each queued post lives inside the posts array and needs three fields: post_date, title, and content.

{
  "posts": [
    {
      "post_date": "2024-03-01T14:00:00",
      "title": "My First Automated Post",
      "content": "<p>This post was published automatically.</p>"
    },
    {
      "post_date": "2024-03-02T14:00:00",
      "title": "A Follow-Up Post",
      "content": "<p>Another scheduled post.</p>"
    }
  ]
}

The script expects:

  • post_date in YYYY-MM-DDTHH:MM:SS format
  • title as the post title and duplicate-check key
  • content as an HTML string for the Blogger post body

If any required field is missing, the script skips that entry instead of crashing the whole run.

Workflow file

The GitHub Actions Workflow

The workflow runs on a schedule and can also run on push, which is useful for testing changes quickly.

name: Daily Automated Actions

on:
  schedule:
    - cron: '0 14 * * *'   # every day at 14:00 UTC
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  daily-run:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.9'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: Automate blog posts
        run: |
          python run.py \
            --client-secret '${{ secrets.client_secret }}' \
            --credentials-json '${{ secrets.credentials_json }}' \
            --blog-id '${{ secrets.blog_id }}' \
            --github-repo '${{ secrets.github_repo }}' \
            --json-file 'blog_posts.json'

The important part is the schedule trigger. GitHub Actions cron schedules are interpreted in UTC, run on the default branch, and have a minimum interval of 5 minutes. Scheduled runs can also be delayed under heavy platform load. :contentReference[oaicite:1]{index=1}

Best habit Add workflow_dispatch so you can test the workflow manually instead of waiting for the next scheduled run.
Script flow

How run.py Works

  1. Authenticate using the token credentials when available
  2. Connect to the Blogger v3 API
  3. Fetch the JSON post queue from GitHub
  4. Check duplicates by looking at existing Blogger post titles
  5. Publish due posts whose post_date has passed and whose titles do not already exist

The duplicate-title check is one of the most important safeguards in the whole system. It keeps reruns from blindly creating the same post again.

Scheduling

Customizing the Schedule

The default expression:

0 14 * * *

means every day at 14:00 UTC.

Other examples:

  • 0 9 * * * — every day at 9:00 UTC
  • 0 18 * * 1 — every Monday at 18:00 UTC
  • 0 8 * * 1,3,5 — Monday, Wednesday, and Friday at 8:00 UTC
Timing caution GitHub recommends not relying on exact minute-level precision for scheduled workflows because runs can be delayed during busy periods. :contentReference[oaicite:2]{index=2}
Verification

How to Confirm It Worked

  • GitHub Actions tab: check the run logs for authentication problems, JSON issues, or Blogger API failures
  • Blogger dashboard: confirm the post appeared on the intended date

If a scheduled workflow seems to stop running in a public repository, remember that GitHub can disable scheduled workflows after 60 days of repository inactivity. :contentReference[oaicite:3]{index=3}

FAQ

Frequently Asked Questions

These are the practical questions people usually have when they first automate Blogger publishing with GitHub Actions.

Do scheduled GitHub Actions run in my local timezone?

No. Scheduled workflows use UTC, so you need to convert local publish times yourself.

What is the shortest interval GitHub Actions allows for cron schedules?

The minimum supported interval is once every 5 minutes.

Can a scheduled workflow run late?

Yes. GitHub can delay scheduled runs during times of high platform load.

Why add workflow_dispatch if the workflow is already scheduled?

It gives you a manual trigger so you can test changes immediately.

Why is duplicate title checking important?

Because reruns happen, and the title check prevents the workflow from publishing the same post twice.

Can the script authenticate interactively inside GitHub Actions?

Not reliably. The scheduled workflow needs a valid token-based credential so it can authenticate without opening a browser.

What branch do scheduled workflows run from?

Scheduled workflows run from the default branch.

What is the simplest workflow here?

Queue posts in JSON, push the queue to the repository, and let the scheduled workflow publish due posts automatically.

Summary

Summary

Once configured, the workflow is simple:

  1. write posts in HTML
  2. add them to blog_posts.json with a post_date
  3. commit and push to the repository

GitHub Actions handles the schedule, the Python script handles authentication and duplicate checking, and Blogger receives the final post automatically.

Raell Dottin

Comments