From d22aa1a3275e380cea524683bd9b049c0a3a6ef2 Mon Sep 17 00:00:00 2001 From: Alex Davies Date: Tue, 28 May 2024 14:55:44 -0300 Subject: [PATCH] Added docks system --- .copier/answers.docs.yml | 5 ++ .github/workflows/build-docs.yaml | 44 ++++++++++++ .gitignore | 2 +- README.md | 11 ++- docs/Makefile | 20 ++++++ docs/README.md | 11 +++ docs/make.bat | 35 ++++++++++ docs/source/_static/custom.css | 34 +++++++++ docs/source/conf.py | 65 ++++++++++++++++++ docs/source/index.rst | 20 ++++++ .../source/logos/SPIRI_STLockup_Mixed_RGB.png | Bin 0 -> 14499 bytes 11 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 .copier/answers.docs.yml create mode 100644 .github/workflows/build-docs.yaml create mode 100644 docs/Makefile create mode 100644 docs/README.md create mode 100644 docs/make.bat create mode 100644 docs/source/_static/custom.css create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst create mode 100644 docs/source/logos/SPIRI_STLockup_Mixed_RGB.png diff --git a/.copier/answers.docs.yml b/.copier/answers.docs.yml new file mode 100644 index 0000000..d1c3d88 --- /dev/null +++ b/.copier/answers.docs.yml @@ -0,0 +1,5 @@ +# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY +_commit: v1.0.2 +_src_path: https://git.spirirobotics.com/Spiri/template-docs.git +author_name: Spiri Robotics +project_name: spiri-sdk diff --git a/.github/workflows/build-docs.yaml b/.github/workflows/build-docs.yaml new file mode 100644 index 0000000..7985db5 --- /dev/null +++ b/.github/workflows/build-docs.yaml @@ -0,0 +1,44 @@ +name: Build Docs + +on: + push: + +env: + REGISTRY: git.spirirobotics.com + IMAGE_NAME: ${{ github.repository }} + +jobs: + build: + runs-on: ubuntu-latest + container: sphinxdoc/sphinx-latexpdf + + steps: + - name: Install sphinx-rtd-theme + run: pip install sphinx-rtd-theme + - name: Install node so that custom actions work. + run : apt-get update && apt-get --yes install nodejs git + + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Build Docs + run: make html latexpdf + working-directory: docs # assuming your documentation is in a 'docs' folder + + - name: Save PDF Artifacts + run: mv docs/build/latex/*.pdf ${{ github.workspace }}/docs.pdf + + - name: Compress HTML + run: tar -czvf docs_html.tar.gz -C docs/build/html . + + - name: Upload Docs + uses: actions/upload-artifact@v3 + with: + name: docs_html.tar.gz + path: docs_html.tar.gz + + - name: Upload PDF + uses: actions/upload-artifact@v3 + with: + name: docs.pdf + path: docs.pdf diff --git a/.gitignore b/.gitignore index ff1c750..078841d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -spiri-sdk-home +docs/build/ diff --git a/README.md b/README.md index 72f11c2..34522bf 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Advanced users can also use the SDK as a docker image. It pairs well with integrate it with their existing linux workflows. ```bash -distrobox create --image git.spirirobotics.com/spiri/spiri-sdk-desktop:main +distrobox create --image git.spirirobotics.com/spiri/spiri-sdk-desktop:master distrobox enter spiri-sdk-desktop-main #You can optionally copy the standard SDK setup from /opt/spiri-sdk/user-home-skeleton/ # cp -r /opt/spiri-sdk/user-home-skeleton/* ~/ @@ -20,6 +20,15 @@ cd /opt/spiri-sdk/PX4-Autopilot/ make px4_sitl gazebo-classic #Start the simulator ``` +You can also run a full init system, and it's own docker container, using + +```bash +distrobox create --root \ + --image git.spirirobotics.com/spiri/spiri-sdk-desktop:master \ + --init \ + --unshare-all +``` + # Building ```bash diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..44b6013 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,11 @@ +If you have a correctly configured sphinx environment you can build this project +using `make html latexpdf`. + +You can also use nektos/act to build this project in the same way our build does. +```bash +cd ../ #Make sure you're in the project root, you should have a hidden folder +# named ./.github/workflows available. +act --artifact-server-path ./doc-build +``` + +Your compiled doc project will now be in the ./doc-build folder. diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..747ffb7 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/_static/custom.css b/docs/source/_static/custom.css new file mode 100644 index 0000000..cdc1a92 --- /dev/null +++ b/docs/source/_static/custom.css @@ -0,0 +1,34 @@ +.wy-side-nav-search { + background: #FFFFFF !important; +} + + +.wy-nav-side { + background-color: #FFFFFF !important; +} + + +/* Add borders and box-shadow */ +.wy-side-nav { + border: 1px solid #899CA3 !important; +} + +.logo { + width: 100px !important; +} + +.wy-menu-vertical a { + color: #899CA3 !important; /* Change to your desired color */ +} + +.document-title { + color: #000 !important; + font-size: 24px !important; + text-transform: uppercase !important; +} + +.icon-home { + font-weight: bold !important; + text-transform: uppercase !important; + color: #000 !important; +} diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..d5b77c9 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,65 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +import sphinx_rtd_theme + +project = "spiri-sdk" +copyright = "2024, Spiri Robotics" +author = "Spiri Robotics" + +html_logo = "logos/SPIRI_STLockup_Mixed_RGB.png" # For HTML output +html_logo_width = '200px' +latex_logo = "logos/SPIRI_STLockup_Mixed_RGB.png" +latex_logo_width = '5cm' + + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + "sphinx.ext.duration", + "sphinx.ext.doctest", + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", +] + + +numfig = True + +todo_include_todos = True +todo_emit_warnings = True +todo_link_only = True + + +templates_path = ["_templates"] +exclude_patterns = [] + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = "sphinx_rtd_theme" +html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + +html_static_path = ['_static'] + +html_css_files = [ + 'custom.css', +] + + +html_theme_options = { + 'collapse_navigation': True, + 'sticky_navigation': True, + 'navigation_depth': 4, #could be set to -1 if we want unlimited depth + 'includehidden': True, + 'titles_only': False +} + +latex_engine = "xelatex" +# Configure LaTeX options for PDF generation diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..e564e24 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,20 @@ +.. spiri-sdk documentation master file, created by + sphinx-quickstart on Wed Feb 14 11:51:45 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to spiri-sdk's documentation! +============================================ + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/source/logos/SPIRI_STLockup_Mixed_RGB.png b/docs/source/logos/SPIRI_STLockup_Mixed_RGB.png new file mode 100644 index 0000000000000000000000000000000000000000..e1a4800c7004200a51268dcea1a169e97e8051d5 GIT binary patch literal 14499 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