Skip to main content

Convert GLEP 42 Gentoo news repositories into static blogs

Project description

geek42

CI CodeQL OpenSSF Scorecard OpenSSF Best Practices License: CC0-1.0 uv Ruff pre-commit

Convert GLEP 42 Gentoo news repositories into a static blog with RSS/Atom feeds, Markdown exports, and a terminal reader — no eselect news required.

Features

  • Local-first blog — write news items in your git repo, push to publish
  • Static site — generates a self-contained HTML site ready for GitHub Pages or any static host
  • Pre-commit blog compiler — auto-generates Markdown files and a README index on commit
  • RSS + Atom feeds — standards-compliant feeds generated from stdlib (no extra deps)
  • Markdown exports — each news item exported as .md with YAML frontmatter (Jekyll/Hugo compatible)
  • Compose and revisenew and revise commands open $EDITOR with templates and auto-lint
  • Full GLEP 42 metadata — packages, architectures, profiles, revision, format version all preserved
  • Multiple sources — optionally aggregate news from remote GLEP 42 git repos
  • Terminal readerlist and read commands with Rich formatting
  • Semantic HTML — Schema.org JSON-LD, Open Graph, proper <article>/<time>/<address> elements
  • Dark mode — respects prefers-color-scheme

Install

Requires Python 3.13+.

uv tool install geek42

Quickstart

# Create a git repo for your news blog
mkdir my-blog && cd my-blog
git init

# Scaffold the repo (config, pre-commit, CI, README, ...)
geek42 init --title "My Blog"

# Set up pre-commit hooks
uv sync --dev && pre-commit install

# Write your first post (opens $EDITOR)
geek42 new

# Commit and push (pre-commit compiles blog automatically)
geek42 commit
geek42 push

Configuration

geek42.toml (created by geek42 init):

title = "My News"
author = "Your Name <you@example.org>"
description = "News Items"
base_url = ""
output_dir = "_site"
data_dir = ".geek42"
language = "en"

[[sources]]
name = "local"
url = "."

# To read news from remote repositories:
# [[sources]]
# name = "gentoo"
# url = "https://anongit.gentoo.org/git/data/glep42-news-gentoo.git"
# branch = "master"

CLI Commands

geek42 init              Create a default geek42.toml
geek42 new               Create a new news item (opens $EDITOR)
geek42 new -e nano       Use a specific editor
geek42 new -C <dir>      Create a news item in a specific directory
geek42 revise <id>       Revise an existing item (bump rev, open $EDITOR)
geek42 lint <path>       Lint a news file or repository directory
geek42 lint --strict .   Treat warnings as errors
geek42 compile-blog      Compile Markdown files and update README index
geek42 build --no-pull   Build static site from local items
geek42 list              List news items in a Rich table
geek42 list -C <dir>     List news items from a specific directory
geek42 read <id>         Read a specific news item in the terminal
geek42 pull              Clone or update remote news sources
geek42 build             Pull remote sources and build the static site
geek42 commit            Stage news, compile blog, commit (like pkgdev commit)
geek42 commit -m "msg"   Commit with a custom message
geek42 push              Push commits to the remote
geek42 deploy-status     Check GitHub Pages and CI status (requires gh)
geek42 sign              Generate gemato-compatible Manifest checksums
geek42 sign -k KEY_ID    Sign the Manifest with gpg
geek42 verify            Verify Manifest checksums and signature

Most commands accept --directory / -C to operate on a directory other than the current one. Config, data, and output paths are resolved relative to that directory.

Lint codes

Code Severity Description
E001 error Missing required header
E002 error Invalid date format
E003 error Invalid revision number
E004 error Unknown News-Item-Format
E005 error Format 1.0 missing Content-Type
E006 error Empty body
E007 error No blank line between headers and body
E008 error Missing news file in directory
E010 error Malformed header line
W001 warning Title exceeds 50 characters
W002 warning Body line exceeds 72 characters
W003 warning Trailing whitespace
W004 warning Author not in Name <email> format
W005 warning File name doesn't match directory name
W006 warning Directory name doesn't match GLEP 42 pattern

Repository Layout

News items live under metadata/news/ (standard portage layout):

my-blog/
  metadata/news/
    2025-11-30-flexiblas-migration/
      2025-11-30-flexiblas-migration.en.txt
    ...
  geek42.toml

Dedicated news-only repos (like glep42-news-gentoo.git) that store items at the root are also supported — geek42 auto-detects the layout.

Output Structure

_site/
  index.html            Main listing page
  style.css             Stylesheet (dark mode aware)
  rss.xml               RSS 2.0 feed
  atom.xml              Atom 1.0 feed
  posts/
    2025-11-30-flexiblas-migration.html
    ...
  markdown/
    2025-11-30-flexiblas-migration.md
    ...

Development

uv sync

# Run tests with coverage
uv run pytest

# Linting
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/

# Type checking
uv run ty check

GitHub Pages Deployment

Add a workflow like .github/workflows/deploy.yml:

name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      pages: write
      id-token: write
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v6
      - run: uv tool install geek42
      - run: geek42 build --no-pull
      - uses: actions/upload-pages-artifact@v3
        with:
          path: _site
      - id: deployment
        uses: actions/deploy-pages@v4

Documentation

Security

  • Disclosure policy: SECURITY.md
  • Contributing: CONTRIBUTING.md (signed commits required)
  • Supply chain: Releases are built by GitHub Actions with SLSA Level 3 provenance, signed with sigstore, and published to PyPI via OIDC trusted publishing. Every release ships with a CycloneDX SBOM and build attestations.

Verifying a release

# Download wheel and attestations
gh release download v0.1.0 --repo IvanAnishchuk/geek42

# Verify sigstore signature (requires `uv tool install sigstore`)
uv tool run sigstore verify identity \
    --cert-identity-regexp '^https://github\.com/IvanAnishchuk/geek42/\.github/workflows/release\.yml@' \
    --cert-oidc-issuer 'https://token.actions.githubusercontent.com' \
    --bundle geek42-0.1.0-py3-none-any.whl.sigstore \
    geek42-0.1.0-py3-none-any.whl

# Verify GitHub build provenance
gh attestation verify geek42-0.1.0-py3-none-any.whl --owner IvanAnishchuk

# Verify SLSA L3 provenance
slsa-verifier verify-artifact \
    --provenance-path geek42-provenance.intoto.jsonl \
    --source-uri github.com/IvanAnishchuk/geek42 \
    --source-tag v0.1.0 \
    geek42-0.1.0-py3-none-any.whl

License

CC0 1.0 Universal — public domain dedication.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

geek42-0.4.1.tar.gz (86.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

geek42-0.4.1-py3-none-any.whl (42.5 kB view details)

Uploaded Python 3

File details

Details for the file geek42-0.4.1.tar.gz.

File metadata

  • Download URL: geek42-0.4.1.tar.gz
  • Upload date:
  • Size: 86.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for geek42-0.4.1.tar.gz
Algorithm Hash digest
SHA256 554c92c440698f7b16116f7732d793ea9727ba6028f79a44cec93753d4c37944
MD5 0d63a37855780bac0c2b2fc72816f3a0
BLAKE2b-256 e7bf6f5616d251d012e8c47c1591ba5756538ff898f08444526ad9d921347baa

See more details on using hashes here.

Provenance

The following attestation bundles were made for geek42-0.4.1.tar.gz:

Publisher: release.yml on IvanAnishchuk/geek42

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file geek42-0.4.1-py3-none-any.whl.

File metadata

  • Download URL: geek42-0.4.1-py3-none-any.whl
  • Upload date:
  • Size: 42.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for geek42-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 94bb051abba1e8d478d80e854bf85e136c7ff05cb2be394b3ddedb36fdc788ed
MD5 09b64e00460f639ac09753cce36957fd
BLAKE2b-256 1cf4ae83ca0b27619249f3172f250e77536aee4045aefb02f56c335f775b79c1

See more details on using hashes here.

Provenance

The following attestation bundles were made for geek42-0.4.1-py3-none-any.whl:

Publisher: release.yml on IvanAnishchuk/geek42

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page