Skip to content

Commit b42ad75

Browse files
beagandicaBeatris Mendez GandicaCopilot
authored
Add frontmatter date auto-update script and pre-commit hook (#639)
Create tools/update-dates.py that keeps Hugo frontmatter date: fields current. Runs as a git pre-commit hook (default) or in batch mode. Features: - Updates existing date: fields to current timestamp - Adds date: field to files that have frontmatter but no date - Skips files without YAML frontmatter - Preserves CRLF/LF line endings across platforms - Handles UTF-8 BOM files (strips BOM on decode) - Handles quoted date values in YAML - Auto-re-stages updated files in pre-commit mode - --dry-run and --verbose flags for safe previewing - Zero external dependencies (Python 3.8+ stdlib only) Also includes: - tools/README.md with usage documentation - tools/install-hooks.sh (bash) and install-hooks.ps1 (PowerShell) install scripts with existing-hook detection and python3 fallback Tested against all 1216 content .md files with 0 errors. Co-authored-by: Beatris Mendez Gandica <bemendez@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 49763a2 commit b42ad75

4 files changed

Lines changed: 432 additions & 0 deletions

File tree

tools/README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# tools/ — Workshop development utilities
2+
3+
Scripts to help contributors maintain the NuevoFoundation workshops repo.
4+
5+
## update-dates.py
6+
7+
Keeps Hugo frontmatter `date:` fields current. When you commit a markdown
8+
file, the date updates automatically so readers know when content last changed.
9+
10+
### Quick start (pre-commit hook)
11+
12+
Install once — all future commits auto-update dates:
13+
14+
```bash
15+
# Linux / macOS / Git Bash
16+
bash tools/install-hooks.sh
17+
18+
# Windows PowerShell
19+
.\tools\install-hooks.ps1
20+
```
21+
22+
Then just commit normally. Any staged `.md` file gets its `date:` field
23+
updated to the current timestamp before the commit completes.
24+
25+
### Manual usage
26+
27+
```bash
28+
# See what would change (staged files)
29+
python tools/update-dates.py --dry-run
30+
31+
# Update all .md files under a path
32+
python tools/update-dates.py --all content/english/python-basics/
33+
34+
# Verbose output
35+
python tools/update-dates.py --verbose --dry-run
36+
```
37+
38+
### How it works
39+
40+
1. Finds `.md` files (staged files by default, or `--all <path>` for batch)
41+
2. Parses YAML frontmatter (the `---` block at the top of each file)
42+
3. Updates the `date:` field to the current timestamp
43+
4. If a file has frontmatter but no `date:` field, one is added
44+
5. Files without frontmatter are skipped
45+
6. In pre-commit mode, updated files are re-staged automatically
46+
47+
### Flags
48+
49+
| Flag | Description |
50+
|------|-------------|
51+
| `--all PATH` | Batch mode: update all `.md` files under PATH |
52+
| `--dry-run` | Show what would change without writing |
53+
| `--verbose` / `-v` | Print each file and its status |
54+
55+
### Date format
56+
57+
Matches the existing Hugo frontmatter format:
58+
59+
```yaml
60+
date: 2026-04-26T21:23:39-07:00
61+
```
62+
63+
### Requirements
64+
65+
- Python 3.8+
66+
- No external dependencies (stdlib only)

tools/install-hooks.ps1

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Install update-dates.py as a git pre-commit hook (Windows).
2+
# Run from the repo root: .\tools\install-hooks.ps1
3+
4+
$ErrorActionPreference = "Stop"
5+
6+
$hook = ".git\hooks\pre-commit"
7+
$script = "tools\update-dates.py"
8+
9+
if (-not (Test-Path $script)) {
10+
Write-Error "Run this from the repo root (cannot find $script)"
11+
exit 1
12+
}
13+
14+
if (Test-Path $hook) {
15+
Write-Warning "$hook already exists:"
16+
Get-Content $hook
17+
$answer = Read-Host "Overwrite? [y/N]"
18+
if ($answer -notin @("y", "Y")) {
19+
Write-Host "Aborted."
20+
exit 0
21+
}
22+
}
23+
24+
if (-not (Test-Path ".git\hooks")) {
25+
New-Item -ItemType Directory -Path ".git\hooks" -Force | Out-Null
26+
}
27+
28+
$hookContent = @"
29+
#!/usr/bin/env bash
30+
# Pre-commit hook: update frontmatter dates on staged .md files
31+
if command -v python3 &>/dev/null; then
32+
python3 tools/update-dates.py
33+
elif command -v python &>/dev/null; then
34+
python tools/update-dates.py
35+
else
36+
echo "Warning: python not found, skipping date update" >&2
37+
fi
38+
"@
39+
40+
# Write UTF-8 without BOM to avoid breaking the shebang line
41+
$resolvedHook = Join-Path (Resolve-Path ".").Path $hook
42+
[System.IO.File]::WriteAllText(
43+
$resolvedHook,
44+
$hookContent,
45+
[System.Text.UTF8Encoding]::new($false)
46+
)
47+
48+
Write-Host "Installed pre-commit hook at $hook"

tools/install-hooks.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env bash
2+
# Install update-dates.py as a git pre-commit hook.
3+
# Run from the repo root: bash tools/install-hooks.sh
4+
5+
set -e
6+
7+
HOOK=".git/hooks/pre-commit"
8+
SCRIPT="tools/update-dates.py"
9+
10+
if [ ! -f "$SCRIPT" ]; then
11+
echo "Error: run this from the repo root (cannot find $SCRIPT)"
12+
exit 1
13+
fi
14+
15+
if [ -f "$HOOK" ]; then
16+
echo "Warning: $HOOK already exists."
17+
echo "Existing content:"
18+
cat "$HOOK"
19+
echo ""
20+
read -p "Overwrite? [y/N] " answer
21+
if [ "$answer" != "y" ] && [ "$answer" != "Y" ]; then
22+
echo "Aborted."
23+
exit 0
24+
fi
25+
fi
26+
27+
mkdir -p .git/hooks
28+
29+
cat > "$HOOK" << 'EOF'
30+
#!/usr/bin/env bash
31+
# Pre-commit hook: update frontmatter dates on staged .md files
32+
if command -v python3 &>/dev/null; then
33+
python3 tools/update-dates.py
34+
elif command -v python &>/dev/null; then
35+
python tools/update-dates.py
36+
else
37+
echo "Warning: python not found, skipping date update" >&2
38+
fi
39+
EOF
40+
41+
chmod +x "$HOOK"
42+
echo "Installed pre-commit hook at $HOOK"

0 commit comments

Comments
 (0)