Skip to content

Conversation

ntBre
Copy link
Contributor

@ntBre ntBre commented Sep 11, 2025

Summary

This PR wires up the GitHub output format moved to ruff_db in #20320 to the ty CLI.

It's a bit smaller than the GitLab version (#20155) because some of the helpers were already in place, but I did factor out a few DisplayDiagnosticConfig constructor calls in Ruff. I also exposed the GithubRenderer and a wrapper DisplayGithubDiagnostics type because we needed a way to configure the program name displayed in the GitHub diagnostics. This was previously hard-coded to Ruff:

image

Another option would be to drop the program name in the output format, but I think it can be helpful in workflows with multiple programs emitting annotations (such as Ruff and ty!)

Test Plan

New CLI test, and a manual test with --config 'terminal.output-format = "github"'

@ntBre ntBre added cli Related to the command-line interface ty Multi-file analysis & type inference labels Sep 11, 2025
Copy link
Contributor

github-actions bot commented Sep 11, 2025

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

Copy link
Contributor

github-actions bot commented Sep 11, 2025

mypy_primer results

No ecosystem changes detected ✅
No memory usage changes detected ✅

Copy link
Contributor

github-actions bot commented Sep 11, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@ntBre ntBre marked this pull request as ready for review September 11, 2025 23:52
Copy link
Member

@dhruvmanila dhruvmanila left a comment

Choose a reason for hiding this comment

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

This looks great!

I just have one minor concern, refer to inline comment.

Comment on lines -5 to +7
::error title=Ruff (F401),file=fib.py,line=1,col=8,endLine=1,endColumn=10::fib.py:1:8: F401 `os` imported but unused
::error title=Ruff (F841),file=fib.py,line=6,col=5,endLine=6,endColumn=6::fib.py:6:5: F841 Local variable `x` is assigned to but never used
::error title=Ruff (F821),file=undef.py,line=1,col=4,endLine=1,endColumn=5::undef.py:1:4: F821 Undefined name `a`
::error title=ty (F401),file=fib.py,line=1,col=8,endLine=1,endColumn=10::fib.py:1:8: F401 `os` imported but unused
::error title=ty (F841),file=fib.py,line=6,col=5,endLine=6,endColumn=6::fib.py:6:5: F841 Local variable `x` is assigned to but never used
::error title=ty (F821),file=undef.py,line=1,col=4,endLine=1,endColumn=5::undef.py:1:4: F821 Undefined name `a`
Copy link
Member

Choose a reason for hiding this comment

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

Just confirming that this change is basically just a side effect of having ty as the default for Program and is not because there's someplace where the program is not being set correctly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that's right!

show_fix_status: false,
show_fix_diff: false,
fix_applicability: Applicability::Safe,
program: Program::Ty,
Copy link
Member

Choose a reason for hiding this comment

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

I think at this point, it might be useful to refactor this into a new method that takes in a program: Program as the sole parameter because there's no valid default value for this field and the caller should always provide the program for which this rendering is to be done for. What do you think?

fix_applicability: Applicability,
/// The program for which diagnostics are being rendered (Ruff or ty).
///
/// This is currently only used by the GitHub output format and defaults to `Program::Ty`.
Copy link
Member

Choose a reason for hiding this comment

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

Refer to my other comment, I'd probably remove the default value for this field.

Comment on lines 1469 to 1473
#[derive(Clone, Debug)]
pub enum Program {
Ruff,
Ty,
}
Copy link
Member

Choose a reason for hiding this comment

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

Nit: It would probably be fine to just use a String here

/// The program for which diagnostics are being rendered (Ruff or ty).
///
/// This is currently only used by the GitHub output format and defaults to `Program::Ty`.
program: Program,
Copy link
Member

Choose a reason for hiding this comment

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

I think I brought this up before and it isn't something that we need to change in this PR but I personally find it a bit difficult to reason about which settings are used for which output format (most settings are only used by one or very few formats).

The main reason I see today why we need a single Config struct is because DisplayDiagnostics matches on the output format, which I'm not sure we should keep because we also match over the output format in ruff's rendering code (meaning, we first match to create the generic configuration only to then match on the format again to call into specific renderers). To me, it would feel simpler to just have a single match in ruff's printer that calls the corresponding renderer directly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought eventually we would be able to hoist the Config out of the match in Ruff and have something like DisplayDiagnosticsConfig::from(ruff_output_format) and a single DisplayDiagnostics call, but I guess you're right. We may not want to port over all of the output formats, and some other logic is mixed in on the Ruff side, such as the SHOW_FIX_SUMMARY flag and writing of summary text. I can follow up on this.

write!(
f,
"::error title=Ruff ({code})",
"::error title={program} ({code})",
Copy link
Member

Choose a reason for hiding this comment

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

I think we want to use the correct severity for ty diagnostics and not always default to error

@ntBre
Copy link
Contributor Author

ntBre commented Sep 15, 2025

Thanks for the reviews! I pushed one commit to use the real severity. I think Dhruv's suggestions about not having a default Program make a lot of sense, but it looks like the Program config field can go away entirely with Micha's restructuring suggestion (we can just pass a &str to GithubRenderer::new instead of a config).

I briefly started that refactor on this branch, but I think it would help to finally make the DisplayDiagnostics rendering take a std::io::Write instead of a std::fmt::Write, so it seems best to address these all at once in an immediate follow-up PR.

## Summary

This is a follow-up to #20358 to
avoid adding a new `DisplayDiagnosticConfig` option (with a surprising
default value) just to print the program name for GitHub diagnostics.

Initially I expected this to be a larger refactor including making the
various `Renderer::render` methods take a `std::io::Write` instead of a
`std::fmt::Formatter` to make them easier to call directly in Ruff.
However, this was a bit more painful than expected because we use the
`Display` implementation of `DisplayDiagnostics` for more than writing
directly to stdout. Implementing `Display` on the individual renderers
seemed like a smaller step in this direction.

At this point it might make sense just to merge this into
#20358. Alternatively, I could
apply the same transformation to the other affected renderers. For
example, the JSON and JSON-lines formats only use their `config` fields
for the `preview` setting. Or we could update all of the renderers and
call them directly in Ruff instead of assembling a config at all. I just
wanted to make sure this approach looked reasonable before applying it
to everything.

## Test Plan

Existing tests
@ntBre ntBre merged commit ac54880 into main Sep 17, 2025
38 checks passed
@ntBre ntBre deleted the brent/ty-github branch September 17, 2025 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cli Related to the command-line interface ty Multi-file analysis & type inference
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants