Skip to content

Release: static blog scaffold + auto-publish CI - #2

Merged
xiami303 merged 1 commit into
mainfrom
develop
Jun 11, 2026
Merged

xiami303 merged 1 commit into
mainfrom
develop

Conversation

@xiami303

@xiami303 xiami303 commented Jun 11, 2026 •

Copy link
Copy Markdown
Owner

概要

把 OpenBlog 从占位仓库升级为一个可运行的「AI 自动生成 + 自动发布」博客系统,并发起首次发布(develop → main)。

改动

  • 静态站点生成器 scripts/build.mjs:posts/*.md → public/(marked + gray-matter,支持 front matter)。
  • 示例文章 + .gitignore(忽略 node_modules/、public/)。
  • CI .github/workflows/publish.yml:每日定时 + push main + 手动触发 → 部署到 GitHub Pages。移除占位 blank.yml。
  • 文档:AGENTS.md / README 写明 develop 为默认分支、main 为发布分支;.codex/setup.sh 启用 npm ci。

验证

  • 本地 npm install && npm run build 通过,生成 public/index.html 与文章页。

发布门槛

合并需 code review 评分 ≥ 80。合并到 main 会触发自动部署到 Pages。

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a static site generator for building and publishing blog posts
    • Introduced automated CI/CD pipeline for daily builds and GitHub Pages deployment
  • Documentation

    • Updated setup guide with complete npm workflow (build, serve, install)
    • Added detailed contribution guidelines and project roadmap
    • Included sample blog post demonstrating format and structure
  • Chores

    • Added project configuration and dependency management

- Add Node static-site generator (scripts/build.mjs) rendering posts/*.md
  to public/ via marked + gray-matter; npm run build/serve.
- Add sample post and .gitignore (node_modules/, public/).
- Replace placeholder CI with publish.yml: scheduled daily build +
  auto-deploy to GitHub Pages from main.
- Document develop-default branch policy in AGENTS.md and README;
  enable npm ci in .codex/setup.sh.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR implements a complete static site generation system for OpenBlog, transforming it from a scaffold into a working blog platform. It adds a Node.js build pipeline that parses Markdown posts, generates HTML pages, and automates deployment to GitHub Pages via CI/CD.

Changes

Static Site Generation and Publication

Layer / File(s) Summary
Build System and Dependencies
package.json, .codex/setup.sh, .gitignore
Project defined as ES module with build and serve npm scripts. Dependencies on gray-matter and marked. Setup script runs npm ci when package.json exists. Git ignores node_modules/, public/, and OS clutter.
Static Site Generator Implementation
scripts/build.mjs
Build script orchestrates site generation: reads Markdown posts, parses YAML front matter, derives metadata (title, date, tags, summary) with fallbacks, sorts by date, renders HTML with escaped values, applies shared layout template, writes individual post pages to public/posts/, generates index.html listing, embeds inline CSS stylesheet, and handles errors with exit code 1.
CI/CD Pipeline for GitHub Pages
.github/workflows/publish.yml, .github/workflows/blank.yml
Publish workflow triggers on main branch pushes, daily cron, and manual dispatch. Checks out code, installs Node.js 20 with npm caching, runs npm ci and npm run build, uploads public/ as artifact, and deploys to GitHub Pages. Removes obsolete blank.yml workflow.
Project Documentation and Developer Guidance
README.md, AGENTS.md
README updated to MVP status, marks static generator and GitHub Pages as complete, documents quick-start (npm install, npm run build, npm run serve), project structure, and develop/main branch policy. AGENTS.md provides concrete guidance: OpenBlog positioning, repository structure, develop as default branch, Node.js tooling expectations, post authoring with front matter schema and field defaulting, and agent verification checklist.
Example Blog Post
posts/2026-06-11-hello-openblog.md
First post with YAML front matter (title, date, tags, summary) and markdown content explaining memory vs. IP distinction, instructing readers to use the file as template and run npm run build.

Sequence Diagram(s)

sequenceDiagram
  participant Dev as Developer
  participant Git as Git/GitHub
  participant CI as GitHub Actions
  participant Generator as Build Script
  participant Pages as GitHub Pages
  
  Dev->>Git: git push to main
  Git->>CI: Trigger publish workflow
  CI->>CI: Checkout code
  CI->>CI: Install Node.js 20
  CI->>Generator: Run npm run build
  Generator->>Generator: Read posts/, parse YAML
  Generator->>Generator: Render HTML from Markdown
  Generator->>Generator: Write public/
  CI->>CI: Upload public/ artifact
  CI->>Pages: Deploy via actions/deploy-pages@v4
  Pages->>Dev: Site live at GitHub Pages URL
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

A rabbit hops through Markdown dreams,
Each post transforms to HTML streams,
From gray-matter YAML gold,
To static pages bright and bold,
GitHub Pages now the stage—
OpenBlog has come of age! 🐰📝

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main objective: releasing a static blog scaffold with auto-publish CI, which directly reflects the core changes (static site generator, GitHub Pages workflow, and first release to main).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

112-124: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: Branch policy contradicts AGENTS.md and project learnings.

Line 123 states "默认分支为 main" (default branch is main), but this directly contradicts:

  • AGENTS.md lines 34-37: "develop — integration branch. This is the default branch for all work and pushes."
  • Retrieved learnings: "Default branch for all work and pushes is 'develop'"
  • The branch rules section above (lines 114-115) which correctly identifies develop as the default

Line 123 should state that develop is the default branch for development work.

🔧 Proposed fix
 本仓库对 AI 编码 Agent 友好。若你使用 **OpenAI Codex** 等 Agent 协作开发:
 
 - 先阅读 [AGENTS.md](AGENTS.md) 了解仓库约定与目标结构。
 - 环境准备脚本位于 [.codex/setup.sh](.codex/setup.sh)。
-- 默认分支为 `main`,集成分支为 `develop`;Pull Request 请提交到 `main`。
+- 默认分支为 `develop`,生产分支为 `main`;日常开发请提交到 `develop`,仅在发布时合并到 `main`。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 112 - 124, The README contains a contradictory
sentence that says "默认分支为 `main`" while the branch rules and AGENTS.md declare
`develop` as the default branch; update the sentence that currently reads "默认分支为
`main`" so it instead states "默认分支为 `develop`" (or otherwise clarifies that
`develop` is the default branch for development and PRs), ensuring the README's
"参与开发" section and the referenced AGENTS.md remain consistent with the earlier
branch rules that designate `develop` as the integration/default branch.

Source: Learnings

🧹 Nitpick comments (2)
.github/workflows/publish.yml (2)

35-35: ⚡ Quick win

Consider disabling credential persistence in checkout.

Adding persist-credentials: false to the checkout action prevents the GITHUB_TOKEN from being persisted in the local git config, reducing the risk if a subsequent step is compromised. While this workflow doesn't push code back to the repository, it's a good defensive practice.

🔒 Proposed fix
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish.yml at line 35, Update the actions/checkout step
(uses: actions/checkout@v4) to disable credential persistence by adding
persist-credentials: false to the step configuration so the GITHUB_TOKEN is not
written to local git config; locate the checkout step in the workflow and insert
the persist-credentials key under that step with a boolean false value.

21-29: ⚡ Quick win

Consider scoping GitHub Pages permissions to the deploy job.

The pages: write and id-token: write permissions are currently set at the workflow level but are only required by the deploy job. Following the principle of least privilege, these should be scoped to the job that needs them.

🔒 Proposed fix to scope permissions
 permissions:
   contents: read
-  pages: write
-  id-token: write
 
 # Allow only one concurrent deployment.
 concurrency:
@@ -52,6 +50,9 @@
 
   deploy:
     needs: build
     runs-on: ubuntu-latest
+    permissions:
+      pages: write
+      id-token: write
     environment:
       name: github-pages
       url: ${{ steps.deployment.outputs.page_url }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish.yml around lines 21 - 29, Move the high-privilege
permissions out of the workflow-level permissions block and scope them to the
job that performs the deployment: remove or reduce "pages: write" and "id-token:
write" from the top-level permissions section and add a permissions block to the
deploy job that explicitly sets pages: write and id-token: write (keeping other
permissions like contents: read at the workflow level if needed); update the
deploy job definition (the job named "deploy" in the workflow) to include the
per-job permissions so only that job has pages and id-token write access.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@AGENTS.md`:
- Around line 15-30: The fenced code block in AGENTS.md showing the repository
layout lacks a language specifier; update the opening fence to include a
language (e.g., change ``` to ```plaintext or ```text) so the block becomes
"```plaintext" and leave the closing fence intact; this ensures proper syntax
highlighting and linting compliance for the repository layout block.

In `@package.json`:
- Line 9: The inline dev server command in the "serve" script uses a typo
calling s.writeCode?0:0 inside the h.createServer request handler (args q,s)
which does not set the HTTP status; replace that expression with a proper call
to s.writeHead(404) before returning so the response is sent with the correct
404 status (ensure the handler still calls s.end('Not found') after writeHead).
Locate the anonymous request handler used in the serve script (the
h.createServer callback) and update the error branch accordingly.

In `@README.md`:
- Around line 103-110: The fenced code block in README.md containing the
directory listing (lines with "posts/", "scripts/build.mjs", "public/",
".github/workflows/") lacks a language specifier; update the opening fence from
``` to include a language like plaintext or text (e.g., ```plaintext) so the
block is properly highlighted and passes linting.

---

Outside diff comments:
In `@README.md`:
- Around line 112-124: The README contains a contradictory sentence that says
"默认分支为 `main`" while the branch rules and AGENTS.md declare `develop` as the
default branch; update the sentence that currently reads "默认分支为 `main`" so it
instead states "默认分支为 `develop`" (or otherwise clarifies that `develop` is the
default branch for development and PRs), ensuring the README's "参与开发" section
and the referenced AGENTS.md remain consistent with the earlier branch rules
that designate `develop` as the integration/default branch.

---

Nitpick comments:
In @.github/workflows/publish.yml:
- Line 35: Update the actions/checkout step (uses: actions/checkout@v4) to
disable credential persistence by adding persist-credentials: false to the step
configuration so the GITHUB_TOKEN is not written to local git config; locate the
checkout step in the workflow and insert the persist-credentials key under that
step with a boolean false value.
- Around line 21-29: Move the high-privilege permissions out of the
workflow-level permissions block and scope them to the job that performs the
deployment: remove or reduce "pages: write" and "id-token: write" from the
top-level permissions section and add a permissions block to the deploy job that
explicitly sets pages: write and id-token: write (keeping other permissions like
contents: read at the workflow level if needed); update the deploy job
definition (the job named "deploy" in the workflow) to include the per-job
permissions so only that job has pages and id-token write access.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d706c20-c946-4547-8187-1e674aa4b024

📥 Commits

Reviewing files that changed from the base of the PR and between 906dc00 and fa81d48.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • .codex/setup.sh
  • .github/workflows/blank.yml
  • .github/workflows/publish.yml
  • .gitignore
  • AGENTS.md
  • README.md
  • package.json
  • posts/2026-06-11-hello-openblog.md
  • scripts/build.mjs
💤 Files with no reviewable changes (1)
  • .github/workflows/blank.yml

Comment thread AGENTS.md
Comment on lines 15 to 30
## Repository layout

```
.
├── AGENTS.md # this file
├── README.md
├── README.md # positioning + usage
├── package.json # scripts: build, serve
├── posts/ # Markdown articles (the content source)
│ └── *.md # front matter: title, date, tags, summary
├── scripts/
│ └── build.mjs # static-site generator (Markdown -> public/)
├── public/ # build output (git-ignored, regenerated)
└── .github/
└── workflows/
└── blank.yml # placeholder CI (echoes hello world)
└── publish.yml # scheduled generate + publish to Pages
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Missing language specifier on fenced code block.

The fenced code block at line 17 should specify a language for proper syntax highlighting and linting compliance.

📝 Proposed fix
 ## Repository layout
 
-```
+```plaintext
 .
 ├── AGENTS.md                  # this file
 ├── README.md                  # positioning + usage
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## Repository layout
```
.
├── AGENTS.md # this file
├── README.md
├── README.md # positioning + usage
├── package.json # scripts: build, serve
├── posts/ # Markdown articles (the content source)
│ └── *.md # front matter: title, date, tags, summary
├── scripts/
│ └── build.mjs # static-site generator (Markdown -> public/)
├── public/ # build output (git-ignored, regenerated)
└── .github/
└── workflows/
└── blank.yml # placeholder CI (echoes hello world)
└── publish.yml # scheduled generate + publish to Pages
```
## Repository layout
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 17-17: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@AGENTS.md` around lines 15 - 30, The fenced code block in AGENTS.md showing
the repository layout lacks a language specifier; update the opening fence to
include a language (e.g., change ``` to ```plaintext or ```text) so the block
becomes "```plaintext" and leave the closing fence intact; this ensures proper
syntax highlighting and linting compliance for the repository layout block.

Comment thread package.json
"type": "module",
"scripts": {
"build": "node scripts/build.mjs",
"serve": "node scripts/build.mjs && node -e \"import('node:http').then(h=>import('node:fs').then(f=>import('node:path').then(p=>{const t={'.html':'text/html;charset=utf-8','.css':'text/css','.js':'text/javascript'};h.createServer((q,s)=>{let u=decodeURIComponent(q.url.split('?')[0]);if(u==='/')u='/index.html';const fp=p.join('public',u);f.readFile(fp,(e,d)=>{if(e){s.writeCode?0:0;s.statusCode=404;return s.end('Not found')}s.setHeader('Content-Type',t[p.extname(fp)]||'application/octet-stream');s.end(d)})}).listen(8080,()=>console.log('OpenBlog dev server: http://localhost:8080'))})))\""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix typo in HTTP response handling.

The inline server has a typo: s.writeCode?0:0 should be s.writeHead(404) to properly send the HTTP 404 status code. The current code attempts to access a non-existent writeCode property.

🐛 Proposed fix
-    "serve": "node scripts/build.mjs && node -e \"import('node:http').then(h=>import('node:fs').then(f=>import('node:path').then(p=>{const t={'.html':'text/html;charset=utf-8','.css':'text/css','.js':'text/javascript'};h.createServer((q,s)=>{let u=decodeURIComponent(q.url.split('?')[0]);if(u==='/')u='/index.html';const fp=p.join('public',u);f.readFile(fp,(e,d)=>{if(e){s.writeCode?0:0;s.statusCode=404;return s.end('Not found')}s.setHeader('Content-Type',t[p.extname(fp)]||'application/octet-stream');s.end(d)})}).listen(8080,()=>console.log('OpenBlog dev server: http://localhost:8080'))})))\""
+    "serve": "node scripts/build.mjs && node -e \"import('node:http').then(h=>import('node:fs').then(f=>import('node:path').then(p=>{const t={'.html':'text/html;charset=utf-8','.css':'text/css','.js':'text/javascript'};h.createServer((q,s)=>{let u=decodeURIComponent(q.url.split('?')[0]);if(u==='/')u='/index.html';const fp=p.join('public',u);f.readFile(fp,(e,d)=>{if(e){s.writeHead(404);return s.end('Not found')}s.setHeader('Content-Type',t[p.extname(fp)]||'application/octet-stream');s.end(d)})}).listen(8080,()=>console.log('OpenBlog dev server: http://localhost:8080'))})))\""
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"serve": "node scripts/build.mjs && node -e \"import('node:http').then(h=>import('node:fs').then(f=>import('node:path').then(p=>{const t={'.html':'text/html;charset=utf-8','.css':'text/css','.js':'text/javascript'};h.createServer((q,s)=>{let u=decodeURIComponent(q.url.split('?')[0]);if(u==='/')u='/index.html';const fp=p.join('public',u);f.readFile(fp,(e,d)=>{if(e){s.writeCode?0:0;s.statusCode=404;return s.end('Not found')}s.setHeader('Content-Type',t[p.extname(fp)]||'application/octet-stream');s.end(d)})}).listen(8080,()=>console.log('OpenBlog dev server: http://localhost:8080'))})))\""
"serve": "node scripts/build.mjs && node -e \"import('node:http').then(h=>import('node:fs').then(f=>import('node:path').then(p=>{const t={'.html':'text/html;charset=utf-8','.css':'text/css','.js':'text/javascript'};h.createServer((q,s)=>{let u=decodeURIComponent(q.url.split('?')[0]);if(u==='/')u='/index.html';const fp=p.join('public',u);f.readFile(fp,(e,d)=>{if(e){s.writeHead(404);return s.end('Not found')}s.setHeader('Content-Type',t[p.extname(fp)]||'application/octet-stream');s.end(d)})}).listen(8080,()=>console.log('OpenBlog dev server: http://localhost:8080'))})))\""
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 9, The inline dev server command in the "serve" script
uses a typo calling s.writeCode?0:0 inside the h.createServer request handler
(args q,s) which does not set the HTTP status; replace that expression with a
proper call to s.writeHead(404) before returning so the response is sent with
the correct 404 status (ensure the handler still calls s.end('Not found') after
writeHead). Locate the anonymous request handler used in the serve script (the
h.createServer callback) and update the error branch accordingly.

Comment thread README.md
Comment on lines +103 to +110
## 目录结构

```
posts/ # Markdown 文章(内容源)
scripts/build.mjs # 静态站点生成器
public/ # 构建产物(自动生成,已 gitignore)
.github/workflows/ # 定时生成 + 自动发布到 Pages
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Missing language specifier on fenced code block.

The fenced code block at line 105 should specify a language for proper syntax highlighting and linting compliance.

📝 Proposed fix
-```
+```plaintext
 posts/                # Markdown 文章(内容源)
 scripts/build.mjs     # 静态站点生成器
 public/               # 构建产物(自动生成,已 gitignore)
 .github/workflows/    # 定时生成 + 自动发布到 Pages
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
## 目录结构

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 105-105: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 103 - 110, The fenced code block in README.md
containing the directory listing (lines with "posts/", "scripts/build.mjs",
"public/", ".github/workflows/") lacks a language specifier; update the opening
fence from ``` to include a language like plaintext or text (e.g., ```plaintext)
so the block is properly highlighted and passes linting.

@xiami303
xiami303 merged commit 01cadb2 into main Jun 11, 2026
1 check passed
This was referenced Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant