diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 000000000..ef01f3f50 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,67 @@ +# This config uses industrial_ci (https://github.com/ros-industrial/industrial_ci.git). +# For troubleshooting, see readme (https://github.com/ros-industrial/industrial_ci/blob/master/README.rst) + +name: CI + +on: + workflow_dispatch: + pull_request: + push: + +jobs: + default: + strategy: + matrix: + env: + - IMAGE: master-source + - IMAGE: noetic-source + env: + DOCKER_IMAGE: moveit/moveit:${{ matrix.env.IMAGE }} + UNDERLAY: /root/ws_moveit/install + CATKIN_LINT: true + CCACHE_DIR: ${{ github.workspace }}/.ccache + BASEDIR: ${{ github.workspace }}/.work + CLANG_TIDY_BASE_REF: ${{ github.base_ref || github.ref }} + + name: ${{ matrix.env.IMAGE }}${{ matrix.env.CATKIN_LINT && ' + catkin_lint' || ''}}${{ matrix.env.CLANG_TIDY && ' + clang-tidy' || '' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + # The target directory cache doesn't include the source directory because + # that comes from the checkout. See "prepare target_ws for cache" task below + - name: cache target_ws + uses: pat-s/always-upload-cache@v2.1.3 + with: + path: ${{ env.BASEDIR }}/target_ws + key: ${{ env.CACHE_PREFIX }}-${{ github.run_id }} + restore-keys: ${{ env.CACHE_PREFIX }} + env: + CACHE_PREFIX: target_ws-${{ matrix.env.IMAGE }}-${{ hashFiles('**/CMakeLists.txt', '**/package.xml') }} + - name: cache ccache + uses: pat-s/always-upload-cache@v2.1.3 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ env.CACHE_PREFIX }}-${{ github.sha }}-${{ github.run_id }} + restore-keys: | + ${{ env.CACHE_PREFIX }}-${{ github.sha }} + ${{ env.CACHE_PREFIX }} + env: + CACHE_PREFIX: ccache-${{ matrix.env.IMAGE }} + + - name: industrial_ci + uses: ros-industrial/industrial_ci@master + env: ${{ matrix.env }} + + - name: upload test artifacts (on failure) + uses: actions/upload-artifact@v2 + if: failure() + with: + name: test-results + path: ${{ env.BASEDIR }}/target_ws/**/test_results/**/*.xml + - name: prepare target_ws for cache + if: ${{ always() }} + run: | + du -sh ${{ env.BASEDIR }}/target_ws + sudo find ${{ env.BASEDIR }}/target_ws -wholename '*/test_results/*' -delete + sudo rm -rf ${{ env.BASEDIR }}/target_ws/src ${{ env.BASEDIR }}/target_ws/logs + du -sh ${{ env.BASEDIR }}/target_ws diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml new file mode 100644 index 000000000..a30069147 --- /dev/null +++ b/.github/workflows/deploy.yaml @@ -0,0 +1,29 @@ +name: Build+Test+Deploy + +on: + workflow_dispatch: + push: + branches: + - master + +jobs: + default: + name: Build + Test + Deploy Website + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ros-tooling/setup-ros@v0.2 + with: + required-ros-distributions: noetic + - uses: actions/setup-python@v2 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '2.7' + - name: "Build+Test: Run htmlproofer.sh" + run: ./htmlproofer.sh + - name: Deploy + if: ${{ success() && github.event_name == 'push'}} + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./build/html diff --git a/.github/workflows/format.yaml b/.github/workflows/format.yaml new file mode 100644 index 000000000..bdb5cc2f7 --- /dev/null +++ b/.github/workflows/format.yaml @@ -0,0 +1,23 @@ +# This is a format job. Pre-commit has a first-party GitHub action, so we use +# that: https://github.com/pre-commit/action + +name: Format (pre-commit) + +on: + workflow_dispatch: + pull_request: + push: + +jobs: + pre-commit: + name: pre-commit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - name: Install clang-format-10 + run: sudo apt-get install clang-format-10 + - uses: rhaschke/install-catkin_lint-action@v1.0 + with: + distro: noetic + - uses: pre-commit/action@v2.0.0 diff --git a/.gitignore b/.gitignore index ebf332215..d7dbdd125 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,4 @@ doc/html build Gemfile native_build -*.gdb \ No newline at end of file +*.gdb diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..71b141cdb --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,55 @@ +# To use: +# +# pre-commit run -a +# +# Or: +# +# pre-commit install # (runs every time you commit in git) +# +# To update this file: +# +# pre-commit autoupdate +# +# See https://github.com/pre-commit/pre-commit + +repos: + # Standard hooks + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.4.0 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: check-json + - id: check-merge-conflict + - id: check-symlinks + - id: check-toml + - id: check-yaml + - id: debug-statements + - id: destroyed-symlinks + - id: detect-private-key + - id: end-of-file-fixer + - id: mixed-line-ending + - id: pretty-format-json + - id: trailing-whitespace + + - repo: https://github.com/psf/black + rev: 20.8b1 + hooks: + - id: black + + - repo: local + hooks: + - id: clang-format + name: clang-format + description: Format files with ClangFormat. + entry: clang-format-10 + language: system + files: \.(c|cc|cxx|cpp|frag|glsl|h|hpp|hxx|ih|ispc|ipp|java|js|m|proto|vert)$ + args: ['-fallback-style=none', '-i'] + - id: catkin_lint + name: catkin_lint + description: Check package.xml and cmake files + entry: catkin_lint . + language: system + always_run: true + pass_filenames: false diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7de54f9e5..000000000 --- a/.travis.yml +++ /dev/null @@ -1,42 +0,0 @@ -# Test build the MoveIt tutorials. Author: Dave Coleman -sudo: required -dist: xenial -language: ruby -rvm: - - 2.7 -python: - - "2.7" - -env: - global: - - SCRIPT=.moveit_ci/travis.sh - - ROS_DISTRO=noetic - - ROS_REPO=ros-testing - - CXXFLAGS="-Wall -Wextra -Wwrite-strings -Wunreachable-code -Wpointer-arith -Wredundant-decls" - - WARNINGS_OK=false - - UPSTREAM_WORKSPACE="https://github.com/ros-planning/moveit_visual_tools - https://github.com/ros-planning/panda_moveit_config" - matrix: - - SCRIPT=htmlproofer.sh - - TEST="clang-format catkin_lint" - - TEST="clang-tidy-fix" - - DOCKER_IMAGE=moveit/moveit:master-source ROS_REPO= - -before_script: - - git clone -q --depth=1 https://github.com/ros-planning/moveit_ci.git .moveit_ci - -script: - ./$SCRIPT - -deploy: - # Deploy to gh-pages branch - provider: pages - # Don't delete built files - skip-cleanup: true - # Add to Environment Variables section of Travis CI repository settings page - github-token: $GITHUB_TOKEN - # Only copy build output directory to gh-pages - local_dir: build/html - on: - branch: master - condition: $SCRIPT = htmlproofer.sh diff --git a/README.md b/README.md index 45486c8cc..2a748845d 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,11 @@ These tutorials use the [reStructuredText](http://www.sphinx-doc.org/en/stable/r All content in this repository is open source and released under the [BSD License v3](https://opensource.org/licenses/BSD-3-Clause). Each individual source code file should contain a copy of the license. -This repository is currently built automatically by two systems. Travis builds the documentation for Melodic and ROS Build Farm builds the documentation for older versions: -- [![Travis Status](https://travis-ci.org/ros-planning/moveit_tutorials.svg?branch=master)](https://travis-ci.org/ros-planning/moveit_tutorials) [Github Pages + Travis](https://ros-planning.github.io/moveit_tutorials/): latest -- [![ROS Melodic Build Farm Status](http://build.ros.org/buildStatus/icon?job=Mdoc__moveit_tutorials__ubuntu_bionic_amd64)](http://build.ros.org/job/Mdoc__moveit_tutorials__ubuntu_bionic_amd64/) [ROS Melodic Build Farm](http://docs.ros.org/melodic/api/moveit_tutorials/html/) -- [![ROS Kinetic Build Farm Status](http://build.ros.org/buildStatus/icon?job=Kdoc__moveit_tutorials__ubuntu_xenial_amd64)](http://build.ros.org/job/Kdoc__moveit_tutorials__ubuntu_xenial_amd64/) [ROS Kinetic Build Farm](http://docs.ros.org/kinetic/api/moveit_tutorials/html/) +This repository is currently built automatically by two systems. Github Actions builds the documentation for Noetic, and ROS Build Farm builds the documentation for older versions: + +- [ROS Noetic](https://ros-planning.github.io/moveit_tutorials/): [![CI](https://github.com/ros-planning/moveit_tutorials/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/ros-planning/moveit_tutorials/actions/workflows/ci.yaml?query=branch%3Amaster) [![Deploy](https://github.com/ros-planning/moveit_tutorials/actions/workflows/deploy.yaml/badge.svg?branch=master)](https://github.com/ros-planning/moveit_tutorials/actions/workflows/deploy.yaml?query=branch%3Amaster) [![Formatting](https://github.com/ros-planning/moveit_tutorials/actions/workflows/format.yaml/badge.svg?branch=master)](https://github.com/ros-planning/moveit_tutorials/actions/workflows/format.yaml?query=branch%3Amaster) +- [ROS Melodic](http://docs.ros.org/melodic/api/moveit_tutorials/html/): [![build farm](http://build.ros.org/buildStatus/icon?job=Mdoc__moveit_tutorials__ubuntu_bionic_amd64)](http://build.ros.org/job/Mdoc__moveit_tutorials__ubuntu_bionic_amd64/) +- [ROS Kinetic](http://docs.ros.org/kinetic/api/moveit_tutorials/html/): [![build farm](http://build.ros.org/buildStatus/icon?job=Kdoc__moveit_tutorials__ubuntu_xenial_amd64)](http://build.ros.org/job/Kdoc__moveit_tutorials__ubuntu_xenial_amd64/) ## Versions @@ -48,7 +49,7 @@ We rely on the community to keep these tutorials up to date and bug free. If you **Code Formatting** -* These tutorials use the same [style guidelines](http://moveit.ros.org/documentation/contributing/code/) as the MoveIt project. When modifying or adding to these tutorials, it is required that code is auto formatted using [clang-format](http://moveit.ros.org/documentation/contributing/code/). +* These tutorials use the same [style guidelines](http://moveit.ros.org/documentation/contributing/code/) as the MoveIt project. When modifying or adding to these tutorials, it is required that code is auto formatted using [clang-format](http://moveit.ros.org/documentation/contributing/code/). To check and apply our style guidelines we use [pre-commit](https://pre-commit.com/). * Tutorials should exemplify best coding practices. If a contribution wouldn't pass review in the MoveIt project, then it shouldn't pass review in the tutorials. * Relevant code should be included and explained using the ``.. tutorial-formatter::`` tag. * Irrelevant code should be excluded from the generated html using the ``BEGIN_TUTORIAL``, ``END_TUTORIAL``, ``BEGIN_SUB_TUTORIAL``, and ``END_SUB_TUTORIAL`` tags. @@ -62,6 +63,20 @@ We rely on the community to keep these tutorials up to date and bug free. If you * Tutorials should flow from show to tell with videos and demos at the beginning followed by explanations. * New tutorials should match the formatting, style and flow of existing tutorials whenever possible. +**pre-commit** + +pre-commit is a tool that is used in ``moveit_tutorials`` to check and apply style guidelines automatically. To install pre-commit into your system: + + pip3 install pre-commit + +In you catkin workspace, under ``moveit_tutorials`` directory you can install the git hooks like this: + + cd $CATKIN_WS/src/moveit_tutorials && pre-commit install + +With this pre-commit will automatically run and check a list of styling including clang-format, end of files and trailing whitespaces whenever you run ``git commit``. To run pre-commit any time other than ``git commit`` you can use the following command: + + cd $CATKIN_WS/src/moveit_tutorials && pre-commit run -a + ### Directory Structure * Each tutorial should live in its own subdirectory within the `./doc/ <>` directory. diff --git a/_scripts/tutorialformatter.py b/_scripts/tutorialformatter.py index 33d58282c..af735c6c4 100644 --- a/_scripts/tutorialformatter.py +++ b/_scripts/tutorialformatter.py @@ -73,7 +73,7 @@ def callback(): from __future__ import print_function -__version__ = '0.1.2' +__version__ = "0.1.2" import os from docutils.parsers import rst @@ -81,31 +81,37 @@ def callback(): from docutils.statemachine import string2lines from pygments.lexers import get_lexer_for_filename + class TutorialFormatterDirective(rst.Directive): has_content = False final_argument_whitespace = True required_arguments = 1 - option_spec = dict(shell=flag, prompt=flag, nostderr=flag, - in_srcdir=flag, extraargs=unchanged, - until=unchanged) + option_spec = dict( + shell=flag, + prompt=flag, + nostderr=flag, + in_srcdir=flag, + extraargs=unchanged, + until=unchanged, + ) def flatten_sub_tutorials(self, file_): lines = [] in_sub = False - begin_sub_tutorial = 'BEGIN_SUB_TUTORIAL' - end_sub_tutorial = 'END_SUB_TUTORIAL' - call_sub_tutorial = 'CALL_SUB_TUTORIAL' - sub_name = '' + begin_sub_tutorial = "BEGIN_SUB_TUTORIAL" + end_sub_tutorial = "END_SUB_TUTORIAL" + call_sub_tutorial = "CALL_SUB_TUTORIAL" + sub_name = "" subs = {} sub_lines = [] regular_lines = [] for line in file_: - begin_pos = line.find( begin_sub_tutorial ) + begin_pos = line.find(begin_sub_tutorial) if begin_pos != -1: - sub_name = line[begin_pos + len(begin_sub_tutorial) : ].strip() + sub_name = line[begin_pos + len(begin_sub_tutorial) :].strip() in_sub = True - elif line.find( end_sub_tutorial ) != -1 and in_sub: + elif line.find(end_sub_tutorial) != -1 and in_sub: in_sub = False subs[sub_name] = sub_lines sub_lines = [] @@ -115,15 +121,18 @@ def flatten_sub_tutorials(self, file_): regular_lines.append(line) flattened_lines = [] for line in regular_lines: - call_pos = line.find( call_sub_tutorial ) + call_pos = line.find(call_sub_tutorial) if call_pos != -1: - sub_name = line[call_pos + len(call_sub_tutorial) : ].strip() + sub_name = line[call_pos + len(call_sub_tutorial) :].strip() if sub_name in subs: - flattened_lines.extend( subs[sub_name] ) + flattened_lines.extend(subs[sub_name]) else: - print('tutorialformatter.py error: sub-tutorial %s not found.' % sub_name) + print( + "tutorialformatter.py error: sub-tutorial %s not found." + % sub_name + ) else: - flattened_lines.append( line ) + flattened_lines.append(line) return flattened_lines def run(self): @@ -132,23 +141,23 @@ def run(self): tag_len = 0 filepath = os.path.dirname(self.state.document.settings.env.docname) - absfilename = os.path.abspath(os.path.join( filepath, filename )) - if absfilename.endswith('.h'): - language = 'c++' - elif absfilename.endswith('CMakeLists.txt'): - language = 'cmake' + absfilename = os.path.abspath(os.path.join(filepath, filename)) + if absfilename.endswith(".h"): + language = "c++" + elif absfilename.endswith("CMakeLists.txt"): + language = "cmake" else: try: - language = get_lexer_for_filename( absfilename ).name.lower() - if language == 'text only': - language = 'none' + language = get_lexer_for_filename(absfilename).name.lower() + if language == "text only": + language = "none" except: - language = 'none' - code_prefix = '\n.. code-block:: ' + language + '\n\n' - code_suffix = '\n' + language = "none" + code_prefix = "\n.. code-block:: " + language + "\n\n" + code_suffix = "\n" print("tutorial-formatter running on " + absfilename) - file_ = open( absfilename, 'r' ) + file_ = open(absfilename, "r") text_to_process = "" current_block = "" in_code = False @@ -157,33 +166,33 @@ def run(self): lines = self.flatten_sub_tutorials(file_) for line in lines: if not in_tutorial: - begin_pos = line.find( 'BEGIN_TUTORIAL' ) + begin_pos = line.find("BEGIN_TUTORIAL") if begin_pos != -1: text_tag = line[:begin_pos].lstrip() - tag_len = len( text_tag ) + tag_len = len(text_tag) in_tutorial = True continue - if line.find( 'END_TUTORIAL' ) != -1: + if line.find("END_TUTORIAL") != -1: break stripped = line.lstrip() - if stripped.startswith( text_tag.strip() ): + if stripped.startswith(text_tag.strip()): if in_code: text_to_process += code_prefix + current_block + code_suffix current_block = "" in_code = False in_text = True addition = stripped[tag_len:] - if addition == '' or addition[-1] != '\n': - addition += '\n' + if addition == "" or addition[-1] != "\n": + addition += "\n" current_block += addition else: if in_text: text_to_process += current_block current_block = "" in_text = False - in_code = True # Code to show begins right after tagged text + in_code = True # Code to show begins right after tagged text if in_code: - current_block += ' ' + line + current_block += " " + line if in_code: text_to_process += code_prefix + current_block + code_suffix elif in_text: @@ -194,10 +203,11 @@ def run(self): # print(text_to_process) # print('= text_to_process') - lines = string2lines( text_to_process ) - self.state_machine.insert_input( lines, absfilename ) + lines = string2lines(text_to_process) + self.state_machine.insert_input(lines, absfilename) return [] + def setup(app): - app.add_directive('tutorial-formatter', TutorialFormatterDirective) + app.add_directive("tutorial-formatter", TutorialFormatterDirective) diff --git a/_themes/sphinx_rtd_theme/layout.html b/_themes/sphinx_rtd_theme/layout.html index bc463f3b7..8ed9779bf 100644 --- a/_themes/sphinx_rtd_theme/layout.html +++ b/_themes/sphinx_rtd_theme/layout.html @@ -101,7 +101,7 @@ - + {% include "version_dropdown.html" %} {% include "searchbox.html" %} @@ -155,7 +155,7 @@ - + {% if not embedded %}