Skip to content

Commit 2cb2bed

Browse files
authored
Run Lighthouse against a local server per push (#216)
1 parent df85690 commit 2cb2bed

File tree

3 files changed

+134
-19
lines changed

3 files changed

+134
-19
lines changed

.github/workflows/artifact.yml

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,3 @@ jobs:
1010
with:
1111
repo-token: ${{ secrets.GITHUB_TOKEN }}
1212
artifact-path: 0/html/index.html
13-
- name: Wait Until Site is Ready
14-
run: |
15-
curl --retry 10 --retry-connrefused --retry-max-time 60 ${{ steps.redirect.outputs.url }}
16-
- name: Make folder for Lighthouse reports
17-
run: mkdir /tmp/lighthouse
18-
- name: Run Lighthouse on Site
19-
id: lighthouse
20-
uses: foo-software/[email protected]
21-
with:
22-
urls: ${{ steps.redirect.outputs.url }}
23-
outputDirectory: /tmp/lighthouse
24-
verbose: true
25-
- name: Upload Lighthouse Reports
26-
uses: actions/upload-artifact@v2
27-
with:
28-
name: Lighthouse Report ${{ github.run_number }}
29-
path: /tmp/lighthouse

.github/workflows/tests.yml

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,12 @@ jobs:
2929
python -m pip install --upgrade pip
3030
python -m pip install --upgrade pre-commit
3131
pip install -e .
32-
yarn install
32+
yarn
3333
3434
- name: Lint
3535
run: |
3636
pre-commit run --all-files
3737
38-
3938
# Build docs on a number of Python versions. In the future this can be
4039
# where tests go.
4140
tests:
@@ -63,6 +62,79 @@ jobs:
6362
export PATH="$HOME/miniconda/bin:$PATH"
6463
sphinx-build -b html docs/ docs/_build/html -W --keep-going
6564
65+
# Run local Lighthouse audit against built site
66+
audit:
67+
68+
runs-on: ubuntu-latest
69+
strategy:
70+
matrix:
71+
python-version: [3.8]
72+
env:
73+
PORT: 8000
74+
# the host interface to listen on, might need to be 0.0.0.0
75+
HOST: 127.0.0.1
76+
# the base url
77+
URL: http://127.0.0.1:8000
78+
79+
steps:
80+
- uses: actions/checkout@v2
81+
- name: Set up Python ${{ matrix.python-version }}
82+
uses: actions/setup-python@v1
83+
with:
84+
python-version: ${{ matrix.python-version }}
85+
- name: Install dependencies
86+
run: |
87+
python -m pip install --upgrade pip
88+
pip install -e .
89+
pip install -r docs/requirements.txt
90+
91+
# Build the docs
92+
- name: Build docs to store
93+
run: |
94+
export PATH="$HOME/miniconda/bin:$PATH"
95+
sphinx-build -b html docs/ docs/_build/html -W --keep-going
96+
97+
# Serve the docs and wait to be ready
98+
- name: Serve the built site
99+
run: |
100+
nohup python docs/serve.py --port=${PORT} --host=${HOST} &
101+
curl --retry 10 --retry-connrefused --retry-max-time 60 ${URL}/index.html
102+
103+
# Run the audit
104+
# TODO: use the hosted API with a secret? would allow for comparison over time...
105+
- name: Make folder for Lighthouse reports
106+
run: mkdir -p /tmp/lighthouse/lighthouse-${{ github.run_number }}
107+
- name: Run Lighthouse on Site
108+
id: lighthouse
109+
uses: foo-software/[email protected]
110+
with:
111+
# TODO: generate this list to audit all html pages
112+
urls: >-
113+
${{ env.URL }}/index.html,
114+
${{ env.URL }}/demo/api.html,
115+
${{ env.URL }}/demo/demo.html,
116+
${{ env.URL }}/demo/example_pandas.html
117+
outputDirectory: /tmp/lighthouse/lighthouse-${{ github.run_number }}
118+
verbose: true
119+
120+
# Store the audit
121+
- name: Upload Lighthouse Reports
122+
uses: actions/upload-artifact@v2
123+
with:
124+
name: Lighthouse Report ${{ github.run_number }}
125+
path: /tmp/lighthouse
126+
127+
# Check the audit for threshold values
128+
# TODO: write this someplace after a PR is merged, and load?
129+
- name: Assess Lighthouse Check results
130+
uses: foo-software/[email protected]
131+
with:
132+
lighthouseCheckResults: ${{ steps.lighthouse.outputs.lighthouseCheckResults }}
133+
minAccessibilityScore: "96"
134+
minBestPracticesScore: "90"
135+
minPerformanceScore: "10"
136+
minSeoScore: "80"
137+
66138
publish:
67139

68140
name: Publish to PyPi

docs/serve.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
""" a minimal static server, primarily for performing audits
2+
3+
this is not meant to be used in production, and some settings are insecure
4+
to game auditing metrics which will vary substantially by deployment
5+
"""
6+
from pathlib import Path
7+
from tornado import ioloop, web, options
8+
9+
options.define("port", default=8080, help="port to listen on")
10+
options.define(
11+
"host", default="localhost", help="host interface to connect on (0.0.0.0 is all)"
12+
)
13+
14+
SETTINGS = dict(
15+
static_path=Path(__file__).parent / "_build/html",
16+
# enabling compression can have security impacts if not done correctly
17+
compress_response=True,
18+
# not really useful for production
19+
autoreload=True,
20+
)
21+
22+
23+
class CacheStaticHandler(web.StaticFileHandler):
24+
def get_cache_time(self, *args, **kwargs):
25+
""" always return a fairly long time. real deployments would have a more
26+
robust solution
27+
"""
28+
return int(1e10)
29+
30+
31+
def make_app():
32+
""" create and return (but do not start) a tornado app
33+
"""
34+
app = web.Application(
35+
[(r"^/(.*)", CacheStaticHandler, dict(path=SETTINGS["static_path"]))],
36+
**SETTINGS
37+
)
38+
39+
return app
40+
41+
42+
def main(port, host):
43+
""" start a tornado app on the desired port
44+
"""
45+
app = make_app()
46+
app.listen(port, host)
47+
url = "http://{}:{}/".format(host, port)
48+
print("Watching files: \t\t{static_path}".format(**SETTINGS))
49+
print("Hosting site on:\t\t{}".format(url))
50+
print("\nPress `Ctrl+C` to stop")
51+
try:
52+
ioloop.IOLoop.current().start()
53+
except KeyboardInterrupt:
54+
ioloop.IOLoop.current().stop()
55+
print("The server was stopped")
56+
57+
58+
if __name__ == "__main__":
59+
options.parse_command_line()
60+
main(port=options.options.port, host=options.options.host)

0 commit comments

Comments
 (0)