Proposal: API Reviews via GitHub#15789
Conversation
|
|
||
| ## Assumptions | ||
|
|
||
| - We need to be able to compare arbitrary versions against one another, as we do in APIView today. |
There was a problem hiding this comment.
I've been thinking about this one. If a service team does PR from one version to the next, I guess the diff is the exact diff between released version.
Now if they do feature by feature, each diff would be more incremental. I guess it's still ok, because each increment are still valid diff, if they don't show the full picture.
Just thinking out loud, I think I'm good if diff are incremental, which would be the simplest likely here.
There was a problem hiding this comment.
It's really going to come down to when you choose to open an API Review PR. If you had PRs for features A, B and C that are all going into version X, it would make sense to wait to produce the API review PR until all three features are merged.
There was a problem hiding this comment.
If I understand correctly ApiView today lets you approve the changes for A, B, and C independently and as long as no new changes come in your release would be unblocked since its able to understand that combined there are no new API changes.
With the new system I would need to review A, B, and C and then again review X (the combined version) and everything in X would appear "new" even though it was previously reviewed?
I am not sure waiting for X is feasible since the doc mentions architects will be set as CodeOwners of the api.md file and it also said that the api.md file will change with every pr (that touches public api surface) enforced by the ci. So the architect will be pinged on every one of those to review.
Also waiting to review it all as one big change gets noisy especially if the features are not related. Reviewing in smaller chunks is always preferred.
There was a problem hiding this comment.
If I understand correctly ApiView today lets you approve the changes for A, B, and C independently and as long as no new changes come in your release would be unblocked since its able to understand that combined there are no new API changes.
So that's not the case today. Your release is ungated if the release artifact's API hash matches any approved revision. In the case where you approve A, B, and C individually, the combined API would have a different hash, so you would still need to (at some point) approve the combined API for the release to be ungated.
You would still have the ability to review features, probably targeting PRs. Most likely, when the service team needs the final approval, they would link to those approved PR reviews. In that sense it would be the same as today--it's just the process of creating the reviews (and seeing that they are approved) is less obvious since they aren't grouped.
There was a problem hiding this comment.
Gotcha thanks for the clarification.
Most likely, when the service team needs the final approval, they would link to those approved PR reviews
Can this be discovered / done automatically as part of the tooling that creates the review PR?
There was a problem hiding this comment.
Long-lived and/or disparate features should probably be done in feature branches anyway, but then that begs the question I asked above: how does that work with any gates to release from a feature (or release) branch?
There was a problem hiding this comment.
A release gate will compare the API hash of the release artifact to an "approved" release hash that comes from approving a review PR. That approval will be stored on the ADO work item for the package in question. So it really doesn't matter whether the approval was on a release branch, feature branch, etc or what the origin of the release artifact is.
There was a problem hiding this comment.
I am not sure waiting for X is feasible since the doc mentions architects will be set as CodeOwners of the api.md file and it also said that the api.md file will change with every pr (that touches public api surface) enforced by the ci. So the architect will be pinged on every one of those to review.
That's really not sustainable for us architects (assuming I understood the flow correctly). This used to be the case for JS (where we already generate api.md files under a review folder) but we were unable to keep up with the flood of api.md changes. A way to "batch" changes to a given review is really nice. Maybe that's something that can be using labels to mark a given PR as "intended for release" and architects can use labels to mark it approved, or just approve that PR. I don't want to prescribe a solution I just want to call out that this has quickly become difficult to keep up with at the PR level
There was a problem hiding this comment.
I am not sure waiting for X is feasible since the doc mentions architects will be set as CodeOwners of the api.md file and it also said that the api.md file will change with every pr (that touches public api surface) enforced by the ci. So the architect will be pinged on every one of those to review.
Ah, good point. It would make more sense then to not put the architects as codeowners, but rather to simply assign them to review PRs. Since review PRs must be triggered (by the service team) this should eliminate that noise.
There was a problem hiding this comment.
That's really not sustainable for us architects (assuming I understood the flow correctly). This used to be the case for JS (where we already generate api.md files under a review folder) but we were unable to keep up with the flood of api.md changes. A way to "batch" changes to a given review is really nice. Maybe that's something that can be using labels to mark a given PR as "intended for release" and architects can use labels to mark it approved, or just approve that PR. I don't want to prescribe a solution I just want to call out that this has quickly become difficult to keep up with at the PR level
Totally fair point, but this same limitation exists today in APIView.
You still could review changes in batches (features), but ultimately, you'll need to approve the actual release in its own PR. Most likely the service team would say "Here my PR for version 2. It consists of features A, B and C, and here are the approved PRs that contained those features."
It's also worth noting that Github has a feature that creates "groups" of changes to help break up large reviews.
|
|
||
| **Wins:** Eliminates stale API artifacts. Ensures review PRs always reflect actual code. Enables hash-based approval validation at any point in history. | ||
|
|
||
| **Losses:** Requires teams to regenerate `API.md` locally or rely on the auto-fix mechanism. |
There was a problem hiding this comment.
For Python, I wanted it part of azpysdk apiview regenerate (not sure the exact name Jenny used). I agree we need to make this simple, likely integrate it into the azsdk CLI the EngSys team is already making available in all repos.
There was a problem hiding this comment.
I have also tested that you can just ask @copilot to fix it on your PR and it was able to successfully do it. It takes a lot longer than just running the update on your machine, but it works.
|
|
||
| **Wins:** Aligns with GitHub's model. Leverages GitHub's built-in notifications so service team communication should be improved. | ||
|
|
||
| **Losses:** GitHub does not support per-comment severity, so that granularity is lost. |
There was a problem hiding this comment.
This is a good point, I wonder what our architect would say about that. Some of those things could be done through a VSCode extension for instance.
There was a problem hiding this comment.
GHC comments do seem to have a kind of severity badge on them. It doesn't seem to be a feature of manual comments right now, but it's possible that it may evolve in that direction.
There was a problem hiding this comment.
We can always do something like this.
- 🔴 High — bugs, security, correctness
- 🟡 Medium — improvements, inconsistencies
- 🔵 Low / ℹ️ — questions, suggestions
It would be really nice if GH exposed the ability to use the same severity marker copilot has access to. Do we know anyone over at GH?
There was a problem hiding this comment.
In the short term, we could do something like what I do in some PRs e.g., preface a comment with "Tip: " or "Nit: ". Having something structured - even better, having access to what Copilot can do - would be better.
|
|
||
| --- | ||
|
|
||
| ## Success Criteria |
| - Instead of introducing a new external Azure resource, approval state will be persisted on the existing ADO Package Work Item used by SDK pipelines. | ||
| - This aligns with current engineering-system ownership: the schema is flexible, already managed by existing pipelines, and operationally maintained today. | ||
| - A GitHub trigger will update the Package Work Item when PR approvals are granted, revoked, or become stale. | ||
| - There is a potential problem here. If you open two reviews, one comparing your change to the last GA and one comparing your change to the last beta, an approval on either could approve the API hash for both. This can be mitigated by marking the beta-baseline PR as Draft and ensuring Draft approvals do not update the Package Work Item approval fields. |
There was a problem hiding this comment.
I am not sure that mitigation will work since a user can simply convert a draft pr to ready for review at which point ga approval would be granted even though beta approval was asked for?
I wonder if we should simply not require approvals if the release artifact will be beta except for the very first one which is what happens today. Approvals are only needed for ga.
There was a problem hiding this comment.
Yeah, the intent it is to replicate the same logic. The concern here is that you want to release a GA, but there are two PRs, one that uses another GA version as the base and the other that uses a preview version as a base. The target is the same for both so approving either would ungate the release. However, I think we could examine the base and make sure that the GA approval is compared to a GA base and ignore if the base was a beta.
There was a problem hiding this comment.
It's not uncommon for a team to be working on a stable and prerelease at the same time. I'm working with a partner right now doing that. I think we need to think more about feature/release branches and how we can utilize those e.g., as base branches rather than just the last tagged release.
There was a problem hiding this comment.
That's a great point. There shouldn't be any reason base couldn't be a branch (though it probably introduces some complexity).
|
|
||
| ### 1. Review Creation (Diff-Based) | ||
| - API reviews are synthetic GitHub pull requests | ||
| - API surface is represented as a generated `API.md` artifact |
There was a problem hiding this comment.
We presumably have one file per language - so do we end up with <service>/api.java.md or <service>/java/api.md?
There was a problem hiding this comment.
The idea is that api.md will live in the package folder. So, for Python it's like sdk\storage\azure-storage-blob\api.md
There was a problem hiding this comment.
Why wouldn't these live in language repos, thus not need the language name as the file name? That is where the package source is, so why shouldn't the API "source" be there as well?
There was a problem hiding this comment.
And to clarify the assumptions; it will live in the target langauge repository, not in azure-rest-api-specs, correct?
There was a problem hiding this comment.
That's correct. The api files would be in the language repos. There is a section that talks about potentially mirroring them to rest-api-specs so that you could look at all languages in one place, but that's not what is being proposed for phase 1.
There was a problem hiding this comment.
There is a section that talks about potentially mirroring them to rest-api-specs so that you could look at all languages in one place
I hadn't gotten that far yet when I originally commented, but I do like that idea.
| ## Scope (Phase 1) | ||
|
|
||
| ### 1. Review Creation (Diff-Based) | ||
| - API reviews are synthetic GitHub pull requests |
There was a problem hiding this comment.
I'm not clear yet on how these PRs will be created. I imagine there are two flows (at least): for teams who are building generated libraries from typespec, and for teams who have built a custom library.
There was a problem hiding this comment.
Essentially they will trigger some kind of script--most likely via the SDK agent. But of course anything you can trigger via an agent is usually exposed through a CLI command or pipeline. Right now in the Python POC PR, it is a script you could call (but again, it will probably be the agent calling it).
|
|
||
| **Wins:** Gain requested features like multi-line comments for free as part of the GH experience. Benefit from any future GH UX enhancements. | ||
|
|
||
| **Losses:** Lose the clickable navigation features that allow you to navigate between concepts. Lose custom formatting and custom filters (example: documentation) that exist in APIView today. There are no GitHub equivalents of those. |
There was a problem hiding this comment.
Having to have docs fully on or fully off is quite a big loss. I often expand the JavaDoc for an API to understand what the API does, but browsing with all apidocs showing will be horrendously bad for some libraries - and having to do essentially separate reviews on two files will be annoying too.
There was a problem hiding this comment.
It might be that reviewing in the IDE could be a solution here--leveraging the ability of VSCode to collapse doc-comment blocks.
Just tried this... and it didn't work.
| - Optionally surfaced as PR annotations via the Check Runs API | ||
|
|
||
| **Result:** | ||
| - Diagnostics shift from review-time to CI-time validation |
There was a problem hiding this comment.
This will be a big change for Java and require a lot of work to move our diagnostics, which we invested heavily in, out of APIView and into separate CI-time validation.
There was a problem hiding this comment.
100%. This will also affect C#, but won't affect other languages that don't use APIView diagnostics.
Since the current proposal leverages the token files to produce the text, it means the diagnostics would be available in some form. I think the simplest thing would be to extract them and have the CI log them as warnings. Other language CIs fail on any linter violations, but this wouldn't be possible since the diagnostics lack a suppression mechanism.
Longer term, the benefit of migrating the rules to a popular static analyzer of choice is that you can simply fail the CI and leverage the suppression mechanism of said analyzer.
heaths
left a comment
There was a problem hiding this comment.
What's the point of a markdown file? If you're not going to prescribe something more structured, why force a markdown file at all? What value does it add? .NET, for example, also publishes 1 or more .cs files that is basically just a large file of sorted declarations (with bodies that throw so it's valid C# and syntax highlights correctly). I could hypothetically do the same for Rust with a giant .rs file.
Is it just to follow a consistent naming pattern? Couldn't it just as easily be API.*? If it has to be markdown and there is no prescribed structural guidance, what stopping us just from:
```rust
// everything declaration goes here
```|
|
||
| ## Assumptions | ||
|
|
||
| - We need to be able to compare arbitrary versions against one another, as we do in APIView today. |
There was a problem hiding this comment.
Long-lived and/or disparate features should probably be done in feature branches anyway, but then that begs the question I asked above: how does that work with any gates to release from a feature (or release) branch?
| - Eliminates duplication and inconsistency across systems | ||
|
|
||
| - **Extensibility** | ||
| - Actions, bots, and automation integrate directly into PR workflows |
There was a problem hiding this comment.
Are we going to hook the current Copilot bot that APIView uses (or similar) to this process? It does provide value.
There was a problem hiding this comment.
We are not. The current plan is for APIView Copilot to be retired alongside APIView.
There was a problem hiding this comment.
Anything new to replace it? Barring some issues I had with our token stream (our processor's issue), it was actually useful. As we look at doing more with less, this would be a major boon. I've already spent a lot of time making sure our guidelines are up-to-date and actionable, so at least having Copilot take a first stab at review would likely save me a lot of time and, naturally - especially on larger PRs - we humans can miss things.
There was a problem hiding this comment.
There's a section on AI-assisted reviews. Essentially, instead of a large black box bespoke solution, each language repo would have skills to facilitate reviews. While these cannot be used by the Github code review agent today, it's likely they will in the future.
|
|
||
| ### 1. Review Creation (Diff-Based) | ||
| - API reviews are synthetic GitHub pull requests | ||
| - API surface is represented as a generated `API.md` artifact |
There was a problem hiding this comment.
Why wouldn't these live in language repos, thus not need the language name as the file name? That is where the package source is, so why shouldn't the API "source" be there as well?
|
|
||
| **Wins:** Aligns with GitHub's model. Leverages GitHub's built-in notifications so service team communication should be improved. | ||
|
|
||
| **Losses:** GitHub does not support per-comment severity, so that granularity is lost. |
There was a problem hiding this comment.
In the short term, we could do something like what I do in some PRs e.g., preface a comment with "Tip: " or "Nit: ". Having something structured - even better, having access to what Copilot can do - would be better.
| - Approvals are tied to a composite key of the package name, API hash and (conditionally) the version | ||
| - Review branches must include the "Dismiss stale approvals when new commits are pushed" feature. This is to ensure that the UI reflects the correct approval status and does not show approval while the CI fails. | ||
| - SDK release pipelines verify approval status largely the same as they do today. | ||
| - Approved PRs are never merged. They exist only for review and approval purposes and can be closed once the associated working branch is merged or closed. |
There was a problem hiding this comment.
Nit, though I'm not sure there's a better way: this is going to look bad, IMO. There will be a lot of red Xes in our list of PRs that seems like, well, bad PR (public relations) unless people know what they are. Perhaps if the title is obvious that it's for review purposes only or something that would at least help the optics.
There was a problem hiding this comment.
I mean, they can be merged. It would just merge the review branch into the base branch... which would do nothing because both branches will be deleted at some point.
| - Instead of introducing a new external Azure resource, approval state will be persisted on the existing ADO Package Work Item used by SDK pipelines. | ||
| - This aligns with current engineering-system ownership: the schema is flexible, already managed by existing pipelines, and operationally maintained today. | ||
| - A GitHub trigger will update the Package Work Item when PR approvals are granted, revoked, or become stale. | ||
| - There is a potential problem here. If you open two reviews, one comparing your change to the last GA and one comparing your change to the last beta, an approval on either could approve the API hash for both. This can be mitigated by marking the beta-baseline PR as Draft and ensuring Draft approvals do not update the Package Work Item approval fields. |
There was a problem hiding this comment.
It's not uncommon for a team to be working on a stable and prerelease at the same time. I'm working with a partner right now doing that. I think we need to think more about feature/release branches and how we can utilize those e.g., as base branches rather than just the last tagged release.
|
|
||
| **Replacement:** | ||
| - Blocking feedback is represented via “Request Changes” at review level | ||
| - Non-blocking guidance remains as regular comments |
There was a problem hiding this comment.
I'd righten up that wording to "regular approvals" since a PR comment sign-off is a thing, just as you noted above. That basically helps nothing. If you're signing off with suggestions, best to actually approve.
There was a problem hiding this comment.
Well, except if you are doing suggestions, you'll often submit a review as "Comment" to ensure the team actually goes through them before you approve. That's how I suspect people would end up using that, but it's really up to the architect.
There was a problem hiding this comment.
That would be "Request changes" then. Practically, they are the same.
But I'm - and seems many other people - hoping that is relaxed. Gone, unfortunately, are the days of "I don't see this as a blocker, but here's a few suggestions." Meaning, they can decide to ignore those and ship and we don't have to see another review.
Signing off as a Comment isn't signing off. Comment in this new world really is pretty useless.
There was a problem hiding this comment.
Comment in this new world really is pretty useless.
Totally agree. 😁
But yeah, I think it'll be up to the architect. If you have suggestions and don't want to see the review again, leave the suggestions and approve. If you want to get some kind of reply (maybe you have questions) then you could just Comment.
|
I wonder how much value we would get from vibe coding a vscode plugin to make the reviews simpler? For example, it could unify docs/no-docs views, it might be able to display some degree of criticality on comments, it could automate some of the scripts / mcp / etc tooling processes. |
The markdown today DOES look exactly as you suggest. It's certainly not set in stone, but a couple reasons:
|
…re-sdk-tools into apiview/GithubProposal
1277c6e to
4147452
Compare
This proposal describes a system for conducting API reviews using GitHub rather than APIView.
A POC for various scenarios can be found here:
Azure/azure-sdk-for-python#47203