diff --git a/.github/workflows/_build-docs.yml b/.github/workflows/_build-docs.yml
new file mode 100644
index 00000000..3c6c29ff
--- /dev/null
+++ b/.github/workflows/_build-docs.yml
@@ -0,0 +1,17 @@
+name: build-docs
+on:
+ workflow_call:
+jobs:
+ build:
+ name: Build docs
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: 3.12
+ - name: Install build dependencies
+ run: pip install --no-cache-dir -U pip .['docs']
+ - name: Build docs
+ run: ./scripts/cd.py --build-docs
\ No newline at end of file
diff --git a/.github/workflows/_deploy-docs.yml b/.github/workflows/_deploy-docs.yml
new file mode 100644
index 00000000..3d7ed0b4
--- /dev/null
+++ b/.github/workflows/_deploy-docs.yml
@@ -0,0 +1,25 @@
+name: deploy-docs
+on:
+ workflow_call:
+jobs:
+ upload:
+ name: Deploy docs to github pages
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Compare tag and package version
+ run: |
+ TAG=${GITHUB_REF#refs/*/}
+ VERSION=$(grep -Po '(?<=version = ")[^"]*' pyproject.toml)
+ if [ "$TAG" != "$VERSION" ]; then
+ echo "Tag value and package version are different: ${TAG} != ${VERSION}"
+ exit 1
+ fi
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: 3.12
+ - name: Install build dependencies
+ run: pip install --no-cache-dir -U pip .['docs']
+ - name: Deploy to github pages
+ run: ./scripts/cd.py --deploy-docs
diff --git a/.github/workflows/main-cicd.yml b/.github/workflows/main-cicd.yml
index 9bc6dc22..a7bc0aca 100644
--- a/.github/workflows/main-cicd.yml
+++ b/.github/workflows/main-cicd.yml
@@ -16,9 +16,14 @@ jobs:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
build-package:
uses: ./.github/workflows/_build-package.yml
+ build-docs:
+ uses: ./.github/workflows/_build-docs.yml
upload-package:
uses: ./.github/workflows/_upload-package.yml
if: startsWith(github.ref, 'refs/tags/')
- needs: [static-checks, integration-tests, build-package]
+ needs: [static-checks, integration-tests, build-package, build-docs]
secrets:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
+ deploy-docs:
+ uses: ./.github/workflows/_deploy-docs.yml
+ needs: [upload-package]
diff --git a/.gitignore b/.gitignore
index 61961588..ac851a23 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,15 @@
+# generic
__pycache__/
thehive4py.egg-info/
build/
dist/
-venv/
-tmp/
-# local garbage yet
-tests/resources/
-examples/
+# pytest
+.coverage
+coverage.xml
+
+# mkdocs
+site/
+
+# misc
+tmp/
diff --git a/LICENSE b/LICENSE
index 78103b04..621b7cf1 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2023 StrangeBee
+Copyright (c) 2024 StrangeBee
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index d5503182..19f19803 100644
--- a/README.md
+++ b/README.md
@@ -5,8 +5,11 @@
thehive4py - the de facto Python API client of TheHive
+
+
+
-
+
diff --git a/docs/img/strangebee.png b/docs/img/strangebee.png
new file mode 100644
index 00000000..9b11d2e9
Binary files /dev/null and b/docs/img/strangebee.png differ
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 00000000..65a0ce48
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,33 @@
+---
+title: Coming Soon!
+hide:
+ - toc
+ - navigation
+---
+#
+
+
+ TheHive4py
+
+
+
+
+
+ :material-bee:{ .strangebee .bluebee .upleftbee }
+ :material-bee:{ .strangebee .yellowbee .upbee }
+ :material-bee:{ .strangebee .bluebee .uprightbee }
+
+
Coming Soon!
+
+ :material-bee:{ .strangebee .yellowbee .downleftbee }
+ :material-bee:{ .strangebee .bluebee .downbee }
+ :material-bee:{ .strangebee .yellowbee .downrightbee }
+
+
+
+
+
Our bees are out buzzing to gather all the docs you need!
+
Check out our Quickstart in the meantime!
+
+
+
diff --git a/docs/styles/extra.css b/docs/styles/extra.css
new file mode 100644
index 00000000..7a77407c
--- /dev/null
+++ b/docs/styles/extra.css
@@ -0,0 +1,64 @@
+:root {
+ --md-primary-fg-color: #0049d4;
+ --md-accent-fg-color: #ffc72c;
+}
+
+@keyframes pulse {
+ 0%, 100% {
+ transform: scale(1);
+ }
+ 50% {
+ transform: scale(1.25);
+ }
+ }
+
+
+.coming-soon {
+ color: var(--md-primary-fg-color);
+ font-size: 1.5rem;
+ font-weight: bold;
+ transition: 0.75s;
+}
+
+.coming-soon:hover{
+ color: var(--md-accent-fg-color);
+ transition: 0.75s;
+}
+
+.upleftbee {
+ rotate: -90deg;
+}
+
+.upbee {
+ rotate: -45deg;
+}
+
+.uprightbee{
+ rotate: 0deg;
+}
+
+.downleftbee {
+ rotate: 180deg;
+}
+
+.downbee {
+ rotate: 135deg;
+}
+
+.downrightbee{
+ rotate: 90deg;
+}
+
+.yellowbee {
+ color: var(--md-accent-fg-color)
+}
+
+.bluebee {
+ color: var(--md-primary-fg-color)
+}
+
+.strangebee {
+ animation: pulse 2s infinite;
+ font-size: 1.5rem;
+ vertical-align: top !important;
+}
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 00000000..9c0d51e4
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,49 @@
+site_name: TheHive4py
+theme:
+ name: material
+ favicon: img/strangebee.png
+ logo: img/strangebee.png
+ features:
+ - navigation.footer
+ palette:
+ - media: "(prefers-color-scheme)"
+ toggle:
+ icon: material/lightbulb-auto
+ name: Switch to light mode
+ - media: '(prefers-color-scheme: light)'
+ scheme: default
+ primary: custom
+ accent: custom
+ toggle:
+ icon: material/lightbulb
+ name: Switch to dark mode
+ - media: '(prefers-color-scheme: dark)'
+ scheme: slate
+ primary: custom
+ accent: custom
+ toggle:
+ icon: material/lightbulb-outline
+ name: Switch to system preference
+extra_css:
+ - styles/extra.css
+repo_name: TheHive-Project/TheHive4py
+repo_url: https://github.com/TheHive-Project/TheHive4py
+markdown_extensions:
+ - attr_list
+ - md_in_html
+ - pymdownx.emoji:
+ emoji_index: !!python/name:material.extensions.emoji.twemoji
+ emoji_generator: !!python/name:material.extensions.emoji.to_svg
+extra:
+ social:
+ - icon: simple/discord
+ link: https://discord.com/invite/XhxG3vzM44
+ name: Discord
+ - icon: simple/github
+ link: https://github.com/TheHive-Project/TheHive4py
+ name: GitHub
+ - icon: simple/python
+ link: https://pypi.org/project/thehive4py/
+ name: PyPI
+
+
diff --git a/pyproject.toml b/pyproject.toml
index 99f373d7..7ddc9034 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -28,6 +28,7 @@ authors = [{ name = "Szabolcs Antal", email = "antalszabolcs01@gmail.com" }]
[project.optional-dependencies]
audit = ["bandit", "pip-audit"]
build = ["build", "twine"]
+docs = ["mkdocs", "mkdocs-material"]
lint = ["black", "flake8-pyproject", "mypy", "pre-commit"]
test = ["pytest", "pytest-cov"]
dev = ["thehive4py[audit, lint, test, build]"]
diff --git a/scripts/cd.py b/scripts/cd.py
index 039313a7..bf366e00 100755
--- a/scripts/cd.py
+++ b/scripts/cd.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
import argparse
import subprocess
-from typing import List
+from typing import Dict
def _run_subprocess(
@@ -23,13 +23,6 @@ def _run_subprocess(
exit(err.returncode)
-def run_all(quiet=False):
- print("Run all deployment tasks...")
- run_build(quiet=quiet)
- run_upload(quiet=quiet)
- print("All tasks succeeded!")
-
-
def run_build(quiet: bool):
print("Building thehive4py with the build module...")
_run_subprocess(
@@ -52,14 +45,34 @@ def run_upload(quiet: bool):
print("Successfully published thehive4py!")
-def build_run_options() -> List[dict]:
- return [
- {"name": "build", "help": "run build step", "func": run_build},
- {"name": "upload", "help": "run upload step", "func": run_upload},
- ]
+def run_build_docs(quiet: bool):
+ print("Building thehive4py docs...")
+ _run_subprocess(
+ command="mkdocs build --clean --strict",
+ quiet=quiet,
+ )
+ print("Successfully built thehive4py docs!")
-def parse_arguments(run_options: List[dict]):
+def run_deploy_docs(quiet: bool):
+ print("Deploying thehive4py docs to gh-pages...")
+ _run_subprocess(
+ command="mkdocs gh-deploy --force",
+ quiet=quiet,
+ )
+ print("Successfully deployed thehive4py docs to gh-pages!")
+
+
+def build_run_options() -> Dict[str, dict]:
+ return {
+ "build": {"help": "build the package locally", "func": run_build},
+ "upload": {"help": "upload the package to pypi", "func": run_upload},
+ "build-docs": {"help": "build the docs locally", "func": run_build_docs},
+ "deploy-docs": {"help": "deploy the docs to gh-pages", "func": run_deploy_docs},
+ }
+
+
+def parse_arguments(run_options: Dict[str, dict]):
parser = argparse.ArgumentParser(
prog="thehive4py-cd",
description="run all cd steps or use options to run cd steps selectively",
@@ -72,14 +85,21 @@ def parse_arguments(run_options: List[dict]):
help="silence verbose output",
)
- for run_option in run_options:
+ for run_option_name, run_option_attributes in run_options.items():
parser.add_argument(
- f"--{run_option['name']}",
- help=run_option["help"],
+ f"--{run_option_name.replace('_', '-')}",
+ help=run_option_attributes["help"],
action="store_true",
)
- return parser.parse_args()
+ args = parser.parse_args()
+
+ if not any(
+ getattr(args, run_option.replace("-", "_")) for run_option in run_options
+ ):
+ parser.error(f"provide at least one option from: {list(run_options)}")
+
+ return args
def main():
@@ -88,17 +108,17 @@ def main():
quiet = args.quiet
- selective_runs = [
- run_option["func"]
- for run_option in run_options
- if getattr(args, run_option["name"])
+ selected_run_funcs = [
+ run_option_attributes["func"]
+ for run_option_name, run_option_attributes in run_options.items()
+ if getattr(args, run_option_name.replace("-", "_"))
]
- if selective_runs:
- for run in selective_runs:
- run(quiet=quiet)
- else:
- run_all(quiet=quiet)
+ for run_func in selected_run_funcs:
+ run_func(quiet=quiet)
+ print()
+
+ print("Done!")
if __name__ == "__main__":