CI/CD Pipeline - Northern Thailand Ping River Monitor / Test Suite (3.11) (push) Failing after 1m43s
CI/CD Pipeline - Northern Thailand Ping River Monitor / Build Docker Image (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Integration Test with Services (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Deploy to Staging (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Deploy to Production (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Performance Test (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Code Quality (push) Successful in 45s
Documentation / Validate Documentation (push) Failing after 17s
Documentation / Generate API Documentation (push) Successful in 12s
Documentation / Build Sphinx Documentation (push) Successful in 19s
CI/CD Pipeline - Northern Thailand Ping River Monitor / Cleanup (push) Successful in 1s
Documentation / Documentation Summary (push) Successful in 4s
Removes 26 tracked files that no longer describe or serve the running system, verified one by one against the whole repo (source, tests, docs, README, Makefile, Dockerfile, .gitea workflows, pyproject, packaging spec) plus dynamic-reference paths, before deletion. Root (11): one-off launch/setup write-ups from the project's first weeks that document events which never happened the way they describe — a github.com publication (the remote is self-hosted Gitea) and a 15-minute scheduler (the service runs hourly). Also .gitlab-ci.yml (unused, CI is .gitea/), .env.postgres and setup.py.backup (a placeholder env file and a backup in version control), and the PyInstaller packaging trio build_executable.py / build_simple.py / ping-river-monitor.spec, which bundled docs that no longer exist and is not how this deploys. docs (9): stale guides superseded by DATABASE_DEPLOYMENT_GUIDE, GITEA_WORKFLOWS, FLOOD_FORECASTING and DATA_SOURCES, plus two snapshots (PROJECT_STATUS, PROJECT_STRUCTURE) describing a 4-file src/ that is now 39. scripts (5): one-shot bootstrap tools already run — init_git.sh/.bat, generate_badges.py, migrate_geolocation.py, encode_password.py. Every inbound reference was fixed rather than left dangling: README doc index and migration section, three Makefile targets, the docs.yml summary step, and the GITEA_WORKFLOWS resource list. src/ is deliberately untouched. The audit proposed removing several live modules; verification showed those proposals were mis-scoped and would have broken production. .gitignore now covers the agent tooling dirs, model eval output and editor/shell leftovers — the working tree had collected 56 zero-byte files named after fragments of shell commands. 136 tests pass; production modules import clean.
367 lines
11 KiB
YAML
367 lines
11 KiB
YAML
name: Documentation
|
|
|
|
on:
|
|
push:
|
|
branches: [ master, develop ]
|
|
paths:
|
|
- 'docs/**'
|
|
- 'README.md'
|
|
- 'CONTRIBUTING.md'
|
|
- 'src/**/*.py'
|
|
pull_request:
|
|
paths:
|
|
- 'docs/**'
|
|
- 'README.md'
|
|
- 'CONTRIBUTING.md'
|
|
workflow_dispatch:
|
|
|
|
env:
|
|
PYTHON_VERSION: '3.11'
|
|
|
|
jobs:
|
|
# Validate documentation
|
|
validate-docs:
|
|
name: Validate Documentation
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
with:
|
|
token: ${{ secrets.GITEA_TOKEN }}
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Install documentation tools
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install -r requirements.txt
|
|
pip install sphinx sphinx-rtd-theme sphinx-autodoc-typehints
|
|
pip install markdown-link-check || true
|
|
|
|
- name: Check markdown links
|
|
run: |
|
|
echo "🔗 Checking markdown links..."
|
|
find . -name "*.md" -not -path "./.git/*" -not -path "./node_modules/*" | while read file; do
|
|
echo "Checking $file"
|
|
# Basic link validation (you can enhance this)
|
|
grep -o 'http[s]*://[^)]*' "$file" | while read url; do
|
|
if curl -s --head "$url" | head -n 1 | grep -q "200 OK"; then
|
|
echo "✅ $url"
|
|
else
|
|
echo "❌ $url (in $file)"
|
|
fi
|
|
done
|
|
done
|
|
|
|
- name: Validate README structure
|
|
run: |
|
|
echo "📋 Validating README structure..."
|
|
|
|
required_sections=(
|
|
"# Northern Thailand Ping River Monitor"
|
|
"## Features"
|
|
"## Quick Start"
|
|
"## Installation"
|
|
"## Usage"
|
|
"## API Endpoints"
|
|
"## Docker"
|
|
"## Contributing"
|
|
"## License"
|
|
)
|
|
|
|
for section in "${required_sections[@]}"; do
|
|
if grep -q "$section" README.md; then
|
|
echo "✅ Found: $section"
|
|
else
|
|
echo "❌ Missing: $section"
|
|
fi
|
|
done
|
|
|
|
- name: Check documentation completeness
|
|
run: |
|
|
echo "📚 Checking documentation completeness..."
|
|
|
|
# Check if all Python modules have docstrings
|
|
python -c "
|
|
import ast
|
|
import os
|
|
|
|
def check_docstrings(filepath):
|
|
with open(filepath, 'r', encoding='utf-8') as f:
|
|
tree = ast.parse(f.read())
|
|
|
|
missing_docstrings = []
|
|
|
|
for node in ast.walk(tree):
|
|
if isinstance(node, (ast.FunctionDef, ast.ClassDef, ast.AsyncFunctionDef)):
|
|
if not ast.get_docstring(node):
|
|
missing_docstrings.append(f'{node.name} in {filepath}')
|
|
|
|
return missing_docstrings
|
|
|
|
all_missing = []
|
|
for root, dirs, files in os.walk('src'):
|
|
for file in files:
|
|
if file.endswith('.py') and not file.startswith('__'):
|
|
filepath = os.path.join(root, file)
|
|
missing = check_docstrings(filepath)
|
|
all_missing.extend(missing)
|
|
|
|
if all_missing:
|
|
print('⚠️ Missing docstrings:')
|
|
for item in all_missing[:10]: # Show first 10
|
|
print(f' - {item}')
|
|
if len(all_missing) > 10:
|
|
print(f' ... and {len(all_missing) - 10} more')
|
|
else:
|
|
print('✅ All functions and classes have docstrings')
|
|
"
|
|
|
|
# Generate API documentation
|
|
generate-api-docs:
|
|
name: Generate API Documentation
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
with:
|
|
token: ${{ secrets.GITEA_TOKEN }}
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install -r requirements.txt
|
|
|
|
- name: Generate OpenAPI spec
|
|
run: |
|
|
echo "📝 Generating OpenAPI specification..."
|
|
python -c "
|
|
import json
|
|
import sys
|
|
sys.path.insert(0, 'src')
|
|
|
|
try:
|
|
from web_api import app
|
|
openapi_spec = app.openapi()
|
|
|
|
with open('openapi.json', 'w') as f:
|
|
json.dump(openapi_spec, f, indent=2)
|
|
|
|
print('✅ OpenAPI spec generated: openapi.json')
|
|
except Exception as e:
|
|
print(f'❌ Failed to generate OpenAPI spec: {e}')
|
|
"
|
|
|
|
- name: Generate API documentation
|
|
run: |
|
|
echo "📖 Generating API documentation..."
|
|
|
|
# Create API documentation from OpenAPI spec
|
|
if [ -f openapi.json ]; then
|
|
cat > api-docs.md << 'EOF'
|
|
# API Documentation
|
|
|
|
This document describes the REST API endpoints for the Northern Thailand Ping River Monitor.
|
|
|
|
## Base URL
|
|
|
|
- Production: `https://ping-river-monitor.b4l.co.th`
|
|
- Staging: `https://staging.ping-river-monitor.b4l.co.th`
|
|
- Development: `http://localhost:8000`
|
|
|
|
## Authentication
|
|
|
|
Currently, the API does not require authentication. This may change in future versions.
|
|
|
|
## Endpoints
|
|
|
|
EOF
|
|
|
|
# Extract endpoints from OpenAPI spec
|
|
python -c "
|
|
import json
|
|
|
|
with open('openapi.json', 'r') as f:
|
|
spec = json.load(f)
|
|
|
|
for path, methods in spec.get('paths', {}).items():
|
|
for method, details in methods.items():
|
|
print(f'### {method.upper()} {path}')
|
|
print()
|
|
print(details.get('summary', 'No description available'))
|
|
print()
|
|
if 'parameters' in details:
|
|
print('**Parameters:**')
|
|
for param in details['parameters']:
|
|
print(f'- `{param[\"name\"]}` ({param.get(\"in\", \"query\")}): {param.get(\"description\", \"No description\")}')
|
|
print()
|
|
print('---')
|
|
print()
|
|
" >> api-docs.md
|
|
|
|
echo "✅ API documentation generated: api-docs.md"
|
|
fi
|
|
|
|
- name: Upload documentation artifacts
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: documentation-${{ github.run_number }}
|
|
path: |
|
|
openapi.json
|
|
api-docs.md
|
|
|
|
# Build Sphinx documentation
|
|
build-sphinx-docs:
|
|
name: Build Sphinx Documentation
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
with:
|
|
token: ${{ secrets.GITEA_TOKEN }}
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install -r requirements.txt
|
|
pip install sphinx sphinx-rtd-theme sphinx-autodoc-typehints
|
|
|
|
- name: Create Sphinx configuration
|
|
run: |
|
|
mkdir -p docs/sphinx
|
|
|
|
cat > docs/sphinx/conf.py << 'EOF'
|
|
import os
|
|
import sys
|
|
sys.path.insert(0, os.path.abspath('../../src'))
|
|
|
|
project = 'Northern Thailand Ping River Monitor'
|
|
copyright = '2025, Ping River Monitor Team'
|
|
author = 'Ping River Monitor Team'
|
|
version = '3.1.3'
|
|
release = '3.1.3'
|
|
|
|
extensions = [
|
|
'sphinx.ext.autodoc',
|
|
'sphinx.ext.viewcode',
|
|
'sphinx.ext.napoleon',
|
|
'sphinx_autodoc_typehints',
|
|
]
|
|
|
|
templates_path = ['_templates']
|
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
|
|
|
html_theme = 'sphinx_rtd_theme'
|
|
html_static_path = ['_static']
|
|
|
|
autodoc_default_options = {
|
|
'members': True,
|
|
'member-order': 'bysource',
|
|
'special-members': '__init__',
|
|
'undoc-members': True,
|
|
'exclude-members': '__weakref__'
|
|
}
|
|
EOF
|
|
|
|
cat > docs/sphinx/index.rst << 'EOF'
|
|
Northern Thailand Ping River Monitor Documentation
|
|
================================================
|
|
|
|
.. toctree::
|
|
:maxdepth: 2
|
|
:caption: Contents:
|
|
|
|
modules
|
|
|
|
Indices and tables
|
|
==================
|
|
|
|
* :ref:`genindex`
|
|
* :ref:`modindex`
|
|
* :ref:`search`
|
|
EOF
|
|
|
|
- name: Generate module documentation
|
|
run: |
|
|
cd docs/sphinx
|
|
sphinx-apidoc -o . ../../src
|
|
|
|
- name: Build documentation
|
|
run: |
|
|
cd docs/sphinx
|
|
sphinx-build -b html . _build/html
|
|
|
|
- name: Upload Sphinx documentation
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: sphinx-docs-${{ github.run_number }}
|
|
path: docs/sphinx/_build/html/
|
|
|
|
# Documentation summary
|
|
docs-summary:
|
|
name: Documentation Summary
|
|
runs-on: ubuntu-latest
|
|
needs: [validate-docs, generate-api-docs, build-sphinx-docs]
|
|
if: always()
|
|
|
|
steps:
|
|
- name: Generate documentation summary
|
|
run: |
|
|
echo "# 📚 Documentation Build Summary" > docs-summary.md
|
|
echo "" >> docs-summary.md
|
|
echo "**Build Date:** $(date -u)" >> docs-summary.md
|
|
echo "**Repository:** ${{ github.repository }}" >> docs-summary.md
|
|
echo "**Commit:** ${{ github.sha }}" >> docs-summary.md
|
|
echo "" >> docs-summary.md
|
|
|
|
echo "## 📊 Results" >> docs-summary.md
|
|
echo "" >> docs-summary.md
|
|
|
|
if [ "${{ needs.validate-docs.result }}" = "success" ]; then
|
|
echo "- ✅ **Documentation Validation**: Passed" >> docs-summary.md
|
|
else
|
|
echo "- ❌ **Documentation Validation**: Failed" >> docs-summary.md
|
|
fi
|
|
|
|
if [ "${{ needs.generate-api-docs.result }}" = "success" ]; then
|
|
echo "- ✅ **API Documentation**: Generated" >> docs-summary.md
|
|
else
|
|
echo "- ❌ **API Documentation**: Failed" >> docs-summary.md
|
|
fi
|
|
|
|
if [ "${{ needs.build-sphinx-docs.result }}" = "success" ]; then
|
|
echo "- ✅ **Sphinx Documentation**: Built" >> docs-summary.md
|
|
else
|
|
echo "- ❌ **Sphinx Documentation**: Failed" >> docs-summary.md
|
|
fi
|
|
|
|
echo "" >> docs-summary.md
|
|
echo "## 🔗 Available Documentation" >> docs-summary.md
|
|
echo "" >> docs-summary.md
|
|
echo "- [README.md](../README.md)" >> docs-summary.md
|
|
echo "- [API Documentation](../docs/)" >> docs-summary.md
|
|
echo "- [Contributing Guide](../CONTRIBUTING.md)" >> docs-summary.md
|
|
|
|
cat docs-summary.md
|
|
|
|
- name: Upload documentation summary
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: docs-summary-${{ github.run_number }}
|
|
path: docs-summary.md |