Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
# Full history: sitemap <lastmod> values come from commit dates.
fetch-depth: 0

- name: Regenerate sitemap.xml from git history
run: scripts/generate-sitemap.sh

- name: Deploy over SFTP
uses: wangyucode/sftp-upload-action@a1e64f60df0d085b26ca9efff77566e79f1c6b78 # v3.0.0
Expand All @@ -32,4 +37,4 @@ jobs:
password: ${{ secrets.DEPLOY_PASSWORD }}
localDir: '.'
remoteDir: ${{ secrets.DEPLOY_REMOTE_PATH }}
exclude: '.git/*,.github/*,README.md,AGENTS.md,renovate.json'
exclude: '.git/*,.github/*,scripts/*,README.md,AGENTS.md,renovate.json'
12 changes: 12 additions & 0 deletions .github/workflows/site-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
# Full history: sitemap <lastmod> values come from commit dates.
fetch-depth: 0

- name: Set up PHP
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2
Expand All @@ -33,6 +35,16 @@ jobs:
sudo apt-get install -y libxml2-utils
xmllint --noout sitemap.xml

- name: Check sitemap matches git history
run: |
expected=$(mktemp)
scripts/generate-sitemap.sh -o "$expected"
if ! diff -u sitemap.xml "$expected"; then
echo
echo "sitemap.xml is out of date. Run scripts/generate-sitemap.sh and commit the result."
exit 1
fi

- name: Smoke-test public pages
run: |
php -S 127.0.0.1:8090 >/tmp/openrtmp-site.log 2>&1 &
Expand Down
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,30 @@ assets/css/content.css Article and quickstart styles
assets/js/ Navigation, copy, and docs behavior
assets/img/ Logo and favicon
robots.txt Crawler policy
sitemap.xml Indexable public pages
sitemap.xml Indexable public pages (generated)
scripts/generate-sitemap.sh Rebuilds sitemap.xml from git history
```

## Sitemap

`sitemap.xml` is generated, not hand-edited. Each `<lastmod>` is the date of the
most recent commit that touched that page's `index.php`, so the sitemap cannot
drift away from the content it describes.

```bash
scripts/generate-sitemap.sh # rewrite sitemap.xml
scripts/generate-sitemap.sh -o - # preview on stdout
```

The URL list, `changefreq`, and `priority` live in the `PAGES` table at the top
of the script. The script fails if an `index.php` exists on disk but is missing
from that table, and it needs full git history — a shallow clone is rejected
rather than silently producing wrong dates.

CI enforces both ends of this: `Website checks` fails when the committed
`sitemap.xml` differs from what the script produces, and the production deploy
regenerates it just before upload.

## Content principles

- Separate the **developer/library** path from the **operator/server** path.
Expand All @@ -68,7 +89,8 @@ sitemap.xml Indexable public pages
2. Set a unique `$pageTitle`, `$pageDescription`, and `$canonicalPath`.
3. Add `TechArticle` structured data when appropriate.
4. Link the guide from `guides/index.php` and relevant existing pages.
5. Add the canonical URL to `sitemap.xml`.
5. Add the page to the `PAGES` table in `scripts/generate-sitemap.sh`, then run
`scripts/generate-sitemap.sh` and commit the regenerated `sitemap.xml`.
6. Run PHP lint and review mobile table/code overflow.

## Deployment
Expand Down
121 changes: 121 additions & 0 deletions scripts/generate-sitemap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/bin/sh
# Generate sitemap.xml with <lastmod> taken from each page's git history.
#
# The lastmod of a URL is the committer date of the most recent commit that
# touched the page's index.php, so the sitemap cannot drift away from the
# content it describes.
#
# Usage:
# scripts/generate-sitemap.sh # rewrite sitemap.xml in place
# scripts/generate-sitemap.sh -o FILE # write to FILE ('-' for stdout)

set -eu

BASE_URL='https://openrtmp.org'

# One row per indexable page: URL path, source file, changefreq, priority.
# Adding a page here is the only step needed to get it into the sitemap; the
# coverage check below fails if a page exists on disk but is missing from this
# table.
PAGES='
/|index.php|weekly|1.0
/quickstart/|quickstart/index.php|monthly|0.9
/guides/|guides/index.php|weekly|0.8
/guides/self-hosted-rtmp-server-docker/|guides/self-hosted-rtmp-server-docker/index.php|monthly|0.8
/guides/rtmps-server-obs/|guides/rtmps-server-obs/index.php|monthly|0.8
/guides/rtmp-server-ha-clustering/|guides/rtmp-server-ha-clustering/index.php|monthly|0.8
/guides/enhanced-rtmp-hevc-av1-opus/|guides/enhanced-rtmp-hevc-av1-opus/index.php|monthly|0.8
/guides/openrtmp-noalbs-json-stats/|guides/openrtmp-noalbs-json-stats/index.php|monthly|0.8
/guides/openrtmp-vs-nginx-rtmp/|guides/openrtmp-vs-nginx-rtmp/index.php|monthly|0.8
/docs/|docs/index.php|weekly|0.8
/download/|download/index.php|weekly|0.8
/legal/|legal/index.php|yearly|0.2
'

output='sitemap.xml'
while [ $# -gt 0 ]; do
case "$1" in
-o|--output) output="${2:?-o needs a file}"; shift 2 ;;
-h|--help)
echo 'Usage: generate-sitemap.sh [-o FILE]'
echo
echo "Rewrite sitemap.xml with each URL's <lastmod> taken from the date of"
echo "the most recent commit touching that page. Use '-o -' for stdout."
exit 0 ;;
*) echo "generate-sitemap: unknown argument '$1'" >&2; exit 2 ;;
esac
done

repo_root=$(git rev-parse --show-toplevel)
cd "$repo_root"

# lastmod is read from commit history, so a shallow checkout would silently
# produce wrong dates. Fail loudly instead.
if [ "$(git rev-parse --is-shallow-repository)" = 'true' ]; then
echo "generate-sitemap: shallow clone - full history is required" >&2
echo " In GitHub Actions, check out with 'fetch-depth: 0'." >&2
exit 1
fi

# Every page on disk must appear in PAGES.
missing=''
for page in $(find . -name 'index.php' -not -path './includes/*' | sed 's|^\./||' | sort); do
case "$PAGES" in
*"|$page|"*) ;;
*) missing="$missing $page
" ;;
esac
done
if [ -n "$missing" ]; then
echo "generate-sitemap: pages are missing from the PAGES table in $0:" >&2
printf '%s' "$missing" >&2
exit 1
fi

emit() {
echo '<?xml version="1.0" encoding="UTF-8"?>'
# The sitemap protocol defines this exact namespace URI. It is an
# identifier, never fetched, and crawlers match it literally - an https
# variant is simply not a sitemap namespace. NOSONAR(S5332): the
# clear-text-protocol warning does not apply to an XML namespace.
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' # NOSONAR
# Redirected, not piped: a failure inside the loop must exit the script.
while IFS='|' read -r path source changefreq priority; do
[ -n "$path" ] || continue

if [ ! -f "$source" ]; then
echo "generate-sitemap: $source does not exist" >&2
exit 1
fi

lastmod=$(git log -1 --format=%cs -- "$source")
if [ -z "$lastmod" ]; then
lastmod=$(date -u +%F)
echo "generate-sitemap: $source has no commit yet, using today ($lastmod)" >&2
fi

echo ' <url>'
echo " <loc>${BASE_URL}${path}</loc>"
echo " <lastmod>${lastmod}</lastmod>"
echo " <changefreq>${changefreq}</changefreq>"
echo " <priority>${priority}</priority>"
echo ' </url>'
done <<EOF
$PAGES
EOF
echo '</urlset>'
}

if [ "$output" = '-' ]; then
emit
else
# mktemp rather than a $$-derived name: predictable temp paths are a
# symlink-attack vector. It creates the file 0600, so restore the mode a
# publicly served file needs before moving it into place.
tmp=$(mktemp "${output}.XXXXXX")
trap 'rm -f "$tmp"' EXIT
emit >"$tmp"
chmod 644 "$tmp"
mv "$tmp" "$output"
echo "generate-sitemap: wrote $output"
fi
23 changes: 12 additions & 11 deletions sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,73 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://openrtmp.org/</loc>
<lastmod>2026-08-09</lastmod>
<lastmod>2026-09-07</lastmod>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://openrtmp.org/quickstart/</loc>
<lastmod>2026-07-18</lastmod>
<lastmod>2026-09-07</lastmod>
<changefreq>monthly</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>https://openrtmp.org/guides/</loc>
<lastmod>2026-08-09</lastmod>
<lastmod>2026-09-07</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://openrtmp.org/guides/self-hosted-rtmp-server-docker/</loc>
<lastmod>2026-08-09</lastmod>
<lastmod>2026-09-07</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://openrtmp.org/guides/rtmps-server-obs/</loc>
<lastmod>2026-07-18</lastmod>
<lastmod>2026-09-07</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://openrtmp.org/guides/rtmp-server-ha-clustering/</loc>
<lastmod>2026-08-09</lastmod>
<lastmod>2026-09-18</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://openrtmp.org/guides/enhanced-rtmp-hevc-av1-opus/</loc>
<lastmod>2026-07-18</lastmod>
<lastmod>2026-09-07</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://openrtmp.org/guides/openrtmp-noalbs-json-stats/</loc>
<lastmod>2026-07-26</lastmod>
<lastmod>2026-09-07</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://openrtmp.org/guides/openrtmp-vs-nginx-rtmp/</loc>
<lastmod>2026-08-09</lastmod>
<lastmod>2026-09-07</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://openrtmp.org/docs/</loc>
<lastmod>2026-08-09</lastmod>
<lastmod>2026-09-07</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://openrtmp.org/download/</loc>
<lastmod>2026-08-09</lastmod>
<lastmod>2026-09-07</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://openrtmp.org/legal/</loc>
<lastmod>2026-09-07</lastmod>
<changefreq>yearly</changefreq>
<priority>0.2</priority>
</url>
Expand Down
Loading