diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 36bdcda9..2e1595d2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,15 +1,32 @@ -# Build releases and (on tags) publish to PyPI +# This is a GitHub workflow defining a set of jobs with a set of steps. +# ref: https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions +# +# Test build release artifacts (PyPI package, Docker images) and publish them on +# pushed git tags. +# name: Release -# always build releases (to make sure wheel-building works) -# but only publish to PyPI on tags on: - push: - branches: - - "!dependabot/**" - tags: - - "*" pull_request: + paths-ignore: + - "docs/**" + - "**.md" + - "**.rst" + - ".github/workflows/*" + - "!.github/workflows/release.yml" + push: + paths-ignore: + - "docs/**" + - "**.md" + - "**.rst" + - ".github/workflows/*" + - "!.github/workflows/release.yml" + branches-ignore: + - "dependabot/**" + - "pre-commit-ci-update-config" + tags: + - "**" + workflow_dispatch: jobs: build-release: diff --git a/.github/workflows/test-docs.yml b/.github/workflows/test-docs.yml new file mode 100644 index 00000000..abc33b6e --- /dev/null +++ b/.github/workflows/test-docs.yml @@ -0,0 +1,64 @@ +# This is a GitHub workflow defining a set of jobs with a set of steps. +# ref: https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions +# +# This workflow validates the REST API definition and runs the pytest tests in +# the docs/ folder. This workflow does not build the documentation. That is +# instead tested via ReadTheDocs (https://readthedocs.org/projects/jupyterhub/). +# +name: Test docs + +# The tests defined in docs/ are currently influenced by changes to _version.py +# and scopes.py. +on: + pull_request: + paths: + - "docs/**" + - "jupyterhub/_version.py" + - "jupyterhub/scopes.py" + - ".github/workflows/*" + - "!.github/workflows/test-docs.yml" + push: + paths: + - "docs/**" + - "jupyterhub/_version.py" + - "jupyterhub/scopes.py" + - ".github/workflows/*" + - "!.github/workflows/test-docs.yml" + branches-ignore: + - "dependabot/**" + - "pre-commit-ci-update-config" + tags: + - "**" + workflow_dispatch: + +env: + # UTF-8 content may be interpreted as ascii and causes errors without this. + LANG: C.UTF-8 + PYTEST_ADDOPTS: "--verbose --color=yes" + +jobs: + validate-rest-api-definition: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + + - name: Validate REST API definition + uses: char0n/swagger-editor-validate@182d1a5d26ff5c2f4f452c43bd55e2c7d8064003 + with: + definition-file: docs/source/_static/rest-api.yml + + test-docs: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: "3.9" + + - name: Install requirements + run: | + pip install -r docs/requirements.txt pytest -e . + + - name: pytest docs/ + run: | + pytest docs/ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fb967889..9463184e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,14 +1,28 @@ # This is a GitHub workflow defining a set of jobs with a set of steps. -# ref: https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions +# ref: https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions # name: Test -# Trigger the workflow's on all PRs but only on pushed tags or commits to -# main/master branch to avoid PRs developed in a GitHub fork's dedicated branch -# to trigger. on: pull_request: + paths-ignore: + - "docs/**" + - "**.md" + - "**.rst" + - ".github/workflows/*" + - "!.github/workflows/test.yml" push: + paths-ignore: + - "docs/**" + - "**.md" + - "**.rst" + - ".github/workflows/*" + - "!.github/workflows/test.yml" + branches-ignore: + - "dependabot/**" + - "pre-commit-ci-update-config" + tags: + - "**" workflow_dispatch: env: @@ -17,25 +31,6 @@ env: PYTEST_ADDOPTS: "--verbose --color=yes" jobs: - rest-api: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - name: Validate REST API - uses: char0n/swagger-editor-validate@182d1a5d26ff5c2f4f452c43bd55e2c7d8064003 - with: - definition-file: docs/source/_static/rest-api.yml - - - uses: actions/setup-python@v2 - with: - python-version: "3.9" - # in addition to the doc requirements - # the docs *tests* require pre-commit and pytest - - run: | - pip install -r docs/requirements.txt pytest pre-commit -e . - - run: | - pytest docs/ - jstest: # Run javascript tests runs-on: ubuntu-20.04 diff --git a/docs/source/rbac/generate-scope-table.py b/docs/source/rbac/generate-scope-table.py index a757aa02..9067c9d8 100644 --- a/docs/source/rbac/generate-scope-table.py +++ b/docs/source/rbac/generate-scope-table.py @@ -1,3 +1,18 @@ +""" +This script updates two files with the RBAC scope descriptions found in +`scopes.py`. + +The files are: + + 1. scope-table.md + + This file is git ignored and referenced by the documentation. + + 2. rest-api.yml + + This file is JupyterHub's REST API schema. Both a version and the RBAC + scopes descriptions are updated in it. +""" import os from collections import defaultdict from pathlib import Path @@ -5,12 +20,13 @@ from pathlib import Path from pytablewriter import MarkdownTableWriter from ruamel.yaml import YAML -import jupyterhub +from jupyterhub import __version__ from jupyterhub.scopes import scope_definitions HERE = os.path.abspath(os.path.dirname(__file__)) DOCS = Path(HERE).parent.parent.absolute() REST_API_YAML = DOCS.joinpath("source", "_static", "rest-api.yml") +SCOPE_TABLE_MD = Path(HERE).joinpath("scope-table.md") class ScopeTableGenerator: @@ -82,8 +98,9 @@ class ScopeTableGenerator: return table_rows def write_table(self): - """Generates the scope table in markdown format and writes it into `scope-table.md`""" - filename = f"{HERE}/scope-table.md" + """Generates the RBAC scopes reference documentation as a markdown table + and writes it to the .gitignored `scope-table.md`.""" + filename = SCOPE_TABLE_MD table_name = "" headers = ["Scope", "Grants permission to:"] values = self._parse_scopes() @@ -99,7 +116,9 @@ class ScopeTableGenerator: ) def write_api(self): - """Generates the API description in markdown format and writes it into `rest-api.yml`""" + """Loads `rest-api.yml` and writes it back with a dynamically set + JupyterHub version field and list of RBAC scopes descriptions from + `scopes.py`.""" filename = REST_API_YAML yaml = YAML(typ='rt') yaml.preserve_quotes = True @@ -107,7 +126,7 @@ class ScopeTableGenerator: with open(filename) as f: content = yaml.load(f.read()) - content["info"]["version"] = jupyterhub.__version__ + content["info"]["version"] = __version__ for scope in self.scopes: description = self.scopes[scope]['description'] doc_description = self.scopes[scope].get('doc_description', '') diff --git a/docs/test_docs.py b/docs/test_docs.py index 6a27b9de..2420e9ec 100644 --- a/docs/test_docs.py +++ b/docs/test_docs.py @@ -10,7 +10,9 @@ here = Path(__file__).absolute().parent root = here.parent -def test_rest_api_version(): +def test_rest_api_version_is_updated(): + """Checks that the version in JupyterHub's REST API definition file + (rest-api.yml) is matching the JupyterHub version.""" version_py = root.joinpath("jupyterhub", "_version.py") rest_api_yaml = root.joinpath("docs", "source", "_static", "rest-api.yml") ns = {} @@ -25,13 +27,11 @@ def test_rest_api_version(): assert jupyterhub_version == rest_api_version -def test_restapi_scopes(): +def test_rest_api_rbac_scope_descriptions_are_updated(): + """Checks that the RBAC scope descriptions in JupyterHub's REST API + definition file (rest-api.yml) as can be updated by generate-scope-table.py + matches what is committed.""" run([sys.executable, "source/rbac/generate-scope-table.py"], cwd=here, check=True) - run( - ['pre-commit', 'run', 'prettier', '--files', 'source/_static/rest-api.yml'], - cwd=here, - check=False, - ) run( [ "git",