Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 2 additions & 9 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
This PR adds/fixes/refactors ...

### Firmware image size difference
<!-- Title this PR like a commit: <type>(<scope>): <summary>. See docs/CONTRIBUTING.md. -->

<!-- We don't automatically evaluate the firmware size difference yet. Please, do it manually. -->

- dronecan_v2: ? -> ? (+?)
- dronecan_v3: ? -> ? (+?)
- cyphal_v2: ? -> ? (+?)
- cyphal_v3: ? -> ? (+?)
This PR adds/fixes/refactors ...

### Test coverage

Expand Down
13 changes: 9 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,19 @@ jobs:
shell: bash
run: make $BUILD_TARGET

# Only vX.Y.Z tags are releases. Other tags (e.g. cubemx-v0.1.0) must not deploy.
- name: Check for a release tag
shell: bash
run: |
if [[ "${{ github.ref }}" =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "IS_RELEASE_TAG=true" >> "$GITHUB_ENV"
fi

- name: Deploy binaries to Telegram
if: >
matrix.runner == 'ubuntu-24.04' &&
github.repository == 'RaccoonlabDev/mini_v2_node' &&
(
github.ref_name == github.event.repository.default_branch ||
startsWith(github.ref, 'refs/tags/')
)
env.IS_RELEASE_TAG == 'true'
uses: PonomarevDA/telegram-upload@v1
with:
bot_token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
Expand Down
10 changes: 10 additions & 0 deletions .sonarcloud.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SonarCloud Automatic Analysis configuration.
#
# Automatic Analysis reads this file only. It ignores sonar-project.properties,
# which is why the previous configuration had no effect and the whole repository
# was scanned, submodules included.
#
# Src is the code we own. Libs/ and scripts/tools/ are git submodules: their
# findings cannot be fixed from this repository, and they accounted for every
# reported bug and all but one vulnerability.
sonar.sources=Src
10 changes: 9 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,13 @@
- When using as a framework (submodule, custom boards/targets), follow [docs/framework.md](docs/framework.md).
- Prebuilt CubeMX HAL archives (CI without CubeMX): [docs/cubemx.md](docs/cubemx.md).
- Firmware contract: [docs/embedded_firmware_contract.md](docs/embedded_firmware_contract.md).
- Match the code style: [docs/code_style.md](docs/code_style.md).
- Commit naming and code style: [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md).
- When writing docs, follow [docs/documentation_guidelines.md](docs/documentation_guidelines.md).
- Treat Git as read-only: you may run inspection commands like `git status`,
`git diff`, and `git log`, but never modify Git state, including
staging/unstaging files, committing, branching, rebasing, resetting, checking
out, stashing, tagging, or changing config.
- Never touch remotes: no `git push`, `git pull`, `git fetch`, or any
equivalent through other tools (`gh`, scripts, CI triggers). This applies to
every branch, including the current one. Pushing is done only by a human,
ever.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![CI](https://github.com/RaccoonlabDev/mini_v2_node/actions/workflows/ci.yml/badge.svg)](https://github.com/RaccoonlabDev/mini_v2_node/actions/workflows/ci.yml) [![SonarCloud](https://github.com/RaccoonlabDev/mini_v2_node/actions/workflows/sonarcloud.yml/badge.svg)](https://github.com/RaccoonlabDev/mini_v2_node/actions/workflows/sonarcloud.yml) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=RaccoonlabDev_mini_v2_node&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=RaccoonlabDev_mini_v2_node) [![LOC](https://sonarcloud.io/api/project_badges/measure?project=RaccoonlabDev_mini_v2_node&metric=ncloc)](https://sonarcloud.io/summary/new_code?id=RaccoonlabDev_mini_v2_node)
[![CI](https://github.com/RaccoonlabDev/mini_v2_node/actions/workflows/ci.yml/badge.svg)](https://github.com/RaccoonlabDev/mini_v2_node/actions/workflows/ci.yml) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=RaccoonlabDev_mini_v2_node&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=RaccoonlabDev_mini_v2_node) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=RaccoonlabDev_mini_v2_node&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=RaccoonlabDev_mini_v2_node) [![LOC](https://sonarcloud.io/api/project_badges/measure?project=RaccoonlabDev_mini_v2_node&metric=ncloc)](https://sonarcloud.io/summary/new_code?id=RaccoonlabDev_mini_v2_node)

# General-purpose CAN node application

Expand Down
15 changes: 9 additions & 6 deletions cmake/create_binary_with_meaningful_name.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,18 @@ if(DEFINED NC_TARGET AND NOT NC_TARGET STREQUAL "" AND
set(RELEASE_BOARD_NAME "${BOARD_NAME}_${NC_TARGET}")
endif()

set(RELEASE_HW_VERSION "${PLATFORM_NAME}")
if(NOT DEFINED RELEASE_HW_VERSION OR RELEASE_HW_VERSION STREQUAL "")
set(RELEASE_HW_VERSION "unknown")
endif()

# BOARD_NAME already identifies the hardware (mini_v2, mini_v3, node_v4), so
# PLATFORM_NAME is deliberately not part of the file name: it would repeat the
# board suffix, and for a custom framework board it would name an unrelated
# MCU family. IMAGE_KIND is abbreviated here only - build dirs and make target
# names keep the full spelling.
set(RELEASE_FW_TYPE "${IMAGE_KIND}")
if(NOT DEFINED RELEASE_FW_TYPE OR RELEASE_FW_TYPE STREQUAL "")
set(RELEASE_FW_TYPE "standalone")
endif()
if(RELEASE_FW_TYPE STREQUAL "application")
set(RELEASE_FW_TYPE "app")
endif()

set(RELEASE_COMMIT_HASH "${GIT_HASH_SHORT_8_DIGITS}")
if(NOT RELEASE_APP_ROOT_DIR STREQUAL "" AND EXISTS "${RELEASE_APP_ROOT_DIR}/.git")
Expand Down Expand Up @@ -100,7 +103,7 @@ if(NOT DEFINED RELEASE_FW_VERSION OR RELEASE_FW_VERSION STREQUAL "")
endif()

string(TIMESTAMP RELEASE_DATE "%Y.%m.%d")
set(DESTINATION_BIN "${DESTINATION_DIR}/${BOARD_VENDOR}_${RELEASE_BOARD_NAME}_${RELEASE_HW_VERSION}_${RELEASE_FW_TYPE}_${RELEASE_FW_VERSION}_${RELEASE_DATE}_${RELEASE_COMMIT_HASH}.bin")
set(DESTINATION_BIN "${DESTINATION_DIR}/${BOARD_VENDOR}_${RELEASE_BOARD_NAME}_${RELEASE_FW_TYPE}_${RELEASE_FW_VERSION}_${RELEASE_DATE}_${RELEASE_COMMIT_HASH}.bin")

# Create the release directory if it doesn't exist
file(MAKE_DIRECTORY "${DESTINATION_DIR}")
Expand Down
55 changes: 55 additions & 0 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Contributing

## Commits and pull requests

Pull requests are squash-merged, so the pull request title becomes the commit
subject. One convention covers both:

```
<type>(<scope>): <summary>
```

- Write the summary in the imperative, lower case, with no trailing dot.
- `<scope>` is optional and names the affected part: `fix(spi):`, `feat(params):`.
- A scope is not a type: write `fix(rcout):`, not `rcout:`.

| Type | Use for |
|---|---|
| `feat` | User-visible feature or new build target |
| `fix` | Bug fix or behaviour correction |
| `docs` | Documentation, including code comments |
| `tests` | Tests, test data, test helpers |
| `refactor` | Restructuring without intended behaviour change |
| `ci` | Workflows, checks, automation |
| `build` | Build system, CMake, release artifacts |
| `chore` | Dependencies, submodules, repository maintenance |

## Code style

We use [PX4-Autopilot code style](https://docs.px4.io/main/en/contribute/code),
with the following (minimal) modifications:

- Indentation: use 4 spaces instead of 8-space Tabs
- Attach a pointer or reference operator (*, &) to the variable type (left)
- Use UPPER_CASE for constants names instead of kThisIsConstant

```
indent=spaces=4
align-pointer=type
align-reference=type
```

```bash
make code_style
```

## Before opening a pull request

- Build every target you touched: [build_system.md](build_system.md).
- Run `make code_style` and the tests: [python_test_guide.md](python_test_guide.md).
- Fill in the firmware size difference in the pull request template.

## Writing docs

Keep docs short and follow [documentation_guidelines.md](documentation_guidelines.md).
Known bugs and the tests covering them live in [issues.md](issues.md).
19 changes: 0 additions & 19 deletions docs/code_style.md

This file was deleted.

25 changes: 20 additions & 5 deletions scripts/kocherga_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,19 @@ def _get_output_file_name(input_file_name: str, descriptor: AppDescriptor) -> st
return f"{base_stem}-{descriptor}.bin"


def _validate_firmware_image_path(raw_path: str) -> str:
"""Resolve the firmware image path and ensure it refers to a regular file.

The path comes from a CLI argument; resolving and checking it before any
file system access keeps a malformed argument from reaching an unintended
target.
"""
resolved = os.path.realpath(raw_path)
if not os.path.isfile(resolved):
raise FileNotFoundError(f"Firmware image is not a regular file: {raw_path!r}")
return resolved


def _validate_side_patch_path(raw_path: str, base_dir: str) -> str:
"""Resolve a side-patch target and ensure it stays within base_dir.

Expand Down Expand Up @@ -488,20 +501,22 @@ def _main() -> int:
return 0
_logger.debug(f"CLI arguments: {args}")

firmware_image = _validate_firmware_image_path(args.firmware_image)

# Read the input file. All operations done in-memory.
with open(args.firmware_image, "rb") as in_file:
with open(firmware_image, "rb") as in_file:
img = in_file.read()
model = ImageModel.construct_from_image(img, uninitialized_only=True)
if not model:
existing_model = ImageModel.construct_from_image(img)
if existing_model and args.lazy:
_logger.info(
f"Image {args.firmware_image!r} does not require processing because it already contains a "
f"Image {firmware_image!r} does not require processing because it already contains a "
f"valid app descriptor: {existing_model.app_descriptor!r}"
)
return 0
_logger.fatal(
f"An uninitialized app descriptor could not be found in {args.firmware_image!r}. "
f"An uninitialized app descriptor could not be found in {firmware_image!r}. "
f"If this is intentional, use --lazy to squelch this error. "
f"Existing app descriptor: {existing_model.app_descriptor if existing_model else None!r}"
)
Expand Down Expand Up @@ -536,15 +551,15 @@ def _main() -> int:
_logger.info(f"Final app descriptor: {model.app_descriptor!r}")

# Write the resulting image into the output file.
out_name = _get_output_file_name(args.firmware_image, model.app_descriptor)
out_name = _get_output_file_name(firmware_image, model.app_descriptor)
with open(out_name, "wb") as out_file:
assert model.validate_app_descriptor(), "Internal logic error: output image validation failed"
out_file.write(model.image)
_logger.info(f"Output image written into {out_name!r}")

# Perform the side-patching. Constrain targets to the firmware image's own
# directory to guard against path traversal from malformed CLI arguments.
base_dir = os.path.dirname(os.path.realpath(args.firmware_image))
base_dir = os.path.dirname(firmware_image)
for raw_path in args.side_patch:
path = _validate_side_patch_path(raw_path, base_dir)
with open(path, "rb") as f:
Expand Down
10 changes: 0 additions & 10 deletions sonar-project.properties

This file was deleted.

Loading