Skip to content

Commit

Permalink
Add Nox setup & setup-remotes commands + other improvements (#384)
Browse files Browse the repository at this point in the history
  • Loading branch information
ccordoba12 authored Sep 25, 2024
2 parents d153e12 + 23eba15 commit 32b9456
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 27 deletions.
36 changes: 25 additions & 11 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ Let us know if you have any further questions, and we look forward to your contr
- [Setting Up a Development Environment Manually](#setting-up-a-development-environment-manually)
- [Create and activate a fresh environment](#create-and-activate-a-fresh-environment)
- [Install dependencies](#install-dependencies)
- [Installing the Pre-Commit Hooks](#installing-the-pre-commit-hooks)
- [Add the upstream remote](#add-the-upstream-remote)
- [Installing and Using the Pre-Commit Hooks](#installing-and-using-the-pre-commit-hooks)
- [Building the Docs](#building-the-docs)
- [Build with Nox](#build-with-nox)
- [Build manually](#build-manually)
Expand Down Expand Up @@ -66,12 +67,6 @@ After cloning the repository, navigate to its new directory using the `cd` comma
cd spyder-docs
```

Finally, set the upstream remote to the official Spyder-Docs repo with:

```shell
git remote add upstream https://github.com/spyder-ide/spyder-docs.git
```



## Setting Up a Development Environment with Nox (Recommended)
Expand All @@ -97,12 +92,21 @@ or, if not using Conda,
python -m pip install nox
```

To check that Nox is installed and browse a list of commands (called "sessions") we provide through Nox and what they do, you can run
To check that Nox is installed and browse a list of commands (called "sessions") we provide through Nox and what they do, run

```shell
nox --list
```

Then, run the ``setup`` session, which performs the project's one-time setup steps; pass either ``--https`` or ``--ssh`` to specify how you'd like to push changes to GitHub.
If not sure, pass ``--https`` for now:

```shell
nox -s setup -- --https
```

You can always switch it later with ``nox -s setup-remotes -- --ssh``.



## Setting Up a Development Environment Manually
Expand Down Expand Up @@ -171,20 +175,30 @@ python -m pip install -r requirements.txt
```


### Add the upstream remote

Make sure to set the upstream Git remote to the official Spyder-Docs repo with:

```shell
git remote add upstream https://github.com/spyder-ide/spyder-docs.git
```



## Installing the Pre-Commit Hooks
## Installing and Using the Pre-Commit Hooks

This repository uses [Pre-Commit](https://pre-commit.com/) to install, configure and update a suite of pre-commit hooks that check for common problems and issues, and fix many of them automatically.
You'll need to install the pre-commit hooks before committing any changes, as they both auto-generate/update specific files and run a comprehensive series of checks to help you find likely errors and enforce the project's code quality guidelines and style guide.
They are also run on all pull requests, and will need to pass before your changes can be merged.

If you've [using Nox](#setting-up-a-development-environment-with-nox-recommended), it installs Pre-Commit in its own environment, and we provide our own simplified command to install the hooks:
If you've [using Nox](#setting-up-a-development-environment-with-nox-recommended), it installs Pre-Commit and its hooks for you when running ``nox -s setup`` (as above).
You can also install them with

```shell
nox -s install-hooks
```

If instead you've followed the [manual install approach](#install-dependencies), pre-commit will be installed directly in your local environment.
If you've followed the [manual install approach](#install-dependencies), Pre-Commit will be installed directly in your local environment.
To install the hooks, run the following from the root of this repo:

```shell
Expand Down
143 changes: 127 additions & 16 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@
nox.options.sessions = ["build"]
nox.options.default_venv_backend = "none"


CI = "CI" in os.environ
ORG_NAME = "spyder-ide"
REPO_NAME = "spyder-docs"
REPO_URL_HTTPS = "https://github.com/{user}/{repo}.git"
REPO_URL_SSH = "[email protected]:{user}/{repo}.git"

CANARY_COMMAND = ("sphinx-build", "--version")

BUILD_INVOCATION = ("python", "-m", "sphinx")
SOURCE_DIR = Path("doc").resolve()
BUILD_DIR = Path("doc/_build").resolve()
Expand All @@ -51,6 +52,8 @@
CONF_PY = SOURCE_DIR / "conf.py"
SCRIPT_DIR = Path("scripts").resolve()

CI = "CI" in os.environ


# ---- Helpers ---- #

Expand Down Expand Up @@ -89,6 +92,8 @@ def extract_option_values(options, option_names, *, split_csv=False):
"""Extract particular option values from a sequence of options."""
option_values = []
remaining_options = []
if isinstance(option_names, str):
option_names = [option_names]

save_next_option = False
for option in options:
Expand Down Expand Up @@ -196,8 +201,11 @@ def build_help(session):


def _run(session):
"""Run an arbitrary command in the project's venv."""
session.run(*session.posargs[1:])
"""Run an arbitrary command invocation in the project's venv."""
posargs = session.posargs[1:]
if not posargs:
session.error("Must pass a command invocation to run")
session.run(*posargs)


@nox.session()
Expand All @@ -209,14 +217,15 @@ def run(session):
def _clean(session):
"""Remove the build directory."""
print(f"Removing build directory {BUILD_DIR.as_posix()!r}")
ignore = session.posargs and session.posargs[0] in {"-i", "--ignore"}
ignore_flag = "--ignore"
should_ignore = ignore_flag in session.posargs

try:
shutil.rmtree(BUILD_DIR, ignore_errors=ignore)
shutil.rmtree(BUILD_DIR, ignore_errors=should_ignore)
except FileNotFoundError:
pass
except Exception:
print("\nError removing files; pass '-i'/'--ignore' flag to ignore\n")
print(f"\nError removing files; pass {ignore_flag!r} flag to ignore\n")
raise


Expand All @@ -226,13 +235,77 @@ def clean(session):
_clean(session)


# --- Set up --- #

def _setup_remotes(session):
"""Set up the origin and upstream remote repositories."""
remote_cmd = ["git", "remote"]
posargs = list(session.posargs[1:])
https = "--https" in posargs
ssh = "--ssh" in posargs
username_args = extract_option_values(posargs, "--username")[0]
if https == ssh:
session.error("Exactly one of '--https' or '--ssh' must be passed")

# Get current origin details
origin_url_cmd = (*remote_cmd, "get-url", "origin")
origin_url = session.run(
*origin_url_cmd, external=True, silent=True, log=False).strip()
if "https://" not in origin_url:
origin_url = origin_url.split(":")[-1]
origin_user, origin_repo = origin_url.split("/")[-2:]
if origin_repo.endswith(".git"):
origin_repo = origin_repo[:-4]

# Check username
if username_args:
origin_user = username_args[0].strip().lstrip("@")
elif origin_user.lower() == ORG_NAME.lower():
code_host = REPO_URL_HTTPS.split(":")[1].lstrip("/").split("/")[0]
session.warn(
"Origin remote currently set to upstream; should be your fork.\n"
f"To fix, fork it and pass --username <Your {code_host} username>"
)

# Set up remotes
existing_remotes = session.run(
*remote_cmd, external=True, silent=True, log=False).strip().split("\n")
for remote, user_name, repo_name in (
("origin", origin_user, origin_repo),
("upstream", ORG_NAME, REPO_NAME),
):
action = "set-url" if remote in existing_remotes else "add"
fetch_url = REPO_URL_HTTPS.format(user=user_name, repo=repo_name)
session.run(*remote_cmd, action, remote, fetch_url, external=True)

ssh_url = REPO_URL_SSH.format(user=user_name, repo=repo_name)
push_url = ssh_url if ssh else fetch_url
session.run(
*remote_cmd, "set-url", "--push", remote, push_url, external=True)

session.run("git", "fetch", "--all", external=True)


@nox.session(name="setup-remotes")
def setup_remotes(session):
"""Set up the Git remotes; pass --https or --ssh to specify URL type."""
session.notify("_execute", posargs=([_setup_remotes], *session.posargs))


@nox.session()
def setup(session):
"""Set up the project; pass --https or --ssh to specify Git URL type."""
session.notify(
"_execute",
posargs=([_setup_remotes, _install_hooks, _clean], *session.posargs),
)


# ---- Build ---- #

def _build(session):
"""Execute the docs build."""
sphinx_invocation = construct_sphinx_invocation(
posargs=session.posargs[1:])
session.run(*sphinx_invocation)
_docs(session)


@nox.session
Expand All @@ -242,6 +315,32 @@ def build(session):


def _autobuild(session):
"""Use Sphinx-Autobuild to rebuild the project and open in browser."""
_autodocs(session)


@nox.session
def autobuild(session):
"""Rebuild the project continuously as source files are changed."""
session.notify("_execute", posargs=([_autobuild], *session.posargs))


# --- Docs --- #

def _docs(session):
"""Execute the docs build."""
sphinx_invocation = construct_sphinx_invocation(
posargs=session.posargs[1:])
session.run(*sphinx_invocation)


@nox.session
def docs(session):
"""Build the documentation."""
session.notify("_execute", posargs=([_docs], *session.posargs))


def _autodocs(session):
"""Use Sphinx-Autobuild to rebuild the project and open in browser."""
session.install("sphinx-autobuild")

Expand All @@ -261,9 +360,9 @@ def _autobuild(session):


@nox.session
def autobuild(session):
"""Rebuild the project continuously as source files are changed."""
session.notify("_execute", posargs=([_autobuild], *session.posargs))
def autodocs(session):
"""Rebuild the docs continuously as source files are changed."""
session.notify("_execute", posargs=([_autodocs], *session.posargs))


def _build_languages(session):
Expand Down Expand Up @@ -298,20 +397,32 @@ def build_multilanguage(session):

# ---- Deploy ---- #

def _serve(_session=None):
def _serve(session=None):
"""Open the docs in a web browser."""
_serve_docs(session)


def _serve_docs(_session=None):
"""Open the docs in a web browser."""
webbrowser.open(HTML_INDEX_PATH.as_uri())


@nox.session
def serve(_session):
"""Display the project."""
"""Display the built project."""
_serve()


@nox.session(name="serve-docs")
def serve_docs(_session):
"""Display the rendered documentation."""
_serve_docs()


def _prepare_multiversion(_session=None):
"""Execute the pre-deployment steps for multi-version support."""
# pylint: disable=import-outside-toplevel
# pylint: disable=import-error

sys.path.append(str(SCRIPT_DIR))
import generateredirects
Expand Down

0 comments on commit 32b9456

Please sign in to comment.