Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Add a test to validate URLs in markdown/Users.md #14120

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
- name: Install package
run: |
sudo apt-get -y install python3-pip ninja-build libjson-glib-dev
pip install hotdoc chevron strictyaml
pip install hotdoc chevron strictyaml aiohttp
- uses: actions/cache/save@v4
with:
Expand Down
2 changes: 0 additions & 2 deletions docs/markdown/Users.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ format files
- [NetPanzer](https://github.com/netpanzer/netpanzer), a 2D online multiplayer tactical warfare game designed for fast action combat
- [NumPy](https://numpy.org/), a Python package for scientific computing
- [nvme-cli](https://github.com/linux-nvme/nvme-cli), NVMe management command line interface
- [OcherBook](https://github.com/ccoffing/OcherBook), an open source book reader for Kobo devices
- [oomd](https://github.com/facebookincubator/oomd), a userspace Out-Of-Memory (OOM) killer for Linux systems
- [OpenH264](https://github.com/cisco/openh264), open source H.264 codec
- [OpenHMD](https://github.com/OpenHMD/OpenHMD), a free and open source API and drivers for immersive technology, such as head mounted displays with built in head tracking
Expand All @@ -140,7 +139,6 @@ format files
- [Peek](https://github.com/phw/peek), simple animated GIF screen recorder with an easy to use interface
- [PicoLibc](https://github.com/keith-packard/picolibc), a standard C library for small embedded systems with limited RAM
- [PipeWire](https://github.com/PipeWire/pipewire), a framework for video and audio for containerized applications
- [Paper Rock Scissors](https://github.com/michaelbrockus/paper_rock_scissors), a game with weapons themed at home paper rock scissors style
- [Pistache](https://github.com/pistacheio/pistache), a high performance REST toolkit written in C++
- [Pithos](https://github.com/pithos/pithos), a Pandora Radio client
- [Pitivi](https://github.com/pitivi/pitivi/), a nonlinear video editor
Expand Down
4 changes: 3 additions & 1 deletion docs/meson.build
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
project('Meson documentation', version: '1.0')

yaml_modname = get_option('unsafe_yaml') ? 'yaml' : 'strictyaml'
py = import('python').find_installation('python3', modules: [yaml_modname], required: false)
py = import('python').find_installation('python3', modules: [yaml_modname, 'aiohttp'], required: false)
if not py.found()
error(f'Cannot build documentation without yaml support')
endif
Expand Down Expand Up @@ -145,3 +145,5 @@ run_target('upload',
],
depends: documentation,
)

test('validate_links', find_program('./validatelinks.py'), args: meson.current_source_dir() / 'markdown' / 'Users.md')
42 changes: 42 additions & 0 deletions docs/validatelinks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env python3

# SPDX-License-Identifier: Apache-2.0
# Copyright 2025 The Meson development team

import sys
import re
import aiohttp
import asyncio

LINK = re.compile(r'\[(?P<name>[A-Za-z0-9 ]+)\]\((?P<url>.*?)\)')


async def fetch(session, name, url, timeout):
try:
async with session.get(url, timeout=timeout) as r:
if not r.ok:
return (name, url, r.status)
except Exception as e:
return (name, url, str(e))


async def main(filename):
with open(filename) as f:
text = f.read()
timeout = aiohttp.ClientTimeout(total=60)
async with aiohttp.ClientSession() as session:
tasks = []
for link in LINK.finditer(text):
name, url = link.groups()
task = asyncio.ensure_future(fetch(session, name, url, timeout))
tasks.append(task)
responses = asyncio.gather(*tasks)
errors = [r for r in await responses if r is not None]
for name, url, result in errors:
print(f'"{name}" {url} {result}')
if errors:
sys.exit(1)


if __name__ == '__main__':
asyncio.run(main(sys.argv[1]))
Loading