Skip to content

Linting#9734

Merged
maliberty merged 9 commits into
The-OpenROAD-Project:masterfrom
Pinata-Consulting:linting
Mar 20, 2026
Merged

Linting#9734
maliberty merged 9 commits into
The-OpenROAD-Project:masterfrom
Pinata-Consulting:linting

Conversation

@oharboe
Copy link
Copy Markdown
Collaborator

@oharboe oharboe commented Mar 12, 2026

Bazel lint and tidy targets for TCL

Summary

  • Add Bazel-managed tclint and tclfmt via py_console_script_binary — no manual pip installs
  • Umbrella targets: bazelisk test //:lint_test (all checks) and bazelisk run //:lint (auto-fix)
  • Runs in ~0.3s, no C++ build required
  • Designed for extension with additional linters (clang-tidy, clang-format, ruff, buildifier, shellcheck)

Motivation

The GitHub Actions workflow .github/workflows/github-actions-lint-tcl.yml runs tclint and
tclfmt checks by creating a virtualenv and pip install tclint==0.7.0 on every CI run. This
is brittle: the version is pinned in a YAML file that can drift, developers can't easily run
the same checks locally without replicating the CI environment, and there's no way to test the
linting setup itself.

By moving to Bazel, tool versions are pinned in bazel/requirements.in with a lock file for
reproducibility, Bazel manages the Python toolchain and all transitive dependencies hermetically,
and developers get a single command that works identically on every machine.

What changed

Commit Scope
pip: add tclint dependency tclint==0.7.0 in bazel/requirements.in, regenerated lock file
bazel: add tclint/tclfmt console script binaries py_console_script_binary targets in bazel/BUILD, wrapper shell scripts
bazel: add lint_test and lint umbrella targets sh_test, sh_binary, test_suite in root BUILD.bazel
docs: add lint targets documentation docs/contrib/LintTargets.md

Usage

# Run all lint checks (~0.3s)
bazelisk test //:lint_test

# Run individual checks
bazelisk test //:tcl_lint_test    # tclint rules
bazelisk test //:tcl_fmt_test     # tclfmt formatting check

# Auto-fix formatting
bazelisk run //:lint              # umbrella fix-all
bazelisk run //:tcl_tidy          # tcl-specific formatting

Design decisions

  1. py_console_script_binary: Idiomatic rules_python way to expose pip console scripts as
    Bazel targets — Bazel manages the full dependency tree hermetically
  2. tags = ["local"]: Lint checks need access to the full source tree spanning Bazel
    subpackages — local tag bypasses sandbox
  3. Umbrella targets: //:lint_test is a test_suite, //:lint is an sh_binary — both
    designed to grow as more linters are added (C++, Python, Bazel files, shell scripts)
  4. Wrapper scripts take tool path as $1: The $(rootpath //bazel:tclint) arg lets Bazel
    resolve the tool binary; scripts resolve it before cd to workspace root

Backwards compatibility

  • GitHub Actions workflow is unchanged — it continues to run independently
  • No existing Bazel targets are modified
  • All new targets are additive

Planned additions to //:lint_test and //:lint

  • C++ clang-tidy and clang-format
  • Python ruff (lint + format)
  • Buildifier (BUILD/bzl file lint + format)
  • ShellCheck (bash script lint)
  • Duplicate message ID check (replace Jenkins stage)
  • Doc consistency checks (replace Jenkins stage)

Test plan

  • bazelisk test //:lint_test — 2/2 pass (tcl_lint_test, tcl_fmt_test)
  • bazelisk run //:lint — auto-formats successfully
  • bazelisk run //:tcl_tidy — auto-formats successfully
  • No C++ build triggered
  • GitHub Actions TCL lint workflow continues to pass (no changes)

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a robust, Bazel-managed framework for TCL linting and formatting, which is a great improvement for developer experience and CI consistency. The use of py_console_script_binary to manage tool dependencies is excellent. The new umbrella targets //:lint_test and //:lint are well-designed for future extension. My feedback includes a couple of minor suggestions to improve maintainability and robustness.

Comment thread BUILD.bazel Outdated
Comment thread bazel/tcl_tidy.sh Outdated
@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

@oharboe
Copy link
Copy Markdown
Collaborator Author

oharboe commented Mar 12, 2026

@hzeller Thoughs?

@oharboe oharboe requested a review from maliberty March 12, 2026 13:31
@maliberty
Copy link
Copy Markdown
Member

I'll wait for @hzeller 's thoughts

@hzeller
Copy link
Copy Markdown
Collaborator

hzeller commented Mar 12, 2026

This is now starting to use pip with OpenROAD, which is kindof side-stepping what bazel is doing (managing dependencies itself). It makes it harder to use, as this won't run on a hardened system anymore that prevents side-loading. So, I am not a fan.

So like clang-tidy and clang-format I suggest these to do just in separate scripts in etc/ for now.

Comment thread BUILD.bazel Outdated
@oharboe
Copy link
Copy Markdown
Collaborator Author

oharboe commented Mar 12, 2026

This is now starting to use pip with OpenROAD, which is kindof side-stepping what bazel is doing (managing dependencies itself). It makes it harder to use, as this won't run on a hardened system anymore that prevents side-loading. So, I am not a fan.

So like clang-tidy and clang-format I suggest these to do just in separate scripts in etc/ for now.

I find dependencies for all the CI rules to be a pain to manage, I much rather that the OpenROAD project takes responsibility for this and provides bazelisk run XXX to do whatever needs doing and bazel tests that I can run locally to check whatever needs checking without me having to worry about tools: fast local workflows for AI and hoomans.

@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

oharboe and others added 7 commits March 13, 2026 15:32
Add tclint==0.7.0 to pip requirements for Bazel-managed TCL linting
and formatting. This is the same version used by the GitHub Actions
workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Expose tclint and tclfmt as py_console_script_binary targets from the
pip-managed tclint package. Add wrapper shell scripts that invoke these
tools against the workspace root.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Add Bazel targets for TCL linting and formatting:
- //:tcl_lint_test — runs tclint (lint rules)
- //:tcl_fmt_test — runs tclfmt --check (formatting)
- //:tcl_tidy — runs tclfmt --in-place (auto-format)
- //:lint_test — umbrella test_suite for all lint checks
- //:lint — umbrella auto-fix target

Designed for extension with additional linters (C++ tidy, etc).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Document the new Bazel lint targets, usage, configuration, how to
add new linters, and planned additions (clang-tidy, clang-format,
ruff, buildifier, shellcheck, doc checks, duplicate ID checks).

Explain why Bazel is the right tool for managing linter dependencies:
hermetic, version-pinned, reproducible across dev machines and CI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
- Rename //:lint to //:fix_lint to clarify it modifies files (gadfort)
- Replace duplicated sh_binary with alias(actual = ":tcl_tidy") (gemini)
- Add BUILD_WORKSPACE_DIRECTORY fallback in tcl_tidy.sh (gemini)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Rename tcl_lint_test → lint_tcl_test, tcl_fmt_test → fmt_tcl_test,
tcl_tidy → tidy_tcl for consistent verb-first naming with _test suffix
per Bazel convention. Update docs to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

@maliberty
Copy link
Copy Markdown
Member

This doesn't work for me:

bazelisk run //:tidy_tcl
AssertionError: Cannot find .runfiles directory for /workspace/bazel/output/execroot/_main/bazel-out/k8-opt/bin/bazel/tclfmt
...

@oharboe oharboe requested a review from gadfort March 17, 2026 19:06
@oharboe
Copy link
Copy Markdown
Collaborator Author

oharboe commented Mar 17, 2026

This doesn't work for me:

bazelisk run //:tidy_tcl
AssertionError: Cannot find .runfiles directory for /workspace/bazel/output/execroot/_main/bazel-out/k8-opt/bin/bazel/tclfmt
...

fixed

- Tests were scanning 0 files because BUILD_WORKSPACE_DIRECTORY is
  unset in test context. Resolve workspace from tclint.toml symlink.
- fix_lint failed because readlink -f resolved through runfiles
  symlinks. Use directory-based path resolution instead.
- All three scripts now use git ls-files to avoid broken symlinks
  in gitignored directories like tmp/.
- Add tmp/ to tclint.toml excludes, fix leading whitespace.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

Copy link
Copy Markdown
Member

@maliberty maliberty left a comment

Choose a reason for hiding this comment

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

nit

Comment thread docs/contrib/LintTargets.md Outdated
Comment on lines +50 to +53
Current settings:
- **Excluded**: `src/sta/`
- **Ignored rules**: `unbraced-expr`
- **Style**: 2-space indent, 100-char line length, spaces in braces
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

no need to repeat what the file already shows - DRY (Excluded is already stale)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

fixed

The settings are already visible in tclint.toml itself (DRY),
and the listed exclusions were already stale.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@oharboe oharboe requested a review from maliberty March 18, 2026 23:00
@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

@maliberty maliberty enabled auto-merge March 19, 2026 15:26
@oharboe
Copy link
Copy Markdown
Collaborator Author

oharboe commented Mar 19, 2026

@vvbandeira @maliberty pr-merge CI outage I think, timeout. 😿

@maliberty
Copy link
Copy Markdown
Member

We had a gcp / jenkins issue today that when resolved left a huge queue of jobs. Various failures today due to overload. Restarted

@maliberty maliberty merged commit 2da3e5b into The-OpenROAD-Project:master Mar 20, 2026
15 checks passed
@oharboe oharboe deleted the linting branch March 31, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants