mirror of
https://github.com/avelino/awesome-go.git
synced 2026-04-11 02:11:43 +08:00
* automate PR review: rewrite quality checks in Go and add diff validation - Replace check-quality.js with Go implementation that adds: open source license detection, repo maturity (5+ months), CI/CD presence check, and README existence verification - Add new check-pr-diff tool that validates README changes: single item per PR, link consistency with PR body, description format, non-promotional language, and category minimum size (3 items) - Update pr-quality-check workflow to run both Go tools with separate quality and diff reporting sections - Improve CONTRIBUTING.md with new "What is checked automatically" section documenting all blocking and non-blocking CI checks, plus what still requires manual maintainer review - Improve PR template with clearer structure separating CI-validated requirements from manual review items https://claude.ai/code/session_01JcdbDdtERhAXFFZmu3pCVY * add actionable fix instructions to automated PR review comments Each failed check now includes a "How to fix" section with specific commands and steps the contributor needs to take, e.g.: - missing go.mod → shows exact `go mod init` + `go mod tidy` commands - missing semver release → shows `git tag v1.0.0` command and GitHub UI link - low Go Report Card grade → shows `gofmt`, `go vet` commands - missing PR body links → shows the exact text to paste - description without period → shows the corrected entry line - link mismatch → shows both URLs and which to update https://claude.ai/code/session_01JcdbDdtERhAXFFZmu3pCVY * add auto-merge when all PR quality checks pass Adds an auto-merge job that enables GitHub's native auto-merge (squash) after the quality and diff checks succeed. GitHub will only execute the merge once ALL required branch protection status checks are green (including the tests workflow). Requires "Allow auto-merge" to be enabled in repo settings. https://claude.ai/code/session_01JcdbDdtERhAXFFZmu3pCVY * add workflow to re-run quality checks on all open PRs Creates a manual workflow_dispatch workflow that iterates through all open PRs and closes/reopens each one to re-trigger the quality check pipeline. Includes a 2s delay between PRs to respect API rate limits. Usage: Actions tab → "Re-check all open PRs" → Run workflow https://claude.ai/code/session_01JcdbDdtERhAXFFZmu3pCVY * skip quality checks for PRs that don't modify README.md The quality checks (forge link, pkg.go.dev, Go Report Card, etc.) only apply to package addition/removal PRs. Internal PRs (workflow changes, docs, scripts) were failing because they naturally don't have those fields in the PR body. Now the workflow first detects if README.md is in the changed files: - If yes: runs full quality + diff checks as before - If no: posts a "Skipped" notice and passes cleanly Fixes false failures like PR #6055. https://claude.ai/code/session_01JcdbDdtERhAXFFZmu3pCVY --------- Co-authored-by: Claude <noreply@anthropic.com>
504 lines
16 KiB
Go
504 lines
16 KiB
Go
// check-quality validates PR body links and repository quality against
|
|
// CONTRIBUTING.md minimum standards. It outputs a markdown report and
|
|
// labels via GITHUB_OUTPUT for the PR Quality Checks workflow.
|
|
//
|
|
// Checks performed:
|
|
// - Repo accessible, not archived, has go.mod and SemVer release
|
|
// - Open source license present
|
|
// - Repository age >= 5 months
|
|
// - CI/CD (GitHub Actions) configured
|
|
// - README exists
|
|
// - Go Report Card grade A- or better
|
|
// - pkg.go.dev page reachable
|
|
// - Coverage link reachable
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
reForgeLink = regexp.MustCompile(`(?i)forge\s+link[^:]*:\s*(https?://(?:github\.com|gitlab\.com|bitbucket\.org)/\S+)`)
|
|
rePkgGoDev = regexp.MustCompile(`(?i)pkg\.go\.dev:\s*(https?://pkg\.go\.dev/\S+)`)
|
|
reGoReport = regexp.MustCompile(`(?i)goreportcard\.com:\s*(https?://goreportcard\.com/\S+)`)
|
|
reCoverage = regexp.MustCompile(`(?i)coverage[^:]*:\s*(https?://(?:coveralls\.io|(?:app\.)?codecov\.io)/\S+)`)
|
|
reGrade = regexp.MustCompile(`(?i)Grade:\s*([A-F][+-]?)`)
|
|
reGithubRepo = regexp.MustCompile(`^https?://github\.com/([^/]+)/([^/]+?)(?:\.git)?/?$`)
|
|
reSemver = regexp.MustCompile(`^v\d+\.\d+\.\d+`)
|
|
)
|
|
|
|
type prEvent struct {
|
|
PullRequest struct {
|
|
Body string `json:"body"`
|
|
} `json:"pull_request"`
|
|
}
|
|
|
|
type repoData struct {
|
|
Archived bool `json:"archived"`
|
|
License *struct {
|
|
SPDXID string `json:"spdx_id"`
|
|
Name string `json:"name"`
|
|
} `json:"license"`
|
|
Message string `json:"message"` // present on API errors
|
|
}
|
|
|
|
type contentEntry struct {
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
type tagEntry struct {
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
type workflowsResponse struct {
|
|
TotalCount int `json:"total_count"`
|
|
}
|
|
|
|
func main() {
|
|
event := readEvent()
|
|
body := event.PullRequest.Body
|
|
|
|
forgeLink := captureMatch(body, reForgeLink)
|
|
pkgLink := captureMatch(body, rePkgGoDev)
|
|
gorepLink := captureMatch(body, reGoReport)
|
|
covLink := captureMatch(body, reCoverage)
|
|
|
|
var (
|
|
critical []string
|
|
warnings []string
|
|
criticalFail bool
|
|
repoOk bool
|
|
pkgOk bool
|
|
gorepOk bool
|
|
coverageOk bool
|
|
labels []string
|
|
)
|
|
|
|
// --- Repo checks ---
|
|
if forgeLink == "" {
|
|
critical = append(critical, icon(false)+" **Repo link**: missing from PR body")
|
|
critical = append(critical, fix("Add the following to your PR description:", "```\nForge link: https://github.com/your-org/your-project\n```"))
|
|
criticalFail = true
|
|
} else {
|
|
r := checkGithubRepo(forgeLink)
|
|
if !r.ok {
|
|
critical = append(critical, fmt.Sprintf("%s **Repo**: %s", icon(false), r.reason))
|
|
critical = append(critical, repoFixMessage(r.reason, forgeLink))
|
|
criticalFail = true
|
|
} else {
|
|
critical = append(critical, icon(true)+" **Repo**: accessible, has go.mod and SemVer release")
|
|
repoOk = true
|
|
}
|
|
|
|
if r.licenseChecked {
|
|
if r.hasLicense {
|
|
warnings = append(warnings, fmt.Sprintf("%s **License**: %s", warnIcon(true), r.licenseName))
|
|
} else {
|
|
warnings = append(warnings, warnIcon(false)+" **License**: no open source license detected")
|
|
warnings = append(warnings, fix("Add a LICENSE file to your repository root.", "Choose one at https://choosealicense.com — common choices for Go projects: MIT, Apache-2.0, BSD-3-Clause."))
|
|
labels = append(labels, "needs-license")
|
|
}
|
|
}
|
|
if r.maturityChecked {
|
|
if r.hasFiveMonths {
|
|
warnings = append(warnings, warnIcon(true)+" **Maturity**: repo has 5+ months of history")
|
|
} else {
|
|
warnings = append(warnings, warnIcon(false)+" **Maturity**: repo appears to have less than 5 months of history")
|
|
warnings = append(warnings, fix("Your repository needs at least 5 months of history since the first commit.", "Please resubmit after the repository meets this requirement."))
|
|
labels = append(labels, "needs-maturity")
|
|
}
|
|
}
|
|
if r.ciChecked {
|
|
if r.hasCI {
|
|
warnings = append(warnings, warnIcon(true)+" **CI/CD**: GitHub Actions workflows detected")
|
|
} else {
|
|
warnings = append(warnings, warnIcon(false)+" **CI/CD**: no GitHub Actions workflows found")
|
|
warnings = append(warnings, fix("Add a CI workflow to run tests automatically.", "Create `.github/workflows/test.yml` — see https://docs.github.com/en/actions/use-cases-and-examples/building-and-testing/building-and-testing-go"))
|
|
}
|
|
}
|
|
if r.readmeChecked {
|
|
if r.hasReadme {
|
|
warnings = append(warnings, warnIcon(true)+" **README**: present")
|
|
} else {
|
|
warnings = append(warnings, warnIcon(false)+" **README**: not found in repository root")
|
|
warnings = append(warnings, fix("Add a `README.md` to your repository root.", "It should explain what the project does, how to install it, and how to use it, in English."))
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- pkg.go.dev ---
|
|
if pkgLink == "" {
|
|
critical = append(critical, icon(false)+" **pkg.go.dev**: missing from PR body")
|
|
critical = append(critical, fix("Add the following to your PR description:", "```\npkg.go.dev: https://pkg.go.dev/github.com/your-org/your-project\n```"))
|
|
criticalFail = true
|
|
} else if !isReachable(pkgLink) {
|
|
critical = append(critical, icon(false)+" **pkg.go.dev**: unreachable")
|
|
critical = append(critical, fix("The pkg.go.dev page could not be reached.", "Ensure your module path in `go.mod` matches the URL. After pushing a tagged release, pkg.go.dev indexes the module automatically — this can take a few minutes. You can trigger it manually by visiting `https://pkg.go.dev/your-module-path`."))
|
|
criticalFail = true
|
|
} else {
|
|
critical = append(critical, icon(true)+" **pkg.go.dev**: OK")
|
|
pkgOk = true
|
|
}
|
|
|
|
// --- Go Report Card ---
|
|
if gorepLink == "" {
|
|
critical = append(critical, icon(false)+" **Go Report Card**: missing from PR body")
|
|
if forgeLink != "" {
|
|
critical = append(critical, fix("Add the following to your PR description:", fmt.Sprintf("```\ngoreportcard.com: https://goreportcard.com/report/%s\n```", strings.TrimPrefix(strings.TrimPrefix(forgeLink, "https://"), "http://"))))
|
|
} else {
|
|
critical = append(critical, fix("Add the following to your PR description:", "```\ngoreportcard.com: https://goreportcard.com/report/github.com/your-org/your-project\n```"))
|
|
}
|
|
criticalFail = true
|
|
} else {
|
|
grade, ok := checkGoReportCard(gorepLink)
|
|
if !ok {
|
|
critical = append(critical, fmt.Sprintf("%s **Go Report Card**: %s", icon(false), grade))
|
|
if grade == "unreachable" || grade == "fetch error" {
|
|
critical = append(critical, fix("The Go Report Card page could not be reached.", "Visit https://goreportcard.com and generate a report for your project. Then add the correct link to your PR body."))
|
|
} else {
|
|
critical = append(critical, fix(fmt.Sprintf("Your project received grade **%s** — minimum required is **A-**.", grade), "Run `gofmt -s -w .` to fix formatting, `go vet ./...` to fix vet issues, and review the report at "+gorepLink+" for specific problems to address."))
|
|
}
|
|
criticalFail = true
|
|
} else {
|
|
msg := icon(true) + " **Go Report Card**: OK"
|
|
if grade != "" {
|
|
msg += fmt.Sprintf(" (grade %s)", grade)
|
|
}
|
|
critical = append(critical, msg)
|
|
gorepOk = true
|
|
}
|
|
}
|
|
|
|
// --- Coverage ---
|
|
if covLink == "" {
|
|
warnings = append(warnings, warnIcon(false)+" **Coverage**: missing from PR body")
|
|
warnings = append(warnings, fix("Add a coverage service link to your PR description:", "```\nCoverage: https://app.codecov.io/gh/your-org/your-project\n```\nPopular options: [Codecov](https://codecov.io), [Coveralls](https://coveralls.io). Integrate one with your CI to track coverage automatically."))
|
|
} else if !isReachable(covLink) {
|
|
warnings = append(warnings, warnIcon(false)+" **Coverage**: unreachable")
|
|
warnings = append(warnings, fix("The coverage link could not be reached.", "Ensure the coverage service is configured for your repository and the link is correct. If you just set it up, it may need a CI run to generate the first report."))
|
|
} else {
|
|
warnings = append(warnings, warnIcon(true)+" **Coverage**: link accessible")
|
|
coverageOk = true
|
|
}
|
|
|
|
// --- Build comment ---
|
|
var lines []string
|
|
lines = append(lines, "## Automated Quality Checks", "")
|
|
lines = append(lines, "### Required checks", "")
|
|
lines = append(lines, critical...)
|
|
lines = append(lines, "", "### Additional checks", "")
|
|
lines = append(lines, warnings...)
|
|
lines = append(lines, "")
|
|
|
|
if criticalFail {
|
|
lines = append(lines, "---")
|
|
lines = append(lines, "> **Action needed:** one or more required checks failed. Please update your PR body with the missing links and ensure the repository meets the [quality standards](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#quality-standards).")
|
|
}
|
|
|
|
lines = append(lines, "")
|
|
lines = append(lines, "_These checks are automated and do not replace maintainer review. See [CONTRIBUTING.md](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md) for full guidelines._")
|
|
|
|
comment := strings.Join(lines, "\n")
|
|
|
|
// --- Labels ---
|
|
if forgeLink == "" || pkgLink == "" || gorepLink == "" {
|
|
labels = append(labels, "needs-info")
|
|
}
|
|
if !coverageOk {
|
|
labels = append(labels, "needs-coverage")
|
|
}
|
|
if criticalFail {
|
|
labels = append(labels, "quality:fail")
|
|
}
|
|
if !criticalFail && repoOk && pkgOk && gorepOk {
|
|
labels = append(labels, "quality:ok")
|
|
}
|
|
|
|
labelsJSON, _ := json.Marshal(labels)
|
|
|
|
setOutput("comment", comment)
|
|
setOutput("fail", boolStr(criticalFail))
|
|
setOutput("labels", string(labelsJSON))
|
|
}
|
|
|
|
// --- Event reading ---
|
|
|
|
func readEvent() prEvent {
|
|
var ev prEvent
|
|
path := os.Getenv("GITHUB_EVENT_PATH")
|
|
if path == "" {
|
|
return ev
|
|
}
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return ev
|
|
}
|
|
_ = json.Unmarshal(data, &ev)
|
|
return ev
|
|
}
|
|
|
|
// --- Regex helpers ---
|
|
|
|
func captureMatch(s string, re *regexp.Regexp) string {
|
|
m := re.FindStringSubmatch(s)
|
|
if len(m) < 2 {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(m[1])
|
|
}
|
|
|
|
// --- HTTP helpers ---
|
|
|
|
var httpClient = &http.Client{Timeout: 30 * time.Second}
|
|
|
|
func isReachable(url string) bool {
|
|
req, err := http.NewRequest(http.MethodHead, url, nil)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
resp, err := httpClient.Do(req)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
resp.Body.Close()
|
|
if resp.StatusCode >= 200 && resp.StatusCode < 400 {
|
|
return true
|
|
}
|
|
// Fallback to GET
|
|
req2, _ := http.NewRequest(http.MethodGet, url, nil)
|
|
resp2, err := httpClient.Do(req2)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
resp2.Body.Close()
|
|
return resp2.StatusCode >= 200 && resp2.StatusCode < 400
|
|
}
|
|
|
|
func githubGet(url string) ([]byte, int, error) {
|
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
req.Header.Set("User-Agent", "awesome-go-quality-check")
|
|
req.Header.Set("Accept", "application/vnd.github+json")
|
|
if token := os.Getenv("GITHUB_TOKEN"); token != "" {
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
}
|
|
resp, err := httpClient.Do(req)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
defer resp.Body.Close()
|
|
body, err := io.ReadAll(resp.Body)
|
|
return body, resp.StatusCode, err
|
|
}
|
|
|
|
// --- GitHub repo checks ---
|
|
|
|
type repoCheckResult struct {
|
|
ok bool
|
|
reason string
|
|
hasLicense bool
|
|
licenseName string
|
|
licenseChecked bool
|
|
hasFiveMonths bool
|
|
maturityChecked bool
|
|
hasCI bool
|
|
ciChecked bool
|
|
hasReadme bool
|
|
readmeChecked bool
|
|
}
|
|
|
|
func checkGithubRepo(repoURL string) repoCheckResult {
|
|
m := reGithubRepo.FindStringSubmatch(repoURL)
|
|
if m == nil {
|
|
return repoCheckResult{reason: "invalid repo url"}
|
|
}
|
|
owner, repo := m[1], m[2]
|
|
base := "https://api.github.com"
|
|
|
|
// Fetch repo metadata
|
|
data, status, err := githubGet(fmt.Sprintf("%s/repos/%s/%s", base, owner, repo))
|
|
if err != nil || status >= 400 {
|
|
return repoCheckResult{reason: "repo api not reachable"}
|
|
}
|
|
|
|
var rd repoData
|
|
if json.Unmarshal(data, &rd) != nil {
|
|
return repoCheckResult{reason: "repo api not reachable"}
|
|
}
|
|
if rd.Message != "" {
|
|
return repoCheckResult{reason: "repo api not reachable"}
|
|
}
|
|
if rd.Archived {
|
|
return repoCheckResult{reason: "repo is archived"}
|
|
}
|
|
|
|
result := repoCheckResult{}
|
|
|
|
// License
|
|
result.licenseChecked = true
|
|
if rd.License != nil && rd.License.SPDXID != "" && rd.License.SPDXID != "NOASSERTION" {
|
|
result.hasLicense = true
|
|
result.licenseName = rd.License.SPDXID
|
|
}
|
|
|
|
// go.mod
|
|
hasGoMod := false
|
|
goModData, goModStatus, _ := githubGet(fmt.Sprintf("%s/repos/%s/%s/contents/go.mod", base, owner, repo))
|
|
if goModStatus == 200 {
|
|
var entry contentEntry
|
|
if json.Unmarshal(goModData, &entry) == nil && entry.Name == "go.mod" {
|
|
hasGoMod = true
|
|
}
|
|
}
|
|
|
|
// SemVer tags
|
|
hasSemver := false
|
|
tagsData, tagsStatus, _ := githubGet(fmt.Sprintf("%s/repos/%s/%s/tags?per_page=100", base, owner, repo))
|
|
if tagsStatus == 200 {
|
|
var tags []tagEntry
|
|
if json.Unmarshal(tagsData, &tags) == nil {
|
|
for _, t := range tags {
|
|
if reSemver.MatchString(t.Name) {
|
|
hasSemver = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Maturity (5+ months)
|
|
result.maturityChecked = true
|
|
fiveMonthsAgo := time.Now().AddDate(0, -5, 0).Format(time.RFC3339)
|
|
commitsData, commitsStatus, _ := githubGet(fmt.Sprintf("%s/repos/%s/%s/commits?per_page=1&until=%s", base, owner, repo, fiveMonthsAgo))
|
|
if commitsStatus == 200 {
|
|
var commits []json.RawMessage
|
|
if json.Unmarshal(commitsData, &commits) == nil && len(commits) > 0 {
|
|
result.hasFiveMonths = true
|
|
}
|
|
}
|
|
|
|
// CI/CD (GitHub Actions)
|
|
result.ciChecked = true
|
|
wfData, wfStatus, _ := githubGet(fmt.Sprintf("%s/repos/%s/%s/actions/workflows", base, owner, repo))
|
|
if wfStatus == 200 {
|
|
var wf workflowsResponse
|
|
if json.Unmarshal(wfData, &wf) == nil && wf.TotalCount > 0 {
|
|
result.hasCI = true
|
|
}
|
|
}
|
|
|
|
// README
|
|
result.readmeChecked = true
|
|
readmeData, readmeStatus, _ := githubGet(fmt.Sprintf("%s/repos/%s/%s/readme", base, owner, repo))
|
|
if readmeStatus == 200 {
|
|
var entry contentEntry
|
|
if json.Unmarshal(readmeData, &entry) == nil && entry.Name != "" {
|
|
result.hasReadme = true
|
|
}
|
|
}
|
|
|
|
result.ok = hasGoMod && hasSemver
|
|
if !hasGoMod {
|
|
result.reason = "missing go.mod"
|
|
} else if !hasSemver {
|
|
result.reason = "missing semver release"
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// --- Go Report Card ---
|
|
|
|
func checkGoReportCard(url string) (grade string, ok bool) {
|
|
if !isReachable(url) {
|
|
return "unreachable", false
|
|
}
|
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
|
if err != nil {
|
|
return "fetch error", false
|
|
}
|
|
resp, err := httpClient.Do(req)
|
|
if err != nil {
|
|
return "fetch error", false
|
|
}
|
|
defer resp.Body.Close()
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "fetch error", false
|
|
}
|
|
m := reGrade.FindSubmatch(body)
|
|
if m == nil {
|
|
return "unknown", true // reachable but no grade found
|
|
}
|
|
g := strings.ToUpper(string(m[1]))
|
|
pass := g == "A" || g == "A+" || g == "A-"
|
|
return g, pass
|
|
}
|
|
|
|
// --- Output helpers ---
|
|
|
|
func setOutput(name, value string) {
|
|
path := os.Getenv("GITHUB_OUTPUT")
|
|
if path == "" {
|
|
fmt.Printf("%s=%s\n", name, value)
|
|
return
|
|
}
|
|
f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer f.Close()
|
|
fmt.Fprintf(f, "%s<<EOF\n%s\nEOF\n", name, value)
|
|
}
|
|
|
|
func icon(ok bool) string {
|
|
if ok {
|
|
return "\u2705"
|
|
}
|
|
return "\u274C"
|
|
}
|
|
|
|
func warnIcon(ok bool) string {
|
|
if ok {
|
|
return "\u2705"
|
|
}
|
|
return "\u26A0\uFE0F"
|
|
}
|
|
|
|
func boolStr(b bool) string {
|
|
if b {
|
|
return "true"
|
|
}
|
|
return "false"
|
|
}
|
|
|
|
func fix(problem, howToFix string) string {
|
|
return fmt.Sprintf(" > **How to fix:** %s\n > %s", problem, howToFix)
|
|
}
|
|
|
|
func repoFixMessage(reason, repoURL string) string {
|
|
switch reason {
|
|
case "invalid repo url":
|
|
return fix("The forge link is not a valid repository URL.", "Use the full URL, e.g. `https://github.com/org/project`.")
|
|
case "repo api not reachable":
|
|
return fix("Could not reach the repository via GitHub API.", "Ensure the repository is **public** and the URL is correct.")
|
|
case "repo is archived":
|
|
return fix("This repository is archived on GitHub.", "Archived repositories are not accepted. The project must be actively maintained or at least open to contributions.")
|
|
case "missing go.mod":
|
|
return fix("No `go.mod` file found at the repository root.", "Initialize Go modules in your project:\n > ```\n > go mod init github.com/your-org/your-project\n > go mod tidy\n > git add go.mod go.sum && git commit -m \"add go module\" && git push\n > ```")
|
|
case "missing semver release":
|
|
return fix("No SemVer release tag (e.g. `v1.0.0`) found.", "Create a tagged release:\n > ```\n > git tag v1.0.0\n > git push origin v1.0.0\n > ```\n > Or create a release via GitHub's UI at `"+repoURL+"/releases/new`.")
|
|
default:
|
|
return fix(reason, "Review the [quality standards](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#quality-standards).")
|
|
}
|
|
}
|