diff --git a/.cookiecutter.json b/.cookiecutter.json
index 6e537e17..c90e2c72 100644
--- a/.cookiecutter.json
+++ b/.cookiecutter.json
@@ -8,7 +8,7 @@
"verbose_name": "Nautobot ChatOps App",
"app_slug": "nautobot-chatops",
"project_slug": "nautobot-app-chatops",
- "repo_url": "https://github.com/nautobot/nautobot-app-chatops/",
+ "repo_url": "https://github.com/nautobot/nautobot-app-chatops",
"base_url": "chatops",
"min_nautobot_version": "2.0.0",
"max_nautobot_version": "2.9999",
@@ -21,7 +21,7 @@
"_drift_manager": {
"template": "https://github.com/nautobot/cookiecutter-nautobot-app.git",
"template_dir": "nautobot-app",
- "template_ref": "refs/tags/nautobot-app-v2.1.0",
+ "template_ref": "refs/tags/nautobot-app-v2.2.0",
"cookie_dir": "",
"branch_prefix": "drift-manager",
"pull_request_strategy": "create",
@@ -29,7 +29,7 @@
"black"
],
"draft": true,
- "baked_commit_ref": "4b6c888ec08af5233332d01d66b9f71c2f9368a8"
+ "baked_commit_ref": "b221d6a21e9b9a07df4b85782af19053e5c6c624"
}
}
}
diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
index 31b4e282..cdba2d2a 100644
--- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
+++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
@@ -31,5 +31,4 @@
- [ ] Attached Screenshots, Payload Example
- [ ] Unit, Integration Tests
- [ ] Documentation Updates (when adding/changing features)
-- [ ] Example App Updates (when adding/changing features)
- [ ] Outline Remaining Work, Constraints from Design
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 66358568..17bd2cfa 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -24,7 +24,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v4"
+ uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Linting: black"
run: "poetry run invoke black"
bandit:
@@ -35,7 +35,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v4"
+ uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Linting: bandit"
run: "poetry run invoke bandit"
ruff:
@@ -46,7 +46,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v4"
+ uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Linting: ruff"
run: "poetry run invoke ruff"
check-docs-build:
@@ -57,7 +57,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v4"
+ uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Check Docs Build"
run: "poetry run invoke build-and-check-docs"
flake8:
@@ -68,7 +68,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v4"
+ uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Linting: flake8"
run: "poetry run invoke flake8"
poetry:
@@ -79,7 +79,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v4"
+ uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Checking: poetry lock file"
run: "poetry run invoke lock --check"
yamllint:
@@ -90,10 +90,10 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v4"
+ uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Linting: yamllint"
run: "poetry run invoke yamllint"
- pylint:
+ check-in-docker:
needs:
- "bandit"
- "ruff"
@@ -114,7 +114,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v4"
+ uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Set up Docker Buildx"
id: "buildx"
uses: "docker/setup-buildx-action@v3"
@@ -136,53 +136,13 @@ jobs:
run: "cp development/creds.example.env development/creds.env"
- name: "Linting: pylint"
run: "poetry run invoke pylint"
- check-migrations:
- needs:
- - "bandit"
- - "ruff"
- - "flake8"
- - "poetry"
- - "yamllint"
- - "black"
- runs-on: "ubuntu-22.04"
- strategy:
- fail-fast: true
- matrix:
- python-version: ["3.11"]
- nautobot-version: ["2.0.0"]
- env:
- INVOKE_NAUTOBOT_CHATOPS_PYTHON_VER: "${{ matrix.python-version }}"
- INVOKE_NAUTOBOT_CHATOPS_NAUTOBOT_VER: "${{ matrix.nautobot-version }}"
- steps:
- - name: "Check out repository code"
- uses: "actions/checkout@v4"
- - name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v4"
- - name: "Set up Docker Buildx"
- id: "buildx"
- uses: "docker/setup-buildx-action@v3"
- - name: "Build"
- uses: "docker/build-push-action@v5"
- with:
- builder: "${{ steps.buildx.outputs.name }}"
- context: "./"
- push: false
- load: true
- tags: "${{ env.APP_NAME }}/nautobot:${{ matrix.nautobot-version }}-py${{ matrix.python-version }}"
- file: "./development/Dockerfile"
- cache-from: "type=gha,scope=${{ matrix.nautobot-version }}-py${{ matrix.python-version }}"
- cache-to: "type=gha,scope=${{ matrix.nautobot-version }}-py${{ matrix.python-version }}"
- build-args: |
- NAUTOBOT_VER=${{ matrix.nautobot-version }}
- PYTHON_VER=${{ matrix.python-version }}
- - name: "Copy credentials"
- run: "cp development/creds.example.env development/creds.env"
+ - name: "Checking: App Config"
+ run: "poetry run invoke validate-app-config"
- name: "Checking: migrations"
run: "poetry run invoke check-migrations"
unittest:
needs:
- - "pylint"
- - "check-migrations"
+ - "check-in-docker"
strategy:
fail-fast: true
matrix:
@@ -204,7 +164,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v4"
+ uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Set up Docker Buildx"
id: "buildx"
uses: "docker/setup-buildx-action@v3"
@@ -240,7 +200,7 @@ jobs:
with:
fetch-depth: "0"
- name: "Setup environment"
- uses: "networktocode/gh-action-setup-poetry-environment@v4"
+ uses: "networktocode/gh-action-setup-poetry-environment@v6"
- name: "Check for changelog entry"
run: |
git fetch --no-tags origin +refs/heads/${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }}
@@ -257,7 +217,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Set up Python"
- uses: "actions/setup-python@v4"
+ uses: "actions/setup-python@v5"
with:
python-version: "3.11"
- name: "Install Python Packages"
@@ -292,7 +252,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Set up Python"
- uses: "actions/setup-python@v4"
+ uses: "actions/setup-python@v5"
with:
python-version: "3.11"
- name: "Install Python Packages"
diff --git a/README.md b/README.md
index 5af700d6..84579bd6 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
-
+
diff --git a/changes/8.housekeeping b/changes/8.housekeeping
new file mode 100644
index 00000000..653c54ac
--- /dev/null
+++ b/changes/8.housekeeping
@@ -0,0 +1 @@
+Re-baked from the latest template.
diff --git a/development/Dockerfile b/development/Dockerfile
index e3c3bec8..69d8a0f9 100644
--- a/development/Dockerfile
+++ b/development/Dockerfile
@@ -28,7 +28,7 @@ ENV INVOKE_NAUTOBOT_CHATOPS_LOCAL=true
# Since this is only used for development and we don't ship this container, pinning Poetry back is not expressly necessary
# We also don't need virtual environments in container
RUN which poetry || curl -sSL https://install.python-poetry.org | python3 - && \
- poetry config virtualenvs.create false
+ poetry config virtualenvs.create false
# !!! USE CAUTION WHEN MODIFYING LINES ABOVE
# -------------------------------------------------------------------------------------
diff --git a/development/app_config_schema.py b/development/app_config_schema.py
new file mode 100644
index 00000000..47009954
--- /dev/null
+++ b/development/app_config_schema.py
@@ -0,0 +1,64 @@
+"""App Config Schema Generator and Validator."""
+import json
+from importlib import import_module
+from os import getenv
+from pathlib import Path
+from urllib.parse import urlparse
+
+import jsonschema
+import toml
+from django.conf import settings
+from to_json_schema.to_json_schema import SchemaBuilder
+
+
+def _enrich_object_schema(schema, defaults, required):
+ schema["additionalProperties"] = False
+ for key, value in schema["properties"].items():
+ if required and key in required:
+ value["required"] = True
+ default_value = defaults and defaults.get(key, None)
+ if value["type"] == "object" and "properties" in value:
+ _enrich_object_schema(value, default_value, None)
+ elif default_value is not None:
+ value["default"] = default_value
+
+
+def _main():
+ pyproject = toml.loads(Path("pyproject.toml").read_text())
+ url = urlparse(pyproject["tool"]["poetry"]["repository"])
+ _, owner, repository = url.path.split("/")
+ package_name = pyproject["tool"]["poetry"]["packages"][0]["include"]
+ app_config = settings.PLUGINS_CONFIG[package_name] # type: ignore
+ schema_path = Path(package_name) / "app-config-schema.json"
+ command = getenv("APP_CONFIG_SCHEMA_COMMAND", "")
+ if command == "generate":
+ schema = {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": f"https://raw.githubusercontent.com/{owner}/{repository}/develop/{package_name}/app-config-schema.json",
+ "$comment": "TBD: Update $id, replace `develop` with the future release tag",
+ **SchemaBuilder().to_json_schema(app_config), # type: ignore
+ }
+ app_config = import_module(package_name).config
+ _enrich_object_schema(schema, app_config.default_settings, app_config.required_settings)
+ schema_path.write_text(json.dumps(schema, indent=4) + "\n")
+ print(f"\n==================\nGenerated schema:\n\n{schema_path}\n")
+ print(
+ "WARNING: Review and edit the generated file before committing.\n"
+ "\n"
+ "Its content is inferred from:\n"
+ "\n"
+ "- The current configuration in `PLUGINS_CONFIG`\n"
+ "- `NautobotAppConfig.default_settings`\n"
+ "- `NautobotAppConfig.required_settings`"
+ )
+ elif command == "validate":
+ schema = json.loads(schema_path.read_text())
+ jsonschema.validate(app_config, schema)
+ print(
+ f"\n==================\nValidated configuration using the schema:\n{schema_path}\nConfiguration is valid."
+ )
+ else:
+ raise RuntimeError(f"Unknown command: {command}")
+
+
+_main()
diff --git a/development/nautobot_config.py b/development/nautobot_config.py
index 52a474f4..06a7fb25 100644
--- a/development/nautobot_config.py
+++ b/development/nautobot_config.py
@@ -92,11 +92,11 @@
"disable_existing_loggers": False,
"formatters": {
"normal": {
- "format": "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)s :\n %(message)s",
+ "format": "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)s : %(message)s",
"datefmt": "%H:%M:%S",
},
"verbose": {
- "format": "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)-20s %(filename)-15s %(funcName)30s() :\n %(message)s",
+ "format": "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)-20s %(filename)-15s %(funcName)30s() : %(message)s",
"datefmt": "%H:%M:%S",
},
},
diff --git a/docs/admin/install.md b/docs/admin/install.md
index a432d036..5dcf3ddb 100644
--- a/docs/admin/install.md
+++ b/docs/admin/install.md
@@ -71,7 +71,12 @@ Set up your chosen chat platform:
!!! warning
Follow the [Nautobot App Installation Instructions](https://nautobot.readthedocs.io/en/stable/plugins/#installing-plugins) for complete and most recent guidelines.
-The App is a Python package available on PyPI, installable with `pip`:
+## Install Guide
+
+!!! note
+ Apps can be installed from the [Python Package Index](https://pypi.org/) or locally. See the [Nautobot documentation](https://docs.nautobot.com/projects/core/en/stable/user-guide/administration/installation/app-install/) for more details. The pip package name for this app is [`nautobot-chatops`](https://pypi.org/project/nautobot-chatops/).
+
+The app is available as a Python package via PyPI and can be installed with `pip`:
```shell
pip install nautobot-chatops
diff --git a/docs/dev/contributing.md b/docs/dev/contributing.md
index 1d03330e..30fa558d 100644
--- a/docs/dev/contributing.md
+++ b/docs/dev/contributing.md
@@ -181,33 +181,30 @@ these checks):
The branching policy includes the following tenets:
-- The `develop` branch is the primary branch to develop off of.
+- The `develop` branch is the branch of the next major and minor paired version planned.
- PRs intended to add new features should be sourced from the `develop` branch.
-- PRs intended to address bug fixes and security patches should be sourced from the `develop` branch.
-- PRs intended to add new features that break backward compatibility should be discussed before a PR is created.
+- PRs intended to fix issues in the Nautobot LTM compatible release should be sourced from the latest `ltm-` branch instead of `develop`.
-Nautobot ChatOps app will observe semantic versioning, as of 1.0. This may result in a quick turn around in minor versions to keep pace with an ever-growing feature set.
+Nautobot ChatOps App will observe semantic versioning, as of 1.0. This may result in a quick turnaround in minor versions to keep pace with an ever growing feature set.
## Release Policy
-Nautobot ChatOps currently has no intended scheduled release schedule, and will release new features in minor versions.
+Nautobot ChatOps App has currently no intended scheduled release schedule, and will release new features in minor versions.
-When a new release of any kind (e.g. from `develop` to `main`, or a release of a `stable-.`) is created the following should happen.
+When a new release, from `develop` to `main`, is created the following should happen.
-- A release PR is created:
- - Add and/or update to the changelog in `docs/admin/release_notes/version_..md` file to reflect the changes.
- - Update the mkdocs.yml file to include updates when adding a new release_notes version file.
- - Change the version from `..-beta` to `..` in `pyproject.toml`.
- - Set the PR to the proper branch, e.g. either `main` or `stable-.`.
+- A release PR is created from `develop` with:
+ - Update the release notes in `docs/admin/release_notes/version_..md` file to reflect the changes.
+ - Change the version from `..-beta` to `..` in `pyproject.toml`.
+ - Set the PR to the `main` branch.
- Ensure the tests for the PR pass.
- Merge the PR.
- Create a new tag:
- - The tag should be in the form of `v..`.
- - The title should be in the form of `v..`.
- - The description should be the changes that were added to the `version_..md` document.
-- If merged into `main`, then push from `main` to `develop`, in order to retain the merge commit created when the PR was merged.
-- If there is a new `.`, create a `stable-.` for the **previous** version, so that security updates to old versions may be applied more easily.
-- A post release PR is created:
- - Change the version from `..` to `..-beta` in `pyproject.toml`.
- - Set the PR to the proper branch, e.g. either `develop` or `stable-.`.
- - Once tests pass, merge.
+ - The tag should be in the form of `v..`.
+ - The title should be in the form of `v..`.
+ - The description should be the changes that were added to the `version_..md` document.
+- If merged into `main`, then push from `main` to `develop`, in order to retain the merge commit created when the PR was merged
+- A post release PR is created with:
+ - Change the version from `..` to `..-beta` in both `pyproject.toml` and `nautobot.__init__.__version__`.
+ - Set the PR to the proper branch, `develop`.
+ - Once tests pass, merge.
diff --git a/docs/dev/dev_environment.md b/docs/dev/dev_environment.md
index 9a9a458e..621c4ea2 100644
--- a/docs/dev/dev_environment.md
+++ b/docs/dev/dev_environment.md
@@ -82,7 +82,7 @@ nautobot-server migrate
!!! note
If you want to develop on the latest develop branch of Nautobot, run the following command: `poetry add --optional git+https://github.com/nautobot/nautobot@develop`. After the `@` symbol must match either a branch or a tag.
-You can now run `nautobot-server` commands as you would from the [Nautobot documentation](https://nautobot.readthedocs.io/en/latest/) for example to start the development server:
+You can now run `nautobot-server` commands as you would from the [Nautobot documentation](https://docs.nautobot.com/projects/core/en/stable/user-guide/administration/tools/nautobot-server/) for example to start the development server:
```shell
nautobot-server runserver 0.0.0.0:8080 --insecure
@@ -478,3 +478,21 @@ To run an individual test, you can run any or all of the following:
➜ invoke ruff
➜ invoke pylint
```
+
+### App Configuration Schema
+
+In the package source, there is the `nautobot_chatops/app-config-schema.json` file, conforming to the [JSON Schema](https://json-schema.org/) format. This file is used to validate the configuration of the app in CI pipelines.
+
+If you make changes to `PLUGINS_CONFIG` or the configuration schema, you can run the following command to validate the schema:
+
+```bash
+invoke validate-app-config
+```
+
+To generate the `app-config-schema.json` file based on the current `PLUGINS_CONFIG` configuration, run the following command:
+
+```bash
+invoke generate-app-config-schema
+```
+
+This command can only guess the schema, so it's up to the developer to manually update the schema as needed.
diff --git a/docs/user/app_overview.md b/docs/user/app_overview.md
index 0e8a188f..e27cfd55 100644
--- a/docs/user/app_overview.md
+++ b/docs/user/app_overview.md
@@ -1,6 +1,6 @@
# App Overview
-This document provides an overview of the App including critical information and import considerations when applying it to your Nautobot environment.
+This document provides an overview of the App including critical information and important considerations when applying it to your Nautobot environment.
!!! note
Throughout this documentation, the terms "app" and "plugin" will be used interchangeably.
diff --git a/mkdocs.yml b/mkdocs.yml
index 804d4f31..73677dc0 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -81,7 +81,11 @@ markdown_extensions:
anchor_linenums: true
- "pymdownx.inlinehilite"
- "pymdownx.snippets"
- - "pymdownx.superfences"
+ - "pymdownx.superfences":
+ custom_fences:
+ - name: "mermaid"
+ class: "mermaid"
+ format: !!python/name:pymdownx.superfences.fence_code_format
- "footnotes"
plugins:
- "search"
diff --git a/nautobot_chatops/app-config-schema.json b/nautobot_chatops/app-config-schema.json
new file mode 100644
index 00000000..27ba77dd
--- /dev/null
+++ b/nautobot_chatops/app-config-schema.json
@@ -0,0 +1 @@
+true
diff --git a/poetry.lock b/poetry.lock
index 88348e98..27b63337 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand.
[[package]]
name = "aiodns"
@@ -4463,6 +4463,20 @@ files = [
{file = "texttable-1.6.7.tar.gz", hash = "sha256:290348fb67f7746931bcdfd55ac7584ecd4e5b0846ab164333f0794b121760f2"},
]
+[[package]]
+name = "to-json-schema"
+version = "1.0.1"
+description = ""
+optional = false
+python-versions = "*"
+files = [
+ {file = "to_json_schema-1.0.1-py3-none-any.whl", hash = "sha256:5708663f1c81815e4ff01fce910ac32ee3964d0c6b3587fd4fff2e38d5c9aa7b"},
+ {file = "to_json_schema-1.0.1.tar.gz", hash = "sha256:ec747bd5129256dd571105f66a7bc9a4546228cd5e5fbf5e06dc9776e255400e"},
+]
+
+[package.extras]
+testing = ["pytest", "pytest-cov", "setuptools"]
+
[[package]]
name = "toml"
version = "0.10.2"
@@ -4846,24 +4860,6 @@ files = [
{file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"},
]
-[[package]]
-name = "yamllint"
-version = "1.32.0"
-description = "A linter for YAML files."
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "yamllint-1.32.0-py3-none-any.whl", hash = "sha256:d97a66e48da820829d96077d76b8dfbe6c6140f106e558dae87e81ac4e6b30b7"},
- {file = "yamllint-1.32.0.tar.gz", hash = "sha256:d01dde008c65de5b235188ab3110bebc59d18e5c65fc8a58267cd211cd9df34a"},
-]
-
-[package.dependencies]
-pathspec = ">=0.5.3"
-pyyaml = "*"
-
-[package.extras]
-dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"]
-
[[package]]
name = "yarl"
version = "1.9.2"
@@ -4980,4 +4976,4 @@ panorama = ["defusedxml", "ipaddr", "netmiko", "netutils", "pan-os-python"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.8,<3.12"
-content-hash = "9edc678921261739f715585db93b205eb9d4e92b525c11a27d87dbe7625d1196"
+content-hash = "352d2cdc13f37b487004c249b50f331e5dfeec1aa37bed959a1da26a08348a82"
diff --git a/pyproject.toml b/pyproject.toml
index 77230393..163d94ed 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,6 +7,7 @@ license = "Apache-2.0"
readme = "README.md"
homepage = "https://github.com/nautobot/nautobot-app-chatops/"
repository = "https://github.com/nautobot/nautobot-app-chatops/"
+documentation = "https://docs.nautobot.com/projects/chatops/en/latest/"
keywords = ["nautobot", "nautobot-app", "nautobot-plugin"]
classifiers = [
"Intended Audience :: Developers",
@@ -92,7 +93,8 @@ requests-mock = "^1.9.3"
ruff = "*"
toml = "*"
towncrier = "~23.6.0"
-yamllint = "*"
+to-json-schema = "*"
+jsonschema = "*"
[tool.poetry.extras]
all = [
@@ -257,7 +259,7 @@ requires = ["poetry_core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.towncrier]
-package = "nautobot"
+package = "nautobot_chatops"
directory = "changes"
filename = "docs/admin/release_notes/version_X.Y.md"
template = "development/towncrier_template.j2"
diff --git a/tasks.py b/tasks.py
index 8891db05..62dad57a 100644
--- a/tasks.py
+++ b/tasks.py
@@ -151,15 +151,27 @@ def docker_compose(context, command, **kwargs):
def run_command(context, command, **kwargs):
"""Wrapper to run a command locally or inside the nautobot container."""
if is_truthy(context.nautobot_chatops.local):
+ if "command_env" in kwargs:
+ kwargs["env"] = {
+ **kwargs.get("env", {}),
+ **kwargs.pop("command_env"),
+ }
context.run(command, **kwargs)
else:
# Check if nautobot is running, no need to start another nautobot container to run a command
docker_compose_status = "ps --services --filter status=running"
results = docker_compose(context, docker_compose_status, hide="out")
if "nautobot" in results.stdout:
- compose_command = f"exec nautobot {command}"
+ compose_command = "exec"
else:
- compose_command = f"run --rm --entrypoint '{command}' nautobot"
+ compose_command = "run --rm --entrypoint=''"
+
+ if "command_env" in kwargs:
+ command_env = kwargs.pop("command_env")
+ for key, value in command_env.items():
+ compose_command += f' --env="{key}={value}"'
+
+ compose_command += f" -- nautobot {command}"
pty = kwargs.pop("pty", True)
@@ -329,15 +341,22 @@ def logs(context, service="", follow=False, tail=0):
# ------------------------------------------------------------------------------
# ACTIONS
# ------------------------------------------------------------------------------
-@task(help={"file": "Python file to execute"})
-def nbshell(context, file=""):
+@task(
+ help={
+ "file": "Python file to execute",
+ "env": "Environment variables to pass to the command",
+ "plain": "Flag to run nbshell in plain mode (default: False)",
+ },
+)
+def nbshell(context, file="", env={}, plain=False):
"""Launch an interactive nbshell session."""
command = [
"nautobot-server",
"nbshell",
+ "--plain" if plain else "",
f"< '{file}'" if file else "",
]
- run_command(context, " ".join(command), pty=not bool(file))
+ run_command(context, " ".join(command), pty=not bool(file), command_env=env)
@task
@@ -672,7 +691,7 @@ def pylint(context):
def autoformat(context):
"""Run code autoformatting."""
black(context, autoformat=True)
- ruff(context, action="both", fix=True)
+ ruff(context, fix=True)
@task(
@@ -800,6 +819,8 @@ def tests(context, failfast=False, keepdb=False, lint_only=False):
pylint(context)
print("Running mkdocs...")
build_and_check_docs(context)
+ print("Checking app config schema...")
+ validate_app_config(context)
if not lint_only:
print("Running unit tests...")
unittest(context, failfast=failfast, keepdb=keepdb)
@@ -807,6 +828,29 @@ def tests(context, failfast=False, keepdb=False, lint_only=False):
print("All tests have passed!")
+@task
+def generate_app_config_schema(context):
+ """Generate the app config schema from the current app config.
+
+ WARNING: Review and edit the generated file before committing.
+
+ Its content is inferred from:
+
+ - The current configuration in `PLUGINS_CONFIG`
+ - `NautobotAppConfig.default_settings`
+ - `NautobotAppConfig.required_settings`
+ """
+ start(context, service="nautobot")
+ nbshell(context, file="development/app_config_schema.py", env={"APP_CONFIG_SCHEMA_COMMAND": "generate"})
+
+
+@task
+def validate_app_config(context):
+ """Validate the app config based on the app config schema."""
+ start(context, service="nautobot")
+ nbshell(context, plain=True, file="development/app_config_schema.py", env={"APP_CONFIG_SCHEMA_COMMAND": "validate"})
+
+
# ------------------------------------------------------------------------------
# APP CUSTOM
# ------------------------------------------------------------------------------