Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f1fcdb3
Add first iteration of lint action
apockill Dec 4, 2024
2e493a4
Point to the dockerfile
apockill Dec 4, 2024
7c368b9
Woops. Forgot to actually run the linter
apockill Dec 4, 2024
9f55b61
Remove JS linter
apockill Dec 4, 2024
b00b3b8
Lint fixes
apockill Dec 4, 2024
c5c36a7
Test fixes
apockill Dec 4, 2024
b477f6f
Remove support for javascript
apockill Dec 4, 2024
366a717
Update cruft
apockill Dec 4, 2024
adbea0b
Remove dash from colcon test
apockill Dec 4, 2024
33ad607
Fix bash code that is failing lint
apockill Dec 4, 2024
2ae1556
Update template
apockill Dec 4, 2024
eb4aed5
Run separate test with safe.directory set
apockill Dec 4, 2024
0d94fe7
Check upstream template when linting
apockill Dec 4, 2024
2490b00
Add `cruft` as a dependency
apockill Dec 4, 2024
8e33cef
Separate linting vs checking cruft into two pipelines
apockill Dec 4, 2024
3eab7d6
Try to fix cloning errors
apockill Dec 4, 2024
a2df9c2
Try to fix cloning errors
apockill Dec 4, 2024
f77afa3
Don't bother copying build artifacts
apockill Dec 4, 2024
118a79f
Run tree
apockill Dec 4, 2024
e6f9e64
Update template
apockill Dec 4, 2024
5f6b129
Try not building
apockill Dec 4, 2024
0725644
Try copying the tests in too?
apockill Dec 4, 2024
bd34ebe
Let's try just building each time?
apockill Dec 4, 2024
4af5130
Try 3
apockill Dec 4, 2024
5e14f40
Try 4
apockill Dec 4, 2024
5209a01
Remove colcon build
apockill Dec 4, 2024
ede9853
Remove base packages
apockill Dec 4, 2024
30cdc4c
Try copying build in again...
apockill Dec 5, 2024
e2841fb
Update Template
apockill Dec 5, 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
7 changes: 4 additions & 3 deletions .cruft.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"template": "git@github.com:UrbanMachine/create-ros-app.git",
"commit": "a4e77fcc6f6764f18d0785c030c60dda90e17ed6",
"template": "https://github.com/UrbanMachine/create-ros-app.git",
"commit": "8c8e34317b3cf0db5459958d7a50accfd0cc93cd",
"checkout": null,
"context": {
"cookiecutter": {
"email": "alex@urbanmachine.build",
"github_username_or_org": "urbanmachine",
"dockerhub_username_or_org": "urbanmachine",
"project_name": "node_helpers",
"__project_name_slug": "node_helpers",
"project_description": "An opinionated ROS2 framework that minimizes boilerplate while maximizing reliability. Features intuitive APIs for parameter management, action handling, and error-resilient RPC. Designed by Urban Machine for safe and scalable robotics.",
"version": "0.5.0",
"license": "MIT",
Expand All @@ -17,7 +18,7 @@
"example_launch_profile": "node_helpers_showcase",
"example_package_version": "0.5.0",
"__example_messages_package_name": "node_helpers_msgs",
"_template": "git@github.com:UrbanMachine/create-ros-app.git"
"_template": "https://github.com/UrbanMachine/create-ros-app.git"
}
},
"directory": null
Expand Down
13 changes: 0 additions & 13 deletions .github/lint/lint_eslint.py

This file was deleted.

5 changes: 0 additions & 5 deletions .github/lint/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@
from .errors import CommandError
from .lint_clang_format import lint_clang_format
from .lint_darglint import lint_darglint
from .lint_eslint import lint_eslint
from .lint_mypy import lint_mypy
from .lint_ruff import lint_ruff_check, lint_ruff_format
from .lint_shellcheck import lint_shellcheck

PYTHON_LANGUAGE = "python"
JAVASCRIPT_LANGUAGE = "javascript"
CPP_LANGUAGE = "cpp"
BASH_LANGUAGE = "bash"
ALL_LANGUAGES = "all"
Expand All @@ -26,9 +24,6 @@
lint_darglint,
lint_mypy,
],
JAVASCRIPT_LANGUAGE: [
lint_eslint,
],
CPP_LANGUAGE: [
lint_clang_format,
],
Expand Down
1 change: 0 additions & 1 deletion .github/lint/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ def required_path(path_str: str) -> Path:

ROS_PATH = required_path("pkgs")
LINT_PATH = required_path(".github/lint")
JS_PATH = Path()
FIRMWARE_PATH = Path()
LAUNCH_PATH = required_path("launch-profiles")

Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

name: Lint

on: [ push ]

jobs:
check_lint:
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v4
- name: pip cache
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: lint-pip-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
lint-pip-
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade poetry
poetry install
- name: Install Bash dependencies
run: sudo apt-get install --yes shellcheck
- name: Lint
run: poetry run lint --languages all --mode check

check_upstream_template:
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v4
- name: pip cache
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: lint-pip-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
lint-pip-
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade poetry
poetry install
- name: Check Upstream Template
run: poetry run cruft check
138 changes: 138 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
name: Test

on: [ push ]

jobs:
# This job builds the Docker image that will be used in the following test job.
# It also publishes the image to the GitHub Container Registry, so every PR can
# have an up-to-date image by the name of ghcr.io/GITHUB_USERNAME/PROJECT_NAME:BRANCH_NAME
build-image:
runs-on: ubuntu-24.04
env:
BUILT_IMAGE_NAME: ghcr.io/urbanmachine/node_helpers
PROJECT_NAME: node_helpers

defaults:
run:
shell: bash
steps:
- name: Create A Unique Tag For This Image Based On Branch Name
id: prep
run: |
if [[ "${GITHUB_REF}" == "refs/heads/"* ]]
then
# This is a build on a branch
TAG=${GITHUB_REF#refs/heads/}
elif [[ "${GITHUB_REF}" == "refs/pull/"* ]]
then
# This is a PR build
TAG=${GITHUB_REF#refs/pull/}
elif [[ "${GITHUB_REF}" == "refs/tags/"* ]]
then
# This is a tagged build
TAG=${GITHUB_REF#refs/tags/}
else
echo "Unexpected reference format ${GITHUB_REF}"
exit 1
fi

# Remove slashes, since they're not allowed in Docker tags
TAG=$(echo "${TAG}" | sed 's#/#-#g')
echo "tagged_image=${BUILT_IMAGE_NAME}:${TAG}" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Load Previous Docker Layers Cache
uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
# Key is named differently to avoid collision
key: v1-${{ env.PROJECT_NAME }}-${{ runner.os }}-multi-buildx-${{ github.sha }}
restore-keys: v1-${{ env.PROJECT_NAME }}-${{ runner.os }}-multi-buildx
- name: Log in to GitHub Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Checkout
uses: actions/checkout@v4
with:
lfs: true
- name: Get Base Image Name
id: get_base_image
run: |
source .env
echo "base_image=${BASE_IMAGE}" >> $GITHUB_OUTPUT
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: docker/Dockerfile
push: true
tags: ${{ steps.prep.outputs.tagged_image }}
build-args: |
BASE_IMAGE=${{ steps.get_base_image.outputs.base_image }}
cache-from: type=local,src=/tmp/.buildx-cache
# Note the mode=max here
# More: https://github.com/moby/buildkit#--export-cache-options
# And: https://github.com/docker/buildx#--cache-tonametypetypekeyvalue
cache-to: type=local,mode=max,dest=/tmp/.buildx-cache-new
# This is done to avoid storing outdated build steps in the cache, since
# BuildKit never clears stuff out of the cache itself
- name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
outputs:
tagged_image: ${{ steps.prep.outputs.tagged_image }}

# This job runs the colcon tests for the project
ros-tests:
needs: build-image
runs-on: ubuntu-24.04
defaults:
run:
shell: bash
timeout-minutes: 40
container:
image: ${{needs.build-image.outputs.tagged_image}}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
env:
GITHUB_WORKSPACE: /repo/
steps:
- name: Install Git LFS
run: sudo apt-get update && sudo apt-get install git-lfs
- name: Checkout
uses: actions/checkout@v4
with:
lfs: true
- name: Fix git error in the following line
# Caused by an update to git that dislikes when users of different ID's touch
# the same git directory, which happens when using a docker runner in CI
# This fixes test reporting in the `Generate Test Report` section
# https://github.blog/2022-04-12-git-security-vulnerability-announced/
# https://github.com/actions/checkout/issues/760
run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
- name: Copy Python dependencies to github workspace
run: cp -r /robot/install install
- name: Copy Build output to github workspace
run: cp -r /robot/install build
- name: Move launch-profile files to /robot/launch-profiles so hardcoded paths work
run: cp -r ${GITHUB_WORKSPACE}/launch-profiles /robot/
- name: Run tests
run: |
enter-workspaces colcon test \
--base-paths pkgs \
--pytest-with-coverage \
--test-result-base test-results \
--pytest-args \
--durations=50
- name: Generate Test Report
uses: dorny/test-reporter@v1
if: always()
with:
name: "Test report"
path: test-results/**/*.xml
reporter: java-junit
- name: Report Codecov Coverage
uses: codecov/codecov-action@v3.1.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
5 changes: 2 additions & 3 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ services:
- ${VOLUMES_DIRECTORY:- 'set in .env'}/ros-nodes:/robot/persistent
# Mounts the 'launch-profiles/LAUNCH_PROFILE' directory into '/robot/launch-profile/'
# This way you can save configuration files from GUI's like rviz right back to your source dir
- "./launch-profiles/${LAUNCH_PROFILE:- 'set in docker/_shared'}:/robot/launch-profile/"
# LAUNCH_PROFILE is set in docker/_shared.sh
- "./launch-profiles/${LAUNCH_PROFILE}:/robot/launch-profile/"
# Necessary for display passthrough
- "/tmp/.X11-unix:/tmp/.X11-unix:rw"
# Necessary for PulseAudio passthrough
Expand Down Expand Up @@ -75,8 +76,6 @@ services:
loki:
image: grafana/loki:3.2.1
user: "root"
ports:
- 3100:3100
volumes:
- ${VOLUMES_DIRECTORY:- 'set in .env'}/loki:/loki
<<: *common-config
Expand Down
4 changes: 2 additions & 2 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ ENV NVIDIA_DRIVER_CAPABILITIES=all
# Set variables for caches
ENV APT_CACHE=/var/cache/apt
ENV PIP_CACHE=/root/.cache/pip
ENV BUILD_CACHE=/cache/build
ENV BUILD_CACHE=/colcon-build-cache/node_helpers/

# TODO: was opengl necessary?

Expand Down Expand Up @@ -116,7 +116,7 @@ RUN --mount=type=cache,target="${BUILD_CACHE}" restore-build-cache
# Build all packages, copying project files under a root `/robot/` directory in the container
COPY ../launch-profiles /robot/launch-profiles
COPY ../pkgs /robot/pkgs
RUN enter-workspaces colcon build --symlink-install
RUN enter-workspaces colcon build
RUN add-workspace /robot/install/setup.bash

# Move the build cache back into the Docker cache mount so it can be reused on
Expand Down
3 changes: 2 additions & 1 deletion docker/_shared.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ function is_stack_running() {
# Then, the stack will be brought down.
function deploy_and_wait {
# Start the stack non-blockingly, because logs are best accessed via the web interface
LAUNCH_PROFILE="${1}" docker compose up --detach
export LAUNCH_PROFILE="${1}"
docker compose up --detach

trap _catch_sigint INT

Expand Down
2 changes: 1 addition & 1 deletion docker/launch
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ set -o nounset
function usage {
echo "Usage: docker/launch [--no-pull] <launch-profile>" >&2
echo "Available launch profiles are:" >&2
ls -1 launch-profiles/ | sed 's/^/ - /' >&2
find launch-profiles/ -maxdepth 1 -type d >&2
echo "" >&2
echo "Read more about 'launch-profiles' under 'docs/about_template.md'" >&2
exit 1
Expand Down
9 changes: 6 additions & 3 deletions docker/utils/environment/restore-build-cache
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
#!/usr/bin/env bash

# Copies the build cache from `/cache` into a place where the build system can
# Copies the build cache from a special dir into a place where the build system can
# use it. Copying like this ensures that the build cache is present in the
# final image, which is necessary for packages containing messages.

set -o errexit
set -o pipefail
set -o nounset

if [[ ! -d "/cache/build" ]]; then
# This directory is mounted by the Dockerfile and is unique to each project.
BUILD_CACHE=/colcon-build-cache/node_helpers/

if [[ ! -d "${BUILD_CACHE}" ]]; then
echo "Build cache directory not mounted" >&2
exit 1
fi

rm -rf /robot/build
cp -r /cache/build /robot/build
cp -r ${BUILD_CACHE} /robot/build
9 changes: 6 additions & 3 deletions docker/utils/environment/save-build-cache
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ set -o nounset
# Makes `*` include hidden files
shopt -s dotglob

if [[ ! -d "/cache/build" ]]; then
# This directory is mounted by the Dockerfile and is unique to each project.
BUILD_CACHE=/colcon-build-cache/node_helpers/

if [[ ! -d "${BUILD_CACHE}" ]]; then
echo "Build cache directory not mounted" >&2
exit 1
fi

rm -rf /cache/build/*
cp -r /robot/build/. /cache/build/.
rm -rf ${BUILD_CACHE}*
cp -r /robot/build/. ${BUILD_CACHE}.
2 changes: 1 addition & 1 deletion docs/about_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This documentation walks through the features of the template, and how to use th
Here's a quick guide on the features of this template

### Scripts
- Linting and autoformatting for python (ruff), C++ (clangformat), bash (shellcheck), and javascript (eslint)
- Linting and autoformatting for python (ruff), C++ (clangformat), bash (shellcheck)

**Relevant Scripts:**
```shell
Expand Down
6 changes: 4 additions & 2 deletions pkgs/node_helpers/node_helpers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
"""**node_helpers**

An opinionated ROS2 framework that minimizes boilerplate while maximizing reliability. Features intuitive APIs for parameter management, action handling, and error-resilient RPC. Designed by Urban Machine for safe and scalable robotics.
"""
An opinionated ROS2 framework that minimizes boilerplate while maximizing reliability.
Features intuitive APIs for parameter management, action handling, and error-resilient
RPC. Designed by Urban Machine for safe and scalable robotics.
"""
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from pydantic import BaseModel
from pydantic_core import PydanticUndefined
from rcl_interfaces.msg import ParameterDescriptor, SetParametersResult, ParameterValue
from rcl_interfaces.msg import ParameterDescriptor, SetParametersResult
from rclpy.exceptions import ParameterAlreadyDeclaredException, ParameterException
from rclpy.node import Node
from rclpy.parameter import Parameter
Expand Down
Loading