ci(flaky-tests): sync GitHub issues and update report#4296
ci(flaky-tests): sync GitHub issues and update report#4296ti-chi-bot[bot] merged 5 commits intomainfrom
Conversation
There was a problem hiding this comment.
I have already done a preliminary review for you, and I hope to help you do a better job.
Summary
This PR introduces GitHub issue synchronization to the flaky test reporter, enabling functionality to search, create, reopen issues, and apply labels/comments. Additionally, it updates the HTML report rendering to include issue statuses and reorganizes columns for clarity. The approach utilizes a new GithubIssueManager class and modifies several core components to support this feature. While the implementation is thorough and well-structured, testing coverage for critical paths is absent, and minor concerns around error handling and performance exist.
Critical Issues
-
Lack of error-specific handling in GitHub API requests (
GithubIssueManager.ts, lines 150-162):-
Currently, all errors during API calls are logged but not categorized or retried. This could lead to missing issue updates if transient errors occur.
-
Solution: Introduce retry logic with exponential backoff for transient errors (e.g., HTTP 429 for rate limits or 500-series errors). You can use a helper function to wrap
fetchcalls.async function requestWithRetry(method: string, url: string, body?: Record<string, unknown>, retries = 3): Promise<unknown> { for (let attempt = 1; attempt <= retries; attempt++) { try { const res = await fetch(url, { method, headers, body }); if (!res.ok && attempt < retries) { const delay = Math.pow(2, attempt) * 100; // Exponential backoff await new Promise((resolve) => setTimeout(resolve, delay)); continue; } if (!res.ok) throw new Error(`${res.status}: ${res.statusText}`); return res.status === 204 ? null : await res.json(); } catch (err) { if (attempt === retries) throw err; } } }
-
-
Potential security risk with
GITHUB_TOKENexposure (ConfigLoader.ts, lines 184-186 andperiodics.yaml, lines 68-73):- Sensitive data like tokens are directly passed in configuration, increasing the risk of accidental exposure.
- Solution: Mask sensitive keys in logs or ensure tokens are environment-locked (
process.env) and not exposed elsewhere.
Code Improvements
-
Hardcoded max flaky cases threshold (
main.ts, lines 243-253):-
The Top 10 threshold for issue mutation is hardcoded, which may limit scalability or flexibility.
-
Solution: Externalize this threshold as a configuration parameter (
PARAM_TOP_MUTATION_LIMIT) and pass it toGithubIssueManager.const topCasesForIssue = report.topFlakyCases.slice(0, cli.topMutationLimit);
-
-
Performance bottleneck in
groupCasesByIssueKey(GithubIssueManager.ts, lines 301-315):-
This function repeatedly computes keys, potentially impacting performance for large datasets.
-
Solution: Use a single loop with precomputed keys for grouping to reduce redundant operations.
const grouped = cases.reduce((acc, c) => { const issueRepo = this.resolveIssueRepo(c); const key = `${issueRepo}@@${buildIssueTitle(c, { includeRepo: this.titleIncludesRepo })}`; acc[key] = acc[key] || []; acc[key].push(c); return acc; }, {} as Record<string, CaseAgg[]>);
-
-
Validation on
parseRepooutput (IssueUtils.ts, lines 4-14):-
Currently, the function only checks for two parts but does not validate against invalid formats (e.g., spaces, special characters).
-
Solution: Add stricter validation with a regex pattern.
const repoRegex = /^[a-zA-Z0-9-_]+\/[a-zA-Z0-9-_]+$/; if (!repoRegex.test(repo)) return null;
-
Best Practices
-
Testing Coverage Gaps:
- Critical paths such as
GithubIssueManager.syncand GitHub API interactions lack automated tests. - Solution: Include unit tests with mocks for API calls and integration tests for syncing logic. For example, mock
fetchand test cases for edge scenarios like rate limits or token expiry.
- Critical paths such as
-
Documentation Needs (
README.md, lines 206-228):- The new GitHub synchronization features are well-documented, but examples lack clarity regarding dry-run behavior.
- Solution: Add explicit examples showing dry-run outputs and their implications.
-
Naming Conventions:
GithubIssueManager.tsuses inconsistent naming (buildIssueBody,findBestIssue, etc.).- Solution: Align method names to follow consistent action-based prefixes (
createIssue,searchIssue,reopenIssue).
-
Code Duplication in HTML Rendering (
HtmlRenderer.ts, lines 273-374):- Duplicate rendering logic for the "By Case" and "Top 10" sections should be refactored into shared helper functions.
- Solution: Extract repetitive rendering as reusable functions for cell formatting.
Suggested Changes
Implement the following fixes to address the issues:
- Add retry logic for
GithubIssueManager.request. - Externalize thresholds for top flaky cases.
- Optimize and validate
groupCasesByIssueKeyandparseRepo. - Expand test coverage for GitHub integrations.
- Refactor repetitive rendering code in
HtmlRenderer.
These changes will improve reliability, scalability, and maintainability of the flaky test reporter, ensuring smooth integration with GitHub issue management.
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly upgrades the flaky test reporting system by integrating directly with GitHub issues. It automates the process of tracking flaky tests by creating or updating GitHub issues, providing a centralized and actionable view of test stability. Additionally, the visual presentation of the reports has been improved to offer clearer insights into test trends and issue statuses. Highlights
Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
I have already done a preliminary review for you, and I hope to help you do a better job.
Summary
This pull request introduces GitHub issue synchronization functionality to the flaky test reporter tool. It integrates issue creation, reopening, labeling, and commenting into the tool. The update also includes enhancements to the rendering of flaky test reports (e.g., new columns for issue status and week-over-week icons). The implementation appears robust with modularized components, but testing has not been executed. While the overall quality is good, there are areas where improvements can be made, particularly regarding error handling, edge case coverage, and performance optimizations.
Critical Issues
1. Lack of validation for GitHub token input
- File:
tools/reporters/ci/flaky-tests/main.ts, lines 239-241 - Issue: The code does not validate the presence of a GitHub token before attempting to sync issues. While an error is logged, the program proceeds with operations, which could cause runtime errors.
- Suggestion: Throw an error or exit early if the
cli.githubTokenis missing whenissueCreateorissueReopenis enabled:if ((cli.issueCreate || cli.issueReopen) && !cli.githubToken) { throw new Error("GitHub token is required for issue operations"); }
2. Error handling in GithubIssueManager.sync
- File:
tools/reporters/ci/flaky-tests/core/GithubIssueManager.ts, lines 387-389 - Issue: Errors during issue synchronization are logged but do not result in actionable changes or retries. This could result in incomplete operations.
- Suggestion: Implement retry logic for transient network errors with exponential backoff. For example:
async syncWithRetry(fn: () => Promise<void>, retries: number = 3): Promise<void> { for (let attempt = 1; attempt <= retries; attempt++) { try { await fn(); return; } catch (e) { if (attempt === retries) throw e; // Re-throw after exhausting retries await new Promise(res => setTimeout(res, attempt * 1000)); // Exponential backoff } } }
Code Improvements
1. Redundant API calls in GithubIssueManager
- File:
tools/reporters/ci/flaky-tests/core/GithubIssueManager.ts, lines 489-495 - Issue: Searching for issues and then normalizing the title adds unnecessary complexity and API calls for validation. This could be optimized.
- Suggestion: Perform normalization locally before API call to reduce the number of requests.
2. Inefficient filtering logic in HtmlRenderer.sectionCase
- File:
tools/reporters/ci/flaky-tests/render/HtmlRenderer.ts, lines 273-278 - Issue: The filtering logic for cases includes redundant checks for flaky counts and previous week counts, which could be simplified.
- Suggestion: Simplify the logic to:
const data = report.byCase.filter(x => (x.flakyCount ?? 0) || (x.previousWeekFlakyCount ?? 0));
3. Hardcoded styling within HtmlRenderer.wowCell
- File:
tools/reporters/ci/flaky-tests/render/HtmlRenderer.ts, lines 491-512 - Issue: Inline styles are hardcoded, which makes maintenance and customization difficult.
- Suggestion: Use CSS classes consistently and define styles in the CSS block.
Best Practices
1. Missing unit tests for GithubIssueManager
- File:
tools/reporters/ci/flaky-tests/core/GithubIssueManager.ts - Issue: The
syncmethod and its associated logic lack unit tests for edge cases (e.g., invalid repo format, API failures). - Suggestion: Add unit tests using mock API responses to ensure all paths are tested. Example test case:
it("should handle invalid repo format gracefully", async () => { const manager = new GithubIssueManager({ token: "dummy" }); const cases = [{ repo: "invalid/repo", case_name: "test" }]; await expect(manager.sync({}, cases)).rejects.toThrow("invalid repo"); });
2. Inconsistent documentation
- File:
tools/reporters/ci/flaky-tests/docs/README.md - Issue: While the new issue sync functionality is well-documented, the examples section does not clearly specify how to test the feature in dry-run mode.
- Suggestion: Update the examples to include testing instructions for
--issue-dry-run.
3. Naming conventions for options
- File:
tools/reporters/ci/flaky-tests/core/ConfigLoader.ts, lines 91-107 - Issue: Option names like
--issue-createand--issue-reopenare descriptive but lack consistency with other flags (e.g.,--email-to). - Suggestion: Consider prefixing all issue-related options with
--issue-for consistency.
Summary of Suggestions
- Validate GitHub token input before operations.
- Add retry logic for transient API errors.
- Optimize filtering and API calls in
HtmlRendererandGithubIssueManager. - Enhance error handling in
GithubIssueManager.sync. - Write unit tests for edge cases and GitHub integration.
- Improve documentation clarity and examples.
- Standardize naming conventions for CLI options.
There was a problem hiding this comment.
Code Review
This pull request introduces a significant new feature to the flaky test reporter: GitHub issue integration. This includes searching for existing issues, creating new ones, reopening closed ones, and adding labels and comments. The changes are comprehensive, touching CI configuration, CLI parsing, core logic, data types, and HTML rendering. The implementation is well-structured, with new modules for GitHub API interaction and issue-related utilities. The report rendering has also been updated to display issue information and week-over-week trends, which is a great improvement for usability.
The code is of high quality. I have one minor suggestion to simplify a utility function for conciseness.
There was a problem hiding this comment.
I have already done a preliminary review for you, and I hope to help you do a better job.
Summary
This pull request introduces GitHub issue syncing capabilities into a flaky test reporter, enabling search, creation, reopening, labeling, and commenting of issues directly within the report workflow. Additionally, it updates the HTML report rendering with new columns, improved formatting for week-over-week (WoW) changes, and a subscription note for flaky test updates. The approach is modular and integrates the GitHub API client through a dedicated manager class. While the code quality is generally good, there are areas for improvement regarding performance efficiency, error handling, and adherence to best practices.
Critical Issues
-
Error Handling for GitHub API Failures
- File:
GithubIssueManager.ts, multiple methods (e.g.,searchIssues,createIssue,reopenIssue,addLabels,addComment) - Issue: The GitHub API client throws generic errors, but these are not granular enough to distinguish between recoverable (e.g., rate limits) and unrecoverable (e.g., missing permissions) issues. This may result in incomplete execution without proper notification.
- Suggested Solution: Enhance error handling to incorporate retries for transient errors like rate limits or network issues. Use HTTP status codes to classify errors and log actionable messages.
private async request(method: string, url: string, body?: Record<string, unknown>): Promise<unknown> { try { const res = await fetch(url, { method, headers: { ...headers }, body }); if (!res.ok) { const errorType = res.status === 403 ? "Permission Error" : res.status === 429 ? "Rate Limit" : "Unknown Error"; throw new Error(`GitHub API ${method} failed (${errorType}): ${res.status} - ${res.statusText}`); } return res.status === 204 ? null : await res.json(); } catch (error) { console.error(`[GitHub API] ${method} ${url} - Error: ${error.message}`); throw error; } }
- File:
-
Potential Performance Bottleneck in Issue Syncing
- File:
GithubIssueManager.ts, methodsync - Issue: The
syncmethod iterates over cases, performing API calls for each group. For large datasets, this could lead to significant latency due to sequential processing. - Suggested Solution: Use batching or parallel execution for API calls to improve performance. For example,
Promise.allcould be used to process multiple issue groups concurrently.const syncPromises = Array.from(groups.entries()).map(([key, group]) => this.processGroup(report, group, canMutate)); await Promise.all(syncPromises);
- File:
Code Improvements
-
Redundant Code in HTML Renderer
- File:
HtmlRenderer.ts, multiple methods (wowCell,subscriptionNote,wowLegend) - Issue: Inline CSS and repeated logic for rendering elements lead to bloated code and reduced maintainability.
- Suggested Solution: Extract reusable components into helper functions or templates to streamline rendering. For example:
private renderStyledCell(content: string, variant: "new" | "up" | "down" | "flat"): string { const styles = { new: "background-color: #fee2e2; color: #7f1d1d;", up: "...", down: "...", flat: "..." }; return `<td style="${styles[variant]}">${content}</td>`; }
- File:
-
Improper Handling of Undefined GitHub Token
- File:
main.ts, lines 243-245 - Issue: The absence of a GitHub token is only logged as a warning but does not prevent execution of issue-related operations, potentially leading to unexpected results.
- Suggested Solution: Abort issue-related operations entirely if the token is undefined.
if (!cli.githubToken) { console.error("GitHub token is not set; aborting issue-related operations."); return 1; // Exit with error code }
- File:
Best Practices
-
Documentation Enhancements
- File:
README.md, multiple sections - Issue: While the documentation describes the new GitHub issue features, it lacks concrete examples for edge cases like dry-run behavior or validation repo setup.
- Suggested Solution: Add examples demonstrating these scenarios, such as dry-run output and repo overriding.
- File:
-
Test Coverage for GitHub Integration
- File: N/A (tests not included in the diff)
- Issue: The PR does not include tests for critical paths like GitHub API interaction or issue syncing logic.
- Suggested Solution: Introduce unit tests for
GithubIssueManagerand integration tests for end-to-end syncing. Mock the GitHub API using tools likenockor custom stubs.it('should handle GitHub API rate limit errors gracefully', async () => { const mockClient = new GitHubClient('fake-token'); jest.spyOn(mockClient, 'request').mockRejectedValue(new Error('Rate Limit')); await expect(mockClient.addLabels('owner', 'repo', 123, ['label'])).rejects.toThrow('Rate Limit'); });
-
Naming Consistency
- File: Multiple files (config keys and variable names)
- Issue: Inconsistent naming patterns for config keys like
issueSubscribeTextPathversusgithubToken. - Suggested Solution: Standardize naming conventions to use camelCase consistently (e.g.,
githubToken->gitHubToken).
-
Avoid Hardcoded Defaults
- File:
IssueUtils.ts, methodbuildIssueBody - Issue: Hardcoded strings like "N/A" for missing build URLs reduce flexibility.
- Suggested Solution: Replace hardcoded values with configurable parameters or constants.
- File:
Conclusion
This pull request significantly enhances the flaky test reporter functionality, particularly with GitHub issue integration. However, addressing the highlighted issues will improve error handling, performance, maintainability, and test coverage, ensuring the changes are robust and scalable.
There was a problem hiding this comment.
I have already done a preliminary review for you, and I hope to help you do a better job.
Summary
This PR adds functionality for syncing GitHub issues within the flaky reporter tool, enabling actions like searching, creating, reopening issues, and updating comments and labels. It also improves the report rendering with new columns for issue statuses, visual enhancements, and configurable options. The changes are well-structured but introduce some areas requiring improvement in terms of error handling, edge cases, and adherence to best practices.
Critical Issues
-
Error handling in GitHub API requests
- File:
GithubIssueManager.ts, Lines: 150-157 - Issue: When a GitHub API request fails (e.g.,
requestmethod), the error is logged but doesn't propagate to the caller. As a result, failures might lead to partial issue syncing without proper notification. - Solution: Add specific error propagation or structured error logging to ensure the caller can handle failures. For example:
if (!res.ok) { const text = await res.text(); const errorDetails = `API ${method} ${url} failed: ${res.status} ${res.statusText} ${text}`; console.error(errorDetails); // Keep logging throw new Error(errorDetails); // Throw error to propagate }
- File:
-
Security risk with GitHub token handling
- File:
ConfigLoader.ts, Lines: 184-187 - Issue: The GitHub token is stored in plaintext and retrieved directly from environment variables. This poses a security risk if accidentally logged or exposed.
- Solution: Mask the token when logging and ensure it's never exposed in logs:
console.debug(`[github] Using token: ****${token.slice(-4)}`); // Mask token
- File:
-
Potential infinite loop in
groupCasesByIssueKey- File:
GithubIssueManager.ts, Lines: 508-511 - Issue: If the
CaseAggobjects contain invalid or conflicting data, this grouping logic could potentially result in unexpected behavior (e.g., infinite loops or memory issues). - Solution: Validate the
CaseAggdata before grouping and throw an error for invalid cases.
- File:
Code Improvements
-
Refactor repeated logic in building issue URLs
- Files:
HtmlRenderer.ts,IssueUtils.ts - Issue: The functions
githubIssueSearchUrlForCaseandgithubNewIssueUrlForCaseduplicate logic for parsing repositories and building strings. - Solution: Consolidate the logic into a shared utility function:
export function buildGitHubUrl(owner: string, repo: string, path: string, queryParams: Record<string, string>) { const query = new URLSearchParams(queryParams).toString(); return `https://github.com/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/${path}?${query}`; }
- Files:
-
Optimize label deduplication in
parseLabelList- File:
ConfigLoader.ts, Lines: 65-74 - Issue: The deduplication logic using
Setcould be simplified and made more readable. - Solution: Use modern JavaScript array methods:
return Array.from(new Set( (input ?? "").split(",").map((label) => label.trim()).filter(Boolean) ));
- File:
-
Improve configurability and validation of GitHub options
- File:
ConfigLoader.ts, Lines: 157-187 - Issue: GitHub-specific CLI options lack validation (e.g., empty labels, invalid repo overrides).
- Solution: Add validation logic for these options:
if (!githubToken) throw new Error("--github-token is required for issue operations"); if (issueLabels.length === 0) throw new Error("--issue-labels cannot be empty");
- File:
Best Practices
-
Testing coverage gaps
- Files:
GithubIssueManager.ts,IssueUtils.ts - Issue: No explicit testing was mentioned, and the logic for API interactions lacks mock tests for edge cases like API outages or invalid responses.
- Solution: Add unit tests using a mocking library (e.g.,
sinonor similar) to simulate GitHub API responses for each method.
- Files:
-
Unclear documentation for new CLI options
- File:
README.md, Lines: Multiple - Issue: While CLI options are documented, their expected behavior (e.g.,
--issue-repo,--issue-labels) is not elaborated with examples or edge-case handling. - Solution: Add detailed descriptions and examples for each option:
--issue-repo - Overrides the default repo for issue operations. Example: "pingcap/tidb". Ensure the repo exists and you have appropriate permissions to manage issues.
- File:
-
Style guideline deviations
- File:
GithubIssueManager.ts, Lines: Multiple - Issue: Some methods have inconsistent formatting and lack clear separation of concerns (e.g.,
processGroupmixes API logic and report updates). - Solution: Extract API calls and report updates into separate helper methods to improve readability.
- File:
-
Naming conventions
- File:
ConfigLoader.ts, Lines: 184-187 - Issue: The variable
issueSubscribeTextPathdoesn't follow consistent naming conventions with other options. - Solution: Rename to
issueSubscriptionHelpTextPathfor clarity and consistency.
- File:
Suggested Changes Summary
- Improve error handling in GitHub API methods.
- Securely handle GitHub tokens to avoid exposure.
- Refactor URL-building logic for consistency.
- Add validation for CLI options and data inputs.
- Expand testing coverage, especially for edge cases.
- Enhance documentation for new options and behaviors.
- Improve code readability and adhere to naming conventions.
There was a problem hiding this comment.
I have already done a preliminary review for you, and I hope to help you do a better job.
Summary
This pull request introduces GitHub issue synchronization for flaky test reports, enabling functionality for searching, creating, reopening, commenting, and labeling issues. It also updates the HTML report rendering with new columns and visual enhancements, including week-over-week (WoW) indicators. The implementation is thorough, leveraging modular design principles and introducing new utilities for GitHub integration. However, there are areas for improvement, particularly around error handling, API usage, and testing coverage.
Critical Issues
-
Error Handling for GitHub API Requests
File:tools/reporters/ci/flaky-tests/core/GithubIssueManager.ts
Line: Multiple instances inGitHubClient.request- Issue: The
requestmethod retries fetch calls on specific errors but lacks robust differentiation for non-retryable errors (e.g., 403 - Forbidden). This could lead to unnecessary retries and delayed failure. - Recommended Fix: Add specific handling for non-retryable statuses (e.g., 403, 404) to fail fast:
if (!this.isRetryableStatus(res.status)) { const text = await res.text(); throw new Error( `GitHub API ${method} ${url} failed: ${res.status} ${res.statusText} ${text}`, ); }
- Issue: The
-
Potential Token Misuse
File:tools/reporters/ci/flaky-tests/core/GithubIssueManager.ts
Line: 49- Issue: GitHub token is passed directly into authorization headers without validation. This poses a security risk if the token is malformed or expired.
- Recommended Fix: Validate the token format and ensure it exists before proceeding with API requests:
if (!this.token || !this.token.startsWith("ghp_")) { throw new Error("Invalid GitHub token format."); }
Code Improvements
-
Optimization of Label Deduplication
File:tools/reporters/ci/flaky-tests/core/ConfigLoader.ts
Line: 7- Issue: The
parseLabelListfunction uses aSetfor deduplication but iterates twice—once to populate and once to extract labels. This can be optimized. - Recommended Fix: Use
Array.from(new Set(...))for direct deduplication:function parseLabelList(input: string | undefined): string[] { return Array.from(new Set(String(input ?? "").split(",").map((s) => s.trim()).filter(Boolean))); }
- Issue: The
-
Grouping Logic in
groupCasesByIssueKey
File:tools/reporters/ci/flaky-tests/core/GithubIssueManager.ts
Line: 837- Issue: The grouping logic for cases by issue key is repeated. This could be refactored as a utility function to improve maintainability.
- Recommended Fix: Extract the grouping logic into a reusable utility function.
Best Practices
-
Testing Coverage Gaps
- Issue: The PR description notes that testing has not been run, yet the code introduces significant functionality changes, particularly with GitHub API integration.
- Recommended Fix: Add unit tests for critical functions like
GitHubClient.request,parseRepo, andbuildIssueTitle. Mock the GitHub API to simulate various responses (e.g., success, rate limit, forbidden).
-
Missing Error Logging Context
File:tools/reporters/ci/flaky-tests/core/GithubIssueManager.ts
Line: 103- Issue: Errors are logged but lack context about the operation that caused the failure, which makes debugging harder.
- Recommended Fix: Include contextual information in error logs:
console.error(`[github] Failed to ${method} ${url}: ${msg}`);
-
Style Consistency in CLI Options
File:tools/reporters/ci/flaky-tests/core/ConfigLoader.ts
Line: 126-183- Issue: Default values for CLI flags are inconsistent (some use environment variables, others hard-coded). This makes it harder to configure the tool uniformly.
- Recommended Fix: Centralize default values in a configuration file or constants module for consistency.
-
Documentation Enhancements
File:tools/reporters/ci/flaky-tests/docs/README.md
Line: 213- Issue: The documentation does not include examples for dry-run mode or error handling for GitHub integration.
- Recommended Fix: Expand the documentation with examples for each CLI flag, particularly
--issue-dry-run, and mention the expected behavior for error cases.
Conclusion
This PR is well-structured and introduces valuable features, but it requires improvements to error handling, token validation, testing coverage, and documentation to ensure robustness and maintainability. Addressing the highlighted issues will strengthen the reliability of the GitHub integration and improve user experience.
|
/approve |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: wuhuizuo The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Summary
Testing