Skip to content
Open
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
25 changes: 25 additions & 0 deletions .github/workflows/compliance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,23 @@ jobs:
west config manifest.group-filter -- +ci,-optional
west update -o=--depth=1 -n 2>&1 1> west.update.log || west update -o=--depth=1 -n 2>&1 1> west.update2.log

- name: Cache npm dependencies
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-

- name: Setup Node.js
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
with:
node-version: "lts/*"
check-latest: true

- name: Install Node dependencies
run: npm ci

- name: Run Compliance Tests
continue-on-error: true
id: compliance
Expand All @@ -86,6 +103,14 @@ jobs:
name: compliance.xml
path: compliance.xml

- name: Upload dts linter patch
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
continue-on-error: true
if: hashFiles('dts_linter.patch') != ''
with:
name: dts_linter.patch
path: dts_linter.patch

- name: check-warns
run: |
if [[ ! -s "compliance.xml" ]]; then
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ target/

# CI output
compliance.xml
dts_linter.patch
_error.types

# Tag files
Expand Down Expand Up @@ -118,3 +119,6 @@ TextEncoding.txt
YAMLLint.txt
ZephyrModuleFile.txt
# zephyr-keep-sorted-stop

# Node dependecies
node_modules
1 change: 1 addition & 0 deletions doc/contribute/style/devicetree.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Devicetree Style Guidelines
###########################

* Indent with tabs.
* Tab size is 8 characters.
* Follow the Devicetree specification conventions and rules.
* If the Linux kernel rules in
`Devicetree Sources (DTS) Coding Style <https://docs.kernel.org/devicetree/bindings/dts-coding-style.html>`_
Expand Down
32 changes: 32 additions & 0 deletions doc/contribute/style/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,35 @@ When there are differences between the `Coding Style Guidelines`_ guidelines and
formatting generated by code formatting tools, the `Coding Style Guidelines`_ guidelines
take precedence. If there is ambiguity between formatting tools and the
guidelines, maintainers may decide which style should be adopted.

dts-linter
============

The `dts-linter <https://www.npmjs.com/package/dts-linter>`_ can be helpful
to quickly reformat large amounts of devicetree files to our `Coding Style Guidelines`_
standards. You can also run it manually like this:
Copy link
Contributor

@JarmouniA JarmouniA Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be reworded to

"Zephyr uses the dts-linter <https://www.npmjs.com/package/dts-linter>_ to enforce and auto-format Devicetree files in CI according to our :ref:Devicetree Style Guidelines <devicetree-style-guidelines>.
This only concerns upstream contributions. Additionally, it is not necessary to use this tool to fix the issues found in CI, they can be corrected manually by following the Coding Style Guidelines
, or by applying the patch file generated by the tool in CI."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And then it would be tool enforcement, and absolutely unacceptable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is style enforcement in CI, not tool usage.

Copy link
Contributor Author

@kylebonnici kylebonnici Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JarmouniA The wording I used is very similar to the working above for clang-format, should we keep constancy?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is style enforcement in CI, not tool usage.

Even if, it is a claim that you have to prove first. Wording you suggest is unacceptable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jfischer-no can you make a proposal?

Copy link
Contributor

@JarmouniA JarmouniA Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I missing something, or is this meant to be run in CI to enforce DT style!? And the contributor does not have to use it to correct the issues found, can correct them manually, or download the patch file generated by the tool and apply it.
And downstream users are not concerned at all.

Copy link
Contributor Author

@kylebonnici kylebonnici Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...this meant to be run in CI to enforce DT style!?

Yes

...the contributor does not have to use it to correct the issues found

Correct

.. can correct them manually, or download the patch file generated by the tool and apply it.

Correct

...downstream users are not concerned at all.

Correct, unless they want to extend the check to check their files too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing the difference between "can be helpful" and "Zephyr uses the dts-linter to enforce and auto-format Devicetree files in CI according to our Devicetree Style Guidelines". For the latter, you need formal proof that it really does so, according to our style guidelines, which you do not have, and there is a complete lack of experience in PRs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jfischer-no can you make a proposal?

Keep it how it is.


For individual files
.. code-block:: bash

npx dts-linter --format --file board.dts --file board_pinctrl.dtsi --patchFile diff.patch
git apply diff.patch

You can omit ``--file`` and this will format all files under the directory where the command
has been called. Alternatively ``--cwd`` can also be passed set the base dir where the tool
should look for files. This option is also used to make the paths relative in the patch file.

You can also fix in place with
.. code-block:: bash

npx dts-linter --formatFixAll


Editor Integration
~~~~~~~~~~~~~~~~~~

* For VS Code: Install the extension from the `VS Code Marketplace <https://marketplace.visualstudio.com/items?itemName=KyleMicallefBonnici.dts-lsp>`_ or `Open VSIX <https://open-vsx.org/extension/KyleMicallefBonnici/dts-lsp>`_
* For other editors with LSP Client support: Use the devicetree-language-server `devicetree-language-server <https://www.npmjs.com/package/devicetree-language-server>`_

Make sure you follow `Devicetree Style Guidelines <https://docs.zephyrproject.org/latest/contribute/style/devicetree.html>`_
requirements to configure the editor correctly.
36 changes: 36 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{

Check warning on line 1 in package.json

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

Copyright missing

package.json:1 File has no SPDX-FileCopyrightText header, consider adding one.

Check warning on line 1 in package.json

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

License missing

package.json:1 File has no SPDX-License-Identifier header, consider adding one.
"private": true,
"dependencies": {
"dts-linter": "^0.3.0-beta3"
}
}
5 changes: 5 additions & 0 deletions scripts/checkpatch.pl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env perl

Check warning on line 1 in scripts/checkpatch.pl

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

License may not be allowed

scripts/checkpatch.pl:1 License file for 'GPL-2.0' not found in /LICENSES. Please check https://docs.zephyrproject.org/latest/contribute/guidelines.html#components-using-other-licenses.

Check warning on line 1 in scripts/checkpatch.pl

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

Copyright missing

scripts/checkpatch.pl:1 File has no SPDX-FileCopyrightText header, consider adding one.
# SPDX-License-Identifier: GPL-2.0
#
# (c) 2001, Dave Jones. (the file handling bit)
Expand Down Expand Up @@ -2572,6 +2572,11 @@
next;
}

# skip package-lock.json and package.json files specifically
if ($realfile =~ /package(-lock)?\.json$/) {
next;
}

#make up the handle for any error we report on this line
if ($showfile) {
$prefix = "$realfile:$realline: "
Expand Down
99 changes: 99 additions & 0 deletions scripts/ci/check_compliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,105 @@ def required_false_check(self, binding):
"'required: false' is redundant, please remove"
)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add an extra empty line


class DevicetreeLintingCheck(ComplianceTest):
"""
Checks if we are introducing syntax or formatting issues to devicetree files.
"""
name = "DevicetreeLinting"
doc = "See https://docs.zephyrproject.org/latest/contribute/style/devicetree.html for more details."

def _parse_json_output(self, cmd, cwd=None):
"""Run command and parse single JSON output with issues array"""
result = subprocess.run(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=False,
text=True,
cwd=cwd or GIT_TOP
)

if not result.stdout.strip():
return None

try:
json_data = json.loads(result.stdout)
return json_data
except json.JSONDecodeError as e:
raise RuntimeError(f"Failed to parse dts-linter JSON output: {e}")

def run(self):
# Get changed DTS files
dts_files = [
file for file in get_files(filter="d")
if file.endswith((".dts", ".dtsi", ".overlay"))
]

if not dts_files:
self.skip('No DTS')

temp_patch_files = []
batch_size = 500

for i in range(0, len(dts_files), batch_size):
batch = dts_files[i:i + batch_size]

# use a temporary file for each batch
temp_patch = f"dts_linter_{i}.patch"
temp_patch_files.append(temp_patch)

cmd = [
"npx", "--no", "dts-linter", "--",
"--outputFormat", "json",
"--format",
"--patchFile", temp_patch,
]
for file in batch:
cmd.extend(["--file", file])

try:
json_output = self._parse_json_output(cmd)

if json_output and "issues" in json_output:
cwd = json_output.get("cwd", "")
logging.info(f"Processing issues from: {cwd}")

for issue in json_output["issues"]:
level = issue.get("level", "unknown")
message = issue.get("message", "")

if level == "info":
logging.info(message)
else:
title = issue.get("title", "")
file = issue.get("file", "")
line = issue.get("startLine", None)
col = issue.get("startCol", None)
end_line = issue.get("endLine", None)
end_col = issue.get("endCol", None)
self.fmtd_failure(level, title, file, line, col, message, end_line, end_col)

except subprocess.CalledProcessError as ex:
stderr_output = ex.stderr if ex.stderr else ""
if stderr_output.strip():
self.failure(f"dts-linter found issues:\n{stderr_output}")
else:
self.failure("dts-linter failed with no output. "
"Make sure you install Node.JS and then run npm ci inside ZEPHYR_BASE")
except RuntimeError as ex:
self.failure(f"{ex}")

# merge all temp patch files into one
with open("dts_linter.patch", "wb") as final_patch:
for patch in temp_patch_files:
with open(patch, "rb") as f:
shutil.copyfileobj(f, final_patch)

# cleanup
for patch in temp_patch_files:
os.remove(patch)

class KconfigCheck(ComplianceTest):
"""
Checks is we are introducing any new warnings/errors with Kconfig,
Expand Down
Loading