Skip to content

Commit 148c78e

Browse files
committed
WIP changelog aggregator
1 parent 058cce0 commit 148c78e

File tree

5 files changed

+160
-22
lines changed

5 files changed

+160
-22
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Aggregate Changelogs
2+
3+
on:
4+
schedule:
5+
# Run 3 times per day: 00:00, 08:00, 16:00 UTC
6+
- cron: '0 0,8,16 * * *'
7+
workflow_dispatch: # Allow manual trigger
8+
9+
permissions:
10+
contents: write # For committing generated files
11+
12+
jobs:
13+
aggregate:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Checkout docs repo
18+
uses: actions/checkout@v4
19+
with:
20+
token: ${{ secrets.APPPACK_DOCS_TOKEN }}
21+
22+
- name: Set up uv
23+
uses: astral-sh/setup-uv@v4
24+
with:
25+
enable-cache: true
26+
27+
- name: Set up Python
28+
uses: actions/setup-python@v5
29+
with:
30+
python-version: '3.14'
31+
32+
- name: Install dependencies
33+
run: uv sync
34+
35+
- name: Aggregate changelogs
36+
env:
37+
GITHUB_TOKEN: ${{ secrets.APPPACK_DOCS_TOKEN }}
38+
run: |
39+
uv run python scripts/aggregate_changelogs.py --verbose
40+
41+
- name: Check for changes
42+
id: verify_diff
43+
run: |
44+
git diff --quiet src/changelog/ || echo "changed=true" >> $GITHUB_OUTPUT
45+
46+
- name: Commit and push if changed
47+
if: steps.verify_diff.outputs.changed == 'true'
48+
run: |
49+
git config user.name "github-actions[bot]"
50+
git config user.email "github-actions[bot]@users.noreply.github.com"
51+
git add src/changelog/
52+
git commit -m "Update aggregated changelogs
53+
54+
🤖 Generated with [Claude Code](https://claude.com/claude-code)
55+
56+
Co-Authored-By: Claude <[email protected]>"
57+
git push

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ plugins:
2121
- macros
2222
- literate-nav:
2323
nav_file: _navigation.md
24+
- tags
2425
repo_url: https://github.com/apppackio/apppack-docs/
2526
edit_uri: edit/main/src/
2627
extra_css:

scripts/aggregate_changelogs.py

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,58 @@ def load_config(config_path: str) -> dict:
219219
return config
220220

221221

222+
def generate_version_page(entry: ChangelogEntry, output_path: Path) -> None:
223+
"""Generate an individual version page"""
224+
with output_path.open("w") as f:
225+
# Front matter
226+
f.write("---\n")
227+
f.write(f'title: "{entry.alias} {entry.version}"\n')
228+
f.write(f"tags: [{entry.alias}]\n")
229+
f.write("---\n\n")
230+
231+
# Page content
232+
f.write(f"# {entry.alias} {entry.version}\n\n")
233+
f.write(f"**Released:** {entry.date.strftime('%Y-%m-%d')}\n")
234+
f.write(f"**Repository:** {entry.repository}\n\n")
235+
236+
for section_name, items in entry.sections.items():
237+
if items:
238+
f.write(f"## {section_name}\n\n")
239+
f.writelines(f"- {item}\n" for item in items)
240+
f.write("\n")
241+
242+
f.write("---\n\n")
243+
f.write("[← Back to Changelog](../index.md)\n")
244+
245+
246+
def generate_index_page(entries: list[ChangelogEntry], output_path: Path) -> None:
247+
"""Generate the combined changelog index page"""
248+
with output_path.open("w") as f:
249+
# Front matter
250+
f.write("---\n")
251+
f.write('title: "AppPack Changelog"\n')
252+
f.write("---\n\n")
253+
254+
# Page content
255+
f.write("# AppPack Changelog\n\n")
256+
f.write(
257+
"This page aggregates changelogs from all AppPack repositories, "
258+
"showing the most recent changes first.\n\n"
259+
)
260+
261+
for entry in entries:
262+
f.write(f"## [{entry.alias} {entry.version}](versions/{entry.version_id}.md)\n\n")
263+
f.write(f"**{entry.date.strftime('%Y-%m-%d')}** • **{entry.repository}**\n\n")
264+
265+
for section_name, items in entry.sections.items():
266+
if items:
267+
f.write(f"### {section_name}\n\n")
268+
f.writelines(f"- {item}\n" for item in items)
269+
f.write("\n")
270+
271+
f.write("---\n\n")
272+
273+
222274
def get_auth_token(args: argparse.Namespace) -> str | None:
223275
"""Get GitHub authentication token from various sources"""
224276
# Priority: CLI arg > env var > gh CLI (automatic)
@@ -262,9 +314,9 @@ def main() -> None:
262314
help="Path to pyproject.toml file",
263315
)
264316
parser.add_argument(
265-
"--output",
266-
default="merged_changelog.md",
267-
help="Output file for merged changelog",
317+
"--output-dir",
318+
default="src/changelog",
319+
help="Output directory for generated changelog pages",
268320
)
269321
parser.add_argument(
270322
"--token",
@@ -310,30 +362,26 @@ def main() -> None:
310362
# Merge all entries
311363
merged = merger.merge_changelogs(all_entries)
312364

313-
# Output merged changelog
314-
logger.info("Writing merged changelog to %s", args.output)
315-
output_file = Path(args.output)
316-
with output_file.open("w") as f:
317-
f.write("# AppPack Merged Changelog\n\n")
318-
f.write(f"Total versions: {len(merged)}\n\n")
319-
f.write("---\n\n")
320-
321-
for entry in merged:
322-
f.write(f"## {entry.alias} {entry.version}\n\n")
323-
f.write(f"**Released:** {entry.date.strftime('%Y-%m-%d')}\n")
324-
f.write(f"**Repository:** {entry.repository}\n\n")
365+
# Create output directories
366+
output_dir = Path(args.output_dir)
367+
versions_dir = output_dir / "versions"
368+
versions_dir.mkdir(parents=True, exist_ok=True)
369+
logger.info("Creating changelog pages in %s", output_dir)
325370

326-
for section_name, items in entry.sections.items():
327-
if items:
328-
f.write(f"### {section_name}\n\n")
329-
f.writelines(f"- {item}\n" for item in items)
330-
f.write("\n")
371+
# Generate individual version pages
372+
for entry in merged:
373+
version_file = versions_dir / f"{entry.version_id}.md"
374+
generate_version_page(entry, version_file)
375+
logger.debug("Generated %s", version_file)
331376

332-
f.write("---\n\n")
377+
# Generate index page
378+
index_file = output_dir / "index.md"
379+
generate_index_page(merged, index_file)
333380

334381
logger.info("✓ Successfully aggregated changelogs!")
335382
logger.info(" Total versions: %d", len(merged))
336-
logger.info(" Output file: %s", args.output)
383+
logger.info(" Index page: %s", index_file)
384+
logger.info(" Version pages: %s", versions_dir)
337385

338386

339387
if __name__ == "__main__":

src/_navigation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
* [How-to guides](how-to/)
66
* [Under the hood](under-the-hood/)
77
* [Command line reference](command-line-reference/)
8+
* [Changelog](changelog/index.md)
89
* [Why AppPack?](why-apppack.md)

src/stylesheets/extra.css

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,34 @@
2323

2424

2525
.md-source__facts { display:none }
26+
27+
/* Changelog styling */
28+
.changelog-entry {
29+
border-left: 4px solid var(--md-primary-fg-color);
30+
padding-left: 1rem;
31+
margin-left: -1rem;
32+
margin-bottom: 2rem;
33+
}
34+
35+
.repo-tag {
36+
display: inline-block;
37+
padding: 0.2em 0.6em;
38+
font-size: 0.875em;
39+
font-weight: 600;
40+
border-radius: 0.25rem;
41+
background-color: var(--md-primary-fg-color--light);
42+
color: white;
43+
margin-left: 0.5em;
44+
}
45+
46+
.repo-tag.cli {
47+
background-color: #7c3aed;
48+
}
49+
50+
.repo-tag.stacks {
51+
background-color: #2563eb;
52+
}
53+
54+
.repo-tag.ci-builder {
55+
background-color: #059669;
56+
}

0 commit comments

Comments
 (0)