Skip to content

Commit

Permalink
Check Sphinx build log in CI
Browse files Browse the repository at this point in the history
Add a script to parse a Sphinx build log and turn it into GitHub Actions
formatted messages. Add ability to specify a build log output location
to Makefile. Use these to scrape the Sphinx build log in order to report
whether there are any warnings or errors encountered during HTML
generation.

This uses job outputs to avoid having to upload the build log as an
artifact. Note however that this has a 1MB size limit. For now, this
should be fine, especially as only warnings/errors are passed this way
(not the entire build log).
  • Loading branch information
mwoehlke committed Mar 21, 2024
1 parent 9a2ea3a commit a2ae71a
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 1 deletion.
16 changes: 15 additions & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ on:
jobs:
build:
runs-on: ubuntu-latest
outputs:
buildlog: ${{steps.check.outputs.messages}}
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -20,7 +22,10 @@ jobs:
- name: Install Environment
run: make setup
- name: Build Documentation
run: make html/fast
run: make html/fast LOGFILE=_build_html.log
- name: Parse Build Logs
id: check
run: python check-build-logs.py _build_html.log "$GITHUB_OUTPUT"
- name: Archive Documentation
run: make archive/fast
- name: Upload Archive
Expand All @@ -29,6 +34,15 @@ jobs:
if-no-files-found: error
name: github-pages
path: ${{github.workspace}}/cps-docs.tar
check:
runs-on: ubuntu-latest
needs: build
steps:
- name: Check Sphinx logs
shell: bash
run: |
echo -e "${{needs.check.outputs.messages}}"
[ -z "${{needs.check.outputs.messages}}" ]
deploy:
if: github.event.repository.default_branch == github.ref_name
needs: build
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ endif
setup.flags += --with=docs

build.flags += $(if $(BUILDER),-b $(BUILDER),-b html)
build.flags += $(if $(LOGFILE),-w "$(LOGFILE)")
build.flags += $(if $(NOCOLOR),,--color)
build.flags += $(SPHINXOPTS)

Expand Down
51 changes: 51 additions & 0 deletions check-build-logs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env python

import os
import re
import sys

from typing import List

# -----------------------------------------------------------------------------
def read_log(path: str) -> List[str]:
out = []

with open(path, 'rt') as f:
for line in f:
out.append(re.sub('\033[[][0-9;]*m', '', line.strip()))

return out

# -----------------------------------------------------------------------------
def main(log_path: str, out_path: str, src_root: str = '.'):
re_loc = r'(?P<file>[^:]+):((?P<line>[0-9]+):)?\s*'
re_info = r'(?P<type>\w+):\s*(?P<message>.*)'
lines = read_log(log_path)

messages = []
for line in lines:
m = re.match(re_loc + re_info, line)
if m:
t = m.group('type').lower()
if t not in {'warning', 'error'}:
t = 'warning'

params = {'file': os.path.relpath(m.group('file'), src_root)}
line = m.group('line')
if line:
params['line'] = line

p = ','.join([f'{k}={v}' for k, v in params.items()])
m = m.group('message')
messages.append(f'::{t} {p}::{m}')

if len(messages):
print(messages)
s = '\\n'.join([m.replace('\\', '\\\\') for m in messages])
with open(out_path, 'at') as f:
f.write(f'messages={s}\n')

# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if __name__ == '__main__':
main(*sys.argv[1:])

0 comments on commit a2ae71a

Please sign in to comment.