Skip to content
Closed
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
15 changes: 9 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
name: CI

on:
push:
branches-ignore:
- "github-pages/*"
- "gh-pages/*"
- "main"
- "master"
# push:
# branches-ignore:
# - "github-pages/*"
# - "gh-pages/*"
# - "main"
# - "master"
pull_request:
types: [ opened, synchronize, reopened ]
schedule:
# “At 00:00 on every 7th day-of-month from 1 through 31.” (https://crontab.guru)
- cron: "0 0 1/7 * *"
Expand All @@ -22,5 +24,6 @@ jobs:
Metrics:
needs: [ CI ]
uses: ./.github/workflows/report.yml
secrets: inherit
permissions:
contents: read
16 changes: 15 additions & 1 deletion .github/workflows/report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- name: Copy Artifacts into Root Folder
working-directory: ./artifacts
run: |
poetry run -- coverage combine --keep coverage-python3.9*/.coverage
poetry run -- coverage combine --keep coverage-python*/.coverage
# Errors during copying are ignored because they are checked in the next step
cp .coverage ../ || true
cp lint-python3.9/.lint.txt ../ || true
Expand All @@ -42,6 +42,20 @@ jobs:
- name: Generate Report
run: poetry run -- nox -s project:report -- --format json | tee metrics.json

- name: Prepare files for sonar
run: |
poetry run -- coverage xml -o ci-coverage.xml --include="exasol/toolbox/*"

- name: SonarQube Scan
uses: SonarSource/sonarqube-scan-action@v5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
args: >
-Dsonar.python.coverage.reportPaths=ci-coverage.xml
# -Dsonar.python.pylint.reportPath .lint.json
# -Dsonar.python.bandit.reportPaths .security.json

- name: Upload Artifacts
uses: actions/[email protected]
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ odbcconfig/odbcinst.ini
.html-documentation

.coverage
.sonar

_build/

Expand Down
5 changes: 5 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,8 @@
"github_url": "https://github.com/exasol/python-toolbox",
"accent_color": "grass",
}
# -- Configure link checking behavior ----------------------------------------
extra_linkcheck_ignores = os.getenv("SPHINX_EXTRA_LINKCHECK_IGNORES")
linkcheck_ignore = (
[] if not extra_linkcheck_ignores else extra_linkcheck_ignores.split(",")
)
2 changes: 1 addition & 1 deletion doc/user_guide/features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Uniform Project Layout
PTB expects a default project layout following "convention over configuration" when possible and reasonable.
See the cookie-cutter project template for details, which is part of the python-toolbox workspace and can be found in directory `project-template`.
You can also generate a project from the template to explore the default structure.
For more details on this, please check out section `"getting started" <getting_started.html>`_ section.
For more details on this, please check out section :ref:`Getting Started` section.

Nox
---
Expand Down
2 changes: 2 additions & 0 deletions doc/user_guide/getting_started.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _Getting Started:

Getting Started
===============

Expand Down
128 changes: 128 additions & 0 deletions exasol/toolbox/nox/_documentation.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
from __future__ import annotations

import json
import os
import re
import shutil
import subprocess
import sys
import tempfile
import webbrowser
from itertools import repeat
from pathlib import Path
from typing import (
Container,
Iterable,
Optional,
Tuple,
)

import nox
from nox import Session
from requests import (
get,
head,
)
from requests.exceptions import Timeout

from exasol.toolbox.nox._shared import DOCS_OUTPUT_DIR
from noxconfig import (
Expand Down Expand Up @@ -88,6 +105,117 @@ def clean_docs(_session: Session) -> None:
shutil.rmtree(docs_folder)


@nox.session(name="docs:links", python=False)
def docs_list_links(session: Session) -> None:
"""List all the links within the documentation."""
ignore = [r".*"]
env = os.environ.copy()
env["SPHINX_EXTRA_LINKCHECK_IGNORES"] = ",".join(ignore)
with tempfile.TemporaryDirectory() as path:
tmpdir = Path(path)
sp = subprocess.run(
[
"poetry",
"run",
"--",
"sphinx-build",
"-b",
"linkcheck",
PROJECT_CONFIG.root / "doc",
tmpdir,
],
capture_output=True,
text=True,
env=env,
)
print(sp.returncode)
if sp.returncode >= 2:
print(sp.stderr)
session.error(2)
output = tmpdir / "output.json"
links = output.read_text().split("\n")
file_links = []
for link in links:
if link != "":
line = json.loads(link)
if not line["uri"].startswith("#"):
file_links.append(line)
file_links.sort(key=lambda file: file["filename"])
print(
"\n".join(
f"filename: {fl['filename']} -> uri: {fl['uri']}" for fl in file_links
)
)


@nox.session(name="docs:links:check", python=False)
def docs_links_check(session: Session) -> None:
"""Checks whether all links in the documentation are accessible."""
ignore = [r"https?://"]
env = os.environ.copy()
env["SPHINX_EXTRA_LINKCHECK_IGNORES"] = ",".join(ignore)
with tempfile.TemporaryDirectory() as path:
tmpdir = Path(path)
sp = subprocess.run(
[
"poetry",
"run",
"--",
"sphinx-build",
"-b",
"linkcheck",
PROJECT_CONFIG.root / "doc",
tmpdir,
],
capture_output=True,
text=True,
env=env,
)
print(sp.returncode)
if sp.returncode >= 2:
print(sp.stderr)
session.error(2)
output = tmpdir / "output.json"
results = output.read_text().split("\n")
reslen = len(results)
resstr = results[-1]
if (reslen == 0) or ((reslen == 1) and (resstr == "")):
return
elif resstr == "":
results.pop()
for line_nr, result in enumerate(results):
resdict = json.loads(result)
if resdict["status"] == "ignored" and resdict["uri"].startswith("http"):
try:
match = re.search(r"https?://[^\s\"\'<>]+", resdict["uri"])
if match:
resdict["uri"] = match.group()
print(f"{line_nr}/{reslen}")
request = head(resdict["uri"], timeout=5)
if request.status_code != 200:
request = get(resdict["uri"], timeout=5, stream=True)
request.close()
if request.status_code >= 400:
resdict["status"] = "broken"
resdict["code"] = request.status_code
if request.status_code < 400:
resdict["status"] = "working"
resdict["code"] = request.status_code
except Timeout:
resdict["status"] = "timeout"
results[line_nr] = json.dumps(resdict)
output.write_text("\n".join(f"{r}" for r in results))
errors = []
for result in results:
data = json.loads(result)
if (data["status"] == "broken") or data["status"] == "timeout":
errors.append(result)
if errors:
print("Error" + "s" if len(errors) > 1 else "")
print("\n".join(error for error in errors))
session.error(1)


@nox.session(name="changelog:updated", python=False)
def updated(_session: Session) -> None:
"""Checks if the change log has been updated"""
Expand Down
Loading