Skip to content

Add GHA workflow to run lint and tests #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a863690
add pyproject.toml
mfiedorowicz Aug 9, 2024
9821415
add docker-compose setup
mfiedorowicz Aug 9, 2024
8b1ee6b
add Makefile recipes for docker compose
mfiedorowicz Aug 9, 2024
c8a2e3d
add GHA workflow to run lint and test
mfiedorowicz Aug 9, 2024
bbc62c3
tidy up docker-compose.yaml
mfiedorowicz Aug 9, 2024
d911394
move workflow into correct directory
mfiedorowicz Aug 9, 2024
0a2f840
fix mounting of local_settings.py
mfiedorowicz Aug 9, 2024
d94c7b8
ignore missing docstrings checks
mfiedorowicz Aug 9, 2024
8404909
add step for building documentation
mfiedorowicz Aug 9, 2024
d3346aa
catch make docker-compose-test exit code (test)
mfiedorowicz Aug 9, 2024
e8ac7c8
catch make docker-compose-test exit code (test 2)
mfiedorowicz Aug 9, 2024
c2fadb6
tidy up make docker-compose-test
mfiedorowicz Aug 9, 2024
3134545
rename GHA job
mfiedorowicz Aug 9, 2024
31c6e87
ignore all missing docstrings
mfiedorowicz Aug 9, 2024
4751e8a
change workflow file ext
mfiedorowicz Aug 9, 2024
fecda42
Merge branch 'develop' into feat/gha-workflows-lint-test
mfiedorowicz Aug 12, 2024
b24b506
Merge branch 'develop' into feat/gha-workflows-lint-test
mfiedorowicz Aug 19, 2024
3b60250
run tests with more native way with matrix of python versions
mfiedorowicz Aug 19, 2024
111a641
fix matrix with python version
mfiedorowicz Aug 19, 2024
8632f4a
fix test command for plugin
mfiedorowicz Aug 19, 2024
114304f
list tests
mfiedorowicz Aug 19, 2024
ec39e30
comment out exclude-package-data from pyproject.toml
mfiedorowicz Aug 19, 2024
99c7a9a
tidy up
mfiedorowicz Aug 19, 2024
3c558a4
keep db when running tests
mfiedorowicz Aug 19, 2024
ee9bed5
Remove v4.1-beta1 tag
jeremystretch Sep 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/lint-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Lint and tests
on:
workflow_dispatch:
pull_request:
push:
branches:
- "!release"

concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false

permissions:
contents: write
checks: write
pull-requests: write

jobs:
tests:
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
matrix:
python: [ "3.10" ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .
pip install .[dev]
pip install .[test]
- name: Lint with Ruff
run: |
ruff check --output-format=github netbox_branching/
continue-on-error: true
- name: Test
run: |
make docker-compose-test
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
ifneq ($(shell docker compose version 2>/dev/null),)
DOCKER_COMPOSE := docker compose
else
DOCKER_COMPOSE := docker-compose
endif

.PHONY: docker-compose-up
docker-compose-up:
@$(DOCKER_COMPOSE) -f docker/docker-compose.yaml up -d

.PHONY: docker-compose-down
docker-compose-down:
@$(DOCKER_COMPOSE) -f docker/docker-compose.yaml down

.PHONY: docker-compose-test
docker-compose-test:
-@$(DOCKER_COMPOSE) -f docker/docker-compose.yaml run -u root --rm netbox ./manage.py test --keepdb netbox_branching
@$(MAKE) docker-compose-down
324 changes: 324 additions & 0 deletions docker/configuration/configuration.py

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions docker/configuration/extra.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
####
## This file contains extra configuration options that can't be configured
## directly through environment variables.
####

## Specify one or more name and email address tuples representing NetBox administrators. These people will be notified of
## application errors (assuming correct email settings are provided).
# ADMINS = [
# # ['John Doe', 'jdoe@example.com'],
# ]


## URL schemes that are allowed within links in NetBox
# ALLOWED_URL_SCHEMES = (
# 'file', 'ftp', 'ftps', 'http', 'https', 'irc', 'mailto', 'sftp', 'ssh', 'tel', 'telnet', 'tftp', 'vnc', 'xmpp',
# )

## Enable installed plugins. Add the name of each plugin to the list.
# from netbox.configuration.configuration import PLUGINS
# PLUGINS.append('my_plugin')

## Plugins configuration settings. These settings are used by various plugins that the user may have installed.
## Each key in the dictionary is the name of an installed plugin and its value is a dictionary of settings.
# from netbox.configuration.configuration import PLUGINS_CONFIG
# PLUGINS_CONFIG['my_plugin'] = {
# 'foo': 'bar',
# 'buzz': 'bazz'
# }


## Remote authentication support
# REMOTE_AUTH_DEFAULT_PERMISSIONS = {}


## By default uploaded media is stored on the local filesystem. Using Django-storages is also supported. Provide the
## class path of the storage driver in STORAGE_BACKEND and any configuration options in STORAGE_CONFIG. For example:
# STORAGE_BACKEND = 'storages.backends.s3boto3.S3Boto3Storage'
# STORAGE_CONFIG = {
# 'AWS_ACCESS_KEY_ID': 'Key ID',
# 'AWS_SECRET_ACCESS_KEY': 'Secret',
# 'AWS_STORAGE_BUCKET_NAME': 'netbox',
# 'AWS_S3_REGION_NAME': 'eu-west-1',
# }


## This file can contain arbitrary Python code, e.g.:
# from datetime import datetime
# now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
# BANNER_TOP = f'<marquee width="200px">This instance started on {now}.</marquee>'
28 changes: 28 additions & 0 deletions docker/configuration/ldap/extra.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
####
## This file contains extra configuration options that can't be configured
## directly through environment variables.
## All vairables set here overwrite any existing found in ldap_config.py
####

# # This Python script inherits all the imports from ldap_config.py
# from django_auth_ldap.config import LDAPGroupQuery # Imported since not in ldap_config.py

# # Sets a base requirement of membetship to netbox-user-ro, netbox-user-rw, or netbox-user-admin.
# AUTH_LDAP_REQUIRE_GROUP = (
# LDAPGroupQuery("cn=netbox-user-ro,ou=groups,dc=example,dc=com")
# | LDAPGroupQuery("cn=netbox-user-rw,ou=groups,dc=example,dc=com")
# | LDAPGroupQuery("cn=netbox-user-admin,ou=groups,dc=example,dc=com")
# )

# # Sets LDAP Flag groups variables with example.
# AUTH_LDAP_USER_FLAGS_BY_GROUP = {
# "is_staff": (
# LDAPGroupQuery("cn=netbox-user-ro,ou=groups,dc=example,dc=com")
# | LDAPGroupQuery("cn=netbox-user-rw,ou=groups,dc=example,dc=com")
# | LDAPGroupQuery("cn=netbox-user-admin,ou=groups,dc=example,dc=com")
# ),
# "is_superuser": "cn=netbox-user-admin,ou=groups,dc=example,dc=com",
# }

# # Sets LDAP Mirror groups variables with example groups
# AUTH_LDAP_MIRROR_GROUPS = ["netbox-user-ro", "netbox-user-rw", "netbox-user-admin"]
113 changes: 113 additions & 0 deletions docker/configuration/ldap/ldap_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
from importlib import import_module
from os import environ

import ldap
from django_auth_ldap.config import LDAPSearch


# Read secret from file
def _read_secret(secret_name, default=None):
try:
f = open('/run/secrets/' + secret_name, encoding='utf-8')
except OSError:
return default
else:
with f:
return f.readline().strip()


# Import and return the group type based on string name
def _import_group_type(group_type_name):
mod = import_module('django_auth_ldap.config')
try:
return getattr(mod, group_type_name)()
except:
return None


# Server URI
AUTH_LDAP_SERVER_URI = environ.get('AUTH_LDAP_SERVER_URI', '')

# The following may be needed if you are binding to Active Directory.
AUTH_LDAP_CONNECTION_OPTIONS = {
ldap.OPT_REFERRALS: 0
}

AUTH_LDAP_BIND_AS_AUTHENTICATING_USER = environ.get('AUTH_LDAP_BIND_AS_AUTHENTICATING_USER', 'False').lower() == 'true'

# Set the DN and password for the NetBox service account if needed.
if not AUTH_LDAP_BIND_AS_AUTHENTICATING_USER:
AUTH_LDAP_BIND_DN = environ.get('AUTH_LDAP_BIND_DN', '')
AUTH_LDAP_BIND_PASSWORD = _read_secret('auth_ldap_bind_password', environ.get('AUTH_LDAP_BIND_PASSWORD', ''))

# Set a string template that describes any user’s distinguished name based on the username.
AUTH_LDAP_USER_DN_TEMPLATE = environ.get('AUTH_LDAP_USER_DN_TEMPLATE', None)

# Enable STARTTLS for ldap authentication.
AUTH_LDAP_START_TLS = environ.get('AUTH_LDAP_START_TLS', 'False').lower() == 'true'

# Include this setting if you want to ignore certificate errors. This might be needed to accept a self-signed cert.
# Note that this is a NetBox-specific setting which sets:
# ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
LDAP_IGNORE_CERT_ERRORS = environ.get('LDAP_IGNORE_CERT_ERRORS', 'False').lower() == 'true'

# Include this setting if you want to validate the LDAP server certificates against a CA certificate directory on your server
# Note that this is a NetBox-specific setting which sets:
# ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, LDAP_CA_CERT_DIR)
LDAP_CA_CERT_DIR = environ.get('LDAP_CA_CERT_DIR', None)

# Include this setting if you want to validate the LDAP server certificates against your own CA.
# Note that this is a NetBox-specific setting which sets:
# ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, LDAP_CA_CERT_FILE)
LDAP_CA_CERT_FILE = environ.get('LDAP_CA_CERT_FILE', None)

AUTH_LDAP_USER_SEARCH_BASEDN = environ.get('AUTH_LDAP_USER_SEARCH_BASEDN', '')
AUTH_LDAP_USER_SEARCH_ATTR = environ.get('AUTH_LDAP_USER_SEARCH_ATTR', 'sAMAccountName')
AUTH_LDAP_USER_SEARCH_FILTER: str = environ.get(
'AUTH_LDAP_USER_SEARCH_FILTER', f'({AUTH_LDAP_USER_SEARCH_ATTR}=%(user)s)'
)

AUTH_LDAP_USER_SEARCH = LDAPSearch(
AUTH_LDAP_USER_SEARCH_BASEDN, ldap.SCOPE_SUBTREE, AUTH_LDAP_USER_SEARCH_FILTER
)

# This search ought to return all groups to which the user belongs. django_auth_ldap uses this to determine group
# heirarchy.

AUTH_LDAP_GROUP_SEARCH_BASEDN = environ.get('AUTH_LDAP_GROUP_SEARCH_BASEDN', '')
AUTH_LDAP_GROUP_SEARCH_CLASS = environ.get('AUTH_LDAP_GROUP_SEARCH_CLASS', 'group')

AUTH_LDAP_GROUP_SEARCH_FILTER: str = environ.get(
'AUTH_LDAP_GROUP_SEARCH_FILTER', f'(objectclass={AUTH_LDAP_GROUP_SEARCH_CLASS})'
)
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
AUTH_LDAP_GROUP_SEARCH_BASEDN, ldap.SCOPE_SUBTREE, AUTH_LDAP_GROUP_SEARCH_FILTER
)
AUTH_LDAP_GROUP_TYPE = _import_group_type(environ.get('AUTH_LDAP_GROUP_TYPE', 'GroupOfNamesType'))

# Define a group required to login.
AUTH_LDAP_REQUIRE_GROUP = environ.get('AUTH_LDAP_REQUIRE_GROUP_DN')

# Define special user types using groups. Exercise great caution when assigning superuser status.
AUTH_LDAP_USER_FLAGS_BY_GROUP = {}

if AUTH_LDAP_REQUIRE_GROUP is not None:
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
"is_active": environ.get('AUTH_LDAP_REQUIRE_GROUP_DN', ''),
"is_staff": environ.get('AUTH_LDAP_IS_ADMIN_DN', ''),
"is_superuser": environ.get('AUTH_LDAP_IS_SUPERUSER_DN', '')
}

# For more granular permissions, we can map LDAP groups to Django groups.
AUTH_LDAP_FIND_GROUP_PERMS = environ.get('AUTH_LDAP_FIND_GROUP_PERMS', 'True').lower() == 'true'
AUTH_LDAP_MIRROR_GROUPS = environ.get('AUTH_LDAP_MIRROR_GROUPS', '').lower() == 'true'

# Cache groups for one hour to reduce LDAP traffic
AUTH_LDAP_CACHE_TIMEOUT = int(environ.get('AUTH_LDAP_CACHE_TIMEOUT', 3600))

# Populate the Django user from the LDAP directory.
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": environ.get('AUTH_LDAP_ATTR_FIRSTNAME', 'givenName'),
"last_name": environ.get('AUTH_LDAP_ATTR_LASTNAME', 'sn'),
"email": environ.get('AUTH_LDAP_ATTR_MAIL', 'mail')
}
12 changes: 12 additions & 0 deletions docker/configuration/local_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from netbox_branching.utilities import DynamicSchemaDict
from netbox.configuration.configuration import DATABASE

# Wrap DATABASES with DynamicSchemaDict for dynamic schema support
DATABASES = DynamicSchemaDict({
'default': DATABASE,
})

# Employ our custom database router
DATABASE_ROUTERS = [
'netbox_branching.database.BranchAwareRouter',
]
55 changes: 55 additions & 0 deletions docker/configuration/logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# # Remove first comment(#) on each line to implement this working logging example.
# # Add LOGLEVEL environment variable to netbox if you use this example & want a different log level.
# from os import environ

# # Set LOGLEVEL in netbox.env or docker-compose.overide.yml to override a logging level of INFO.
# LOGLEVEL = environ.get('LOGLEVEL', 'INFO')

# LOGGING = {

# 'version': 1,
# 'disable_existing_loggers': False,
# 'formatters': {
# 'verbose': {
# 'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
# 'style': '{',
# },
# 'simple': {
# 'format': '{levelname} {message}',
# 'style': '{',
# },
# },
# 'filters': {
# 'require_debug_false': {
# '()': 'django.utils.log.RequireDebugFalse',
# },
# },
# 'handlers': {
# 'console': {
# 'level': LOGLEVEL,
# 'filters': ['require_debug_false'],
# 'class': 'logging.StreamHandler',
# 'formatter': 'simple'
# },
# 'mail_admins': {
# 'level': 'ERROR',
# 'class': 'django.utils.log.AdminEmailHandler',
# 'filters': ['require_debug_false']
# }
# },
# 'loggers': {
# 'django': {
# 'handlers': ['console'],
# 'propagate': True,
# },
# 'django.request': {
# 'handlers': ['mail_admins'],
# 'level': 'ERROR',
# 'propagate': False,
# },
# 'django_auth_ldap': {
# 'handlers': ['console',],
# 'level': LOGLEVEL,
# }
# }
# }
7 changes: 7 additions & 0 deletions docker/configuration/plugins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Add your plugins and plugin settings here.
# Of course uncomment this file out.

# To learn how to build images with your required plugins
# See https://github.com/netbox-community/netbox-docker/wiki/Using-Netbox-Plugins

PLUGINS = ["netbox_branching"]
Loading