Skip to content

ci(nrg): generate README.md and README.zh.md from a single template - #1124

Open
andriishin wants to merge 3 commits into
ArtalkJS:masterfrom
andriishin:nrg-readme-template
Open

ci(nrg): generate README.md and README.zh.md from a single template#1124
andriishin wants to merge 3 commits into
ArtalkJS:masterfrom
andriishin:nrg-readme-template

Conversation

@andriishin

Copy link
Copy Markdown

What this changes

README.md and README.zh.md are currently maintained as two separate hand-edited files. Every commit that touches one needs a parallel edit in the other (and the git history confirms: every README commit so far has been a co-edit by you). This PR consolidates them into a single source โ€” README.src.md โ€” and adds a GitHub Action (nanolaba/nrg-action@v1) that regenerates both whenever the template changes.

After the merge: both rendered files on GitHub are unchanged; future content edits land in README.src.md once, and the bot updates both files in a single follow-up commit.

Byte-perfect preservation

Locally regenerated with NRG 1.2 โ€” diff vs current master:

README.md       3 metadata-header insertions (only)
README.zh.md    3 metadata-header insertions (only)

No translation content, link, code block, locale-specific value (TZ, ATK_LOCALE, ATK_SITE_DEFAULT), heading, or image changed.

The 3-line metadata header marks each file as auto-generated:

<!-- This file was automatically generated by Nanolaba Readme Generator (NRG) 1.2 -->
<!-- Visit https://github.com/nanolaba/readme-generator for details -->

It signals to future contributors not to hand-edit, and the drift-check job below enforces it on PRs.

How the template works

  • Untagged lines render in all languages โ€” used for shared bits like badges, the <p align=\"center\">/<img> block, prettier-ignore markers, the contrib.rocks/repobeats/starchart images, and blank lines.
  • Lines tagged <!--en--> or <!--zh--> only render in that language. Used for translated text, locale-specific code-block values (TZ=America/New_York vs Asia/Shanghai, ATK_LOCALE=en vs zh-CN, ATK_SITE_DEFAULT='Artalk Blog' vs 'Artalk ็š„ๅšๅฎข'), and the Learn More โ†’ URL pointer (/en/ vs /zh/).
  • File-name mapping: default lang โ†’ README.md, configured nrg.fileNamePattern.zh=README.zh.md.

Editing future README updates becomes: open README.src.md, edit the <!--en--> line, edit the <!--zh--> line, push. Drift-check on the PR catches if you forget the second edit (it just refuses to pass until both files reflect the template).

Adding a third language later (Japanese, etc.) is purely additive โ€” append ja to <!--@nrg.languages=...-->, add <!--@nrg.fileNamePattern.ja=README.ja.md-->, and add <!--ja-->-tagged lines next to existing <!--en--> lines. Existing files stay untouched.

CI behavior

Two jobs in .github/workflows/nrg.yml:

  • regenerate (push to master, when README.src.md or the workflow itself changes) โ€” regenerates both READMEs and commits them as github-actions[bot].
  • drift-check (pull_request, when any README*.md or the template changes) โ€” fails the PR if a contributor hand-edited a generated file. The failure log shows a clear diff: 'regenerated content differs from on-disk; edit README.src.md instead.'

Both jobs pinned to nrg-version: '1.2'. No conflict with existing CI โ€” test-docs.yml runs prettier/eslint on docs/** only, not on root README files.

If you don't want this

Easy to revert โ€” drop README.src.md, drop .github/workflows/nrg.yml, the existing README.md and README.zh.md are byte-identical except for the auto-generated header (which is also trivial to strip). Happy to discuss alternative shapes if the byte-perfect-mirror approach isn't right for your workflow.

Adds README.src.md as the single source for the existing two READMEs and
wires up nanolaba/nrg-action@v1 to regenerate them on push to master.
A drift-check job on PRs catches any direct hand-edits to a generated
file with a clear diff pointing back at README.src.md.

Output preserves both files byte-for-byte except for a 3-line auto-generated
header injected at the top of each (NRG metadata, marks the file as
generated). No translation content, link, code-block content, image, or
heading changed.

How the template works:

  - README.src.md contains untagged shared lines (badges, prettier
    markers, structural images, blank lines) and per-language lines
    tagged <!--en--> / <!--zh--> for the translatable bits and the
    locale-specific values inside the docker / Artalk.init code blocks.
  - The default NRG file-name pattern produces README.md (default lang)
    and README.zh.md (configured via nrg.fileNamePattern.zh).

Both jobs pinned to nrg-version: '1.2'.
andriishin added 2 commits May 2, 2026 22:03
Two security hardenings:

  1. Drop top-level 'contents: write'; default workflow permissions
     to 'contents: read', and grant write only on the regenerate job
     that needs it for git push. The drift-check job inherits the
     read-only default.

  2. Replace 'nanolaba/nrg-action@v1' (floating tag) with the
     immutable commit SHA. Standard supply-chain hygiene.
Future-proof against adding languages later: instead of hardcoding
'README.md README.zh.md', use a git pathspec array of 'README.md' +
'README.*.md' with an explicit ':(exclude)README.src.md' guard so the
source template never gets re-staged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant