Skip to content

Commit 6928d4b

Browse files
pp-motrexfeathers
andauthored
Run linkchecks regularly, instead of on PRs (#6386)
* Add lychee-based linkcheck workflow. * Remove old nox-based per-PR linkcheck. * Remove nox-linkcheck from python-version-checks test. * Configure manifest to exclude the linkcheck ignores file. * Update .github/workflows/ci-linkchecks.yml Co-authored-by: Martin Yeo <[email protected]> * Update .github/workflows/ci-linkchecks.yml Co-authored-by: Martin Yeo <[email protected]> * Add links badge to README. * Test urls in all files python, exclude or replace failing urls in python. * Run checks every day, including weekends. * Apply Iris-friendly labels to linkcheck failure Issues. --------- Co-authored-by: Martin Yeo <[email protected]>
1 parent 2605673 commit 6928d4b

File tree

15 files changed

+114
-58
lines changed

15 files changed

+114
-58
lines changed

.github/workflows/ci-linkchecks.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Linkcheck
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
- cron: "00 06 * * *"
7+
8+
jobs:
9+
linkChecker:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
issues: write # required for peter-evans/create-issue-from-file
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Link Checker
17+
id: lychee
18+
uses: lycheeverse/lychee-action@f613c4a64e50d792e0b31ec34bbcbba12263c6a6
19+
with:
20+
fail: false
21+
args: "--verbose './docs/**/*.rst' './docs/**/*.inc' './lib/**/*.py'"
22+
23+
- name: Create Issue From File
24+
if: steps.lychee.outputs.exit_code != 0
25+
uses: peter-evans/create-issue-from-file@e8ef132d6df98ed982188e460ebb3b5d4ef3a9cd
26+
with:
27+
title: Link Checker Report
28+
content-filepath: ./lychee/out.md
29+
labels: "Bot, Type: Documentation, Type: Bug"
30+
31+
- name: Fail Workflow On Link Errors
32+
if: steps.lychee.outputs.exit_code != 0
33+
run:
34+
exit {{ steps.lychee.outputs.exit_code }}

.github/workflows/ci-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
matrix:
3737
os: ["ubuntu-latest"]
3838
python-version: ["3.13"]
39-
session: ["doctest", "gallery", "linkcheck"]
39+
session: ["doctest", "gallery"]
4040
include:
4141
- os: "ubuntu-latest"
4242
python-version: "3.13"

.lycheeignore

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# nonfunctional, found in some code examples
2+
file:///
3+
4+
# DEAD : legacy in various old whatsnews
5+
https://biggus.readthedocs.io
6+
7+
# unkown problem, works in browser : used in further_topics/ugrid/data_model
8+
https://doi.org/10.3390/jmse2010194
9+
10+
# DEAD, todo:remove, used in docs/src/userguide/plotting_a_cube.rst
11+
https://effbot.org
12+
13+
# nonfunctional, found in some code examples
14+
https://foo/
15+
16+
# DEAD, todo:remove, used in docs/src/further_topics/ugrid/data_model.rst
17+
https://ibm-design-language.eu-de.mybluemix.net/design/language/resources/color-library
18+
19+
# DEAD, legacy in whatsnew/1.4.rst
20+
https://geoport.whoi.edu/thredds/dodsC/bathy/gom15
21+
22+
# exist, but bad certificates
23+
https://georepository.com
24+
https://geoport.whoi.edu:80/thredds/
25+
26+
# catch (at least) github userids, of which many in whatsnews, too many --> "too many requests" failures
27+
https://github.com/[^/]*$
28+
29+
# nonfunctional example, used in docs/src/developers_guide/gitwash/development_workflow.rst
30+
https://github.com/your-user-name/iris
31+
32+
# problem with bad certificate (review sometime?)
33+
https://scitools.github.com/cartopy
34+
35+
# legacy ref in whatsnew/3.0.rst
36+
https://stickler-ci.com
37+
38+
# DEAD, todo:remove, used in lib/iris/symbols.py
39+
https://www.wmo.int/pages/prog/www/DPFS/documents/485_Vol_I_en_colour.pdf
40+
41+
# DEAD, todo:remove, used in docs/src/userguide/plotting_a_cube.rst
42+
# unkown problem, works in browser : used in docs/src/index.rst
43+
https://www.flaticon.com
44+
45+
# nonfunctional example, used in lib/iris/io/__init__.py
46+
https://www.thing.com
47+
48+
# DEAD, todo:remove, used in docs/src/userguide/plotting_a_cube.rst
49+
https://www.personal.psu.edu/cab38/ColorBrewer/ColorBrewer_updates.html
50+
51+
# nonfunctional, found in some code examples
52+
https://www.somehost.com

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ exclude .git-blame-ignore-revs
1111
exclude .git_archival.txt
1212
exclude .gitattributes
1313
exclude .gitignore
14+
exclude .lycheeignore
1415
exclude .mailmap
1516
exclude .pre-commit-config.yaml
1617
exclude .readthedocs.yml

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
|------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
1414
| ⚙️ CI | [![ci-manifest](https://github.com/SciTools/iris/actions/workflows/ci-manifest.yml/badge.svg)](https://github.com/SciTools/iris/actions/workflows/ci-manifest.yml) [![ci-tests](https://github.com/SciTools/iris/actions/workflows/ci-tests.yml/badge.svg)](https://github.com/SciTools/iris/actions/workflows/ci-tests.yml) [![ci-wheels](https://github.com/SciTools/iris/actions/workflows/ci-wheels.yml/badge.svg)](https://github.com/SciTools/iris/actions/workflows/ci-wheels.yml) [![pre-commit](https://results.pre-commit.ci/badge/github/SciTools/iris/main.svg)](https://results.pre-commit.ci/latest/github/SciTools/iris/main) |
1515
| 💬 Community | [![Contributor Covenant](https://img.shields.io/badge/contributor%20covenant-2.1-4baaaa.svg)](https://www.contributor-covenant.org/version/2/1/code_of_conduct/) [![GH Discussions](https://img.shields.io/badge/github-discussions%20%F0%9F%92%AC-yellow?logo=github&logoColor=lightgrey)](https://github.com/SciTools/iris/discussions) [![twitter](https://img.shields.io/twitter/follow/scitools_iris?color=yellow&label=twitter%7Cscitools_iris&logo=twitter&style=plastic)](https://twitter.com/scitools_iris) |
16-
| 📖 Documentation | [![rtd](https://readthedocs.org/projects/scitools-iris/badge/?version=latest)](https://scitools-iris.readthedocs.io/en/latest/?badge=latest) |
16+
| 📖 Documentation | [![rtd](https://readthedocs.org/projects/scitools-iris/badge/?version=latest)](https://scitools-iris.readthedocs.io/en/latest/?badge=latest) [![Check Links](https://github.com/SciTools/iris/actions/workflows/ci-linkchecks.yml/badge.svg)](https://github.com/SciTools/iris/actions/workflows/ci-linkchecks.yml) |
1717
| 📈 Health | [![codecov](https://codecov.io/gh/SciTools/iris/branch/main/graph/badge.svg?token=0GeICSIF3g)](https://codecov.io/gh/SciTools/iris) |
1818
| ✨ Meta | [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![NEP29](https://raster.shields.io/badge/follows-NEP29-orange.png)](https://numpy.org/neps/nep-0029-deprecation_policy.html) [![license - bds-3-clause](https://img.shields.io/github/license/SciTools/iris)](https://github.com/SciTools/iris/blob/main/LICENSE) [![conda platform](https://img.shields.io/conda/pn/conda-forge/iris.svg)](https://anaconda.org/conda-forge/iris) |
1919
| 📦 Package | [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.595182.svg)](https://doi.org/10.5281/zenodo.595182) [![conda-forge](https://img.shields.io/conda/vn/conda-forge/iris?color=orange&label=conda-forge&logo=conda-forge&logoColor=white)](https://anaconda.org/conda-forge/iris) [![pypi](https://img.shields.io/pypi/v/scitools-iris?color=orange&label=pypi&logo=python&logoColor=white)](https://pypi.org/project/scitools-iris/) [![pypi - python version](https://img.shields.io/pypi/pyversions/scitools-iris.svg?color=orange&logo=python&label=python&logoColor=white)](https://pypi.org/project/scitools-iris/) |

docs/src/further_topics/dask_best_practices/index.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ CPU available. This interacts badly with Dask:
4444
* NumPy will generate enough threads to use all available CPUs even
4545
if Dask is deliberately configured to only use a subset of CPUs. The
4646
resulting sharing of CPUs between threads greatly reduces performance.
47-
* `Dask is already designed to parallelise with NumPy arrays <https://docs
48-
.dask.org/en/latest/array.html>`_, so adding NumPy's 'competing' layer of
49-
parallelisation could cause unpredictable performance.
47+
* `Dask is already designed to parallelise with NumPy arrays
48+
<https://docs.dask.org/en/latest/array.html>`_, so adding NumPy's 'competing' layer
49+
of parallelisation could cause unpredictable performance.
5050

5151
Therefore it is best to prevent NumPy performing its own parallelisation, `a
52-
suggestion made in Dask's own documentation <https://docs.dask
53-
.org/en/stable/array-best-practices.html#avoid-oversubscribing-threads>`_.
52+
suggestion made in Dask's own documentation
53+
<https://docs.dask.org/en/stable/array-best-practices.html#avoid-oversubscribing-threads>`_.
5454
The following commands will ensure this in all scenarios:
5555

5656
in Python...
@@ -158,8 +158,8 @@ NetCDF Files
158158

159159
NetCDF files can include their own chunking specification. This is either
160160
specified when creating the file, or is automatically assigned if one or
161-
more of the dimensions is `unlimited <https://www.unidata.ucar
162-
.edu/software/netcdf/docs/unlimited_dims.html>`_.
161+
more of the dimensions is
162+
`unlimited <https://www.unidata.ucar.edu/software/netcdf/docs/unlimited_dims.html>`_.
163163
Importantly, netCDF chunk shapes are **not optimised for Dask
164164
performance**.
165165

docs/src/userguide/glossary.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ Glossary
188188
189189
Standard Name
190190
A name describing a :term:`phenomenon`, one from a fixed list
191-
defined at `CF Standard Names <https://cfconventions.org/standard-names.html>`_.
191+
defined at `CF Standard Names <https://cfconventions.org/Data/cf-standard-names/current/build/cf-standard-name-table.html>`_.
192192

193193
| **Related:** :term:`Long Name` **|** :term:`Cube`
194194
| **More information:** :doc:`iris_cubes`

docs/src/whatsnew/2.3.rst

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ Features
2929
.. admonition:: Climatological Coordinate Support
3030

3131
Iris can now load, store and save `NetCDF climatological coordinates
32-
<https://cfconventions.org/Data/cf-conventions/cf-conventions-1
33-
.7/cf-conventions.html#climatological-statistics>`_. Any cube time
32+
<https://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/cf-conventions.html#climatological-statistics>`_. Any cube time
3433
coordinate can be marked as a climatological time axis using the boolean
3534
property: ``climatological``. The climatological bounds are stored in the
3635
coordinate's ``bounds`` property.
@@ -41,9 +40,8 @@ Features
4140
coordinate's ``bounds`` property are written to a NetCDF boundary variable
4241
called '<coordinate-name>_bounds'. These are in place of a standard
4342
'bounds' attribute and accompanying boundary variable. See below
44-
for an `example adapted from CF conventions <https://cfconventions
45-
.org/Data/cf-conventions/cf-conventions-1.7/cf-conventions
46-
.html#climatological-statistics>`_:
43+
for an
44+
`example adapted from CF conventions <https://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/cf-conventions.html#climatological-statistics>`_:
4745

4846
.. code-block:: none
4947
@@ -116,8 +114,7 @@ Features
116114

117115
* New coordinate system: :class:`iris.coord_systems.Geostationary`,
118116
including load and save support, based on the `CF Geostationary projection
119-
definition <https://cfconventions
120-
.org/cf-conventions/cf-conventions.html#_geostationary_projection>`_.
117+
definition <https://cfconventions.org/cf-conventions/cf-conventions.html#_geostationary_projection>`_.
121118

122119
* :class:`iris.coord_systems.VerticalPerspective` can now be saved to and
123120
loaded from NetCDF files.
@@ -164,8 +161,7 @@ Bugs Fixed
164161
points.
165162

166163
* :class:`iris.coord_systems.VerticalPerspective` coordinate system now uses
167-
the `CF Vertical perspective definition <https://cfconventions
168-
.org/cf-conventions/cf-conventions.html#vertical-perspective>`_; had been
164+
the `CF Vertical perspective definition <https://cfconventions.org/cf-conventions/cf-conventions.html#vertical-perspective>`_; had been
169165
erroneously using Geostationary.
170166

171167
* :class:`~iris.coords.CellMethod` will now only use valid
@@ -227,8 +223,7 @@ Internal
227223
========
228224

229225
* Iris now supports Proj4 up to version 5, but not yet 6 or beyond, pending
230-
`fixes to some cartopy tests <https://github
231-
.com/SciTools/cartopy/pull/1289#pullrequestreview-272774087>`_.
226+
`fixes to some cartopy tests <https://github.com/SciTools/cartopy/pull/1289#pullrequestreview-272774087>`_.
232227

233228
* Iris now requires Dask >= 1.2 to allow for improved coordinate equality
234229
checks.
@@ -238,7 +233,7 @@ Documentation
238233
=============
239234

240235
* Adopted a
241-
`new colour logo for Iris <https://github.com/SciTools/iris/blob/main/docs/src/_static/Iris7_1_trim_100.png>`_
236+
`new colour logo for Iris <https://github.com/SciTools/iris/blob/v2.3.0/docs/iris/src/_static/Iris7_1_trim_100.png>`_
242237

243238
* Added a gallery example showing how to concatenate NEMO ocean model data,
244239
see :ref:`sphx_glr_generated_gallery_oceanography_plot_load_nemo.py`.

docs/src/why_iris.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ giving you a powerful, format-agnostic interface for working with your data.
1111
It excels when working with multi-dimensional Earth Science data, where tabular
1212
representations become unwieldy and inefficient.
1313

14-
`CF Standard names <https://cfconventions.org/standard-names.html>`_,
14+
`CF Standard names <https://cfconventions.org/Data/cf-standard-names/current/build/cf-standard-name-table.html>`_,
1515
`units <https://github.com/SciTools/cf_units>`_, and coordinate metadata
1616
are built into Iris, giving you a rich and expressive interface for maintaining
1717
an accurate representation of your data. Its treatment of data and

lib/iris/common/metadata.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
]
4747

4848

49-
# https://www.unidata.ucar.edu/software/netcdf/docs/netcdf_data_set_components.html#object_name
49+
# https://docs.unidata.ucar.edu/nug/current/netcdf_data_set_components.html#object_name
5050

5151
_TOKEN_PARSE = re.compile(r"""^[a-zA-Z0-9][\w\.\+\-@]*$""")
5252

lib/iris/experimental/raster.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def export_geotiff(cube, fname):
118118
Notes
119119
-----
120120
For more details on GeoTiff specification and PixelIsArea, see:
121-
https://www.remotesensing.org/geotiff/spec/geotiff2.5.html#2.5.2.2
121+
https://docs.ogc.org/is/19-008r4/19-008r4.html#_pixelisarea_raster_space
122122
123123
.. deprecated:: 3.2.0
124124

lib/iris/fileformats/netcdf/saver.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -512,8 +512,8 @@ def write(
512512
example, if `least_significant_digit=1`, data will be quantized
513513
using `numpy.around(scale*data)/scale`, where `scale = 2**bits`,
514514
and `bits` is determined so that a precision of 0.1 is retained (in
515-
this case `bits=4`). From
516-
`here <https://www.esrl.noaa.gov/psd/data/gridded/conventions/cdc_netcdf_standard.shtml>`__:
515+
this case `bits=4`). From the
516+
`metadata conventions <https://docs.unidata.ucar.edu/nug/current/attribute_conventions.html>`__:
517517
"least_significant_digit -- power of ten of the smallest decimal
518518
place in unpacked data that is a reliable value". Default is
519519
`None`, or no quantization, or 'lossless' compression.
@@ -2473,7 +2473,7 @@ def save(
24732473
Used to manually specify the HDF5 chunksizes for each dimension of the
24742474
variable. A detailed discussion of HDF chunking and I/O performance is
24752475
available
2476-
`here <https://www.esrl.noaa.gov/psd/data/gridded/conventions/cdc_netcdf_standard.shtml>`__.
2476+
`here <https://docs.unidata.ucar.edu/nug/current/netcdf_perf_chunking.html>`__.
24772477
Basically, you want the chunk size for each dimension to match as
24782478
closely as possible the size of the data block that users will read
24792479
from the file. `chunksizes` cannot be set if `contiguous=True`.
@@ -2502,8 +2502,8 @@ def save(
25022502
describes a numpy integer dtype (i.e. 'i2', 'short', 'u4') or a dict
25032503
of packing parameters as described below or an iterable of such types,
25042504
strings, or dicts. This provides support for netCDF data packing as
2505-
described in
2506-
`here <https://www.esrl.noaa.gov/psd/data/gridded/conventions/cdc_netcdf_standard.shtml>`__
2505+
described in the
2506+
`metadata conventions <https://docs.unidata.ucar.edu/nug/current/attribute_conventions.html>`__
25072507
If this argument is a type (or type string), appropriate values of
25082508
scale_factor and add_offset will be automatically calculated based
25092509
on `cube.data` and possible masking. For more control, pass a dict with

lib/iris/tests/test_coding_standards.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def test_python_versions():
103103
ci_tests_file,
104104
(
105105
f'python-version: ["{latest_supported}"]\n'
106-
f'{" " * 8}session: ["doctest", "gallery", "linkcheck"]'
106+
f'{" " * 8}session: ["doctest", "gallery"]'
107107
),
108108
),
109109
(benchmark_runner_file, f'python_version = "{latest_supported}"'),

lib/iris/tests/unit/coord_categorisation/test_add_categorised_coord.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def make_cube(self, calendar):
110110
def test_calendars(self):
111111
for calendar in calendars:
112112
# Skip the Julian calendar due to
113-
# https://github.com/Unidata/netcdftime/issues/13
113+
# https://github.com/Unidata/cftime/issues/13
114114
# Remove this if block once the issue is resolved.
115115
if calendar == "julian":
116116
continue

noxfile.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -240,32 +240,6 @@ def gallery(session: nox.sessions.Session):
240240
)
241241

242242

243-
@nox.session(python=_PY_VERSION_DOCSBUILD, venv_backend="conda")
244-
def linkcheck(session: nox.sessions.Session):
245-
"""Perform iris doc link check.
246-
247-
Parameters
248-
----------
249-
session : object
250-
A `nox.sessions.Session` object.
251-
252-
"""
253-
prepare_venv(session)
254-
session.install("--no-deps", "--editable", ".")
255-
session.cd("docs")
256-
session.run(
257-
"make",
258-
"clean",
259-
"html",
260-
external=True,
261-
)
262-
session.run(
263-
"make",
264-
"linkcheck",
265-
external=True,
266-
)
267-
268-
269243
@nox.session(python=PY_VER, venv_backend="conda")
270244
def wheel(session: nox.sessions.Session):
271245
"""Perform iris local wheel install and import test.

0 commit comments

Comments
 (0)