You are viewing a plain text version of this content. The canonical link for it is here.
Posted to site-notify@rai.apache.org by ak...@apache.org on 2026/10/21 04:55:03 UTC
(rai-site) branch preview/akm-blog updated: Fixing site build issues
This is an automated email from the ASF dual-hosted git repository.
andrewmusselman pushed a commit to branch preview/akm-blog
in repository https://gitbox.apache.org/repos/asf/rai-site.git
The following commit(s) were added to refs/heads/preview/akm-blog by this push:
new 2d4d4fe Fixing site build issues
2d4d4fe is described below
commit 2d4d4fe5f278a262ee39ad2f15920db299b795b7
Author: Andrew Musselman <an...@gmail.com>
AuthorDate: Tue Oct 20 21:54:50 2026 -0700
Fixing site build issues
---
AGENTS.md | 55 +++++++++++++++++++++++---------
README.md | 10 ++++--
content/pages/blog.md | 9 ++++++
content/theme/templates/author.html | 4 +++
content/theme/templates/blog.html | 2 ++
content/theme/templates/blogindex.html | 24 +-------------
content/theme/templates/breadcrumbs.html | 4 +--
content/theme/templates/category.html | 4 +++
content/theme/templates/postlist.html | 24 ++++++++++++++
content/theme/templates/tag.html | 4 +++
content/theme/templates/taxonomy.html | 51 +++++++++++++++++++++++++++++
pelicanconf.py | 14 +-------
12 files changed, 150 insertions(+), 55 deletions(-)
diff --git a/AGENTS.md b/AGENTS.md
index 389f2f8..6dd1d1d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -14,17 +14,32 @@ There is **no simple local build**. The authoritative build runs on **ASF
infrastructure**, driven by `.asf.yaml`: the `pelican`/`publish` configuration builds
the `main` branch and publishes the generated HTML to the `asf-site` branch, which is
served at `rai.apache.org` (see [`apache/infrastructure-asfyaml`](https://github.com/apache/infrastructure-asfyaml#deploy)
-for how that mechanism works). In CI this is mirrored by
-`apache/infrastructure-actions/pelican` (`.github/workflows/build-pelican.yml`).
-
-That action — not `pyproject.toml` — supplies the ASF Pelican plugins the config
-requires (`asfgenid`, `asfrun`, plus `toc`, `spu`, `gfm`). `pyproject.toml` lists only
-`pelican` + helpers, so `pelican` alone will **not** reproduce the real build. To build
-outside the ASF action you need the plugins from
-[`apache/infrastructure-pelican`](https://github.com/apache/infrastructure-pelican).
-
-`pagefind.sh` (referenced as `ASF_POSTRUN` in `pelicanconf.py`) downloads the `pagefind`
-binary at build time and generates the search index into `_pagefind/`.
+for how that mechanism works). The build runs on **ASF BuildBot**
+([ci2.apache.org](https://ci2.apache.org)) — commits on `asf-site` are labelled
+"Automatic Site Publish by Buildbot". There is **no GitHub Actions build**: the only
+workflow in this repo is `pre-commit.yml`, so the Actions tab will never show a site
+build, and build results arrive by email instead (`notifications.jobs` in `.asf.yaml`,
+plus the pushing committer's `@apache.org` address).
+
+> **`pelicanconf.py` is not what the build reads.** `buildsite.py` in
+> [`apache/infrastructure-pelican`](https://github.com/apache/infrastructure-pelican)
+> checks for `pelicanconf.yaml` first, and when it exists — it does here — it
+> *generates* `pelican.auto.py` from that YAML via `bin/pelican.auto.ezt` and passes
+> that to Pelican. `pelicanconf.py` is only a fallback for repositories with no YAML,
+> and the copy in this repository is a stale snapshot of the generated file, kept for
+> local builds. **Editing `pelicanconf.py` has no effect on the published site**, and
+> the YAML schema is fixed: it accepts the keys in
+> [`pelicanconf.md`](https://github.com/apache/infrastructure-pelican/blob/master/pelicanconf.md)
+> and offers no way to set arbitrary Pelican settings. Anything the generated settings
+> don't give you has to be solved in the theme or in content metadata.
+
+The ASF plugins the config requires (`asfgenid`, `asfrun`, plus `toc`, `spu`, `gfm`) come
+from `infrastructure-pelican`, not `pyproject.toml`, which lists only `pelican` + helpers.
+So `pelican` alone will **not** reproduce the real build.
+
+`pagefind.sh` (`postrun` in `pelicanconf.yaml`, `ASF_POSTRUN` in the generated settings)
+downloads the `pagefind` binary at build time and generates the search index into
+`_pagefind/`.
## Build and test commands
@@ -45,10 +60,20 @@ before opening or updating a PR.
Pelican metadata block — at least `Title:` and `license:`; the home page also sets
`Template: index`. Mermaid code blocks render as diagrams.
- Blog posts live in `content/blog/*.md` and need `Date:` as well (plus optional
- `Author:`, `Tags:`, `Summary:`). They publish to `/blog/<slug>.html` with an index at
- `/blog/index.html`, rendered by `blog.html` as a Pelican `DIRECT_TEMPLATES` entry. Tag,
- category and author pages are deliberately not generated (`TAG_SAVE_AS` and friends are
- `""`); tags are labels only. See README.md for the post front matter.
+ `Author:`, `Tags:`, `Summary:`). They publish to `/blog/<slug>.html`. See README.md for
+ the front matter.
+- **The blog index is a page, not a direct template.** `content/pages/blog.md` carries
+ `Template: blog`, `Save_as: blog/index.html` and `URL: blog/`, and holds no content of
+ its own. It is done this way because `DIRECT_TEMPLATES` can only be set in Pelican
+ settings, and the generated settings aren't ours to change (see above).
+- **`tag.html`, `category.html` and `author.html` must exist.** The generated settings set
+ only the plural switches (`TAGS_SAVE_AS` and friends) and leave the singular ones at
+ their defaults, so Pelican writes one page per tag, category and author for every post
+ whether we want them or not. With no template of our own it falls back to Pelican's
+ built-in simple theme, which extends `index.html`, which expects a `page` — and the
+ whole build dies with something unhelpful like `'str' object has no attribute 'slug'`.
+ The three thin templates and the shared `taxonomy.html` exist to catch that. **Removing
+ them breaks every build that has a post in it**, not just the taxonomy pages.
- Adding a page does **not** add it to the navigation. Update the nav by hand in
`content/theme/templates/menu.html`.
- **Links are deliberately relative** (`about.html`, `css/…`, not `/about.html`,
diff --git a/README.md b/README.md
index 1498bf3..35d2dec 100644
--- a/README.md
+++ b/README.md
@@ -15,8 +15,8 @@ content/
blog/ Markdown blog posts (one file per post, published under /blog/)
theme/ Pelican theme (templates)
css/ js/ fonts/ highlight/ images/ static assets
-pelicanconf.py Pelican configuration (Python)
-pelicanconf.yaml
+pelicanconf.yaml Pelican configuration — the one the ASF build reads
+pelicanconf.py Stale copy of the generated settings, for local builds only
.asf.yaml ASF infrastructure configuration (build + notifications)
pyproject.toml Python dependencies (managed with uv)
```
@@ -57,6 +57,12 @@ Two things to watch:
`../get-involved.html`, not `get-involved.html`. Links between posts are plain
(`other-post.html`), and so are external links.
+The index at `/blog/` is `content/pages/blog.md`, which only tells Pelican where to put
+the page; the heading and the post list come from the theme. Posts also generate
+`/tag/*.html`, `/category/*.html` and `/author/*.html` listings — those are a requirement
+of the ASF build rather than a feature, and they're marked `noindex`. See AGENTS.md
+before touching any of it.
+
## Local build (optional)
The authoritative build runs on ASF infrastructure. To preview locally you need the ASF
diff --git a/content/pages/blog.md b/content/pages/blog.md
new file mode 100644
index 0000000..6eaf8da
--- /dev/null
+++ b/content/pages/blog.md
@@ -0,0 +1,9 @@
+Title: Blog
+Template: blog
+Save_as: blog/index.html
+URL: blog/
+license: https://www.apache.org/licenses/LICENSE-2.0
+
+The blog index is built from the posts in `content/blog/`; this page only tells
+Pelican where to put it. The heading and the list of posts come from the
+`blog.html` template.
diff --git a/content/theme/templates/author.html b/content/theme/templates/author.html
new file mode 100644
index 0000000..945ae21
--- /dev/null
+++ b/content/theme/templates/author.html
@@ -0,0 +1,4 @@
+{% set root = '../' %}
+{% set taxonomy_label = 'Author' %}
+{% set taxonomy_name = author %}
+{% include "taxonomy.html" %}
diff --git a/content/theme/templates/blog.html b/content/theme/templates/blog.html
index 6f6a7c9..12069a9 100644
--- a/content/theme/templates/blog.html
+++ b/content/theme/templates/blog.html
@@ -1,4 +1,6 @@
{% set root = '../' %}
+{# the Blog crumb is already the last one here, so don't repeat the page #}
+{% set hide_page_crumb = true %}
{% block head %}
<!doctype html>
<html class="no-js" lang="en" dir="ltr">
diff --git a/content/theme/templates/blogindex.html b/content/theme/templates/blogindex.html
index 1707b9b..1c031ee 100644
--- a/content/theme/templates/blogindex.html
+++ b/content/theme/templates/blogindex.html
@@ -5,29 +5,7 @@
<div class="mx-auto">
<h1>Blog</h1>
<p class="rai-lede">News and updates from the Responsible AI initiative at The Apache Software Foundation.</p>
-
- {% if articles %}
- <ul class="rai-postlist">
- {% for article in articles %}
- <li class="rai-postlist-item">
- <h2><a href="{{ root }}blog/{{ article.slug }}.html">{{ article.title }}</a></h2>
- <p class="rai-meta">
- <time datetime="{{ article.date.isoformat() }}">{{ article.date.strftime('%d %B %Y') }}</time>
- {%- if article.author %} · {{ article.author }}{% endif %}
- </p>
- {% if article.summary %}<div class="rai-summary">{{ article.summary }}</div>{% endif %}
- {% if article.tags %}
- <p class="rai-tags">
- {% for tag in article.tags %}<span class="rai-tag">{{ tag.name }}</span>{% endfor %}
- </p>
- {% endif %}
- <p><a class="rai-more" href="{{ root }}blog/{{ article.slug }}.html">Continue reading →</a></p>
- </li>
- {% endfor %}
- </ul>
- {% else %}
- <p>No posts yet.</p>
- {% endif %}
+ {% include "postlist.html" %}
</div>
</div>
</div>
diff --git a/content/theme/templates/breadcrumbs.html b/content/theme/templates/breadcrumbs.html
index 2226975..40a39eb 100644
--- a/content/theme/templates/breadcrumbs.html
+++ b/content/theme/templates/breadcrumbs.html
@@ -10,8 +10,8 @@
{% if article %}
<li class="breadcrumb-item active"><a href="{{ root }}blog/{{ article.slug }}.html">{{ article.title }}</a></li>
<li class="breadcrumb-item active">(<a href="https://github.com/apache/rai-site/tree/main/content/blog/{{ article.slug }}.md">edit</a>)</li>
- {% elif page %}
- <li class="breadcrumb-item active"><a href="{{ root }}{{ page.slug }}.html">{{ page.title }}</a></li>
+ {% elif page and not hide_page_crumb %}
+ <li class="breadcrumb-item active"><a href="{{ root }}{{ page.url }}">{{ page.title }}</a></li>
<li class="breadcrumb-item active">(<a href="https://github.com/apache/rai-site/tree/main/content/pages/{{ page.slug }}.md">edit</a>)</li>
{% endif %}
</ol>
diff --git a/content/theme/templates/category.html b/content/theme/templates/category.html
new file mode 100644
index 0000000..30d817c
--- /dev/null
+++ b/content/theme/templates/category.html
@@ -0,0 +1,4 @@
+{% set root = '../' %}
+{% set taxonomy_label = 'Category' %}
+{% set taxonomy_name = category %}
+{% include "taxonomy.html" %}
diff --git a/content/theme/templates/postlist.html b/content/theme/templates/postlist.html
new file mode 100644
index 0000000..fb2a4e0
--- /dev/null
+++ b/content/theme/templates/postlist.html
@@ -0,0 +1,24 @@
+{% set root = root|default('') %}
+<!-- shared list of posts, used by the blog index and the taxonomy pages -->
+{% if articles %}
+<ul class="rai-postlist">
+ {% for article in articles %}
+ <li class="rai-postlist-item">
+ <h2><a href="{{ root }}blog/{{ article.slug }}.html">{{ article.title }}</a></h2>
+ <p class="rai-meta">
+ <time datetime="{{ article.date.isoformat() }}">{{ article.date.strftime('%d %B %Y') }}</time>
+ {%- if article.author %} · {{ article.author }}{% endif %}
+ </p>
+ {% if article.summary %}<div class="rai-summary">{{ article.summary }}</div>{% endif %}
+ {% if article.tags %}
+ <p class="rai-tags">
+ {% for tag in article.tags %}<span class="rai-tag">{{ tag.name }}</span>{% endfor %}
+ </p>
+ {% endif %}
+ <p><a class="rai-more" href="{{ root }}blog/{{ article.slug }}.html">Continue reading →</a></p>
+ </li>
+ {% endfor %}
+</ul>
+{% else %}
+<p>No posts yet.</p>
+{% endif %}
diff --git a/content/theme/templates/tag.html b/content/theme/templates/tag.html
new file mode 100644
index 0000000..2bf6af0
--- /dev/null
+++ b/content/theme/templates/tag.html
@@ -0,0 +1,4 @@
+{% set root = '../' %}
+{% set taxonomy_label = 'Tag' %}
+{% set taxonomy_name = tag %}
+{% include "taxonomy.html" %}
diff --git a/content/theme/templates/taxonomy.html b/content/theme/templates/taxonomy.html
new file mode 100644
index 0000000..3e5fe65
--- /dev/null
+++ b/content/theme/templates/taxonomy.html
@@ -0,0 +1,51 @@
+{% set root = root|default('../') %}
+{#
+ Shared page for Pelican's per-tag, per-category and per-author listings.
+
+ These pages exist because the ASF build generates its settings from
+ pelicanconf.yaml, and that template sets only the plural switches
+ (TAGS_SAVE_AS and friends). The singular ones default to tag/{slug}.html,
+ category/{slug}.html and author/{slug}.html, so Pelican writes one page per
+ tag, category and author whether or not we want them. Without a template of
+ our own it falls back to Pelican's simple theme, which extends index.html and
+ takes the whole build down. Giving it somewhere to land is the fix.
+#}
+{% block head %}
+<!doctype html>
+<html class="no-js" lang="en" dir="ltr">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="x-ua-compatible" content="ie=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>{{ taxonomy_label }}: {{ taxonomy_name }} - {{SITENAME}}</title>
+ <meta name="robots" content="noindex, follow">
+ {% include "styles.html" %}
+ </head>
+ <body class="d-flex flex-column h-100">
+ {% include "menu.html" %}
+ <main class="flex-shrink-0">
+ <div class="card" style="height: 34px;">
+ <nav aria-label="breadcrumb" style="padding-left: 12px; padding-top: 4px;">
+ <ol class="breadcrumb">
+ <li class="breadcrumb-item"><a href="{{ root }}index.html">Home</a></li>
+ <li class="breadcrumb-item"><a href="{{ root }}blog/">Blog</a></li>
+ <li class="breadcrumb-item active">{{ taxonomy_label }}: {{ taxonomy_name }}</li>
+ </ol>
+ </nav>
+ </div>
+ <div id="contents">
+ <div class="bg-white rounded">
+ <div class="mx-auto">
+ <h1>{{ taxonomy_name }}</h1>
+ <p class="rai-lede">Posts filed under this {{ taxonomy_label|lower }}.</p>
+ {% include "postlist.html" %}
+ <p class="rai-backlink"><a href="{{ root }}blog/">← All posts</a></p>
+ </div>
+ </div>
+ </div>
+ {% include "footer.html" %}
+ </main>
+ {% include "post.html" %}
+ </body>
+</html>
+{% endblock %}
diff --git a/pelicanconf.py b/pelicanconf.py
index a492315..8854cef 100644
--- a/pelicanconf.py
+++ b/pelicanconf.py
@@ -45,23 +45,11 @@ TAGS_SAVE_AS = ""
CATEGORIES_SAVE_AS = ""
AUTHORS_SAVE_AS = ""
ARCHIVES_SAVE_AS = ""
-# Per-tag / per-category / per-author pages too: the theme has no template for
-# them, and posts carry tags only as labels on the post and the blog index.
-TAG_SAVE_AS = ""
-CATEGORY_SAVE_AS = ""
-AUTHOR_SAVE_AS = ""
# Blog posts live in content/blog/ and are published under /blog/
ARTICLE_PATHS = ["blog"]
+# needed to create blogs page
ARTICLE_URL = "blog/{slug}.html"
ARTICLE_SAVE_AS = "blog/{slug}.html"
-ARTICLE_ORDER_BY = "reversed-date"
-# The blog index: content/theme/templates/blog.html rendered to /blog/index.html
-DIRECT_TEMPLATES = ["blog"]
-BLOG_URL = "blog/"
-BLOG_SAVE_AS = "blog/index.html"
-# Posts carry a Date; drafts are excluded until their status says published
-DEFAULT_DATE_FORMAT = "%d %B %Y"
-WITH_FUTURE_DATES = False
# Disable all processing of .html files
READERS = {
"html": None,