From 21b9d4eda0047f66e377dcbe68e60284b4597344 Mon Sep 17 00:00:00 2001 From: Tom Fleet Date: Fri, 24 Sep 2021 12:18:29 +0100 Subject: [PATCH 1/2] Initial pass at the cookbook --- docs/cookbook.rst | 138 ++++++++++++++++++++++++++++++++++++++++++++++ docs/index.rst | 1 + 2 files changed, 139 insertions(+) create mode 100644 docs/cookbook.rst diff --git a/docs/cookbook.rst b/docs/cookbook.rst new file mode 100644 index 00000000..6b494876 --- /dev/null +++ b/docs/cookbook.rst @@ -0,0 +1,138 @@ +The Nox Cookbook +================ + +The What? +--------- + +A lot of people and a lot of projects use ``nox`` for their python automation powers. + +Some of these sessions are the classic "run pytest and linting", some are more unique and more interesting! + +The nox cookbook is a collection of these such sessions. + +``nox`` is super easy to get started with, and super powerful right out of the box. But when things get complex or you want to chain together some more powerful tasks, often the only examples can be found hunting around GitHub for novel ``nox`` sessions. + +The kind of sessions that make you think "I didn't know you could do that!" + +This cookbook is intended to be a centralized, community-driven repository of awesome ``nox`` sessions to act as a source of inspiration and a reference guide for nox's users. If you're doing something cool with ``nox``, why not add your session here? + + +Contributing a Session +---------------------- + +Anyone can contribute sessions to the cookbook. However, there are a few guiding principles you should keep in mind: + +* Your session should be interesting or unique, it should do something out of the ordinary or otherwise interesting. +* You should explain briefly what it does and why it's interesting. +* You should include the full session as a code block, if it's too large, try to include a minimal example. Bonus points if a user can copy and paste it into their ``noxfile.py`` and run it straight away! + + +And now on with the recipes... + +Recipes +------- + +Instant Dev Environment +^^^^^^^^^^^^^^^^^^^^^^^ + +A common sticking point in contributing to python projects (especially for beginners) is the problem of wrangling virtual environments and installing dependencies. + +Enter the ``dev`` nox session: + +.. code-block:: python + + import os + + import nox + + # It's a good idea to keep your dev session out of the default list + # so it's not run twice accidentally + nox.options.sessions = [] + + @nox.session + def dev(session: nox.Session) -> None: + """ + Sets up a python development environment for the project. + + This session will: + - Create a python virtualenv for the session + - Install the `virtualenv` cli tool into this environment + - Use `virtualenv` to create a global project virtual environment + - Invoke the python interpreter from the global project environment to install + the project and all it's development dependencies. + """ + + session.install("virtualenv") + # VENV_DIR here is a pathlib.Path location of the project virtualenv + # e.g. .venv + session.run("virtualenv", os.fsdecode(VENV_DIR), silent=True) + + python = os.fsdecode(VENV_DIR.joinpath("bin/python")) + + # Use the venv's interpreter to install the project along with + # all it's dev dependencies, this ensures it's installed in the right way + session.run(python, "-m", "pip", "install", "-e", ".[dev]", external=True) + +With this, a user can simply run ``nox -s dev`` and have their entire environment set up automatically! + + +The Auto-Release +^^^^^^^^^^^^^^^^ + +Releasing a new version of an open source project can be a real pain, with lots of intricate steps. Tools like `Bump2Version `_ really help here. + +Even more so with a sprinkling of ``nox``: + +.. code-block:: python + + import nox + + @nox.session + def release(session: nox.Session) -> None: + """ + Kicks off an automated release process by creating and pushing a new tag. + + Invokes bump2version with the posarg setting the version. + + Usage: + $ nox -s release -- [major|minor|patch] + """ + + allowed_args = {"major", "minor", "patch"} + n_args = len(session.posargs) + + # Ensure the correct args are passed + if n_args != 1: + session.error( + f"Only 1 session arg allowed, got {n_args}. Pass one of: {allowed_args}" + ) + + # If we get here, we know there's only 1 posarg + version = session.posargs.pop() + + if version not in allowed_args: + session.error( + f"Invalid argument: got {version!r}, expected one of: {allowed_args}" + ) + + # If we get here, we should be good to go + # Let's do a final check for safety + confirm = input( + f"You are about to bump the {version!r} version. Are you sure? [y/n]: " + ) + + # Abort on anything other than 'y' + if confirm.lower().strip() != "y": + session.error(f"You said no when prompted to bump the {version!r} version.") + + + session.install("bump2version") + + session.log(f"Bumping the {version!r} version") + session.run("bump2version", version) + + session.log("Pushing the new tag") + session.run("git", "push", external=True) + session.run("git", "push", "--tags", external=True) + +Now a simple ``nox -s release -- patch`` will automate your release (provided you have Bump2Version set up to change your files). This is especially powerful if you have a CI/CD pipeline set up! \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 59e51542..f32a5811 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,6 +8,7 @@ Welcome to Nox tutorial config usage + cookbook CONTRIBUTING CHANGELOG From 5d18e499f668e48d1604399ad8d32df125686c42 Mon Sep 17 00:00:00 2001 From: Tom Fleet Date: Sat, 2 Oct 2021 20:48:39 +0100 Subject: [PATCH 2/2] Update cookbook with review comments --- docs/cookbook.rst | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/docs/cookbook.rst b/docs/cookbook.rst index 6b494876..3ce96ad1 100644 --- a/docs/cookbook.rst +++ b/docs/cookbook.rst @@ -4,17 +4,17 @@ The Nox Cookbook The What? --------- -A lot of people and a lot of projects use ``nox`` for their python automation powers. +A lot of people and a lot of projects use Nox for their python automation powers. Some of these sessions are the classic "run pytest and linting", some are more unique and more interesting! -The nox cookbook is a collection of these such sessions. +The Nox cookbook is a collection of these such sessions. -``nox`` is super easy to get started with, and super powerful right out of the box. But when things get complex or you want to chain together some more powerful tasks, often the only examples can be found hunting around GitHub for novel ``nox`` sessions. +Nox is super easy to get started with, and super powerful right out of the box. But when things get complex or you want to chain together some more powerful tasks, often the only examples can be found hunting around GitHub for novel sessions. The kind of sessions that make you think "I didn't know you could do that!" -This cookbook is intended to be a centralized, community-driven repository of awesome ``nox`` sessions to act as a source of inspiration and a reference guide for nox's users. If you're doing something cool with ``nox``, why not add your session here? +This cookbook is intended to be a centralized, community-driven repository of awesome Nox sessions to act as a source of inspiration and a reference guide for nox's users. If you're doing something cool with Nox, why not add your session here? Contributing a Session @@ -24,10 +24,8 @@ Anyone can contribute sessions to the cookbook. However, there are a few guiding * Your session should be interesting or unique, it should do something out of the ordinary or otherwise interesting. * You should explain briefly what it does and why it's interesting. -* You should include the full session as a code block, if it's too large, try to include a minimal example. Bonus points if a user can copy and paste it into their ``noxfile.py`` and run it straight away! - -And now on with the recipes... +For general advice on how to contribute to Nox see our :doc:`CONTRIBUTING` guide Recipes ------- @@ -47,7 +45,7 @@ Enter the ``dev`` nox session: # It's a good idea to keep your dev session out of the default list # so it's not run twice accidentally - nox.options.sessions = [] + nox.options.sessions = [...] # Sessions other than 'dev' @nox.session def dev(session: nox.Session) -> None: @@ -81,7 +79,7 @@ The Auto-Release Releasing a new version of an open source project can be a real pain, with lots of intricate steps. Tools like `Bump2Version `_ really help here. -Even more so with a sprinkling of ``nox``: +Even more so with a sprinkling of Nox: .. code-block:: python @@ -97,23 +95,16 @@ Even more so with a sprinkling of ``nox``: Usage: $ nox -s release -- [major|minor|patch] """ - - allowed_args = {"major", "minor", "patch"} - n_args = len(session.posargs) - - # Ensure the correct args are passed - if n_args != 1: - session.error( - f"Only 1 session arg allowed, got {n_args}. Pass one of: {allowed_args}" - ) - - # If we get here, we know there's only 1 posarg - version = session.posargs.pop() - - if version not in allowed_args: - session.error( - f"Invalid argument: got {version!r}, expected one of: {allowed_args}" - ) + parser = argparse.ArgumentParser(description="Release a semver version.") + parser.add_argument( + "version", + type=str, + nargs=1, + help="The type of semver release to make.", + choices={"major", "minor", "patch"}, + ) + args: argparse.Namespace = parser.parse_args(args=session.posargs) + version: str = args.version.pop() # If we get here, we should be good to go # Let's do a final check for safety