Skip to content

Commit 4a1e789

Browse files
trallarddrammock
andauthored
MAINT - CI improvements (security and maintenance) (#2077)
I thought I would do some winter/summer cleaning (depending on your location) ⛄🌞. This PR adds several improvements/updates to our CI with a focus on improving the contributor experience and security Details below: ## 🔒 Security focused - Use SHA for third-party actions and our internal action for development setup - Replace potentially [dangerous trigger `workflow_run`](https://woodruffw.github.io/zizmor/audits/#dangerous-triggers) for `workflow_call` and use as a reusable workflow - Create and use a dedicated environment for releases: - [x] Created a `pst-release` environment in the repo (restricted to `main` only) - [x] Use `pst-release` for our `release-PST` step in `publish.yml` - [ ] Add `pst-release` as the default env in PyPI - Add a `zizmor.yml` workflow to run static analysis on our GH workflows - Add explicit `persist-credentials: false` to relevant actions (where we do not need further git operations) ## 👩🏽‍🎤 Contributor experience - Prevent the `pre-release.yml` workflow from running in repos not under the `pydata` org (forks) - Our CI workflow has grown significantly with the various tests and checks. This PR splits it into: - `CI.yml`: pytest, a11y-tests, profiling, coverage - `docs.yml`: docs-related checks like building across OSes and Python and Sphinx versions, check for broken links (new, note that I had to fix some broken links to get this in 🙈 and there seem to be still some others to fix) - Add `tox run -e docs-linkcheck` to check for broken links in our docs - Add workflow to add a link to the RTD docs preview in PRs. ## 🧰 Maintenance - Adds Python `3.13` to our testing matrices (`3.12` is left as the `default` until we are confident all is ok with `3.13`) - Add an explicit `ubuntu-22.04` target as `ubuntu-latest` will soon be `24.04` (being rolled out right now) -> I think I might actually have explicit versions on both and only change to latest (or not) when the rollout is completed ---- ## Questions / notes - @drammock, we have `"sphinx-theme-builder @ https://github.com/pradyunsg/sphinx-theme-builder/archive/87214d0671c943992c05e3db01dca997e156e8d6.zip",` in our `project. tool` and `tox.ini`. I do not believe this pin is needed anymore, so I would like to remove it, too. WDYT? - @drammock did you create the token for Anaconda.org? I would like to make this an environment secret (vs a repository secret as it is right now) - Also, while adding a new environment, I noticed a `github-pages` environment that I do not think we are using, so I'd like to delete it. - Finally, I deleted a leftover `PYPI_TOKEN,` which should have been removed when we changed to trusted publishers. Closes #2095 --------- Co-authored-by: Daniel McCloy <[email protected]>
1 parent 1772132 commit 4a1e789

23 files changed

+488
-171
lines changed

.github/actions/set-dev-env/action.yml

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# Reusable action to set our PST development environment
2+
# DO NOT use for release jobs since we cache dependencies
3+
# IMPORTANT: if you make changes to this action, you will need to open a follow-up
4+
# PR after merge to update the action SHA in the a11y, CI, docs, and prerelease
5+
# workflows
16
name: Setup PST CI environment
27
description: Create a PST dev environment
38

.github/dependabot.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ updates:
44
- package-ecosystem: "github-actions"
55
directory: "/"
66
schedule:
7-
interval: "weekly"
7+
interval: "monthly"
88
labels:
99
- "tag: dependencies"
1010
- "tag: CI"
1111
# npm
1212
- package-ecosystem: "npm"
1313
directory: "/"
1414
schedule:
15-
interval: "weekly"
15+
interval: "monthly"
1616
labels:
1717
- "tag: dependencies"
1818
- "tag: javascript"

.github/workflows/CI.yml

+54-109
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# This workflow runs our usual CI jobs: testing with pytest, profiling,
2+
# and coverage checks for PST
3+
# IMPORTANT: if you make changes to this workflow, you will need to open a follow-up
4+
# PR after merge to update the action SHA in the publish workflow
5+
16
name: continuous-integration
27

38
# Concurrency group that uses the workflow name and PR number if available
@@ -21,6 +26,9 @@ on:
2126
branches:
2227
- main
2328
pull_request:
29+
branches:
30+
- "*"
31+
# allows this to be used as a composite action in other workflows
2432
workflow_call:
2533
# allow manual triggering of the workflow, while debugging
2634
workflow_dispatch:
@@ -31,10 +39,12 @@ jobs:
3139
strategy:
3240
fail-fast: true
3341
matrix:
42+
# https://github.com/actions/runner-images
3443
# macos-14==latest
35-
# ubuntu-20.04==latest
36-
os: ["ubuntu-latest", "ubuntu-24.04", "macos-14", "windows-latest"]
37-
python-version: ["3.9", "3.10", "3.11", "3.12"]
44+
# ubuntu-24.04==latest
45+
# windows-2022==latest
46+
os: ["ubuntu-latest", "ubuntu-22.04", "macos-14", "windows-latest"]
47+
python-version: ["3.9", "3.13"]
3848
sphinx-version: [""]
3949
include:
4050
# oldest Python version with the oldest Sphinx version
@@ -58,12 +68,17 @@ jobs:
5868
runs-on: ${{ matrix.os }}
5969
steps:
6070
- name: "Checkout repository 🛎"
61-
uses: actions/checkout@v4
71+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
72+
with:
73+
persist-credentials: false
74+
6275
- name: "Setup CI environment 🛠"
63-
uses: ./.github/actions/set-dev-env
76+
# Important: make sure to update the SHA after making any changes to the set-dev-env action
77+
uses: pydata/pydata-sphinx-theme/.github/actions/set-dev-env@01731d0cc57768b9eff1c97f38909932ecd7e7d1
6478
with:
6579
python-version: ${{ matrix.python-version }}
6680
pandoc: true
81+
6782
- name: "Run tests ✅"
6883
shell: bash
6984
run: |
@@ -77,125 +92,40 @@ jobs:
7792
else
7893
python -Im tox run -e compile-assets,i18n-compile,py$(echo ${{ matrix.python-version }} | tr -d .)-tests
7994
fi
95+
8096
- name: "Upload coverage data to GH artifacts 📤"
8197
if: matrix.python-version == '3.12' && matrix.os == 'ubuntu-latest' && matrix.sphinx-version == 'dev'
82-
uses: actions/upload-artifact@v4
98+
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08
8399
with:
84100
name: coverage-data-${{ matrix.python-version }}
85101
path: .coverage
86102
if-no-files-found: ignore
87103
include-hidden-files: true
88104

89-
# Only run accessibility tests on the latest Python version (3.12) and Ubuntu
90-
a11y-tests:
91-
name: "a11y-tests (ubuntu-latest, 3.12)"
92-
runs-on: ubuntu-latest
93-
steps:
94-
- name: "Checkout repository 🛎"
95-
uses: actions/checkout@v4
96-
- name: "Setup CI environment 🛠"
97-
uses: ./.github/actions/set-dev-env
98-
with:
99-
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
100-
pandoc: true
101-
graphviz: true
102-
- name: "Run accessibility tests with playwright 🎭"
103-
# build PST, build docs, then run a11y-tests
104-
run: python -Im tox run -m a11y
105-
- name: "Upload Playwright traces, if any 🐾"
106-
uses: actions/upload-artifact@v4
107-
if: ${{ failure() }}
108-
with:
109-
name: playwright-traces
110-
path: test-results/
111-
112-
# Build our docs (PST) on major OSes and check for warnings
113-
build-site:
114-
name: "build PST docs"
115-
strategy:
116-
fail-fast: false
117-
matrix:
118-
os: [ubuntu-latest, macos-latest, windows-latest]
119-
python-version: ["3.12"]
120-
include:
121-
# oldest Python version with the oldest Sphinx version
122-
- os: ubuntu-latest
123-
python-version: "3.9"
124-
sphinx-version: "6.1"
125-
runs-on: ${{ matrix.os }}
126-
steps:
127-
- name: "Checkout repository 🛎"
128-
uses: actions/checkout@v4
129-
- name: "Setup CI environment 🛠"
130-
uses: ./.github/actions/set-dev-env
131-
with:
132-
python-version: ${{ matrix.python-version }}
133-
pandoc: true
134-
graphviz: true
135-
- name: "Build docs and check for warnings 📖"
136-
shell: bash
137-
run: |
138-
# check if there is a specific Sphinx version to build with
139-
# example substitution: tox run -e py39-sphinx61-docs
140-
if [ -n "${{matrix.sphinx-version}}" ]; then
141-
python -Im tox run -e py$(echo ${{ matrix.python-version }} | tr -d .)-sphinx$(echo ${{ matrix.sphinx-version }} | tr -d .)-docs
142-
# build with the default Sphinx version
143-
# example substitution: tox run -e py312-docs
144-
else
145-
python -Im tox run -e py$(echo ${{ matrix.python-version }} | tr -d .)-docs
146-
fi
147-
148-
# Run Lighthouse audits on the built site (kitchen-sink only)
149-
lighthouse-audit:
150-
needs: build-site
151-
runs-on: ubuntu-latest
152-
env:
153-
DOCS_DIR: "audit"
154-
steps:
155-
- name: "Checkout repository 🛎"
156-
uses: actions/checkout@v4
157-
- name: "Setup CI environment 🛠"
158-
uses: ./.github/actions/set-dev-env
159-
with:
160-
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
161-
- name: "Copy kitchen sink to a tiny site"
162-
run: |
163-
mkdir -p ${{ env.DOCS_DIR }}/site
164-
cp -r docs/examples/kitchen-sink ${{ env.DOCS_DIR }}/site/kitchen-sink
165-
printf "Test\n====\n\n.. toctree::\n\n kitchen-sink/index\n" > ${{ env.DOCS_DIR }}/site/index.rst
166-
echo 'html_theme = "pydata_sphinx_theme"' > ${{ env.DOCS_DIR }}/site/conf.py
167-
echo '.. toctree::\n :glob:\n\n *' >> ${{ env.DOCS_DIR }}/site/index.rst
168-
169-
# build docs without checking for warnings
170-
python -Im tox run -e docs-no-checks
171-
172-
- name: "Audit with Lighthouse 🔦"
173-
uses: treosh/lighthouse-ci-action@v12
174-
with:
175-
configPath: ".github/workflows/lighthouserc.json"
176-
temporaryPublicStorage: true
177-
uploadArtifacts: true
178-
runs: 3 # Multiple runs to reduce variance
179-
180105
coverage:
181106
name: "Check coverage"
182107
needs: run-pytest
183108
runs-on: ubuntu-latest
184-
# avoid running this on schedule, releases, or workflow_call
185-
if: github.event_name != 'schedule' && github.event_name != 'release' && github.event_name != 'workflow_call'
109+
# avoid running this on schedule, releases, workflow_call, or workflow_dispatch
110+
if: github.event_name != 'schedule' && github.event_name != 'release' && github.event_name != 'workflow_call' && github.event_name != 'workflow_dispatch'
186111
permissions:
187112
contents: write
188113
pull-requests: write
189114
steps:
190115
- name: "Checkout repository 🛎"
191-
uses: actions/checkout@v4
116+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
117+
with:
118+
persist-credentials: false
119+
192120
- name: "Setup CI environment 🛠"
193-
uses: ./.github/actions/set-dev-env
121+
uses: pydata/pydata-sphinx-theme/.github/actions/set-dev-env@01731d0cc57768b9eff1c97f38909932ecd7e7d1
194122
with:
195123
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
124+
196125
- run: python -Im pip install --upgrade coverage[toml]
126+
197127
- name: "Download coverage data 📥"
198-
uses: actions/download-artifact@v4
128+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16
199129
with:
200130
pattern: coverage-data-*
201131
merge-multiple: true
@@ -213,45 +143,60 @@ jobs:
213143
python -Im coverage report --fail-under=80
214144
215145
- name: "Upload HTML report if check failed 📤"
216-
uses: actions/upload-artifact@v4
146+
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08
217147
with:
218148
name: html-report
219149
path: htmlcov
220150
if: ${{ failure() }}
221151

222152
# seems we need to call this from the main CI workflow first
223153
- name: "Coverage comment 💬"
224-
uses: py-cov-action/python-coverage-comment-action@v3
154+
uses: py-cov-action/python-coverage-comment-action@b2eb38dd175bf053189b35f738f9207278b00925
225155
id: coverage_comment
226156
with:
227157
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
228158

229159
- name: "Store Pull Request comment to be posted 📤"
230-
uses: actions/upload-artifact@v4
160+
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08
231161
if: steps.coverage_comment.outputs.COMMENT_FILE_WRITTEN == 'true'
232162
with:
233163
# leave default names
234164
name: python-coverage-comment-action
235165
path: python-coverage-comment-action.txt
236166

237167
profiling:
238-
needs: [build-site, run-pytest]
168+
needs: [run-pytest]
239169
runs-on: ubuntu-latest
240170
steps:
241171
- name: "Checkout repository 🛎"
242-
uses: actions/checkout@v4
172+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
173+
with:
174+
persist-credentials: false
175+
243176
- name: "Setup CI environment 🛠"
244-
uses: ./.github/actions/set-dev-env
177+
uses: pydata/pydata-sphinx-theme/.github/actions/set-dev-env@01731d0cc57768b9eff1c97f38909932ecd7e7d1
245178
with:
246179
# 3.12 is not supported by py-spy yet
247180
python-version: "3.11"
181+
248182
- name: "Run profiling with py-spy 🕵️‍♂️"
249183
# profiling needs to be run as sudo
250184
run: python -m tox run -e py311-profile-docs -- -o docbuild_profile.svg
251185
continue-on-error: true
186+
252187
- name: "Upload profiling data to GH artifacts 📤"
253-
uses: actions/upload-artifact@v4
188+
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08
254189
with:
255190
name: profile-results
256191
path: docbuild_profile.svg
257192
if-no-files-found: ignore
193+
194+
# Calling the coverage-comment action from the main CI workflow
195+
# we might want to pin the SHA once merged
196+
coverage-comment:
197+
uses: ./.github/workflows/coverage.yml
198+
needs: [coverage]
199+
permissions:
200+
contents: write
201+
pull-requests: write
202+
actions: read

.github/workflows/a11y.yml

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Accessibility tests for PST, using playwright and axe-core
2+
3+
name: a11y-tests
4+
5+
# Concurrency group that uses the workflow name and PR number if available
6+
# or commit SHA as a fallback. If a new build is triggered under that
7+
# concurrency group while a previous build is running it will be canceled.
8+
# Repeated pushes to a PR will cancel all previous builds, while multiple
9+
# merges to main will not cancel.
10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
12+
cancel-in-progress: true
13+
14+
env:
15+
FORCE_COLOR: "1" # Make tools pretty
16+
DEFAULT_PYTHON_VERSION: "3.12" # keep in sync with tox.ini
17+
PIP_DISABLE_PIP_VERSION_CHECK: "1" # Don't check for pip updates
18+
19+
permissions: {}
20+
21+
on:
22+
push:
23+
branches:
24+
- main
25+
pull_request:
26+
branches:
27+
- "*"
28+
# allows this to be used as a composite action in other workflows
29+
workflow_call:
30+
# allow manual triggering of the workflow, while debugging
31+
workflow_dispatch:
32+
33+
jobs:
34+
a11y-tests:
35+
strategy:
36+
fail-fast: true
37+
matrix:
38+
# ubuntu-latest = 24.04
39+
os: ["ubuntu-latest", "ubuntu-22.04", "macos-14"]
40+
browser: ["firefox", "chromium"]
41+
runs-on: ${{ matrix.os }}
42+
steps:
43+
- name: "Checkout repository 🛎"
44+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
45+
with:
46+
persist-credentials: false
47+
48+
- name: "Setup CI environment 🛠"
49+
uses: pydata/pydata-sphinx-theme/.github/actions/set-dev-env@01731d0cc57768b9eff1c97f38909932ecd7e7d1
50+
with:
51+
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
52+
pandoc: true
53+
graphviz: true
54+
55+
- name: "Run accessibility tests with playwright 🎭"
56+
# build PST, build docs, then run a11y-tests
57+
run: python -Im tox run -e compile-assets,i18n-compile,py312-docs,a11y-tests-${{ matrix.browser }}
58+
59+
- name: "Upload Playwright traces, if any 🐾"
60+
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6
61+
if: ${{ failure() }}
62+
with:
63+
name: playwright-traces
64+
path: test-results/

0 commit comments

Comments
 (0)