Releases and downloads

Keep release facts, archive links, checksums, and rolling or pinned download channels consistent without remote API calls.

Oink separates immutable release facts from their presentation. A release page owns the version and repository identity; local download data owns distribution channels. Cards, lists, checksum tables, documentation pages, and Landing pages derive from those records instead of copying URLs and commands into several templates.

Define release facts

Add a strict release map to the page front matter:

YAML
release:
  product: Pig
  version: 1.7.0
  repo: pgsty/pig
  tag: v1.7.0
  date: 2026-08-14
  prev: v1.6.0
  checksums: SHA256SUMS

version and repo are required. Omit tag to derive v{version} and omit date to use the page date. Optional product, prev, and checksums fields complete the record. Unknown keys, wrong types, or a repository outside the owner/name form fail the build.

For a simple GitHub release, the exact tag URL is also accepted as shorthand:

YAML
release: https://github.com/pgsty/pig/releases/tag/v1.7.0

Oink derives repository, release, archive, compare, checksum, and asset links locally. It does not call GitHub during a build and does not claim that a tag or asset exists remotely.

Render the release card

Place the parameter-free shortcode where the fact summary should appear:

GO-HTML-TEMPLATE
{{< release-card >}}

The invocation accepts no facts and no parameters; the page front matter is the only authority. HTML receives a semantic link card with no runtime. Print and RSS receive a static link list, and Markdown receives ordinary Markdown links.

Build a release index

A release section can opt into deterministic ordering:

YAML
---
title: Releases
layout: releases
release_group_by_product: true
release_products: [OINK, Pig]
---

Pages sort by normalized release date descending, then valid SemVer precedence, then a deterministic lexical fallback. The default is one global sequence. release_group_by_product: true requires each selected page to define product. release_products accepts one product or an array, matches the product string exactly, and filters before sorting. Invalid filters fail instead of rendering a plausible but empty page.

Publish checksum assets

Write exact sha*sum lines inside release-assets:

GO-HTML-TEMPLATE
{{< release-assets group="auto" >}}
0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef  pig-1.7.0-linux-amd64.tar.gz
fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210 *pig-1.7.0-darwin-arm64.tar.gz
{{< /release-assets >}}

Or commit a checksum file as a page or Hugo asset and reference exactly one source:

GO-HTML-TEMPLATE
{{< release-assets src="release/SHA256SUMS" group="auto" >}}

The parser rejects malformed lines with their line number, mixed algorithms, algorithm/hash-length disagreement, path-like filenames, and ambiguous input sources. HTML links each asset and conditionally loads one local copy runtime; print shows complete hashes without controls; Markdown and RSS emit full-hash tables.

group="auto" groups common platform and architecture names. Use algo only when declaring the expected checksum algorithm, and base only when the asset base differs from the URL derived from release facts.

Define download channels once

Create data/download/pig.yaml:

YAML
version: 1.7.0
repo: pgsty/pig
published: true
channels:
  - id: script
    kind: rolling
    title: Install script
    title_zh: 安装脚本
    icon: fa-solid fa-bolt
    note: Tracks the rolling stable channel.
    note_zh: 跟随滚动稳定渠道。
    steps:
      - title: Install
        title_zh: 安装
        code: curl -fsSL https://repo.example.org/pig/install | bash
        lang: bash
  - id: source
    kind: pinned
    title: Source archive
    title_zh: 源码归档
    icon: fa-solid fa-code-branch
    url: https://github.com/pgsty/pig/archive/refs/tags/${tag}.tar.gz
    steps:
      - title: Clone the tag
        title_zh: 克隆标签
        code: git clone --branch ${tag} https://github.com/pgsty/pig.git
        lang: bash
  - id: assets
    kind: pinned
    title: Release assets
    title_zh: 发布资产
    icon: fa-solid fa-box-open
    checksums_src: release/pig-SHA256SUMS

A record needs a string version directly or through params.version, plus a non-empty channels array. Every channel needs a unique anchor-safe id, one kind (rolling or pinned), and a localized title.

Shared fields resolve from the exact language suffix, then the primary-language suffix, then the unsuffixed field. For example, Chinese may resolve title_zh_cn, then title_zh, then title. Only a pinned channel’s url and steps[].code may interpolate ${version} or ${tag}. Rolling channels reject all interpolation so a stable command cannot accidentally pretend to be pinned.

Render downloads

Reference the data key with one positional parameter:

GO-HTML-TEMPLATE
{{< download "pig" >}}

HTML renders a channel index and static-first sections. Code steps reuse Oink’s enhanced code renderer; checksum channels reuse Release Assets. Print expands the same safe content, Markdown emits headings, source fences, and full hashes, and RSS omits the component.

Set published: false before the immutable release exists. Rolling channels remain usable, while pinned channels show a non-linking pending state, omit pinned commands, and disable asset links and copy controls. Flip the fact only after the tag and assets resolve; never paste speculative links into prose.

A Landing page can consume the same record with a download section:

YAML
sections:
  - type: download
    data:
      title: Download Pig
      keys: [pig]

Release checklist

  1. Confirm the version, tag, previous tag, repository, and date from the source release process.
  2. Validate every checksum against the published artifact before committing it.
  3. Build HTML, print, and Markdown; inspect complete hashes outside HTML.
  4. Test published: false before publication and true only after the remote tag and assets resolve.
  5. Verify every language and a subpath deployment.
  6. Treat source completion, theme tag publication, module resolution, consumer pinning, and hosted availability as separate gates.